Compare commits
364 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c691400630 | |||
| 6acbfb1181 | |||
| 5f7474140f | |||
| c56d6f4c75 | |||
| c874ae50e5 | |||
| 25e7cc97f9 | |||
| 837e4bc537 | |||
| 65fa93d853 | |||
| 28b0276f17 | |||
| 10ac15f8a2 | |||
| a45633e214 | |||
| a42ba5446a | |||
| ccfe1bded5 | |||
| dfedf4e879 | |||
| 0682c404f2 | |||
| 80ece70450 | |||
| f6245c712d | |||
| e0c5f0d4f1 | |||
| b616e2ea33 | |||
| 6fb6995103 | |||
| 47bc0c2382 | |||
| 59a919d888 | |||
| 17d673c288 | |||
| 985fd46243 | |||
| 6d99e296e4 | |||
| 21c34efb6a | |||
| 9c2f923c26 | |||
| 52d2d70838 | |||
| edd8824c5e | |||
| 4f12ad9533 | |||
| 2a5850e67f | |||
| 15341edece | |||
| 30f8b4160e | |||
| 937ca5ecf6 | |||
| ba1757d4f1 | |||
| 5a2b5f43b8 | |||
| 2f487705c3 | |||
| 558d59ce88 | |||
| 1030edd322 | |||
| 981c8fd706 | |||
| 45ade602b5 | |||
| ef8a8682cd | |||
| 112ac4b6d5 | |||
| 3a26d2cb0b | |||
| a678bf42f1 | |||
| dc314a1d1b | |||
| 3af56f6bb1 | |||
| a996664e6c | |||
| 6e865fef06 | |||
| 588bd0f341 | |||
| 69f6abf4b6 | |||
| c8eb4ac31a | |||
| e3e69390ce | |||
| d0b34dfdf8 | |||
| bcdb3dc351 | |||
| a7b0031b8d | |||
| 2c05bc6961 | |||
| c2d0ec92bf | |||
| 407b4dce94 | |||
| 796157384f | |||
| 3446977df6 | |||
| f8016aba99 | |||
| 56d8527ed9 | |||
| 302788bcba | |||
| db075e602a | |||
| 67011d4740 | |||
| a35d867b34 | |||
| 23b59e54d7 | |||
| da2665d2bc | |||
| 919fe29ffb | |||
| 3b2870a318 | |||
| 1076e8531c | |||
| 72f2effda4 | |||
| 7566f56858 | |||
| c1f9c9e25e | |||
| 380a52efb3 | |||
| 028c3ba92b | |||
| f80aba33f1 | |||
| bb15c9e2d0 | |||
| 518c80bb1d | |||
| 0067d049e6 | |||
| bf60dd24aa | |||
| 38d9cc4892 | |||
| c4f2f55617 | |||
| 8f73fb85e9 | |||
| 3bd126c11d | |||
| 7e7aba06a6 | |||
| 2bf00f7ddc | |||
| 24b88e4ac0 | |||
| 3df3130395 | |||
| c0c388d1b9 | |||
| 9f27cc61da | |||
| 8fa1987ec0 | |||
| 39eae42b05 | |||
| 4dfbb437f9 | |||
| f132d22308 | |||
| b7dd2ff8b4 | |||
| b6b78591bc | |||
| ec54a0dbce | |||
| 8793912b65 | |||
| 70c430ddc2 | |||
| 815dbba497 | |||
| dc5bac67aa | |||
| 5427fd7860 | |||
| 119c09d730 | |||
| 1da6833c71 | |||
| 4b8cf53731 | |||
| d646ddd91d | |||
| 764719afde | |||
| 75ec7688b1 | |||
| 7fc508603f | |||
| fb2d78fd57 | |||
| 4480132c74 | |||
| 38c0a9d403 | |||
| 4169db33e6 | |||
| ee48072137 | |||
| a3c1a5c731 | |||
| e74f922e8d | |||
| 16cd90f7b7 | |||
| e2ba10d224 | |||
| 459e9359db | |||
| d2a044f958 | |||
| 2fbcd644d0 | |||
| cf8e736f46 | |||
| d4378731ae | |||
| 000344a942 | |||
| bf6abd301c | |||
| 143a1dd39b | |||
| 9b3a8258ce | |||
| 646b8f8736 | |||
| 2528e4acad | |||
| 286d939097 | |||
| ca3d661830 | |||
| 63fee653e8 | |||
| 9da2473976 | |||
| 6d1eeacc49 | |||
| f85748fef9 | |||
| 9f34b33b7e | |||
| 1510f39a8a | |||
| bbbe011482 | |||
| 82ab7a043f | |||
| 798253a50e | |||
| 52432ca068 | |||
| b3f1d8464b | |||
| 87bb62b359 | |||
| 3f914d02cc | |||
| d1db77d0f5 | |||
| 6aa297c1a4 | |||
| f3647e9bc1 | |||
| 5b43c62f2d | |||
| 23ffb15a8d | |||
| adb2ce4846 | |||
| cdee6ca743 | |||
| fe30aa4af2 | |||
| 9943728eab | |||
| 8ae7cf05cc | |||
| a7c944e8ef | |||
| 102339d7e8 | |||
| 9a0ad0c663 | |||
| f86afc08fa | |||
| cd1b328b1b | |||
| 48f2bb1c75 | |||
| d416fe913e | |||
| 7f8744725c | |||
| e5d1b82a9d | |||
| 619cf2e134 | |||
| 28b522f015 | |||
| 39233f261e | |||
| 00f0127caf | |||
| f69b575381 | |||
| 986973a605 | |||
| 0d6b4591f1 | |||
| 2c62749d9b | |||
| 4be4288ef0 | |||
| c7eec167cf | |||
| 7bae956ffa | |||
| a2f59a5b1b | |||
| df56af9b0e | |||
| 83f7f9584f | |||
| a2d440e54f | |||
| 4132e8449b | |||
| ee444416e4 | |||
| 10c12c3c48 | |||
| db3775ae99 | |||
| 393acce884 | |||
| 68fe663730 | |||
| f65a4b0db0 | |||
| cdfb502e6e | |||
| 1a2c83e49b | |||
| e6c7a675a9 | |||
| 69c04f29f4 | |||
| 04c6f9b4fe | |||
| 86ec12a9db | |||
| 72b3111c64 | |||
| 6709c91779 | |||
| bb6e7495f5 | |||
| df17929681 | |||
| e083719ceb | |||
| bfdc69f18c | |||
| e7ae20afb7 | |||
| 229d92055f | |||
| 64c77cfd13 | |||
| 3a63894562 | |||
| 1d272f8b37 | |||
| bac433b640 | |||
| 62f573eac0 | |||
| b3ea62c53c | |||
| b0731503a8 | |||
| 2421c02c24 | |||
| 25e868118d | |||
| 2880044e0e | |||
| 5300404b46 | |||
| d949d58076 | |||
| 997b223e95 | |||
| ba52a97e26 | |||
| cc4c7b5fe9 | |||
| 8e2ebd11fc | |||
| 9cae4da9f4 | |||
| c05d7e99e2 | |||
| 2390599e8f | |||
| 1a4d45fa9c | |||
| 57447e5bf4 | |||
| 8e411daaef | |||
| 183aebf841 | |||
| e3e500ccc2 | |||
| e7a2535ece | |||
| 761e369313 | |||
| 5248275d73 | |||
| cb033279dd | |||
| 41d50d8c28 | |||
| a52c2b4c3c | |||
| b5917cb184 | |||
| 57348472f8 | |||
| 4b6223dc00 | |||
| 5525e45a15 | |||
| 80a2ae60b0 | |||
| d7e95f5d2f | |||
| ca4e5ae5ee | |||
| b673658c0c | |||
| 5c5c130700 | |||
| 2d89ca6c0e | |||
| 806a7c2609 | |||
| 501ce8067d | |||
| 6429f82829 | |||
| fe626218ea | |||
| b62b1bc063 | |||
| d980f36246 | |||
| b469addd29 | |||
| 6923c2a8b7 | |||
| 1d3f32fb99 | |||
| 42a550788a | |||
| b1c68972c9 | |||
| 3978e32d5f | |||
| ba2b5d182e | |||
| bef04fa899 | |||
| 4f8609421c | |||
| 07660c9d44 | |||
| a324dad2ba | |||
| dbaa0f5d49 | |||
| 478721d349 | |||
| a669a23dbc | |||
| cfeb6478cc | |||
| 64539c49c1 | |||
| 0399ae37ec | |||
| 173a411a36 | |||
| 62013a2ea2 | |||
| c82cf4a4c2 | |||
| df42085be6 | |||
| b09d3065ae | |||
| c050f5a9e3 | |||
| 78e6c0eca0 | |||
| da4da45348 | |||
| dc2af86db8 | |||
| 7502004aba | |||
| 2e8678e4c6 | |||
| 97569016fc | |||
| fe72798592 | |||
| 4583c4e028 | |||
| 0b98197a86 | |||
| 0e94a9c33f | |||
| 3dff1fcb4d | |||
| e163286dd4 | |||
| a99e12f12e | |||
| c3dd997e57 | |||
| a730384baf | |||
| 43cf91e877 | |||
| 75bee027e1 | |||
| 5cbf69a8bd | |||
| ecbb3086d8 | |||
| 7476767aa7 | |||
| e5b8987a9d | |||
| 6ca74c21bf | |||
| e0099141aa | |||
| d0491ed202 | |||
| cbc2137ced | |||
| f9ac13ba11 | |||
| b3533c285f | |||
| a636ae6592 | |||
| 69e3ee0aff | |||
| a39a87ba6d | |||
| 5b22d6ac01 | |||
| 7334cd26f8 | |||
| 44555215cf | |||
| 0cc25913c0 | |||
| 004b30b737 | |||
| 632f330b4c | |||
| 666433912f | |||
| db98ce8db7 | |||
| 71dcfae5ff | |||
| 04155f5b23 | |||
| b4058389ec | |||
| 483fa81b74 | |||
| a8d1c4bbbc | |||
| 0a8c2faa74 | |||
| dd3231e70f | |||
| 7ff9c00032 | |||
| 9ed483abf7 | |||
| b9aeaf29a4 | |||
| 65e3f81f36 | |||
| c6641dba31 | |||
| e48d1e0e59 | |||
| d1e5aee84e | |||
| 5cb22d0bed | |||
| d1c6f53d7c | |||
| 6e238f98c0 | |||
| 290274d6c8 | |||
| e1de0239c9 | |||
| bec77d59e8 | |||
| 84f8794d7c | |||
| 4cddf41bf3 | |||
| 125a7e238e | |||
| 468200b717 | |||
| bdfcb99781 | |||
| 38da650861 | |||
| dd006badfc | |||
| 87e4e3fe5b | |||
| af3e38254f | |||
| 70843f54d3 | |||
| bda75b29b4 | |||
| 750830d593 | |||
| 3c0f1a1d2f | |||
| 4253b0ed29 | |||
| 3c9b3f23df | |||
| e0d83608be | |||
| a0301d599b | |||
| 7dcaa0e8d7 | |||
| 129f49bcc7 | |||
| fc3b68c390 | |||
| 52c7df8a15 | |||
| ce1c4dd488 | |||
| fc6a1a3819 | |||
| 69bd6d0e70 | |||
| 6d383d54e8 | |||
| 998c48b1d3 | |||
| 7217d122b5 | |||
| 1c37c5bb3d | |||
| e8f785b558 | |||
| c94d314f6d | |||
| 2672a8f922 | |||
| 8a8d80d692 | |||
| 95698813c6 | |||
| 4001e877b4 | |||
| 99defc6d79 | |||
| a94883089e |
@@ -1,8 +1,10 @@
|
||||
--ignore-dir=.svelte-kit
|
||||
--ignore-dir=android
|
||||
--ignore-dir=target
|
||||
--ignore-dir=build
|
||||
--ignore-dir=ios/DerivedData
|
||||
--ignore-dir=ios/App/App/public
|
||||
--ignore-dir=ios/App/Pods
|
||||
--ignore-file=match:.svg
|
||||
--ignore-file=match:package-lock.json
|
||||
|
||||
|
||||
@@ -2,3 +2,11 @@ node_modules
|
||||
android
|
||||
ios
|
||||
build
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Env files (keep .env for build; exclude local overrides)
|
||||
.env.local
|
||||
.env.*.local
|
||||
@@ -1,18 +1,22 @@
|
||||
VITE_DEFAULT_PUBKEYS=06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,391819e2f2f13b90cac7209419eb574ef7c0d1f4e81867fc24c47a3ce5e8a248,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185,58c741aa630c2da35a56a77c1d05381908bd10504fdd2d8b43f725efa6d23196,61066504617ee79387021e18c89fb79d1ddbc3e7bff19cf2298f40466f8715e9,6389be6491e7b693e9f368ece88fcd145f07c068d2c1bbae4247b9b5ef439d32,63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed,6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e,76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa,7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,b676ded7c768d66a757aa3967b1243d90bf57afb09d1044d3219d8d424e4aea0,dace63b00c42e6e017d00dd190a9328386002ff597b841eb5ef91de4f1ce8491,eeb11961b25442b16389fe6c7ebea9adf0ac36dd596816ea7119e521b8821b9e,fe7f6bc6f7338b76bbf80db402ade65953e20b2f23e66e898204b63cc42539a3
|
||||
VITE_BURROW_URL=
|
||||
VITE_PLATFORM_URL=https://flotilla.social
|
||||
VITE_DEFAULT_BLOSSOM_SERVERS=https://blossom.primal.net/
|
||||
VITE_POMADE_SIGNERS=
|
||||
VITE_PLATFORM_URL=https://app.flotilla.social
|
||||
VITE_PLATFORM_TERMS=https://flotilla.social/terms
|
||||
VITE_PLATFORM_PRIVACY=https://flotilla.social/privacy
|
||||
VITE_PLATFORM_NAME=Flotilla
|
||||
VITE_PLATFORM_LOGO=static/flotilla.png
|
||||
VITE_PLATFORM_LOGO=static/logo.png
|
||||
VITE_PLATFORM_RELAYS=
|
||||
VITE_PLATFORM_ACCENT="#7161FF"
|
||||
VITE_PLATFORM_SECONDARY="#EB5E28"
|
||||
VITE_PLATFORM_DESCRIPTION="Flotilla is nostr — for communities."
|
||||
VITE_INDEXER_RELAYS=wss://purplepag.es/,wss://relay.damus.io/,wss://relay.nostr.band/,wss://indexer.coracle.social/
|
||||
VITE_SIGNER_RELAYS=wss://relay.nsec.app/,wss://bucket.coracle.social/
|
||||
VITE_NOTIFIER_PUBKEY=27b7c2ed89ef78322114225ea3ebf5f72c7767c2528d4d0c1854d039c00085df
|
||||
VITE_NOTIFIER_RELAY=wss://anchor.coracle.social/
|
||||
VITE_PUSH_SERVER=https://nps.flotilla.social/
|
||||
VITE_PUSH_BRIDGE=wss://npb.coracle.social/
|
||||
VITE_BLOCKED_RELAYS=brb.io,relay.nostr.band,nostr.mutinywallet.com,feeds.nostr.band,nostr.zbd.gg,wot.utxo.one,blastr.f7z.xyz,relay.current.fyi
|
||||
VITE_INDEXER_RELAYS=purplepag.es,relay.damus.io,indexer.coracle.social
|
||||
VITE_DEFAULT_RELAYS=relay.damus.io,relay.primal.net,nostr.mom
|
||||
VITE_DEFAULT_MESSAGING_RELAYS=auth.nostr1.com
|
||||
VITE_SIGNER_RELAYS=relay.nsec.app,ephemeral.snowflare.cc,bucket.coracle.social
|
||||
VITE_VAPID_PUBLIC_KEY=BIt2D4BdgdbCowD_0d3Np6GbrIGHxd7aIEUeZNe3hQuRlHz02OhzvDaai0XSFoJYVzSzdMjdyW-QhvW9_yq8j4Y
|
||||
VITE_GLITCHTIP_API_KEY=
|
||||
GLITCHTIP_AUTH_TOKEN=
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['master']
|
||||
branches: [master]
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
@@ -14,8 +14,6 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -25,8 +23,8 @@ jobs:
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
@@ -50,10 +48,3 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
@@ -1,5 +1,6 @@
|
||||
# Env
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
@@ -27,6 +28,10 @@ node_modules/
|
||||
build/
|
||||
.svelte-kit/
|
||||
|
||||
# Rust/Tauri
|
||||
*target/
|
||||
src-tauri/binaries/
|
||||
|
||||
# iOS
|
||||
ios/App/App/public
|
||||
ios/DerivedData
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
"svelteSortOrder": "options-styles-scripts-markup",
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": false,
|
||||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
||||
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-svelte"],
|
||||
"overrides": [{"files": "*.svelte", "options": {"parser": "svelte"}}]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
## Project Overview
|
||||
|
||||
Flotilla is a Nostr "relays as groups" community chat client. It implements NIP-29 (relay-based groups) to create Discord-like spaces (servers) and rooms (channels).
|
||||
|
||||
**Tech Stack:**
|
||||
|
||||
- SvelteKit 5.48+ with TypeScript 5.9+
|
||||
- Capacitor for cross-platform (Web/PWA, Android, iOS)
|
||||
- TailwindCSS + DaisyUI for styling
|
||||
- Welshman library suite for Nostr protocol
|
||||
- IndexedDB for local storage
|
||||
- Vite for building
|
||||
|
||||
**Key Concepts:**
|
||||
|
||||
- **Spaces** - Relays used as community groups (like Discord servers)
|
||||
- **Rooms** - NIP-29 groups within spaces (like Discord channels), identified by `h`
|
||||
- **Chats** - Direct message conversations (NIP-04/NIP-44 encrypted)
|
||||
|
||||
## Architecture & Dependency Graph
|
||||
|
||||
The project follows a **strict acyclic dependency hierarchy**:
|
||||
|
||||
```
|
||||
routes/ (top layer - can depend on anything)
|
||||
↓
|
||||
app/components/ (can depend on app/* and lib/*)
|
||||
↓
|
||||
app/core/ & app/util/ (can only depend on lib/*)
|
||||
↓
|
||||
lib/ (can only depend on external libraries)
|
||||
↓
|
||||
external libraries (bottom layer)
|
||||
```
|
||||
|
||||
**Import Ordering Convention (CRITICAL):**
|
||||
Always sort imports by dependency level:
|
||||
|
||||
1. Third-party libraries first
|
||||
2. Then `lib/` imports
|
||||
3. Then `app/` imports
|
||||
|
||||
Example:
|
||||
|
||||
```typescript
|
||||
import {derived} from "svelte/store"
|
||||
import {throttle} from "throttle-debounce"
|
||||
import {Dialog} from "$lib/components"
|
||||
import {repository} from "$app/core/state"
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── lib/ # Generic reusable code
|
||||
│ ├── components/ # 38 UI components (Button, Dialog, etc.)
|
||||
│ ├── html.ts # DOM utilities
|
||||
│ ├── indexeddb.ts # IndexedDB helpers
|
||||
│ └── util.ts # Generic utilities
|
||||
│
|
||||
├── app/
|
||||
│ ├── core/
|
||||
│ │ ├── state.ts # State management, stores, constants (687 lines)
|
||||
│ │ ├── commands.ts # Publishing events and other write operations (440+ lines)
|
||||
│ │ ├── requests.ts # Loading data from network (191 lines)
|
||||
│ │ ├── sync.ts # Data synchronization (296 lines)
|
||||
│ │ └── storage.ts # IndexedDB setup
|
||||
│ │
|
||||
│ ├── util/
|
||||
│ │ ├── notifications.ts # Push notifications (731 lines)
|
||||
│ │ ├── policies.ts # Relay policies
|
||||
│ │ ├── routes.ts # Routing helpers
|
||||
│ │ ├── modal.ts # Modal management
|
||||
│ │ ├── toast.ts # Toast notifications
|
||||
│ │ ├── theme.ts # Theme switching
|
||||
│ │ └── keyboard.ts # Keyboard handling
|
||||
│ │
|
||||
│ ├── editor/ # Rich text editor config
|
||||
│ │ ├── index.ts # TipTap setup with Nostr integration
|
||||
│ │ ├── EditorContent.svelte
|
||||
│ │ └── MentionNodeView.ts
|
||||
│ │
|
||||
│ └── components/ # 188 app-specific components
|
||||
│ ├── Space*.svelte # Space/relay management
|
||||
│ ├── Room*.svelte # Room/channel management
|
||||
│ ├── Chat*.svelte # Direct messaging
|
||||
│ ├── Profile*.svelte # User profiles
|
||||
│ ├── Thread*.svelte # Threaded posts
|
||||
│ └── ...
|
||||
│
|
||||
├── routes/ # SvelteKit file-based routing
|
||||
│ ├── +layout.svelte # Root layout (sync logic here)
|
||||
│ ├── spaces/ # Space management
|
||||
│ │ └── [relay]/ # Specific space
|
||||
│ │ ├── chat/ # Space chat
|
||||
│ │ ├── threads/ # Thread posts
|
||||
│ │ ├── calendar/ # Events
|
||||
│ │ └── [h]/ # Specific room (h = room id)
|
||||
│ ├── chat/ # Direct messages
|
||||
│ ├── settings/ # User settings
|
||||
│ └── [bech32]/ # Bech32 entity viewer
|
||||
│
|
||||
├── assets/icons/ # ~1,277 SVG icons
|
||||
├── app.html # HTML template
|
||||
├── app.css # Global styles
|
||||
└── types.d.ts # Type definitions
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
**Core Principles:**
|
||||
|
||||
- Use Svelte 4 **stores** for all state (NOT runes outside UI components)
|
||||
- Most global state flows through Welshman's `repository` (unidirectional)
|
||||
- Query state using `deriveEventsMapped` or `deriveProfile` etc
|
||||
- Update state by publishing events via `publishThunk`
|
||||
|
||||
**Thunks:**
|
||||
|
||||
- Reduce UI latency by handling signatures and sending in background
|
||||
- Return status that should be displayed to user
|
||||
- Allow cancellation and error handling
|
||||
- Immediately publish to local repository for optimistic updates
|
||||
|
||||
## Nostr Integration
|
||||
|
||||
**Welshman Library Suite:**
|
||||
|
||||
- `@welshman/app` - High-level state (pubkey, signer, repository, tracker)
|
||||
- `@welshman/net` - Network layer (Pool, Socket, load, pull, request)
|
||||
- `@welshman/store` - Svelte integration (deriveEventsMapped, etc.)
|
||||
- `@welshman/util` - Event utilities (kinds, tags, validation)
|
||||
- `@welshman/signer` - Signing abstraction (NIP-01, NIP-07, NIP-46)
|
||||
- `@welshman/router` - Relay routing (inbox/outbox model)
|
||||
- `@welshman/editor` - Rich text editor with Nostr
|
||||
- `@welshman/content` - Content parsing
|
||||
- `@welshman/feeds` - Feed management
|
||||
|
||||
**Key NIPs Implemented:**
|
||||
|
||||
- NIP-01: Basic protocol
|
||||
- NIP-44/59/17: Encrypted DMs
|
||||
- NIP-07: Browser extension signing
|
||||
- NIP-19: Bech32 encoding
|
||||
- NIP-29: Relay-based Groups
|
||||
- NIP-42: Relay authentication
|
||||
- NIP-43: Relay membership
|
||||
- NIP-46: Nostr Connect (remote signing)
|
||||
- NIP-57: Lightning Zaps
|
||||
|
||||
## Development Conventions
|
||||
|
||||
**Component Parameterization:**
|
||||
|
||||
- Only pass entity identifiers (`url` for spaces, `h` for rooms)
|
||||
- Derive all other data inside the component from identifiers
|
||||
- Example: Don't pass `members` prop, derive it from `h` inside component
|
||||
|
||||
**CRITICAL Code Style Guidelines:**
|
||||
|
||||
- **No `null`** - only use `undefined`
|
||||
- Svelte 5 runes (`$state`, `$derived`, `$effect`) only in UI components
|
||||
- TailwindCSS and DaisyUI styling
|
||||
- Only add comments for really weird stuff
|
||||
- Do not call functions in components unless a parameter is reactive. Instead, use a svelte store or rune to make it reactive.
|
||||
- Do not use `any`. If there are type errors related to `unknown`, they are likely because the upstream definition of the data is incorrect.
|
||||
- When dynamically building classes, use `cx` from `classnames` rather than embedded ternaries or svelte 4's old `class:` syntax.
|
||||
- When creating forms, use `FieldInline` or `Field` instead of custom elements/tailwindcss
|
||||
- Do not define svelte event handlers inline, instead name them and put them in the script section of templates
|
||||
- Avoid using `as`, except where necessary. Instead, annotate function parameters, and ensure upstream values are typed correctly.
|
||||
|
||||
**Human-First Simplicity (Jon Staab Style):**
|
||||
|
||||
- Prefer direct, readable code over layered abstractions.
|
||||
- Do not add indirection (extra helpers, wrappers, stores, or derived state) unless it removes real repeated complexity.
|
||||
- Reuse existing Welshman and Flotilla primitives before introducing new utilities or dependencies.
|
||||
- Favor linear control flow and explicit naming over clever patterns.
|
||||
- Remove defensive checks that do not apply in this runtime model.
|
||||
- When two approaches work, pick the one that feels more human and easier to maintain.
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Component
|
||||
|
||||
1. Determine if it's generic (`lib/components/`) or app-specific (`app/components/`)
|
||||
2. Follow naming convention: `PascalCase.svelte`
|
||||
3. Import in dependency order (3rd party → lib → app)
|
||||
4. Use stores for state, runes only for UI reactivity
|
||||
|
||||
### Creating a New Route
|
||||
|
||||
1. Add to `src/routes/` following SvelteKit conventions
|
||||
2. Use `+page.svelte` for page component
|
||||
3. Use `+layout.svelte` for shared layouts
|
||||
4. Top-level sync logic goes in root `+layout.svelte`
|
||||
|
||||
### Loading Data from Network
|
||||
|
||||
1. Use utilities from `app/core/requests.ts`
|
||||
2. Or create derived stores in `app/core/state.ts`
|
||||
3. Use `load`, `pull`, or `request` from `@welshman/net`
|
||||
|
||||
### Publishing Events
|
||||
|
||||
1. Create `make*` function to build event template
|
||||
2. Create `publish*` function using `publishThunk`
|
||||
3. Display thunk status to user (for cancel/error handling)
|
||||
4. These go in in `app/core/commands.ts`
|
||||
|
||||
### Managing Modals/Toasts
|
||||
|
||||
- Import from `app/util/modal.ts` or `app/util/toast.ts`
|
||||
- Pass component objects with parameters
|
||||
- Use `$state.snapshot` if calling component might unmount
|
||||
|
||||
## Development Workflow
|
||||
|
||||
Agents should not run the dev server or build the app. Instead, use the following commands:
|
||||
|
||||
```bash
|
||||
pnpm run format # Format changed files
|
||||
pnpm run lint # Check formatting and linting
|
||||
pnpm run check # Type check
|
||||
```
|
||||
|
||||
**Welshman Development:**
|
||||
|
||||
- Clone welshman to parent directory
|
||||
- Use `./link_deps` script to link local welshman packages
|
||||
- Avoid committing `pnpm.overrides` changes
|
||||
|
||||
**Git Workflow:**
|
||||
|
||||
- `master` branch auto-deploys to production
|
||||
- Work on feature branches based on `dev` branch
|
||||
- Pre-commit hooks run lint/typecheck automatically
|
||||
|
||||
## Environment Variables
|
||||
|
||||
See `.env.template` for all options.
|
||||
|
||||
## Important Files to Reference
|
||||
|
||||
- **src/app/core/state.ts** - All stores and constants
|
||||
- **src/app/core/sync.ts** - Data synchronization
|
||||
- **src/app/core/requests.ts** - Utilities for requesting data
|
||||
- **src/app/core/commands.ts** - Publishing patterns
|
||||
- **src/app/util/notifications.ts** - Notification badges and push notifications
|
||||
- **src/routes/+layout.svelte** - Top-level sync logic
|
||||
|
||||
## Mobile Development
|
||||
|
||||
**Capacitor Integration:**
|
||||
|
||||
- Android: Full support, APK builds via `pnpm run release:android`
|
||||
- iOS: Full support (zaps disabled due to App Store policy)
|
||||
- PWA: Progressive Web App with service worker
|
||||
|
||||
**Native Features:**
|
||||
|
||||
- Push notifications (FCM/APNs)
|
||||
- Deep linking (nostr: and https: URLs)
|
||||
- Native signing plugin
|
||||
- Keyboard management
|
||||
- Safe area handling
|
||||
- Badge management
|
||||
@@ -1,5 +1,196 @@
|
||||
# Changelog
|
||||
|
||||
# 1.6.5
|
||||
|
||||
* Attempt to fix permission grant for notifications
|
||||
* Make sync logic more robust
|
||||
* Add unban/unallow support
|
||||
* Improve support for downloading/opening protected images
|
||||
* Add manual send/receive to wallet
|
||||
* Show wallet status when wallet is unreachable
|
||||
* Update nostr signer capacitor plugin
|
||||
* Fix some safe area insets
|
||||
* Update NIP 55 signer plugin (fixes Primal login)
|
||||
* Refine space join dialogs and discover page
|
||||
* Reopen the last DM that was open when navigating back to chat
|
||||
* Get rid of ChatEnable interstitial
|
||||
* Enable auth for relays we're publishing to
|
||||
* Drag and drop space icons
|
||||
* Add better muting support
|
||||
* Add back button to settings menu
|
||||
* Add page titles
|
||||
* Improve scroll to event behavior
|
||||
* Add in-memory search to rooms
|
||||
* Fix editing messages with html tags
|
||||
* Fix DM media detection
|
||||
* Clean up reporting dialogs
|
||||
* Improve room detail
|
||||
|
||||
# 1.6.4
|
||||
|
||||
* Clean up modal design
|
||||
* Fix overflowing popovers
|
||||
* Use space urls for relay hints
|
||||
* Re-work notification badges
|
||||
* Add push notification support via NIP 9a
|
||||
* Optimistically load messaging relays to avoid unnecessary warning
|
||||
* Recover from indexeddb not being available
|
||||
* Fix safe area inset support
|
||||
* Show space URL in top bar on mobile
|
||||
* Fix calendar detail page
|
||||
* Improve relay synchronization, especially for pyramid and relay29
|
||||
* Improve invite code error handling
|
||||
* Add wallet receive flow
|
||||
* Fix safari image uploads
|
||||
* Re-work recent activity page
|
||||
* Add classified listing content type
|
||||
* Use address for page param for replaceable events
|
||||
* Refine discover page to avoid slowness
|
||||
* Upgrade som dependencies
|
||||
* Tag event author when tagging parent event
|
||||
* Disable macos build
|
||||
* Add room muting
|
||||
|
||||
# 1.6.3
|
||||
|
||||
* Fix scroll down button z index
|
||||
* Hide tooltips on mobile
|
||||
* Sort comments ascending
|
||||
* Make video embeds rounded
|
||||
* Fix ProfileMultiSelect styling
|
||||
* Accept hex pubkeys/npubs/nprofiles in ProfileMultiSelect
|
||||
* Tweak room edit form design
|
||||
* Report pending signer to user
|
||||
* Update default relays
|
||||
* Fix chat list responsiveness
|
||||
* Fix memory leak, notification badge not showing
|
||||
* Improve space join flow
|
||||
* Fix opening images in fullscreen dialog
|
||||
* Add support for blocked relays
|
||||
* Add authentication policy setting
|
||||
* Add login with key if no signer is detected
|
||||
* Publish default relay selections on signup
|
||||
|
||||
# 1.6.2
|
||||
|
||||
* Fix modal scrolling and style
|
||||
|
||||
# 1.6.1
|
||||
|
||||
* Fix skinny profile images
|
||||
* Custom handler for relay urls
|
||||
* Improve time based chat partitioning
|
||||
* Improve authenticated image access interop
|
||||
* Fix image detail dialog
|
||||
* Fix zapper loading
|
||||
* Fix recent events missing in feeds
|
||||
|
||||
# 1.6.0
|
||||
|
||||
* Switch back to indexeddb to fix memory and performance
|
||||
* Add pay invoice functionality
|
||||
* Add space membership management and bans
|
||||
* Add event info to profile dialog
|
||||
* Add better room membership management
|
||||
* Refactor stores for performance
|
||||
* Hide nav when keyboard is open
|
||||
* Handle flotilla links in-app
|
||||
* Fix new messages indicator z-index
|
||||
* Fix some display bugs
|
||||
* Add date to chat items
|
||||
* Refine data synchronization
|
||||
* Hide nav when keyboard is open on mobile
|
||||
|
||||
# 1.5.3
|
||||
|
||||
* Add space edit form
|
||||
* Improve room syncing
|
||||
* Return better blossom errors
|
||||
* Fix access restricted bugs
|
||||
* Add room detail dialog
|
||||
* Fix broken link to self hosting
|
||||
* Tweak shadows
|
||||
* Always join spaces when visiting them
|
||||
|
||||
# 1.5.2
|
||||
|
||||
* Fix negentropy room syncing
|
||||
|
||||
# 1.5.1
|
||||
|
||||
* Fix chat path link
|
||||
|
||||
# 1.5.0
|
||||
|
||||
* Restyle mobile dialogs
|
||||
* Add room membership lists
|
||||
* Add space membership lists
|
||||
* Add edit room form
|
||||
* Support closed/private/restricted/hidden rooms
|
||||
* Add hosting services page
|
||||
* Improve performance and UI
|
||||
* Fix push notifications
|
||||
* Improve error detection and handling
|
||||
* Support invite links on discover page
|
||||
* Add link to landlubber if user is admin
|
||||
* Clear reply/share/edit on escape
|
||||
|
||||
# 1.4.1
|
||||
|
||||
* Improve data synchronization
|
||||
* Fix app url on capacitor deployments
|
||||
|
||||
# 1.4.0
|
||||
|
||||
* Allow "editing" chat messages
|
||||
* Check for room create permission
|
||||
* Re-work space navigation
|
||||
* Show all messages in non-nip29 chat
|
||||
* Improve synchronization logic
|
||||
* Add connection status to space menu
|
||||
* Add icon picker to room create component
|
||||
* Improve mention suggestions
|
||||
* Improve storage adapter and relay list performance
|
||||
* Fix modals
|
||||
* Add room deletion
|
||||
* Fix zapper loading
|
||||
* Add support for relay/group member lists and join/leave events
|
||||
|
||||
# 1.3.1
|
||||
|
||||
* Fix memory leak in storage adapter
|
||||
* Show fewer annoying toast messages
|
||||
|
||||
# 1.3.0
|
||||
|
||||
* Add optional badge and sound for notifications
|
||||
* Improve link rendering
|
||||
* Remove imgproxy
|
||||
* Bring back blossom feature detection for spaces
|
||||
* Improve light theme
|
||||
* Add more info to signer status
|
||||
* Simplify navigation for adding a space
|
||||
* Add ability to scan QR code for invite links
|
||||
* Streamline wallet setup and move receive address setting
|
||||
* Remove indexeddb on mobile, use capacitor file storage API
|
||||
* Fix duplicate DMs showing up
|
||||
|
||||
# 1.2.5
|
||||
|
||||
* Fix icons in build
|
||||
|
||||
# 1.2.4
|
||||
|
||||
* Add direct message alerts
|
||||
* Add alert settings page
|
||||
* Add instructions to key download
|
||||
* Add option that allows relays to strip signatures
|
||||
* Detect relays that mostly refuse to serve requests
|
||||
* Compress and upload profile images
|
||||
* Use system theme by default
|
||||
* Switch icon set, refactor how they're included
|
||||
* Use capacitor's preferences for storage instead of localStorage
|
||||
|
||||
# 1.2.3
|
||||
|
||||
* Add `created_at` to event info dialog
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
# Contributing guidelines
|
||||
|
||||
## Project Overview
|
||||
|
||||
Flotilla is a svelte/typescript/capacitor project. It's intended to be an alternative to Discord for Nostr users. A high-quality UX is a priority, with an emphasis on well-tested, intuitive designs, and robust implementations.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Run `pnpm run dev` to get a dev server, and `pnpm run check:watch` to watch for typescript errors. When you're ready to commit, a pre-commit hook will run to lint and typecheck your work. To run the project on Android or iOS, use Android Studio or Xcode.
|
||||
|
||||
The `master` branch is automatically deployed to production, so always work on feature branches based on the `dev` branch. This project frequently uses unreleased versions of [welshman](https://welshman.coracle.social), using `pnpm` link to hotlink a local copy of the code. To set that up, clone welshman to the parent directory of your `coracle` client, then add `link:../welshman/packages/packagename` to the `pnpm.overrides` section of your `package.json`. Below is a nodejs script that will do that automatically for you:
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'))
|
||||
|
||||
packageJson.pnpm.overrides = Object.keys(packageJson.dependencies)
|
||||
.filter(pkg => pkg.startsWith('@welshman/'))
|
||||
.reduce((acc, pkg) => {
|
||||
const packageName = pkg.split('/')[1]
|
||||
acc[pkg] = `link:../welshman/packages/${packageName}`
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2) + '\n')
|
||||
|
||||
console.log('Added welshman package overrides.')
|
||||
```
|
||||
|
||||
Be sure to avoid committing overrides to either `package.json` or `pnpm-lock.yaml`. These overrides can generally be added, installed, and removed, and will persist until another `pnpm install` command gets run.
|
||||
|
||||
## File Structure
|
||||
|
||||
The main parts of the application are as follows:
|
||||
|
||||
- `static` - static assets like fonts, images, etc.
|
||||
- `src/assets` - svgs for use as icons.
|
||||
- `src/lib` - general purpose components and utilities.
|
||||
- `src/app/core/state` - environment variables, constants, custom stores, and some utilities derived from them.
|
||||
- `src/app/core/requests` - utilities related to loading data from the nostr network.
|
||||
- `src/app/core/commands` - utilities related to publishing nostr events and uploading media to blossom servers.
|
||||
- `src/app/utils` - other application logic, including stuff related to modals, routing, etc.
|
||||
- `src/app/editor` - configuration for `@welshman/editor` for use in various app views.
|
||||
- `src/app/components` - reusable components that depend on other `app` stuff.
|
||||
- `src/routes` - file-based routing interpreted by sveltekit.
|
||||
|
||||
Application organization is based on an acyclic dependency graph:
|
||||
|
||||
- `routes` can depend on anything
|
||||
- `app/components` can depend on anything in `app` or `lib`
|
||||
- `app/utils` and `app/core` can only depend on `lib`
|
||||
- `lib` (and everything else) can depend only on external libraries
|
||||
|
||||
The main stylistic/organizational rule when working in this project is that imports should be sorted based on the dependency graph. Third-party libraries should come first, then `lib`, then `app`.
|
||||
|
||||
## System Architecture
|
||||
|
||||
Flotilla's architecture generally mirrors the file structure. State is stored using Svelte `store`s provided either by `@welshman/app` or by `app/core/state`, allowing for idiomatic svelte 4 usage (svelte 5 runes are [ghey](https://habla.news/u/hodlbod@coracle.social/1739830562159) and not allowed outside of UI components).
|
||||
|
||||
State is then synchronized to local storage or indexeddb using storage helpers provided by welshman in `routes/+layout.svelte`. Other top level synchronization logic generally belongs there.
|
||||
|
||||
`app/core/state` contains all environment variables, constants, custom stores, and utilities derived from them. Most stores are `derived` from our event `repository` using `deriveEventsMapped`, which efficiently queries the repository and maps events to custom data structures. Some of these data structures are provided by `welshman`, and some are defined in `app/core/state`. In either case, they can always be mapped back to an event, which is important for updating replaceables without dropping unknown data.
|
||||
|
||||
Here are a few important domain objects:
|
||||
|
||||
- Spaces are relays used as community groups. Their `url`s are core to a lot of data and components, and are frequently passed around from place to place.
|
||||
- Chats are direct message conversations. There is currently some ambiguity in routing, since relays that don't support NIP 29 also have a "chat" tab, which uses vanilla NIP-C7.
|
||||
- NIP 29 groups are variously called "rooms" and "channels". Conventionally, a "room" is a group id, while a "channel" as an object representing the group's metadata.
|
||||
- "Alerts" are records of requests the user has made to be notified, following [this NIP](https://github.com/nostr-protocol/nips/pull/1796)
|
||||
|
||||
`app/core/requests` contains utilities related to loading data from the nostr network. This might include feed manager utilities, loaders, or listeners.
|
||||
|
||||
`app/core/commands` contains utilities related to publishing nostr events and uploading media to blossom servers. This also includes utilities related to sending lighting payments, authenticating with relays, or probing relay policy. Event creation should generally be split into `make` functions which build the event, and `publish` functions which publish the event using `publishThunk`.
|
||||
|
||||
Any of these utilities can be included either in `app/components` or `routes`. Crucial to keep in mind is that nearly all global state runs through welshman's `repository` in a unidirectional way. To update state, run `publishThunk`, which immediately publishes the event to the local repository. State can be read from the repository using `deriveEventsMapped` or other utilities provided by welshman like `deriveProfile`.
|
||||
|
||||
Thunks are designed to reduce UI latency, handling signatures and delayed sending the background. In most cases, thunk status should be displayed to the user so that they can cancel sending or address errors.
|
||||
|
||||
Toast, modals, and sidebar dialogs are controlled in `app/util/modal` and `app/util/toast`. In both cases, component objects can be passed along with parameters, but care has to be taken that the calling component either doesn't unmount before the modal (as when one modal replaces another), or that `$state.snapshot` is appropriately called on any state runes. These components frequently run into weird svelte compiler bugs too, in which case you may have to do some silly things to cope.
|
||||
|
||||
## Issues and Pull Requests
|
||||
|
||||
All work by contributors should be done against an issue. If there is no issue for the work you're doing, please open one or ask the project owner to open one. All PRs should be opened against the `dev` branch (unless for hotfixes).
|
||||
|
||||
## Communication
|
||||
|
||||
Discussion about development is done [on Flotilla](https://app.flotilla.social/spaces/internal.coracle.social). The group is currently closed, so please let me know if you'd like access.
|
||||
|
||||
## Project License
|
||||
|
||||
This project is licensed under the MIT license. By contributing, you agree to waive all intellectual property rights to your contributions to this project.
|
||||
|
||||
@@ -1,24 +1,31 @@
|
||||
FROM node:20-slim
|
||||
# Stage 1: Build
|
||||
# Uses .env from build context for config (logo, branding, etc.)
|
||||
# Optional: docker build --build-arg VITE_BUILD_HASH=$(git rev-parse --short HEAD) -t flotilla .
|
||||
|
||||
FROM node:20-bookworm AS builder
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm@latest
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm i
|
||||
|
||||
# Copy the rest of the application
|
||||
# Copy everything (including .env when present) - build.sh will source it
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
ARG VITE_BUILD_HASH
|
||||
ENV VITE_BUILD_HASH=${VITE_BUILD_HASH}
|
||||
|
||||
ENV NODE_OPTIONS=--max_old_space_size=16384
|
||||
RUN pnpm run build
|
||||
|
||||
# Default to serving the build directory
|
||||
CMD ["npx", "serve", "build"]
|
||||
# Stage 2: Runtime
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the built output - no source, no .env, no dev deps
|
||||
COPY --from=builder /app/build ./build
|
||||
|
||||
CMD ["npx", "serve", "build"]
|
||||
|
||||
@@ -8,21 +8,19 @@ If you would like to be interoperable with Flotilla, please check out this guide
|
||||
|
||||
You can also optionally create an `.env` file and populate it with the following environment variables (see `.env` for examples):
|
||||
|
||||
- `VITE_DEFAULT_PUBKEYS` - A comma-separated list of hex pubkeys for bootstrapping web of trust.
|
||||
- `VITE_PLATFORM_URL` - The url where the app will be hosted. This is only used for build-time population of meta tags.
|
||||
- `VITE_DEFAULT_PUBKEYS` - A comma-separated list of hex pubkeys for bootstrapping web of trust
|
||||
- `VITE_PLATFORM_URL` - The url where the app will be hosted
|
||||
- `VITE_PLATFORM_NAME` - The name of the app
|
||||
- `VITE_PLATFORM_LOGO` - A logo url for the app
|
||||
- `VITE_PLATFORM_LOGO` - A logo url for the app. Can be a local path or https link. Must be a PNG file.
|
||||
- `VITE_PLATFORM_RELAYS` - A list of comma-separated relay urls that will make flotilla operate in "platform mode". Disables all space browse/add/select functionality and makes the first platform relay the home page.
|
||||
- `VITE_PLATFORM_ACCENT` - A hex color for the app's accent color
|
||||
- `VITE_PLATFORM_DESCRIPTION` - A description of the app
|
||||
- `VITE_GLITCHTIP_API_KEY` - A Sentry DSN for use with glitchtip (error reporting)
|
||||
- `GLITCHTIP_AUTH_TOKEN` - A glitchtip auth token for error reporting
|
||||
|
||||
If you're deploying a custom version of flotilla, be sure to remove the `plausible.coracle.social` script from `app.html`. This sends analytics to a server hosted by the developer.
|
||||
|
||||
## Development
|
||||
|
||||
See [./CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
See [CONTRIBUTING.md](AGENTS.md).
|
||||
|
||||
## Deployment
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
namespace "social.flotilla"
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
namespace = "social.flotilla"
|
||||
compileSdk = rootProject.ext.compileSdkVersion
|
||||
defaultConfig {
|
||||
applicationId "social.flotilla"
|
||||
minSdk rootProject.ext.minSdkVersion
|
||||
targetSdk rootProject.ext.targetSdkVersion
|
||||
versionCode 24
|
||||
versionName "1.2.3"
|
||||
versionCode 41
|
||||
versionName "1.6.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
|
||||
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
|
||||
@@ -11,8 +11,11 @@ apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-community-safe-area')
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-filesystem')
|
||||
implementation project(':capacitor-keyboard')
|
||||
implementation project(':capacitor-preferences')
|
||||
implementation project(':capacitor-push-notifications')
|
||||
implementation project(':capawesome-capacitor-android-dark-mode-support')
|
||||
implementation project(':capawesome-capacitor-badge')
|
||||
implementation project(':nostr-signer-capacitor-plugin')
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
|
||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 705 B After Width: | Height: | Size: 711 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.9 KiB |
@@ -7,8 +7,8 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.8.0'
|
||||
classpath 'com.google.gms:google-services:4.4.2'
|
||||
classpath 'com.android.tools.build:gradle:8.13.2'
|
||||
classpath 'com.google.gms:google-services:4.4.4'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@7.2.0_@capacitor+core@7.2.0/node_modules/@capacitor/android/capacitor')
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-community-safe-area'
|
||||
project(':capacitor-community-safe-area').projectDir = new File('../node_modules/.pnpm/@capacitor-community+safe-area@7.0.0-alpha.1_@capacitor+core@7.2.0/node_modules/@capacitor-community/safe-area/android')
|
||||
project(':capacitor-community-safe-area').projectDir = new File('../node_modules/.pnpm/@capacitor-community+safe-area@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor-community/safe-area/android')
|
||||
|
||||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/app/android')
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/app/android')
|
||||
|
||||
include ':capacitor-filesystem'
|
||||
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.1.0_@capacitor+core@8.0.1/node_modules/@capacitor/filesystem/android')
|
||||
|
||||
include ':capacitor-keyboard'
|
||||
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/keyboard/android')
|
||||
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/keyboard/android')
|
||||
|
||||
include ':capacitor-preferences'
|
||||
project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/preferences/android')
|
||||
|
||||
include ':capacitor-push-notifications'
|
||||
project(':capacitor-push-notifications').projectDir = new File('../node_modules/.pnpm/@capacitor+push-notifications@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/push-notifications/android')
|
||||
project(':capacitor-push-notifications').projectDir = new File('../node_modules/.pnpm/@capacitor+push-notifications@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/push-notifications/android')
|
||||
|
||||
include ':capawesome-capacitor-android-dark-mode-support'
|
||||
project(':capawesome-capacitor-android-dark-mode-support').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-android-dark-mode-support@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-android-dark-mode-support/android')
|
||||
|
||||
include ':capawesome-capacitor-badge'
|
||||
project(':capawesome-capacitor-badge').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-badge@7.0.1_@capacitor+core@7.2.0/node_modules/@capawesome/capacitor-badge/android')
|
||||
project(':capawesome-capacitor-badge').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-badge/android')
|
||||
|
||||
include ':nostr-signer-capacitor-plugin'
|
||||
project(':nostr-signer-capacitor-plugin').projectDir = new File('../node_modules/.pnpm/nostr-signer-capacitor-plugin@0.0.4_@capacitor+core@7.2.0/node_modules/nostr-signer-capacitor-plugin/android')
|
||||
project(':nostr-signer-capacitor-plugin').projectDir = new File('../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_2704ecccfd05fcfb1ad8852744422b7c/node_modules/nostr-signer-capacitor-plugin/android')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -86,8 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -115,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -206,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
@@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
@@ -70,11 +70,11 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
ext {
|
||||
minSdkVersion = 23
|
||||
compileSdkVersion = 35
|
||||
targetSdkVersion = 35
|
||||
androidxActivityVersion = '1.9.2'
|
||||
minSdkVersion = 24
|
||||
compileSdkVersion = 36
|
||||
targetSdkVersion = 36
|
||||
androidxActivityVersion = '1.11.0'
|
||||
//https://github.com/ionic-team/capacitor/issues/7866
|
||||
// androidxAppCompatVersion = '1.7.0'
|
||||
androidxAppCompatVersion = '1.6.1'
|
||||
androidxCoordinatorLayoutVersion = '1.2.0'
|
||||
androidxCoreVersion = '1.15.0'
|
||||
androidxFragmentVersion = '1.8.4'
|
||||
coreSplashScreenVersion = '1.0.1'
|
||||
androidxWebkitVersion = '1.12.1'
|
||||
// androidxAppCompatVersion = '1.7.1'
|
||||
androidxAppCompatVersion = '1.7.1'
|
||||
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||
androidxCoreVersion = '1.17.0'
|
||||
androidxFragmentVersion = '1.8.9'
|
||||
coreSplashScreenVersion = '1.2.0'
|
||||
androidxWebkitVersion = '1.14.0'
|
||||
junitVersion = '4.13.2'
|
||||
androidxJunitVersion = '1.2.1'
|
||||
androidxEspressoCoreVersion = '3.6.1'
|
||||
cordovaAndroidVersion = '10.1.1'
|
||||
androidxJunitVersion = '1.3.0'
|
||||
androidxEspressoCoreVersion = '3.7.0'
|
||||
cordovaAndroidVersion = '14.0.1'
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@ temp_env=$(declare -p -x)
|
||||
if [ -f .env.template ]; then
|
||||
source .env.template
|
||||
fi
|
||||
|
||||
if [ -f .env ]; then
|
||||
source .env
|
||||
if [ -f .env.local ]; then
|
||||
source .env.local
|
||||
fi
|
||||
|
||||
# Avoid overwriting env vars provided directly
|
||||
@@ -18,12 +17,13 @@ if [[ -z $VITE_BUILD_HASH ]]; then
|
||||
export VITE_BUILD_HASH=$(git rev-parse --short HEAD)
|
||||
fi
|
||||
|
||||
if [[ $VITE_PLATFORM_LOGO =~ ^https://* ]]; then
|
||||
curl $VITE_PLATFORM_LOGO > static/logo.png
|
||||
if [[ $VITE_PLATFORM_LOGO =~ ^https:// ]]; then
|
||||
curl -fSL "$VITE_PLATFORM_LOGO" -o static/logo.png
|
||||
export VITE_PLATFORM_LOGO=static/logo.png
|
||||
fi
|
||||
|
||||
npx pwa-assets-generator
|
||||
# Ensure generator uses local path (dotenv may have loaded URL from .env)
|
||||
VITE_PLATFORM_LOGO="${VITE_PLATFORM_LOGO}" npx pwa-assets-generator
|
||||
npx vite build
|
||||
|
||||
# Replace index.html variables with stuff from our env
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import type { CapacitorConfig } from '@capacitor/cli';
|
||||
import type {CapacitorConfig} from "@capacitor/cli"
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'social.flotilla',
|
||||
appName: 'Flotilla',
|
||||
webDir: 'build'
|
||||
server: {
|
||||
androidScheme: "https"
|
||||
},
|
||||
appId: "social.flotilla",
|
||||
appName: "Flotilla",
|
||||
webDir: "build",
|
||||
android: {
|
||||
adjustMarginsForEdgeToEdge: false,
|
||||
adjustMarginsForEdgeToEdge: true,
|
||||
},
|
||||
plugins: {
|
||||
CapacitorHttp: {
|
||||
enabled: true,
|
||||
},
|
||||
SystemBars: {
|
||||
insetsHandling: "enable",
|
||||
},
|
||||
SplashScreen: {
|
||||
androidSplashResourceName: "splash"
|
||||
androidSplashResourceName: "splash",
|
||||
},
|
||||
Keyboard: {
|
||||
style: "DARK",
|
||||
@@ -20,14 +23,14 @@ const config: CapacitorConfig = {
|
||||
},
|
||||
Badge: {
|
||||
persist: true,
|
||||
autoClear: true
|
||||
autoClear: true,
|
||||
},
|
||||
},
|
||||
// Use this for live reload https://capacitorjs.com/docs/guides/live-reload
|
||||
// server: {
|
||||
// url: "http://192.168.1.115:1847",
|
||||
// cleartext: true
|
||||
// },
|
||||
};
|
||||
server: {
|
||||
// Use this for live reload https://capacitorjs.com/docs/guides/live-reload
|
||||
// url: "http://192.168.1.17:1847",
|
||||
// cleartext: true,
|
||||
},
|
||||
}
|
||||
|
||||
export default config;
|
||||
export default config
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
||||
3478F0332E846FEB002431E0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3478F0322E846FEB002431E0 /* PrivacyInfo.xcprivacy */; };
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
||||
@@ -21,6 +22,7 @@
|
||||
051414282E0CC28400BE0BC8 /* Flotilla Chat.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Flotilla Chat.entitlements"; sourceTree = "<group>"; };
|
||||
1F53EE54954731A2328CBC4B /* Pods-Flotilla Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Flotilla Chat.release.xcconfig"; path = "Pods/Target Support Files/Pods-Flotilla Chat/Pods-Flotilla Chat.release.xcconfig"; sourceTree = "<group>"; };
|
||||
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
||||
3478F0322E846FEB002431E0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
||||
504EC3041FED79650016851F /* Flotilla Chat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Flotilla Chat.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
@@ -58,6 +60,7 @@
|
||||
504EC2FB1FED79650016851F = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3478F0322E846FEB002431E0 /* PrivacyInfo.xcprivacy */,
|
||||
051414282E0CC28400BE0BC8 /* Flotilla Chat.entitlements */,
|
||||
504EC3061FED79650016851F /* App */,
|
||||
504EC3051FED79650016851F /* Products */,
|
||||
@@ -162,6 +165,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
|
||||
3478F0332E846FEB002431E0 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */,
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
|
||||
@@ -287,7 +291,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -338,7 +342,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
@@ -354,18 +358,19 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 17;
|
||||
CURRENT_PROJECT_VERSION = 32;
|
||||
DEVELOPMENT_TEAM = S26U9DYW3A;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.2.3;
|
||||
MARKETING_VERSION = 1.6.5;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -380,17 +385,18 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 17;
|
||||
CURRENT_PROJECT_VERSION = 32;
|
||||
DEVELOPMENT_TEAM = S26U9DYW3A;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.2.3;
|
||||
MARKETING_VERSION = 1.6.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
@@ -1,6 +1,6 @@
|
||||
require_relative '../../node_modules/.pnpm/@capacitor+ios@7.2.0_@capacitor+core@7.2.0/node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
require_relative '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
|
||||
platform :ios, '14.0'
|
||||
platform :ios, '15.0'
|
||||
use_frameworks!
|
||||
|
||||
# workaround to avoid Xcode caching of Pods that requires
|
||||
@@ -9,14 +9,16 @@ use_frameworks!
|
||||
install! 'cocoapods', :disable_input_output_paths => true
|
||||
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/.pnpm/@capacitor+ios@7.2.0_@capacitor+core@7.2.0/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/.pnpm/@capacitor+ios@7.2.0_@capacitor+core@7.2.0/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCommunitySafeArea', :path => '../../node_modules/.pnpm/@capacitor-community+safe-area@7.0.0-alpha.1_@capacitor+core@7.2.0/node_modules/@capacitor-community/safe-area'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/.pnpm/@capacitor+app@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/app'
|
||||
pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/keyboard'
|
||||
pod 'CapacitorPushNotifications', :path => '../../node_modules/.pnpm/@capacitor+push-notifications@7.0.1_@capacitor+core@7.2.0/node_modules/@capacitor/push-notifications'
|
||||
pod 'CapawesomeCapacitorBadge', :path => '../../node_modules/.pnpm/@capawesome+capacitor-badge@7.0.1_@capacitor+core@7.2.0/node_modules/@capawesome/capacitor-badge'
|
||||
pod 'NostrSignerCapacitorPlugin', :path => '../../node_modules/.pnpm/nostr-signer-capacitor-plugin@0.0.4_@capacitor+core@7.2.0/node_modules/nostr-signer-capacitor-plugin'
|
||||
pod 'Capacitor', :path => '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCommunitySafeArea', :path => '../../node_modules/.pnpm/@capacitor-community+safe-area@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor-community/safe-area'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/.pnpm/@capacitor+app@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/app'
|
||||
pod 'CapacitorFilesystem', :path => '../../node_modules/.pnpm/@capacitor+filesystem@8.1.0_@capacitor+core@8.0.1/node_modules/@capacitor/filesystem'
|
||||
pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/keyboard'
|
||||
pod 'CapacitorPreferences', :path => '../../node_modules/.pnpm/@capacitor+preferences@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/preferences'
|
||||
pod 'CapacitorPushNotifications', :path => '../../node_modules/.pnpm/@capacitor+push-notifications@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/push-notifications'
|
||||
pod 'CapawesomeCapacitorBadge', :path => '../../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-badge'
|
||||
pod 'NostrSignerCapacitorPlugin', :path => '../../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_2704ecccfd05fcfb1ad8852744422b7c/node_modules/nostr-signer-capacitor-plugin'
|
||||
end
|
||||
|
||||
target 'Flotilla Chat' do
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'fs'
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
const force = process.argv.includes('--force')
|
||||
|
||||
if (execSync('git status --porcelain', { encoding: 'utf8' }).trim() && !force) {
|
||||
console.error('Error: Git working tree is dirty. Please commit or stash your changes first, or re-run with --force.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'))
|
||||
|
||||
pkg.pnpm.overrides = pkg.pnpm.overrides || {}
|
||||
pkg.pnpm.overrides["@welshman/app"] = "link:../welshman/packages/app"
|
||||
pkg.pnpm.overrides["@welshman/content"] = "link:../welshman/packages/content"
|
||||
pkg.pnpm.overrides["@welshman/editor"] = "link:../welshman/packages/editor"
|
||||
pkg.pnpm.overrides["@welshman/feeds"] = "link:../welshman/packages/feeds"
|
||||
pkg.pnpm.overrides["@welshman/lib"] = "link:../welshman/packages/lib"
|
||||
pkg.pnpm.overrides["@welshman/net"] = "link:../welshman/packages/net"
|
||||
pkg.pnpm.overrides["@welshman/router"] = "link:../welshman/packages/router"
|
||||
pkg.pnpm.overrides["@welshman/signer"] = "link:../welshman/packages/signer"
|
||||
pkg.pnpm.overrides["@welshman/store"] = "link:../welshman/packages/store"
|
||||
pkg.pnpm.overrides["@welshman/util"] = "link:../welshman/packages/util"
|
||||
// pkg.pnpm.overrides["nostr-editor"] = "link:../nostr-editor"
|
||||
// pkg.pnpm.overrides["@pomade/core"] = "link:../pomade/packages/core"
|
||||
// pkg.pnpm.overrides["nostr-signer-capacitor-plugin"] = "link:../nostr-signer-capacitor-plugin"
|
||||
|
||||
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n')
|
||||
|
||||
execSync('pnpm i', { stdio: 'inherit' })
|
||||
|
||||
execSync('git checkout -f pnpm-lock.yaml', { stdio: 'inherit' })
|
||||
execSync('git checkout -f package.json', { stdio: 'inherit' })
|
||||
@@ -1,83 +1,91 @@
|
||||
{
|
||||
"name": "flotilla",
|
||||
"version": "1.2.3",
|
||||
"version": "1.6.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "./build.sh",
|
||||
"sourcemaps": "./build.sh && ./sourcemaps.sh",
|
||||
"release:android": "./build.sh && cap build android --androidreleasetype APK --signing-type apksigner",
|
||||
"tauri:dev": "tauri dev",
|
||||
"tauri:build": "tauri build",
|
||||
"tauri:info": "tauri info",
|
||||
"tauri:icons": "tauri icon assets/logo.png --output src-tauri/icons",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check src && eslint src",
|
||||
"format": "prettier --write src",
|
||||
"format": "git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte|css)$' | xargs -r prettier --write",
|
||||
"format:all": "prettier --write src",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.5",
|
||||
"@eslint/js": "^9.26.0",
|
||||
"@sentry/cli": "^2.40.0",
|
||||
"@sveltejs/kit": "^2.5.27",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||
"@types/eslint": "^9.6.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@sveltejs/kit": "^2.50.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||
"@tauri-apps/cli": "^2.9.6",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"autoprefixer": "^10.4.23",
|
||||
"classnames": "^2.5.1",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.45.1",
|
||||
"globals": "^15.0.0",
|
||||
"postcss": "^8.4.40",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss": "^3.4.7",
|
||||
"typescript": "^5.5.0",
|
||||
"typescript-eslint": "^8.0.0",
|
||||
"vite": "^5.4.4"
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^9.1.2",
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"globals": "^15.15.0",
|
||||
"postcss": "^8.5.6",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-svelte": "^3.4.1",
|
||||
"svelte": "^5.48.0",
|
||||
"svelte-check": "^4.3.5",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.53.1",
|
||||
"vite": "^5.4.21"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@capacitor-community/safe-area": "7.0.0-alpha.1",
|
||||
"@capacitor/android": "^7.0.0",
|
||||
"@capacitor/app": "^7.0.0",
|
||||
"@capacitor/cli": "^7.0.0",
|
||||
"@capacitor/core": "^7.0.1",
|
||||
"@capacitor/ios": "^7.0.0",
|
||||
"@capacitor/keyboard": "^7.0.0",
|
||||
"@capacitor/push-notifications": "^7.0.1",
|
||||
"@capawesome/capacitor-badge": "^7.0.1",
|
||||
"@getalby/sdk": "^5.1.0",
|
||||
"@capacitor-community/safe-area": "^8.0.1",
|
||||
"@capacitor/android": "^8.0.1",
|
||||
"@capacitor/app": "^8.0.0",
|
||||
"@capacitor/cli": "^8.0.1",
|
||||
"@capacitor/core": "^8.0.1",
|
||||
"@capacitor/filesystem": "^8.1.0",
|
||||
"@capacitor/ios": "^8.0.1",
|
||||
"@capacitor/keyboard": "^8.0.0",
|
||||
"@capacitor/preferences": "^8.0.0",
|
||||
"@capacitor/push-notifications": "^8.0.0",
|
||||
"@capawesome/capacitor-android-dark-mode-support": "^8.0.0",
|
||||
"@capawesome/capacitor-badge": "^8.0.0",
|
||||
"@getalby/lightning-tools": "^6.1.0",
|
||||
"@getalby/sdk": "^5.1.2",
|
||||
"@noble/curves": "^1.9.7",
|
||||
"@pomade/core": "^0.2.1",
|
||||
"@poppanator/sveltekit-svg": "^4.2.1",
|
||||
"@sentry/browser": "^8.35.0",
|
||||
"@sveltejs/adapter-static": "^3.0.4",
|
||||
"@tiptap/core": "^2.12.0",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@tiptap/core": "^2.27.2",
|
||||
"@types/qrcode": "^1.5.6",
|
||||
"@types/throttle-debounce": "^5.0.2",
|
||||
"@vite-pwa/assets-generator": "^0.2.6",
|
||||
"@vite-pwa/sveltekit": "^0.6.6",
|
||||
"@welshman/app": "^0.4.3",
|
||||
"@welshman/content": "^0.4.3",
|
||||
"@welshman/editor": "^0.4.3",
|
||||
"@welshman/feeds": "^0.4.3",
|
||||
"@welshman/lib": "^0.4.3",
|
||||
"@welshman/net": "^0.4.3",
|
||||
"@welshman/relay": "^0.4.3",
|
||||
"@welshman/router": "^0.4.3",
|
||||
"@welshman/signer": "^0.4.3",
|
||||
"@welshman/store": "^0.4.3",
|
||||
"@welshman/util": "^0.4.3",
|
||||
"compressorjs": "^1.2.1",
|
||||
"daisyui": "^4.12.10",
|
||||
"date-picker-svelte": "^2.13.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"emoji-picker-element": "^1.22.8",
|
||||
"fuse.js": "^7.0.0",
|
||||
"husky": "^9.1.6",
|
||||
"idb": "^8.0.0",
|
||||
"nostr-signer-capacitor-plugin": "^0.0.4",
|
||||
"nostr-tools": "^2.14.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"@vite-pwa/sveltekit": "^0.6.8",
|
||||
"@welshman/app": "^0.8.8",
|
||||
"@welshman/content": "^0.8.8",
|
||||
"@welshman/editor": "^0.8.8",
|
||||
"@welshman/feeds": "^0.8.8",
|
||||
"@welshman/lib": "^0.8.8",
|
||||
"@welshman/net": "^0.8.8",
|
||||
"@welshman/router": "^0.8.8",
|
||||
"@welshman/signer": "^0.8.8",
|
||||
"@welshman/store": "^0.8.8",
|
||||
"@welshman/util": "^0.8.8",
|
||||
"compressorjs-next": "^1.1.2",
|
||||
"daisyui": "^4.12.24",
|
||||
"date-picker-svelte": "^2.17.0",
|
||||
"dotenv": "^16.6.1",
|
||||
"emoji-picker-element": "^1.28.1",
|
||||
"fuse.js": "^7.1.0",
|
||||
"husky": "^9.1.7",
|
||||
"idb": "^8.0.3",
|
||||
"nostr-signer-capacitor-plugin": "github:coracle-social/nostr-signer-capacitor-plugin#main",
|
||||
"nostr-tools": "^2.19.4",
|
||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||
"qr-scanner": "^1.4.2",
|
||||
"qrcode": "^1.5.4",
|
||||
"throttle-debounce": "^5.0.2",
|
||||
@@ -85,11 +93,14 @@
|
||||
},
|
||||
"pnpm": {
|
||||
"ignoredBuiltDependencies": [
|
||||
"@sentry/cli",
|
||||
"esbuild"
|
||||
],
|
||||
"onlyBuiltDependencies": [
|
||||
"sharp"
|
||||
]
|
||||
"sharp",
|
||||
"nostr-signer-capacitor-plugin"
|
||||
],
|
||||
"overrides": {
|
||||
"sharp": "0.35.0-rc.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import dotenv from "dotenv"
|
||||
import {defineConfig, minimalPreset as preset} from "@vite-pwa/assets-generator/config"
|
||||
|
||||
dotenv.config({path: ".env"})
|
||||
dotenv.config({path: ".env.local"})
|
||||
dotenv.config({path: ".env.template"})
|
||||
|
||||
export default defineConfig({
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "1.92.0"
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
hash=$(find build -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum | awk '{print $1}')
|
||||
|
||||
sentry-cli \
|
||||
--url https://glitchtip.coracle.social \
|
||||
--auth-token $GLITCHTIP_AUTH_TOKEN \
|
||||
--api-key $VITE_GLITCHTIP_API_KEY \
|
||||
sourcemaps \
|
||||
--org coracle \
|
||||
--project flotilla \
|
||||
--release $hash \
|
||||
upload \
|
||||
--url-prefix /_app/immutable/ \
|
||||
build/_app/immutable
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "flotilla"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "flotilla_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.5.3", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.9.5", features = [] }
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Default desktop capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": ["core:default"]
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 8.8 KiB |