Compare commits
1 commit
main
...
krille/pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e66bf0a10c |
81 changed files with 4372 additions and 4204 deletions
3
.github/ISSUE_TEMPLATE/test_report.md
vendored
3
.github/ISSUE_TEMPLATE/test_report.md
vendored
|
|
@ -39,6 +39,3 @@ labels: test
|
|||
10. Drag&Drop to send a file into a chat still works:
|
||||
- [ ] Web
|
||||
- [ ] Linux
|
||||
11. Deeplinks are still working? https://matrix.to/#/@krille:janian.de
|
||||
- [ ] Android
|
||||
- [ ] iOS
|
||||
16
.github/workflows/integrate.yaml
vendored
16
.github/workflows/integrate.yaml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
- run: git diff --exit-code
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- name: Check for unused translations
|
||||
run: flutter pub run translations_cleaner list-unused-terms -a
|
||||
|
|
@ -28,10 +28,6 @@ jobs:
|
|||
- name: Check license compliance
|
||||
run: dart run license_checker check-licenses -c licenses.yaml --problematic
|
||||
- run: flutter analyze
|
||||
- name: Search unused dependencies
|
||||
run: |
|
||||
dart pub global activate dependency_validator
|
||||
dart pub global run dependency_validator
|
||||
- run: dart run dart_code_linter:metrics analyze lib --reporter=github
|
||||
- run: dart run dart_code_linter:metrics check-unused-code lib
|
||||
- run: dart run dart_code_linter:metrics check-unused-files lib
|
||||
|
|
@ -56,7 +52,7 @@ jobs:
|
|||
- uses: ./.github/actions/free_up_space
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- uses: moonrepo/setup-rust@v1
|
||||
with:
|
||||
|
|
@ -84,7 +80,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- uses: moonrepo/setup-rust@v1
|
||||
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
|
||||
|
|
@ -108,7 +104,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.1-dev -y
|
||||
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < .tool_versions.yaml)" >> $GITHUB_ENV
|
||||
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < pubspec.yaml)" >> $GITHUB_ENV
|
||||
- name: Install Flutter
|
||||
run: |
|
||||
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
|
||||
|
|
@ -124,7 +120,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- name: Use Xcode 16.4
|
||||
run: sudo xcode-select --switch /Applications/Xcode_16.4.app
|
||||
|
|
@ -198,7 +194,7 @@ jobs:
|
|||
echo "Generated AVD snapshot for caching."
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- uses: remarkablemark/setup-maestro-cli@v1
|
||||
- name: Load integration test env
|
||||
|
|
|
|||
4
.github/workflows/main_deploy.yaml
vendored
4
.github/workflows/main_deploy.yaml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
- uses: moonrepo/setup-rust@v1
|
||||
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
|
||||
- name: Prepare web
|
||||
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
|
|
|
|||
1
.github/workflows/matrix_notify.yaml
vendored
1
.github/workflows/matrix_notify.yaml
vendored
|
|
@ -8,7 +8,6 @@ on:
|
|||
|
||||
jobs:
|
||||
notify:
|
||||
if: ${{ (github.event_name == 'issues' && github.event.issue.user.login != 'krille-chan') || (github.event_name == 'pull_request_target' && github.event.pull_request.user.login != 'krille-chan') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send notification to Matrix room
|
||||
|
|
|
|||
30
.github/workflows/release.yaml
vendored
30
.github/workflows/release.yaml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- uses: moonrepo/setup-rust@v1
|
||||
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
|
||||
|
|
@ -46,25 +46,13 @@ jobs:
|
|||
asset_path: fluffychat-web.tar.gz
|
||||
asset_name: fluffychat-web.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
- name: Clone fluffychat website
|
||||
- name: Build Website
|
||||
run: |
|
||||
git clone https://github.com/krille-chan/fluffychat-website.git
|
||||
cp CHANGELOG.md fluffychat-website/
|
||||
cp PRIVACY.md fluffychat-website/
|
||||
- name: Build website
|
||||
working-directory: fluffychat-website
|
||||
run: |
|
||||
npm install tailwindcss @tailwindcss/cli
|
||||
npx tailwindcss -i ./src/styles.css -o ./src/assets/tailwind.css --minify
|
||||
npx @11ty/eleventy
|
||||
mv public ../
|
||||
- name: Copy FluffyChat web into it
|
||||
run: |
|
||||
mkdir public/web
|
||||
mkdir public
|
||||
mkdir public/nightly
|
||||
cp -r build/web/* public/web/
|
||||
cp -r build/web/* public/
|
||||
cp -r build/web/* public/nightly/
|
||||
echo "fluffychat.im" >> public/CNAME
|
||||
echo "app.fluffy.chat" >> public/CNAME
|
||||
- name: Deploy to GitHub Pages
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
|
|
@ -72,7 +60,7 @@ jobs:
|
|||
personal_token: ${{ secrets.PAGES_DEPLOY_TOKEN }}
|
||||
publish_dir: ./public
|
||||
publish_branch: gh-pages
|
||||
cname: fluffychat.im
|
||||
cname: app.fluffy.chat
|
||||
|
||||
build_apk:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -80,7 +68,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- name: Add Firebase Messaging
|
||||
run: |
|
||||
|
|
@ -115,7 +103,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.1-dev -y
|
||||
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < .tool_versions.yaml)" >> $GITHUB_ENV
|
||||
- run: echo "FLUTTER_VERSION=$(yq '.environment.flutter' < pubspec.yaml)" >> $GITHUB_ENV
|
||||
- name: Install Flutter
|
||||
run: |
|
||||
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
|
||||
|
|
@ -141,7 +129,7 @@ jobs:
|
|||
- uses: actions/checkout@v6
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version-file: .tool_versions.yaml
|
||||
flutter-version-file: pubspec.yaml
|
||||
cache: true
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
environment:
|
||||
flutter: 3.41.4
|
||||
159
CHANGELOG.md
159
CHANGELOG.md
|
|
@ -1,162 +1,3 @@
|
|||
## v2.5.0
|
||||
FluffyChat 2.5.0 introduces a new homeserver picker for onboarding, better image compression performance and several smaller new features, design adjustments and bug fixes.
|
||||
|
||||
- feat: Add mute notification action (Christian Kußowski)
|
||||
- feat: Add presetHomeserver config to enforce a homeserver for web (Christian Kußowski)
|
||||
- feat: Display particle animation on login page (Christian Kußowski)
|
||||
- feat: Display read receipts for every event (Christian Kußowski)
|
||||
- feat: Enable audio recording on web (Christian Kußowski)
|
||||
- feat: Implement low priority for rooms (Christian Kußowski)
|
||||
- feat: Implement matrix native oidc (Christian Kußowski)
|
||||
- feat: Implement new sign in flow (Christian Kußowski)
|
||||
- feat: OIDC Login on same page (Christian Kußowski)
|
||||
- feat: Reenable native imaging for all platforms (Christian Kußowski)
|
||||
- feat: Remember last successful logged in homeserver (Christian Kußowski)
|
||||
- Add lld to install custom dependency for Linux in README (Stephen)
|
||||
- build: Add llvm-18 to packages for snap (krille-chan)
|
||||
- build: Add maestro based integration tests (Christian Kußowski)
|
||||
- chore(translations): Added translation using Weblate (Albanian) (Besnik Bleta)
|
||||
- chore(translations): Added translation using Weblate (Kabyle) (Amadɣas)
|
||||
- chore(translations): Translated using Weblate (Basque) (xabirequejo)
|
||||
- chore(translations): Translated using Weblate (Catalan) (fadelkon)
|
||||
- chore(translations): Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山)
|
||||
- chore(translations): Translated using Weblate (Croatian) (Milo Ivir)
|
||||
- chore(translations): Translated using Weblate (Czech) (Matyáš Caras)
|
||||
- chore(translations): Translated using Weblate (Danish) (Øjvind Fritjof Arnfred)
|
||||
- chore(translations): Translated using Weblate (Dutch) (Jelv)
|
||||
- chore(translations): Translated using Weblate (English) (Christian)
|
||||
- chore(translations): Translated using Weblate (English) (SpikyBee)
|
||||
- chore(translations): Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||
- chore(translations): Translated using Weblate (Galician) (josé m.)
|
||||
- chore(translations): Translated using Weblate (Georgian) (Dimitri Tabatadze)
|
||||
- chore(translations): Translated using Weblate (Georgian) (Temuri Doghonadze)
|
||||
- chore(translations): Translated using Weblate (German) (Christian)
|
||||
- chore(translations): Translated using Weblate (German) (Ettore Atalan)
|
||||
- chore(translations): Translated using Weblate (German) (nautilusx)
|
||||
- chore(translations): Translated using Weblate (Hindi) (Vishal Singh)
|
||||
- chore(translations): Translated using Weblate (Indonesian) (Arif Budiman)
|
||||
- chore(translations): Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin)
|
||||
- chore(translations): Translated using Weblate (Japanese) (NPL)
|
||||
- chore(translations): Translated using Weblate (Japanese) (Sayaka Halton)
|
||||
- chore(translations): Translated using Weblate (Kabyle) (Amadɣas)
|
||||
- chore(translations): Translated using Weblate (Kabyle) (ButterflyOfFire)
|
||||
- chore(translations): Translated using Weblate (Kabyle) (Christian)
|
||||
- chore(translations): Translated using Weblate (Latvian) (Edgars Andersons)
|
||||
- chore(translations): Translated using Weblate (Norwegian Bokmål) (Frank Paul Silye)
|
||||
- chore(translations): Translated using Weblate (Norwegian Bokmål) (sunniva)
|
||||
- chore(translations): Translated using Weblate (Persian) (saok91)
|
||||
- chore(translations): Translated using Weblate (Polish) (gredzikk)
|
||||
- chore(translations): Translated using Weblate (Portuguese (Brazil)) (Logaritmica)
|
||||
- chore(translations): Translated using Weblate (Russian) (-)
|
||||
- chore(translations): Translated using Weblate (Russian) (Artem Pereverzev)
|
||||
- chore(translations): Translated using Weblate (Russian) (mikinol)
|
||||
- chore(translations): Translated using Weblate (Spanish) (Kimby)
|
||||
- chore(translations): Translated using Weblate (Spanish) (SpikyBee)
|
||||
- chore(translations): Translated using Weblate (Swedish) (Malva Jakobsson)
|
||||
- chore(translations): Translated using Weblate (Swedish) (spinningpaprika)
|
||||
- chore(translations): Translated using Weblate (Tamil) (தமிழ்நேரம்)
|
||||
- chore(translations): Translated using Weblate (Ukrainian) (Andriy Kushnir)
|
||||
- chore(translations): Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||
- chore(translations): Translated using Weblate (Uzbek) (BeMeritus)
|
||||
- chore: Add config search textfield (Christian Kußowski)
|
||||
- chore: Add matrix notify workflow (Christian Kußowski)
|
||||
- chore: Add recommended homeservers (Christian Kußowski)
|
||||
- chore: Add reset button for config viewer (Christian Kußowski)
|
||||
- chore: Add support button everywhere (Christian Kußowski)
|
||||
- chore: Added deeplinks to test protocol (Christian Kußowski)
|
||||
- chore: Adjust avatar size and chat list item design (krille-chan)
|
||||
- chore: Adjust chat input row design (Christian Kußowski)
|
||||
- chore: Adjust design (Christian Kußowski)
|
||||
- chore: Adjust design of navrail (Christian Kußowski)
|
||||
- chore: Adjust design of space avatars and more (Christian Kußowski)
|
||||
- chore: Adjust design of user viewer and popup buttons (Christian Kußowski)
|
||||
- chore: Adjust join space child UX (Christian Kußowski)
|
||||
- chore: Adjust paddings (krille-chan)
|
||||
- chore: Adjust power level UX (Christian Kußowski)
|
||||
- chore: Adjust search field design (Christian Kußowski)
|
||||
- chore: Adjust status header design (Christian Kußowski)
|
||||
- chore: Adjust styles and animations (Christian Kußowski)
|
||||
- chore: Adjust support button design (Christian Kußowski)
|
||||
- chore: Always show filter for messages (Christian Kußowski)
|
||||
- chore: Avoid unnecessary lambdas (Christian Kußowski)
|
||||
- chore: Better context menu for space children (Christian Kußowski)
|
||||
- chore: bump ios version (ShootingStarDragons)
|
||||
- chore: Check conventional commits in CI (krille-chan)
|
||||
- chore: Check if pubspec.lock is up to date in CI (Christian Kußowski)
|
||||
- chore: Check of unused localizations (Christian Kußowski)
|
||||
- chore: Clean up pages build (Christian Kußowski)
|
||||
- chore: Display spaces filter chip when spaces present even without children (Christian Kußowski)
|
||||
- chore: Execute dart code linter in CI (Christian Kußowski)
|
||||
- chore: Exempt assignees from stale (Christian Kußowski)
|
||||
- chore: Fix oidc login on web (Christian Kußowski)
|
||||
- chore: Give issues and PRs more time for stale (Christian Kußowski)
|
||||
- chore: Hide homepage button if not preset (Christian Kußowski)
|
||||
- chore: Hide status list by default (Christian Kußowski)
|
||||
- chore: Implement pick SSO provider from dialog and add tchncs.de (Christian Kußowski)
|
||||
- chore: Introduce tool versions file (Christian Kußowski)
|
||||
- chore: Login with localhost (Christian Kußowski)
|
||||
- chore: Make banner light red (Christian Kußowski)
|
||||
- chore: Make key fingerprints in chat encryption page selectable (Christian Kußowski)
|
||||
- chore: make sendTimelineEventTimeout configurable (Christian Kußowski)
|
||||
- chore: Make unread bubble full round (Christian Kußowski)
|
||||
- chore: Move file cache to subdirectory (Christian Kußowski)
|
||||
- chore: Move show image viewer one step up (Christian Kußowski)
|
||||
- chore: Move website back to fluffychat.im (Christian Kußowski)
|
||||
- chore: Only show confirm dialog once (Christian Kußowski)
|
||||
- chore: Put oidc behind a feature flag until fixed (Christian Kußowski)
|
||||
- chore: Remove converser from recommended homeservers as it doesn't have open registration (Christian Kußowski)
|
||||
- chore: Remove frei.chat from homeserver list (Christian Kußowski)
|
||||
- chore: Remove web notification custom sound (Christian Kußowski)
|
||||
- chore: Replace duplicate check for stale bot (Christian Kußowski)
|
||||
- chore: Retry sign in tap in tests (Christian Kußowski)
|
||||
- chore: Run matrix notification in pull request target (Christian Kußowski)
|
||||
- chore: Sanitize hash param for oidc (Christian Kußowski)
|
||||
- chore: Set erase flag true on account deactivation (krille-chan)
|
||||
- chore: Set operations per run to 1000 (krille-chan)
|
||||
- chore: Skip matrix notify for events from myself (Christian Kußowski)
|
||||
- chore: Update locale config (Christian Kußowski)
|
||||
- chore: Update matrix ID localization (Christian Kußowski)
|
||||
- chore: Update recommended homeservers (Christian Kußowski)
|
||||
- chore: Update redirect android scheme (Christian Kußowski)
|
||||
- chore: Use fixed version of fcm shared isolate (Christian Kußowski)
|
||||
- fix: Add app id to TileLayer user agent (Vespe-r)
|
||||
- fix: Add missing @@locale (Krille-chan)
|
||||
- fix: Audioplayer on web buggy (Christian Kußowski)
|
||||
- fix: build failed on archlinux (ShootingStarDragons)
|
||||
- fix: Do not cancel notification on reply (Christian Kußowski)
|
||||
- fix: Do not display formatted body if body is just filename (Christian Kußowski)
|
||||
- fix: Do not route to backup on soft logout (Christian Kußowski)
|
||||
- fix: Edit space child button opens space details page and not space child details page (Christian Kußowski)
|
||||
- fix: Fix formatting of messages with newlines (Philip Fritzsche)
|
||||
- fix: get correct aspect ratio from VideoPlayerController (Matias)
|
||||
- fix: Join room by alias even if not found (Christian Kußowski)
|
||||
- fix: Open deep links (Christian Kußowski)
|
||||
- fix: Receipt row not auto updating (Christian Kußowski)
|
||||
- fix: Receipts disappear after reaction (Christian Kußowski)
|
||||
- fix: Reply voice message displays a broken html body (Christian Kußowski)
|
||||
- fix: Send reply to voice messages (Christian Kußowski)
|
||||
- fix: Set mimetype for video player on web (Christian Kußowski)
|
||||
- fix: Use correct own person for android notification replies (Christian Kußowski)
|
||||
- fix: Wrong placeholder in kab (Christian Kußowski)
|
||||
- refactor: Add Flutter lints (Christian Kußowski)
|
||||
- refactor: Add more linter rules (Christian Kußowski)
|
||||
- refactor: Add more stricter lints (Christian Kußowski)
|
||||
- refactor: Avoid redundant async (Christian Kußowski)
|
||||
- refactor: Avoid unnecessary bool comparison (Christian Kußowski)
|
||||
- refactor: Better UX for create space children (Christian Kußowski)
|
||||
- refactor: Disable custom image resizer for macOS and windows (Christian Kußowski)
|
||||
- refactor: Do show message bubble even for big emotes (Christian Kußowski)
|
||||
- refactor: Enable avoid-returning-widgets lint (Christian Kußowski)
|
||||
- refactor: Enable more strict lints (Christian Kußowski)
|
||||
- refactor: Enable rule avoid dynamic (Christian Kußowski)
|
||||
- refactor: Make file events more fail safe for failed to send (Christian Kußowski)
|
||||
- refactor: Remove animation dependency (Christian Kußowski)
|
||||
- refactor: Remove unused localizations (Christian Kußowski)
|
||||
- refactor: Remove unused translations (Christian Kußowski)
|
||||
- refactor: Use getCryptoIdentityState to check backup state (krille-chan)
|
||||
- refactor: Use more robust and performant way to detect single emoji messages (Christian Kußowski)
|
||||
- refactor: Use native uri data from bytes instead of html (Christian Kußowski)
|
||||
|
||||
## v2.4.0
|
||||
FluffyChat 2.4.0 adds a new improved GUI for managing stickers with tutorials how to
|
||||
easily add your own sticker packs.
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="im.fluffychat" android:path="/login"/>
|
||||
<data android:scheme="chat.fluffy" android:host="login"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
FluffyChat 2.5.0 introduces a new homeserver picker for onboarding,
|
||||
better image compression performance and several smaller new features,
|
||||
design adjustments and bug fixes.
|
||||
FluffyChat 2.4.0 adds a new improved GUI for managing stickers with tutorials how to
|
||||
easily add your own sticker packs.
|
||||
It also improves the search and image gallery in chats, especially encrypted chats.
|
||||
Besides that this update comes with a lot of fixes and improvements under the hood.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
ignore:
|
||||
- handy_window
|
||||
- sqlcipher_flutter_libs
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
<array>
|
||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<string>im.fluffychat</string>
|
||||
<string>chat.fluffy</string>
|
||||
<string>matrix</string>
|
||||
</array>
|
||||
</dict>
|
||||
|
|
|
|||
|
|
@ -22,21 +22,22 @@ abstract class AppConfig {
|
|||
static const double columnWidth = 360.0;
|
||||
|
||||
static const String enablePushTutorial =
|
||||
'https://fluffychat.im/faq/#push_without_google_services';
|
||||
'https://fluffy.chat/faq/#push_without_google_services';
|
||||
static const String encryptionTutorial =
|
||||
'https://fluffychat.im/faq/#how_to_use_end_to_end_encryption';
|
||||
'https://fluffy.chat/faq/#how_to_use_end_to_end_encryption';
|
||||
static const String startChatTutorial =
|
||||
'https://fluffychat.im/faq/#how_do_i_find_other_users';
|
||||
'https://fluffy.chat/faq/#how_do_i_find_other_users';
|
||||
static const String howDoIGetStickersTutorial =
|
||||
'https://fluffychat.im/faq/#how_do_i_get_stickers';
|
||||
'https://fluffy.chat/faq/#how_do_i_get_stickers';
|
||||
static const String appId = 'im.fluffychat.FluffyChat';
|
||||
static const String appOpenUrlScheme = 'im.fluffychat';
|
||||
static const String appOpenUrlScheme = 'chat.fluffy';
|
||||
|
||||
static const String sourceCodeUrl =
|
||||
'https://github.com/krille-chan/fluffychat';
|
||||
static const String supportUrl =
|
||||
'https://github.com/krille-chan/fluffychat/issues';
|
||||
static const String changelogUrl = 'https://fluffy.chat/en/changelog/';
|
||||
static const String donationUrl = 'https://ko-fi.com/krille';
|
||||
|
||||
static const Set<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:fluffychat/pages/settings_profile/settings_profile_presenter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -170,14 +171,8 @@ abstract class AppRoutes {
|
|||
),
|
||||
GoRoute(
|
||||
path: 'newprivatechat',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
NewPrivateChat(
|
||||
key: ValueKey('new_chat_${state.uri.query}'),
|
||||
deeplink: state.uri.queryParameters['deeplink'],
|
||||
),
|
||||
),
|
||||
pageBuilder: (context, state) =>
|
||||
defaultPageBuilder(context, state, const NewPrivateChat()),
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
GoRoute(
|
||||
|
|
@ -224,6 +219,15 @@ abstract class AppRoutes {
|
|||
: const Settings(),
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'profile_settings',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
const SettingsProfilePresenter(),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'notifications',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
|
|
|
|||
|
|
@ -56,19 +56,16 @@ enum AppSettings<T> {
|
|||
enableMatrixNativeOIDC<bool>('chat.fluffy.enable_matrix_native_oidc', false),
|
||||
presetHomeserver<String>('chat.fluffy.preset_homeserver', ''),
|
||||
welcomeText<String>('chat.fluffy.welcome_text', ''),
|
||||
website<String>('chat.fluffy.website_url', 'https://fluffychat.im'),
|
||||
website<String>('chat.fluffy.website_url', 'https://fluffy.chat'),
|
||||
logoUrl<String>(
|
||||
'chat.fluffy.logo_url',
|
||||
'https://fluffychat.im/assets/favicon.png',
|
||||
'https://fluffy.chat/assets/favicon.png',
|
||||
),
|
||||
privacyPolicy<String>(
|
||||
'chat.fluffy.privacy_policy_url',
|
||||
'https://fluffychat.im/en/privacy',
|
||||
'https://fluffy.chat/en/privacy',
|
||||
),
|
||||
tos<String>('chat.fluffy.tos_url', 'https://fluffychat.im/en/tos'),
|
||||
sendTimelineEventTimeout<int>('chat.fluffy.send_timeline_event_timeout', 15),
|
||||
lastSeenSupportBanner<int>('chat.fluffy.last_seen_support_banner', 0),
|
||||
supportBannerOptOut<bool>('chat.fluffy.support_banner_opt_out', false);
|
||||
tos<String>('chat.fluffy.tos_url', 'https://fluffy.chat/en/tos');
|
||||
|
||||
final String key;
|
||||
final T defaultValue;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ abstract class FluffyThemes {
|
|||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
),
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2992,6 +2992,8 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Даць грошы",
|
||||
"@donate": {},
|
||||
"startedAPoll": "{username} пачаў апытанне.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2691,6 +2691,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Dona",
|
||||
"startedAPoll": "{username} ha creat una enquesta.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2560,6 +2560,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Přispět",
|
||||
"startedAPoll": "{username} spustil/a hlasování.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2697,6 +2697,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Spenden",
|
||||
"resume": "Fortsetzen",
|
||||
"startedAPoll": "{username} hat eine Umfrage gestartet.",
|
||||
"@startedAPoll": {
|
||||
|
|
@ -2780,31 +2781,11 @@
|
|||
"createNewAccount": "Neues Konto erstellen",
|
||||
"signUpGreeting": "FluffyChat ist dezentral! Wähle einen Server, auf dem du dein Konto erstellen möchtest, und los geht's!",
|
||||
"signInGreeting": "Du hast bereits ein Konto bei Matrix? Willkommen zurück! Wähle deinen Homeserver aus und melde dich an.",
|
||||
"appIntro": "Mit FluffyChat kannst du mit deinen Freunden chatten. Es ist ein sicherer, dezentralisierter [Matrix]-Messenger! Erfahre mehr auf https://matrix.org wenn du möchtest, oder melde dich einfach an.",
|
||||
"appIntro": "Mit FluffyChat kannst du mit deinen Freunden chatten. Es ist ein sicherer, dezentralisierter [Matrix]-Messenger! Erfahre mehr auf https://matrix.org, wenn du möchtest, oder melde dich einfach an.",
|
||||
"theProcessWasCanceled": "Der Vorgang wurde abgebrochen.",
|
||||
"federationBaseUrl": "Basis-URL der Föderation",
|
||||
"clientWellKnownInformation": "Bekannte Informationen zum Client:",
|
||||
"join": "Beitreten",
|
||||
"searchOrEnterHomeserverAddress": "Homeserver-Adresse suchen oder eingeben",
|
||||
"matrixId": "Matrix ID",
|
||||
"reset": "Zurücksetzen",
|
||||
"setPowerLevel": "Power-Level einstellen",
|
||||
"makeModerator": "Zum Moderator machen",
|
||||
"makeAdmin": "Zum Admin machen",
|
||||
"removeModeratorRights": "Moderatorenrechte entziehen",
|
||||
"removeAdminRights": "Adminrechte entziehen",
|
||||
"powerLevel": "Power-Level",
|
||||
"setPowerLevelDescription": "Die Power-Level legen fest, was ein Mitglied in diesem Raum tun darf und liegen üblicherweise zwischen 0 und 100.",
|
||||
"owner": "Besitzer",
|
||||
"mute": "Stumm",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Neuen Chat erstellen",
|
||||
"supportFluffyChat": "FluffyChat unterstützen",
|
||||
"support": "Unterstützen",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat braucht DEINE Hilfe!\n❤️❤️❤️\nFluffyChat wird immer kostenlos bleiben, aber Entwicklung und Hosting kosten Geld.\nDie Zukunft des Projekts hängt von deiner Unterstützung ab.",
|
||||
"skipSupportingFluffyChat": "FluffyChat unterstützen überspringen",
|
||||
"iDoNotWantToSupport": "Ich möchte nicht unterstützen",
|
||||
"iAlreadySupportFluffyChat": "I unterstütze FluffyChat bereits"
|
||||
}
|
||||
"matrixId": "Matrix ID"
|
||||
}
|
||||
|
|
@ -2681,6 +2681,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Donate",
|
||||
"startedAPoll": "{username} started a poll.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
@ -2782,12 +2783,8 @@
|
|||
},
|
||||
"createNewChat": "Create new chat",
|
||||
"reset": "Reset",
|
||||
"supportFluffyChat": "Support FluffyChat",
|
||||
"support": "Support",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat needs YOUR help!\n❤️❤️❤️\nFluffyChat will always be free, but development and hosting still cost money.\nThe future of the project depends on support from people like you.",
|
||||
"skipSupportingFluffyChat": "Skip supporting FluffyChat",
|
||||
"iDoNotWantToSupport": "I do not want to support",
|
||||
"iAlreadySupportFluffyChat": "I already support FluffyChat",
|
||||
"setLowPriority": "Set low priority",
|
||||
"unsetLowPriority": "Unset low priority"
|
||||
}
|
||||
"profileSettings": "Profile settings",
|
||||
"timezone": "Timezone",
|
||||
"pronouns": "Pronouns",
|
||||
"save": "Save"
|
||||
}
|
||||
|
|
@ -2713,6 +2713,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Donar",
|
||||
"pollQuestion": "Pregunta de encuesta",
|
||||
"answerOption": "Respuesta",
|
||||
"addAnswerOption": "Añadir respuesta",
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"askSSSSSign": "Selleks, et teist osapoolt identifitseerivat allkirja anda, palun sisesta oma turvahoidla salafraas või taastevõti.",
|
||||
"askSSSSSign": "Selleks, et teist osapoolt identifitseerivat allkirja anda, palun sisesta oma turvahoidla paroolifraas või taastevõti.",
|
||||
"@askSSSSSign": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -339,7 +339,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"changeTheNameOfTheGroup": "Muuda jututoa nime",
|
||||
"changeTheNameOfTheGroup": "Muuda vestlusrühma nime",
|
||||
"@changeTheNameOfTheGroup": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -489,7 +489,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"contactHasBeenInvitedToTheGroup": "Sinu kontakt on kutsutud liituma jututoaga",
|
||||
"contactHasBeenInvitedToTheGroup": "Sinu kontakt on kutsutud liituma vestlusrühma",
|
||||
"@contactHasBeenInvitedToTheGroup": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -776,22 +776,22 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"group": "Jututuba",
|
||||
"group": "Vestlusrühm",
|
||||
"@group": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"groupIsPublic": "Jututuba on avalik",
|
||||
"groupIsPublic": "Vestlusrühm on avalik",
|
||||
"@groupIsPublic": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"groups": "Jututoad",
|
||||
"groups": "Vestlusrühmad",
|
||||
"@groups": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"groupWith": "Jututuba {displayname} kasutajanimega",
|
||||
"groupWith": "Vestlusrühm {displayname} kasutajanimega",
|
||||
"@groupWith": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
|
|
@ -862,7 +862,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"incorrectPassphraseOrKey": "Vigane salafraas või taastevõti",
|
||||
"incorrectPassphraseOrKey": "Vigane paroolifraas või taastevõti",
|
||||
"@incorrectPassphraseOrKey": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -877,7 +877,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"inviteContactToGroup": "Kutsu sõpru ja tuttavaid {groupName} jututoa liikmeks",
|
||||
"inviteContactToGroup": "Kutsu sõpru ja tuttavaid {groupName} liikmeks",
|
||||
"@inviteContactToGroup": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
|
|
@ -1221,7 +1221,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"passphraseOrKey": "salafraas või taastevõti",
|
||||
"passphraseOrKey": "paroolifraas või taastevõti",
|
||||
"@passphraseOrKey": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -1839,7 +1839,7 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"whoIsAllowedToJoinThisGroup": "Kes võivad selle jututoaga liituda",
|
||||
"whoIsAllowedToJoinThisGroup": "Kes võivad selle vestlusrühmaga liituda",
|
||||
"@whoIsAllowedToJoinThisGroup": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
|
|
@ -1927,7 +1927,7 @@
|
|||
"type": "String",
|
||||
"description": "Usage hint for the command /dm"
|
||||
},
|
||||
"commandHint_create": "Loo tühi jututuba\nKrüptimise keelamiseks kasuta --no-encryption võtit",
|
||||
"commandHint_create": "Loo tühi vestlusrühm\nKrüptimise keelamiseks kasuta --no-encryption võtit",
|
||||
"@commandHint_create": {
|
||||
"type": "String",
|
||||
"description": "Usage hint for the command /create"
|
||||
|
|
@ -2049,7 +2049,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"commandHint_markasgroup": "Märgi jututoaks",
|
||||
"commandHint_markasgroup": "Märgi vestlusrühmaks",
|
||||
"commandHint_markasdm": "Märgi otsevestusluseks antud Matrixi ID jaoks",
|
||||
"whyIsThisMessageEncrypted": "Miks see sõnum pole loetav?",
|
||||
"noKeyForThisMessage": "See võib juhtuda, kui sõnum oli saadetud enne, kui siin seadmes oma kontoga sisse logisid.\n\nSamuti võib juhtuda siis, kui saatja on lugemises selles seadmes blokeerinud või on tekkinud tõrkeid veebiühenduses.\n\nAga mõnes teises seadmes saad seda sõnumit lugeda? Siis sa võid sõnumi sealt üle tõsta. Ava Seadistused -> Seadmed ning kontrolli, et kõik sinu seadmed on omavahel verifitseeritud. Kui avad selle vestluse või jututoa ning mõlemad sessioonid on avatud, siis vajalikud krüptovõtmed saadetakse automaatset.\n\nKas sa soovid vältida krüptovõtmete kadumist väljalogimisel ja seadmete vahetusel? Siis palun kontrolli, et seadistuses on krüptovõtmete varundus sisse lülitatud.",
|
||||
|
|
@ -2130,7 +2130,7 @@
|
|||
"importNow": "Impordi kohe",
|
||||
"importEmojis": "Impordi emojid",
|
||||
"sendTypingNotifications": "Saada kirjutamise teavitusi",
|
||||
"createGroup": "Loo jututuba",
|
||||
"createGroup": "Loo vestlusrühm",
|
||||
"tryAgain": "Proovi uuesti",
|
||||
"chatPermissions": "Vestluse õigused",
|
||||
"chatDescription": "Vestluse kirjeldus",
|
||||
|
|
@ -2166,7 +2166,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"inviteGroupChat": "📨 Kutse jututuppa",
|
||||
"inviteGroupChat": "📨 Kutse vestlusrühma",
|
||||
"emoteKeyboardNoRecents": "Hiljuti kasutatud emotikonid kuvame siin...",
|
||||
"@emoteKeyboardNoRecents": {
|
||||
"type": "String",
|
||||
|
|
@ -2201,9 +2201,9 @@
|
|||
"pleaseEnterANumber": "Palun sisesta 0'st suurem number",
|
||||
"kickUserDescription": "See kasutaja on nüüd jutuoast välja müksatud, kuid talle pole seatud suhtluskeeldu. Avaliku jututoa puhul saab ta alati uuesti liituda.",
|
||||
"blockListDescription": "Sul on võimalik blokeerida neid kasutajaid, kes sind segavad. Oma isiklikku blokerimisloendisse lisatud kasutajad ei saa sulle saata sõnumeid ega kutseid.",
|
||||
"createGroupAndInviteUsers": "Lisa jututuba ja kutsu sinna kasutajaid",
|
||||
"createGroupAndInviteUsers": "Lisavestlusrühm ja kutsu sinna kasutajaid",
|
||||
"blockedUsers": "Blokeeritud kasutajad",
|
||||
"groupCanBeFoundViaSearch": "Jututuba on leitav otsinguga",
|
||||
"groupCanBeFoundViaSearch": "Vestlusrühm on leitav otsinguga",
|
||||
"noUsersFoundWithQuery": "Päringuga „{query}“ ei leidunud kahkus ühtegi kasutajat. Palun kontrolli, et päringus poleks vigu.",
|
||||
"@noUsersFoundWithQuery": {
|
||||
"type": "String",
|
||||
|
|
@ -2218,7 +2218,7 @@
|
|||
"commandHint_sendraw": "Saada json oma algupärasel kujul",
|
||||
"wrongRecoveryKey": "Vabandust..., see ei tundu olema korrektne taastevõti.",
|
||||
"blockUsername": "Eira kasutajanime",
|
||||
"groupName": "Jututoa nimi",
|
||||
"groupName": "Vestlusrühma nimi",
|
||||
"databaseMigrationTitle": "Andmebaas on optimeeritud",
|
||||
"searchChatsRooms": "Otsi #vestlusi, @kasutajaid...",
|
||||
"databaseMigrationBody": "Palun oota üks hetk. Natuke võib kuluda aega.",
|
||||
|
|
@ -2442,7 +2442,7 @@
|
|||
"changeGeneralChatSettings": "Muuda vestluse üldiseid seadistusi",
|
||||
"inviteOtherUsers": "Kutsu teisi osalejaid sellesse vestlusesse",
|
||||
"changeTheChatPermissions": "Muuda vestluse õigusi",
|
||||
"changeTheDescriptionOfTheGroup": "Muuda vestluse/jututoa kirjeldust",
|
||||
"changeTheDescriptionOfTheGroup": "Muuda vestluse kirjeldust",
|
||||
"chatPermissionsDescription": "Määra erinevatele kasutajatele selles vestluses vajalikud õigused. Tüüpiliselt on need 0, 50 ja 100 (vastavalt kasutajad, moderaatorid ja peakasutajad), kuid igasugused vahepealsed variatsioonid on ka võimalikud.",
|
||||
"invitedBy": "📩 Kutsujaks {user}",
|
||||
"@invitedBy": {
|
||||
|
|
@ -2690,6 +2690,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Toeta meid rahaliselt",
|
||||
"startedAPoll": "{username} koostas küsitluse.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
@ -2786,19 +2787,5 @@
|
|||
"removeAdminRights": "Eemalda peakasutaja õigused",
|
||||
"powerLevel": "Õiguste tase",
|
||||
"setPowerLevelDescription": "Õiguste tase on üks võimalusi kirjeldamaks seda, mida kasutaja saab jututoas teha ning see tavaliselt väljendub numbriga vahemikust 0 kuni 100.",
|
||||
"owner": "Omanik",
|
||||
"mute": "Summuta",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Loo uus vestlus",
|
||||
"reset": "Lähtesta",
|
||||
"supportFluffyChat": "Toeta FluffyChati",
|
||||
"support": "Toeta meid",
|
||||
"iAlreadySupportFluffyChat": "Ma juba toetan FluffyChati arendust",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat vajab SINU abi!\n❤️❤️❤️\nFluffyChat jääb alati vabaks ja vabalt saadavaks, aga arendus ja serveriteenused vajavad ikkagi rahastamist.\nMeie projekti tulevik sõltub sinust ja teistest kasutajatest, nagu sina.",
|
||||
"skipSupportingFluffyChat": "Jäta FluffyChati toetamine vahele",
|
||||
"iDoNotWantToSupport": "Ma ei soovi toetada",
|
||||
"setLowPriority": "Märgi vähetähtsaks",
|
||||
"unsetLowPriority": "Eemalda märkimine vähetähtsaks"
|
||||
}
|
||||
"owner": "Omanik"
|
||||
}
|
||||
|
|
@ -2672,6 +2672,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Egin dohaintza",
|
||||
"spaceMemberOf": "{spaces} guneko kidea",
|
||||
"@spaceMemberOf": {
|
||||
"type": "String",
|
||||
|
|
@ -2778,19 +2779,5 @@
|
|||
"theProcessWasCanceled": "Eragiketa bertan behera utzi da.",
|
||||
"join": "Batu",
|
||||
"searchOrEnterHomeserverAddress": "Bilatu edo sartu zerbitzariaren helbidea",
|
||||
"matrixId": "Matrix IDa",
|
||||
"setPowerLevel": "Ezarri botere-maila",
|
||||
"makeModerator": "Izendatu moderatzaile",
|
||||
"makeAdmin": "Izendatu administrari",
|
||||
"removeModeratorRights": "Kendu moderatzaile eskubideak",
|
||||
"removeAdminRights": "Kendu administratzaile eskubideak",
|
||||
"powerLevel": "Botere-maila",
|
||||
"setPowerLevelDescription": "Botere-mailek zehazten dute kide batek zer egin dezakeen gela honetan, eta tartea 0tik 100era artekoa izan ohi da.",
|
||||
"owner": "Jabea",
|
||||
"mute": "Mututu",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Sortu txat berria",
|
||||
"reset": "Berrezarri"
|
||||
"matrixId": "Matrix IDa"
|
||||
}
|
||||
|
|
@ -3003,6 +3003,8 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Lahjoita",
|
||||
"@donate": {},
|
||||
"startedAPoll": "{username} aloitti kyselyn.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2696,6 +2696,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Tabhair Síntiús",
|
||||
"startedAPoll": "Chuir {username} tús le pobalbhreith.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
@ -2792,17 +2793,5 @@
|
|||
"removeAdminRights": "Bain cearta riarthóra",
|
||||
"powerLevel": "Leibhéal cumhachta",
|
||||
"setPowerLevelDescription": "Sainmhíníonn leibhéil chumhachta cad a cheadaítear do bhall a dhéanamh sa seomra seo agus is gnách go mbíonn siad idir 0 agus 100.",
|
||||
"owner": "Úinéir",
|
||||
"mute": "Balbhaigh",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Cruthaigh comhrá nua",
|
||||
"reset": "Athshocraigh",
|
||||
"supportFluffyChat": "Tacaigh le FluffyChat",
|
||||
"support": "Tacaíocht",
|
||||
"fluffyChatSupportBannerMessage": "Tá DO chabhair ag teastáil ó FluffyChat!\n❤️❤️❤️\nBeidh FluffyChat saor in aisce i gcónaí, ach cosnaíonn forbairt agus óstáil airgead fós.\nBraitheann todhchaí an tionscadail ar thacaíocht ó dhaoine cosúil leatsa.",
|
||||
"skipSupportingFluffyChat": "Seachain tacú le FluffyChat",
|
||||
"iDoNotWantToSupport": "Nílim ag iarraidh tacú leis",
|
||||
"iAlreadySupportFluffyChat": "Tacaím le FluffyChat cheana féin"
|
||||
}
|
||||
"owner": "Úinéir"
|
||||
}
|
||||
|
|
@ -2672,6 +2672,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Doar",
|
||||
"spaceMemberOf": "Participa no espazo {spaces}",
|
||||
"@spaceMemberOf": {
|
||||
"type": "String",
|
||||
|
|
@ -2786,19 +2787,5 @@
|
|||
"removeAdminRights": "Retirar permiso de administración",
|
||||
"powerLevel": "Nivel responsabilidade",
|
||||
"setPowerLevelDescription": "Os niveis de responsabilidade definen o que pode facer unha usuaria na sala, normalmente varía de 0 a 100.",
|
||||
"owner": "Propietaria",
|
||||
"mute": "Acalar",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Crear nova conversa",
|
||||
"reset": "Restablecer",
|
||||
"supportFluffyChat": "Apoia a FluffyChat",
|
||||
"support": "Axuda",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat precisa a TÚA axuda!\n❤️❤️❤️\nFluffyChat vai ser sempre gratuíta, pero o desenvolvemento e a hospedaxe costan cartos.\nO futuro do proxecto depende da axuda de persoas coma ti.",
|
||||
"skipSupportingFluffyChat": "Omitir apoiar a FluffyChat",
|
||||
"iDoNotWantToSupport": "Non quero axudar",
|
||||
"iAlreadySupportFluffyChat": "Xa apoiei a FluffyChat",
|
||||
"setLowPriority": "Establecer prioridade baixa",
|
||||
"unsetLowPriority": "Non establecer prioridade baixa"
|
||||
}
|
||||
"owner": "Propietaria"
|
||||
}
|
||||
|
|
@ -2692,6 +2692,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Doniraj",
|
||||
"startedAPoll": "{username} je pokrenuo/la anketu.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2691,6 +2691,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Donasi",
|
||||
"startedAPoll": "{username} memulai polling.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -1392,6 +1392,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Mudd tawsa",
|
||||
"startedAPoll": "{username}yessenker tafrent.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2673,6 +2673,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Ziedot",
|
||||
"startedAPoll": "{username} uzsāka aptauju.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2540,6 +2540,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Doner",
|
||||
"banUserDescription": "Brukeren vil bli utestengt fra chatten og vil ikke kunne delta i chatten igjen før utestengelsen er opphevet.",
|
||||
"unbanUserDescription": "Brukeren vil kunne gå inn i chatten igjen hvis vedkommende prøver.",
|
||||
"kickUserDescription": "Brukeren blir kastet ut av chatten, men ikke utestengt. I offentlige chatter kan brukeren bli med på nytt når som helst.",
|
||||
|
|
@ -2793,19 +2794,5 @@
|
|||
"removeAdminRights": "Fjern admin-rettigheter",
|
||||
"powerLevel": "Styrkenivå",
|
||||
"setPowerLevelDescription": "Styrkenivåer definerer hva et medlem har lov til å gjøre i dette rommet, og varierer vanligvis mellom 0 og 100.",
|
||||
"owner": "Eier",
|
||||
"mute": "Demp",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Opprett ny chat",
|
||||
"reset": "Nullstill",
|
||||
"supportFluffyChat": "Støtt FluffyChat",
|
||||
"support": "Støtte",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat trenger DIN hjelp!\n❤️❤️❤️\nFluffyChat vil alltid være gratis, men utvikling og drift koster fortsatt penger. \nProsjektets fremtid avhenger av støtte fra folk som deg.",
|
||||
"skipSupportingFluffyChat": "Hopp over støtte til FluffyChat",
|
||||
"iDoNotWantToSupport": "Jeg ønsker ikke å støtte",
|
||||
"iAlreadySupportFluffyChat": "Jeg støtter allerede FluffyChat",
|
||||
"setLowPriority": "Sett lav prioritet",
|
||||
"unsetLowPriority": "Fjern lav prioritet"
|
||||
}
|
||||
"owner": "Eier"
|
||||
}
|
||||
|
|
@ -2383,7 +2383,7 @@
|
|||
"newPassword": "Nieuw wachtwoord",
|
||||
"pleaseChooseAStrongPassword": "Kies a.j.b. een sterk wachtwoord",
|
||||
"select": "Selecteer",
|
||||
"leaveEmptyToClearStatus": "Laat leeg om jouw status te herstellen.",
|
||||
"leaveEmptyToClearStatus": "Laat leeg om je status te resetten.",
|
||||
"addChatOrSubSpace": "Voeg chat of subspace toe",
|
||||
"pleaseEnterYourCurrentPassword": "Vul je huidige wachtwoord in",
|
||||
"passwordsDoNotMatch": "Wachtwoorden komen niet overeen",
|
||||
|
|
@ -2661,6 +2661,7 @@
|
|||
"longPressToRecordVoiceMessage": "Lang drukken om een spraakbericht op te nemen.",
|
||||
"pause": "Pauzeer",
|
||||
"resume": "Hervat",
|
||||
"donate": "Doneer",
|
||||
"removeFromSpaceDescription": "De chat zal worden verwijderd uit de space, maar blijft in je chats.",
|
||||
"countChats": "{chats} chats",
|
||||
"@countChats": {
|
||||
|
|
@ -2785,19 +2786,5 @@
|
|||
"removeAdminRights": "Verwijder beheerder-rechten",
|
||||
"powerLevel": "Rechtenniveau",
|
||||
"setPowerLevelDescription": "Rechtenniveau's definiëren wat een persoon mag doen in deze chat en variëren meestal tussen 0 en 100.",
|
||||
"owner": "Eigenaar",
|
||||
"mute": "Demp",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Creëer nieuw chat",
|
||||
"reset": "Herstellen",
|
||||
"fluffyChatSupportBannerMessage": "Fluffy Chat heeft JOUW hulp nodig. _\n❤️❤️❤️\nFluffyChat zal altijd gratis zijn, maar ontwikkeling en hosting kost geld.\nDe toekomst van het project hangt af van steun van mensen zoals jij.",
|
||||
"skipSupportingFluffyChat": "FluffyChat steunen overslaan",
|
||||
"iDoNotWantToSupport": "Ik wil niet ondersteunen",
|
||||
"iAlreadySupportFluffyChat": "Ik steun FluffyChat al",
|
||||
"supportFluffyChat": "FluffyChat steunen",
|
||||
"support": "Steunen",
|
||||
"setLowPriority": "Lage prioriteit instellen",
|
||||
"unsetLowPriority": "Lage prioriteit uitschakelen"
|
||||
}
|
||||
"owner": "Eigenaar"
|
||||
}
|
||||
|
|
@ -2699,4 +2699,4 @@
|
|||
"moreEvents": "Więcej zdarzeń",
|
||||
"declineInvitation": "Odrzuć zaproszenie",
|
||||
"@declineInvitation": {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2689,6 +2689,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Doar",
|
||||
"startedAPoll": "{username} iniciou uma enquete.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2640,6 +2640,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Пожертвовать",
|
||||
"startedAPoll": "{username} начал опрос.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2606,6 +2606,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Donera",
|
||||
"answerOption": "Svarsalternativ",
|
||||
"addAnswerOption": "Lägg till svarsalternativ",
|
||||
"allowMultipleAnswers": "Tillåt flera svar",
|
||||
|
|
|
|||
5741
lib/l10n/intl_ta.arb
5741
lib/l10n/intl_ta.arb
File diff suppressed because it is too large
Load diff
|
|
@ -2690,6 +2690,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Задонатити",
|
||||
"startedAPoll": "Нове опитування від {username}.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2598,6 +2598,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "Xayriya qilmoq",
|
||||
"startedAPoll": "{username} so‘rovnoma boshladi.",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
|
|||
|
|
@ -2690,6 +2690,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"donate": "捐赠",
|
||||
"startedAPoll": "{username} 启动了投票。",
|
||||
"@startedAPoll": {
|
||||
"type": "String",
|
||||
|
|
@ -2786,19 +2787,5 @@
|
|||
"removeAdminRights": "删除管理员权限",
|
||||
"powerLevel": "权限级别",
|
||||
"setPowerLevelDescription": "权限级别定义群成员在这个聊天室中可以做什么,取值范围 0 到 100。",
|
||||
"owner": "所有者",
|
||||
"mute": "静音",
|
||||
"@mute": {
|
||||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "新建聊天",
|
||||
"reset": "重置",
|
||||
"supportFluffyChat": "支持 FluffyChat",
|
||||
"support": "支持",
|
||||
"fluffyChatSupportBannerMessage": "FluffyChat 需要您的帮助!\n❤️❤️❤️\nFluffyChat 将始终免费,但开发和托管仍然要花钱。\n项目的未来仰赖像您这样的人的支持。",
|
||||
"skipSupportingFluffyChat": "跳过支持 FluffyChar",
|
||||
"iDoNotWantToSupport": "我不想支持",
|
||||
"iAlreadySupportFluffyChat": "我已支持 FluffyChat",
|
||||
"setLowPriority": "设置低优先级",
|
||||
"unsetLowPriority": "取消设置低优先级"
|
||||
}
|
||||
"owner": "所有者"
|
||||
}
|
||||
|
|
@ -462,18 +462,21 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
scrollUpBannerEventId = eventId;
|
||||
});
|
||||
|
||||
bool firstUpdateReceived = false;
|
||||
|
||||
void updateView() {
|
||||
if (!mounted) return;
|
||||
setReadMarker();
|
||||
setState(() {
|
||||
firstUpdateReceived = true;
|
||||
});
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future<void>? loadTimelineFuture;
|
||||
|
||||
int? animateInEventIndex;
|
||||
|
||||
void onInsert(int i) {
|
||||
// setState will be called by updateView() anyway
|
||||
if (timeline?.allowNewEvent == true) animateInEventIndex = i;
|
||||
}
|
||||
|
||||
Future<void> _getTimeline({String? eventContextId}) async {
|
||||
await Matrix.of(context).client.roomsLoading;
|
||||
await Matrix.of(context).client.accountDataLoading;
|
||||
|
|
@ -486,11 +489,15 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
timeline = await room.getTimeline(
|
||||
onUpdate: updateView,
|
||||
eventContextId: eventContextId,
|
||||
onInsert: onInsert,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to load timeline on event ID $eventContextId', e, s);
|
||||
if (!mounted) return;
|
||||
timeline = await room.getTimeline(onUpdate: updateView);
|
||||
timeline = await room.getTimeline(
|
||||
onUpdate: updateView,
|
||||
onInsert: onInsert,
|
||||
);
|
||||
if (!mounted) return;
|
||||
if (e is TimeoutException || e is IOException) {
|
||||
_showScrollUpMaterialBanner(eventContextId!);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class ChatEventList extends StatelessWidget {
|
|||
final events = timeline.events.filterByVisibleInGui(
|
||||
threadId: controller.activeThreadId,
|
||||
);
|
||||
final animateInEventIndex = controller.animateInEventIndex;
|
||||
|
||||
// create a map of eventId --> index to greatly improve performance of
|
||||
// ListView's findChildIndexCallback
|
||||
|
|
@ -119,7 +120,10 @@ class ChatEventList extends StatelessWidget {
|
|||
|
||||
// The message at this index:
|
||||
final event = events[i];
|
||||
final animateIn = i == 0 && controller.firstUpdateReceived;
|
||||
final animateIn =
|
||||
animateInEventIndex != null &&
|
||||
timeline.events.length > animateInEventIndex &&
|
||||
event == timeline.events[animateInEventIndex];
|
||||
|
||||
final nextEvent = i + 1 < events.length ? events[i + 1] : null;
|
||||
final previousEvent = i > 0 ? events[i - 1] : null;
|
||||
|
|
@ -135,13 +139,16 @@ class ChatEventList extends StatelessWidget {
|
|||
!controller.expandedEventIds.contains(event.eventId);
|
||||
|
||||
return AutoScrollTag(
|
||||
key: ValueKey(event.transactionId ?? event.eventId),
|
||||
key: ValueKey(event.eventId),
|
||||
index: i,
|
||||
controller: controller.scrollController,
|
||||
child: Message(
|
||||
event,
|
||||
bigEmojis: controller.bigEmojis,
|
||||
animateIn: animateIn,
|
||||
resetAnimateIn: () {
|
||||
controller.animateInEventIndex = null;
|
||||
},
|
||||
onSwipe: () => controller.replyAction(replyTo: event),
|
||||
onInfoTab: controller.showEventInfo,
|
||||
onMention: () => controller.sendController.text +=
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:emoji_picker_flutter/locales/default_emoji_set_locale.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
|
|
@ -272,11 +273,27 @@ class ChatInputRow extends StatelessWidget {
|
|||
child: IconButton(
|
||||
tooltip: L10n.of(context).emojis,
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
icon: Icon(
|
||||
controller.showEmojiPicker
|
||||
? Icons.keyboard
|
||||
: Icons.add_reaction_outlined,
|
||||
key: ValueKey(controller.showEmojiPicker),
|
||||
icon: PageTransitionSwitcher(
|
||||
transitionBuilder:
|
||||
(
|
||||
Widget child,
|
||||
Animation<double> primaryAnimation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
return SharedAxisTransition(
|
||||
animation: primaryAnimation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
transitionType: SharedAxisTransitionType.scaled,
|
||||
fillColor: Colors.transparent,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
controller.showEmojiPicker
|
||||
? Icons.keyboard
|
||||
: Icons.add_reaction_outlined,
|
||||
key: ValueKey(controller.showEmojiPicker),
|
||||
),
|
||||
),
|
||||
onPressed: controller.emojiPickerAction,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -165,11 +165,11 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
|||
: null,
|
||||
);
|
||||
|
||||
final attachmentUrl = widget.event.attachmentOrThumbnailMxcUrl();
|
||||
|
||||
if (!kIsWeb && attachmentUrl != null) {
|
||||
if (!kIsWeb) {
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final fileName = Uri.encodeComponent(attachmentUrl.pathSegments.last);
|
||||
final fileName = Uri.encodeComponent(
|
||||
widget.event.attachmentOrThumbnailMxcUrl()!.pathSegments.last,
|
||||
);
|
||||
file = File('${tempDir.path}/${fileName}_${matrixFile.name}');
|
||||
|
||||
await file.writeAsBytes(matrixFile.bytes);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:async/async.dart' show Result;
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
import 'package:matrix/matrix.dart' hide Result;
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
|
|
@ -54,9 +53,8 @@ class SendFileDialogState extends State<SendFileDialog> {
|
|||
}
|
||||
scaffoldMessenger.showLoadingSnackBar(l10n.prepareSendingAttachment);
|
||||
Navigator.of(context, rootNavigator: false).pop();
|
||||
final clientConfig = await Result.capture(widget.room.client.getConfig());
|
||||
final maxUploadSize =
|
||||
clientConfig.asValue?.value.mUploadSize ?? 100 * 1000 * 1000;
|
||||
final clientConfig = await widget.room.client.getConfig();
|
||||
final maxUploadSize = clientConfig.mUploadSize ?? 100 * 1000 * 1000;
|
||||
|
||||
for (final xfile in widget.files) {
|
||||
final MatrixFile file;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
import 'package:flutter_shortcuts_new/flutter_shortcuts_new.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart' as sdk;
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat_list/chat_list_view.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
|
|
@ -73,6 +71,8 @@ class ChatListController extends State<ChatList>
|
|||
|
||||
StreamSubscription? _intentFileStreamSubscription;
|
||||
|
||||
StreamSubscription? _intentUriStreamSubscription;
|
||||
|
||||
late ActiveFilter activeFilter;
|
||||
|
||||
String? _activeSpaceId;
|
||||
|
|
@ -308,12 +308,6 @@ class ChatListController extends State<ChatList>
|
|||
void _processIncomingSharedMedia(List<SharedMediaFile> files) {
|
||||
if (files.isEmpty) return;
|
||||
|
||||
if (files.singleOrNull?.path.startsWith(AppConfig.deepLinkPrefix) == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
inspect(files);
|
||||
|
||||
showScaffoldDialog(
|
||||
context: context,
|
||||
builder: (context) => ShareScaffoldDialog(
|
||||
|
|
@ -332,6 +326,14 @@ class ChatListController extends State<ChatList>
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _processIncomingUris(Uri? uri) async {
|
||||
if (uri == null) return;
|
||||
context.go('/rooms');
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
UrlLauncher(context, uri.toString()).openMatrixToUrl();
|
||||
});
|
||||
}
|
||||
|
||||
void _initReceiveSharingIntent() {
|
||||
if (!PlatformInfos.isMobile) return;
|
||||
|
||||
|
|
@ -345,6 +347,11 @@ class ChatListController extends State<ChatList>
|
|||
_processIncomingSharedMedia,
|
||||
);
|
||||
|
||||
// For receiving shared Uris
|
||||
_intentUriStreamSubscription = AppLinks().uriLinkStream.listen(
|
||||
_processIncomingUris,
|
||||
);
|
||||
|
||||
if (PlatformInfos.isAndroid) {
|
||||
final shortcuts = FlutterShortcuts();
|
||||
shortcuts.initialize().then(
|
||||
|
|
@ -367,7 +374,6 @@ class ChatListController extends State<ChatList>
|
|||
_hackyWebRTCFixForWeb();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) {
|
||||
_showLastSeenSupportBanner();
|
||||
searchServer = Matrix.of(
|
||||
context,
|
||||
).store.getString(_serverStoreNamespace);
|
||||
|
|
@ -388,86 +394,11 @@ class ChatListController extends State<ChatList>
|
|||
void dispose() {
|
||||
_intentDataStreamSubscription?.cancel();
|
||||
_intentFileStreamSubscription?.cancel();
|
||||
_intentUriStreamSubscription?.cancel();
|
||||
scrollController.removeListener(_onScroll);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _showLastSeenSupportBanner() async {
|
||||
if (AppSettings.supportBannerOptOut.value) return;
|
||||
|
||||
if (AppSettings.lastSeenSupportBanner.value == 0) {
|
||||
await AppSettings.lastSeenSupportBanner.setItem(
|
||||
DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final lastSeenSupportBanner = DateTime.fromMillisecondsSinceEpoch(
|
||||
AppSettings.lastSeenSupportBanner.value,
|
||||
);
|
||||
|
||||
if (DateTime.now().difference(lastSeenSupportBanner) >=
|
||||
Duration(days: 6 * 7)) {
|
||||
final theme = Theme.of(context);
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
messenger.showMaterialBanner(
|
||||
MaterialBanner(
|
||||
backgroundColor: theme.colorScheme.errorContainer,
|
||||
leading: CloseButton(
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
onPressed: () async {
|
||||
final okCancelResult = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).skipSupportingFluffyChat,
|
||||
message: L10n.of(context).fluffyChatSupportBannerMessage,
|
||||
okLabel: L10n.of(context).iDoNotWantToSupport,
|
||||
cancelLabel: L10n.of(context).iAlreadySupportFluffyChat,
|
||||
isDestructive: true,
|
||||
);
|
||||
switch (okCancelResult) {
|
||||
case null:
|
||||
return;
|
||||
case OkCancelResult.ok:
|
||||
messenger.clearMaterialBanners();
|
||||
return;
|
||||
case OkCancelResult.cancel:
|
||||
messenger.clearMaterialBanners();
|
||||
await AppSettings.supportBannerOptOut.setItem(true);
|
||||
return;
|
||||
}
|
||||
},
|
||||
),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Text(
|
||||
L10n.of(context).fluffyChatSupportBannerMessage,
|
||||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
messenger.clearMaterialBanners();
|
||||
launchUrlString(
|
||||
'https://fluffychat.im/faq/#how_can_i_support_fluffychat',
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
L10n.of(context).support,
|
||||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
await AppSettings.lastSeenSupportBanner.setItem(
|
||||
DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Future<void> chatContextAction(
|
||||
Room room,
|
||||
BuildContext posContext, [
|
||||
|
|
@ -578,44 +509,23 @@ class ChatListController extends State<ChatList>
|
|||
],
|
||||
),
|
||||
),
|
||||
if (!room.isLowPriority)
|
||||
PopupMenuItem(
|
||||
value: ChatContextAction.favorite,
|
||||
child: Row(
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
Icon(
|
||||
room.isFavourite ? Icons.push_pin : Icons.push_pin_outlined,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
room.isFavourite
|
||||
? L10n.of(context).unpin
|
||||
: L10n.of(context).pin,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!room.isFavourite)
|
||||
PopupMenuItem(
|
||||
value: ChatContextAction.lowPriority,
|
||||
child: Row(
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
Icon(
|
||||
room.isLowPriority
|
||||
? Icons.low_priority
|
||||
: Icons.low_priority_outlined,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
room.isLowPriority
|
||||
? L10n.of(context).unsetLowPriority
|
||||
: L10n.of(context).setLowPriority,
|
||||
),
|
||||
],
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: ChatContextAction.favorite,
|
||||
child: Row(
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
Icon(
|
||||
room.isFavourite ? Icons.push_pin : Icons.push_pin_outlined,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
room.isFavourite
|
||||
? L10n.of(context).unpin
|
||||
: L10n.of(context).pin,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (spacesWithPowerLevels.isNotEmpty)
|
||||
PopupMenuItem(
|
||||
value: ChatContextAction.addToSpace,
|
||||
|
|
@ -749,12 +659,6 @@ class ChatListController extends State<ChatList>
|
|||
context: context,
|
||||
future: () => space.setSpaceChild(room.id),
|
||||
);
|
||||
case ChatContextAction.lowPriority:
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => room.setLowPriority(!room.isLowPriority),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -964,7 +868,6 @@ enum ChatContextAction {
|
|||
open,
|
||||
goToSpace,
|
||||
favorite,
|
||||
lowPriority,
|
||||
markUnread,
|
||||
mute,
|
||||
leave,
|
||||
|
|
|
|||
|
|
@ -191,17 +191,6 @@ class ChatListItem extends StatelessWidget {
|
|||
padding: EdgeInsets.only(left: 4.0),
|
||||
child: Icon(Icons.notifications_off_outlined, size: 16),
|
||||
),
|
||||
if (room.isLowPriority)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: hasNotifications ? 4.0 : 0.0,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.low_priority,
|
||||
size: 16,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
if (room.isFavourite)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
|
|
@ -68,6 +69,17 @@ class ClientChooserButton extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
if (Matrix.of(context).backgroundPush?.firebaseEnabled != true)
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.support,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.favorite, color: Colors.red),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).donate),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.settings,
|
||||
child: Row(
|
||||
|
|
@ -78,16 +90,6 @@ class ClientChooserButton extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.support,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.favorite, color: Colors.red),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).supportFluffyChat),
|
||||
],
|
||||
),
|
||||
),
|
||||
const PopupMenuDivider(),
|
||||
for (final bundle in bundles) ...[
|
||||
if (matrix.accountBundles[bundle]!.length != 1 ||
|
||||
|
|
@ -222,9 +224,7 @@ class ClientChooserButton extends StatelessWidget {
|
|||
FluffyShare.shareInviteLink(context);
|
||||
break;
|
||||
case SettingsAction.support:
|
||||
launchUrlString(
|
||||
'https://fluffychat.im/faq/#how_can_i_support_fluffychat',
|
||||
);
|
||||
launchUrlString(AppConfig.donationUrl);
|
||||
break;
|
||||
case SettingsAction.settings:
|
||||
context.go('/rooms/settings');
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class IntroPage extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () => PlatformInfos.showDialog(context),
|
||||
value: () => PlatformInfos.showDialog(context),
|
||||
child: Row(
|
||||
mainAxisSize: .min,
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -191,9 +191,10 @@ class _InviteContactListTile extends StatelessWidget {
|
|||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: theme.colorScheme.secondary),
|
||||
),
|
||||
trailing: TextButton(
|
||||
trailing: TextButton.icon(
|
||||
onPressed: isMember ? null : onTap,
|
||||
child: Text(isMember ? l10n.participant : l10n.invite),
|
||||
label: Text(isMember ? l10n.participant : l10n.invite),
|
||||
icon: Icon(isMember ? Icons.check : Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||
import '../../widgets/adaptive_dialogs/user_dialog.dart';
|
||||
|
||||
class NewPrivateChat extends StatefulWidget {
|
||||
final String? deeplink;
|
||||
const NewPrivateChat({super.key, required this.deeplink});
|
||||
const NewPrivateChat({super.key});
|
||||
|
||||
@override
|
||||
NewPrivateChatController createState() => NewPrivateChatController();
|
||||
|
|
@ -34,18 +33,6 @@ class NewPrivateChatController extends State<NewPrivateChat> {
|
|||
|
||||
static const Duration _coolDown = Duration(milliseconds: 500);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final deeplink = widget.deeplink;
|
||||
if (deeplink != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
UrlLauncher(context, deeplink).openMatrixToUrl();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> searchUsers([String? input]) async {
|
||||
final searchTerm = input ?? controller.text;
|
||||
if (searchTerm.isEmpty) {
|
||||
|
|
|
|||
|
|
@ -118,24 +118,6 @@ class SettingsView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
FutureBuilder(
|
||||
future: Matrix.of(context).client.getAuthMetadata(),
|
||||
builder: (context, snapshot) {
|
||||
final accountManageUrl = snapshot.data?.issuer;
|
||||
if (accountManageUrl == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.account_circle_outlined),
|
||||
title: Text(L10n.of(context).manageAccount),
|
||||
trailing: const Icon(Icons.open_in_new_outlined),
|
||||
onTap: () => launchUrl(
|
||||
accountManageUrl,
|
||||
mode: LaunchMode.inAppBrowserView,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Divider(color: theme.dividerColor),
|
||||
SwitchListTile.adaptive(
|
||||
controlAffinity: ListTileControlAffinity.trailing,
|
||||
|
|
@ -145,6 +127,34 @@ class SettingsView extends StatelessWidget {
|
|||
onChanged: controller.firstRunBootstrapAction,
|
||||
),
|
||||
Divider(color: theme.dividerColor),
|
||||
|
||||
FutureBuilder(
|
||||
future: Matrix.of(context).client.getAuthMetadata(),
|
||||
builder: (context, snapshot) {
|
||||
final accountManageUrl = snapshot.data?.issuer;
|
||||
if (accountManageUrl == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.admin_panel_settings_outlined),
|
||||
title: Text(L10n.of(context).manageAccount),
|
||||
trailing: const Icon(Icons.open_in_new_outlined),
|
||||
onTap: () => launchUrl(
|
||||
accountManageUrl,
|
||||
mode: LaunchMode.inAppBrowserView,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.account_circle_outlined),
|
||||
title: Text(L10n.of(context).profileSettings),
|
||||
tileColor:
|
||||
activeRoute.startsWith('/rooms/settings/profile_settings')
|
||||
? theme.colorScheme.surfaceContainerHigh
|
||||
: null,
|
||||
onTap: () => context.go('/rooms/settings/profile_settings'),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.format_paint_outlined),
|
||||
title: Text(L10n.of(context).changeTheme),
|
||||
|
|
|
|||
62
lib/pages/settings_profile/settings_profile_page.dart
Normal file
62
lib/pages/settings_profile/settings_profile_page.dart
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingsProfilePage extends StatelessWidget {
|
||||
final TextEditingController? pronounsController;
|
||||
final String? timezone;
|
||||
final VoidCallback save;
|
||||
final bool isLoading;
|
||||
|
||||
const SettingsProfilePage({
|
||||
super.key,
|
||||
required this.pronounsController,
|
||||
required this.save,
|
||||
required this.timezone,
|
||||
required this.isLoading,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: !FluffyThemes.isColumnMode(context),
|
||||
title: Text(L10n.of(context).profileSettings),
|
||||
),
|
||||
body: MaxWidthBody(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: .stretch,
|
||||
spacing: 32,
|
||||
children: [
|
||||
TextField(
|
||||
controller: pronounsController,
|
||||
readOnly: pronounsController == null,
|
||||
decoration: InputDecoration(
|
||||
labelText: L10n.of(context).pronouns,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Material(
|
||||
elevation: 8,
|
||||
shadowColor: theme.appBarTheme.shadowColor,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: pronounsController == null || isLoading ? null : save,
|
||||
child: isLoading
|
||||
? LinearProgressIndicator()
|
||||
: Text(L10n.of(context).saveChanges),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
91
lib/pages/settings_profile/settings_profile_presenter.dart
Normal file
91
lib/pages/settings_profile/settings_profile_presenter.dart
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import 'package:fluffychat/pages/settings_profile/settings_profile_page.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class SettingsProfilePresenter extends StatefulWidget {
|
||||
const SettingsProfilePresenter({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsProfilePresenter> createState() =>
|
||||
_SettingsProfilePresenterState();
|
||||
}
|
||||
|
||||
class _SettingsProfilePresenterState extends State<SettingsProfilePresenter> {
|
||||
static const String pronounsKey = 'io.fsky.nyx.pronouns';
|
||||
static const String timezoneFallbackKey = 'us.cloke.msc4175.tz';
|
||||
|
||||
TextEditingController? _pronounsController;
|
||||
String? _timezone;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_loadProfile();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> _loadProfile() async {
|
||||
final client = Matrix.of(context).client;
|
||||
final cachedProfile = await client.getUserProfile(
|
||||
client.userID!,
|
||||
maxCacheAge: Duration.zero,
|
||||
);
|
||||
print(cachedProfile.additionalProperties);
|
||||
setState(() {
|
||||
_timezone =
|
||||
cachedProfile.mTz ??
|
||||
cachedProfile.additionalProperties.tryGet<String>(
|
||||
timezoneFallbackKey,
|
||||
);
|
||||
_pronounsController = TextEditingController(
|
||||
text: cachedProfile.additionalProperties.tryGet<String>(pronounsKey),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
final client = Matrix.of(context).client;
|
||||
final cachedProfile = await client.getUserProfile(client.userID!);
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
final newPronouns = _pronounsController!.text.trim();
|
||||
if (newPronouns !=
|
||||
cachedProfile.additionalProperties.tryGet<String>(pronounsKey)) {
|
||||
await client.setProfileField(client.userID!, pronounsKey, {
|
||||
pronounsKey: newPronouns,
|
||||
});
|
||||
}
|
||||
|
||||
if (cachedProfile.mTz != _timezone) {
|
||||
await client.setProfileField(client.userID!, 'm.tz', {
|
||||
'm.tz': _timezone,
|
||||
});
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logs().e('Unable to update profile', e, s);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsProfilePage(
|
||||
pronounsController: _pronounsController,
|
||||
save: _save,
|
||||
timezone: _timezone,
|
||||
isLoading: _isLoading,
|
||||
);
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/utils/account_config.dart';
|
||||
import 'package:fluffychat/utils/file_selector.dart';
|
||||
|
|
@ -110,6 +111,32 @@ class SettingsStyleController extends State<SettingsStyle> {
|
|||
ThemeMode get currentTheme => ThemeController.of(context).themeMode;
|
||||
Color? get currentColor => ThemeController.of(context).primaryColor;
|
||||
|
||||
static final List<Color?> customColors = [
|
||||
null,
|
||||
AppConfig.chatColor,
|
||||
Colors.indigo,
|
||||
Colors.blue,
|
||||
Colors.blueAccent,
|
||||
Colors.teal,
|
||||
Colors.tealAccent,
|
||||
Colors.green,
|
||||
Colors.greenAccent,
|
||||
Colors.yellow,
|
||||
Colors.yellowAccent,
|
||||
Colors.orange,
|
||||
Colors.orangeAccent,
|
||||
Colors.red,
|
||||
Colors.redAccent,
|
||||
Colors.pink,
|
||||
Colors.pinkAccent,
|
||||
Colors.purple,
|
||||
Colors.purpleAccent,
|
||||
Colors.blueGrey,
|
||||
Colors.grey,
|
||||
Colors.white,
|
||||
Colors.black,
|
||||
];
|
||||
|
||||
void switchTheme(ThemeMode? newTheme) {
|
||||
if (newTheme == null) return;
|
||||
switch (newTheme) {
|
||||
|
|
|
|||
|
|
@ -82,13 +82,14 @@ class SettingsStyleView extends StatelessWidget {
|
|||
Theme.of(context).brightness == Brightness.light
|
||||
? light?.primary
|
||||
: dark?.primary;
|
||||
final colors = [null, AppConfig.chatColor, ...Colors.primaries];
|
||||
final colors = List<Color?>.from(
|
||||
SettingsStyleController.customColors,
|
||||
);
|
||||
if (systemColor == null) {
|
||||
colors.remove(null);
|
||||
}
|
||||
return GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 64,
|
||||
),
|
||||
|
|
|
|||
24
lib/pages/sign_in/utils/sort_homeservers.dart
Normal file
24
lib/pages/sign_in/utils/sort_homeservers.dart
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:fluffychat/pages/sign_in/view_model/model/public_homeserver_data.dart';
|
||||
|
||||
int sortHomeservers(PublicHomeserverData a, PublicHomeserverData b) {
|
||||
return _calcHomeserverScore(b).compareTo(_calcHomeserverScore(a));
|
||||
}
|
||||
|
||||
int _calcHomeserverScore(PublicHomeserverData homeserver) {
|
||||
var score = 0;
|
||||
if (homeserver.description?.isNotEmpty == true) score++;
|
||||
if (homeserver.website?.isNotEmpty == true) score++;
|
||||
score += (homeserver.languages?.length ?? 0);
|
||||
score += (homeserver.features?.length ?? 0);
|
||||
score += (homeserver.onlineStatus ?? 0);
|
||||
if (homeserver.ipv6 == true) score++;
|
||||
if (homeserver.isp?.isNotEmpty == true) score++;
|
||||
if (homeserver.privacy?.isNotEmpty == true) score++;
|
||||
if (homeserver.rules?.isNotEmpty == true) score++;
|
||||
if (homeserver.version?.isNotEmpty == true) score++;
|
||||
if (homeserver.usingVanillaReg == true) score--;
|
||||
if (homeserver.regLink != null) score--;
|
||||
if (homeserver.regMethod != 'SSO') score--;
|
||||
if (homeserver.regMethod == 'In-house Element') score--;
|
||||
return score;
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import 'package:matrix/matrix_api_lite/utils/logs.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pages/sign_in/utils/sort_homeservers.dart';
|
||||
import 'package:fluffychat/pages/sign_in/view_model/model/public_homeserver_data.dart';
|
||||
import 'package:fluffychat/pages/sign_in/view_model/sign_in_state.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
|
@ -39,7 +40,7 @@ class SignInViewModel extends ValueNotifier<SignInState> {
|
|||
.toList() ??
|
||||
[];
|
||||
if (filterText.length >= 3 &&
|
||||
(filterText.contains('.') || filterText == 'localhost') &&
|
||||
filterText.contains('.') &&
|
||||
Uri.tryParse(filterText) != null &&
|
||||
!filteredPublicHomeservers.any(
|
||||
(homeserver) => homeserver.name == filterText,
|
||||
|
|
@ -73,6 +74,8 @@ class SignInViewModel extends ValueNotifier<SignInState> {
|
|||
});
|
||||
}
|
||||
|
||||
publicHomeservers.sort(sortHomeservers);
|
||||
|
||||
final defaultServer = publicHomeservers.singleWhereOrNull(
|
||||
(server) => server.name == AppSettings.defaultHomeserver.value,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -123,9 +123,7 @@ abstract class ClientManager {
|
|||
// To make room emotes work
|
||||
'im.ponies.room_emotes',
|
||||
},
|
||||
customImageResizer: PlatformInfos.supportsCustomImageResizer
|
||||
? customImageResizer
|
||||
: null,
|
||||
customImageResizer: customImageResizer,
|
||||
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
||||
database: await flutterMatrixSdkDatabaseBuilder(clientName),
|
||||
supportedLoginTypes: {
|
||||
|
|
@ -143,9 +141,6 @@ abstract class ClientManager {
|
|||
onSoftLogout: enableSoftLogout
|
||||
? (client) => client.refreshAccessToken()
|
||||
: null,
|
||||
sendTimelineEventTimeout: Duration(
|
||||
seconds: AppSettings.sendTimelineEventTimeout.value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@ abstract class PlatformInfos {
|
|||
static bool get supportsVideoPlayer =>
|
||||
!PlatformInfos.isWindows && !PlatformInfos.isLinux;
|
||||
|
||||
static bool get supportsCustomImageResizer =>
|
||||
PlatformInfos.isWeb || PlatformInfos.isMobile;
|
||||
|
||||
/// Web could also record in theory but currently only wav which is too large
|
||||
static bool get platformCanRecord => (isMobile || isMacOS || isWeb);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ Future<void> connectToHomeserverFlow(
|
|||
if (authMetadata != null && AppSettings.enableMatrixNativeOIDC.value) {
|
||||
await oidcLoginFlow(client, context, signUp);
|
||||
} else if (supportsSso) {
|
||||
await ssoLoginFlow(client, context, signUp, loginFlows);
|
||||
await ssoLoginFlow(client, context, signUp);
|
||||
} else {
|
||||
if (signUp && regLink != null) {
|
||||
await launchUrlString(regLink);
|
||||
|
|
|
|||
|
|
@ -3,52 +3,20 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/utils/sign_in_flows/calc_redirect_url.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart';
|
||||
|
||||
Future<void> ssoLoginFlow(
|
||||
Client client,
|
||||
BuildContext context,
|
||||
bool signUp,
|
||||
List<LoginFlow> loginFlows,
|
||||
) async {
|
||||
final (redirectUrl, urlScheme) = calcRedirectUrl(withAuthHtmlPath: true);
|
||||
|
||||
Logs().i('Starting legacy SSO Flow with redirect URL', redirectUrl);
|
||||
|
||||
final ssoProviders =
|
||||
(loginFlows
|
||||
.firstWhere((flow) => flow.type == 'm.login.sso')
|
||||
.additionalProperties['identity_providers']
|
||||
as List?)
|
||||
?.map(
|
||||
(json) => (
|
||||
name: json['name'] as String,
|
||||
id: json['id'] as String,
|
||||
brand: json['brand'] as String?,
|
||||
icon: json['icon'] as String?,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
final provider = ssoProviders == null
|
||||
? null
|
||||
: await showModalActionPopup(
|
||||
context: context,
|
||||
title: L10n.of(context).logInTo(client.homeserver!.host),
|
||||
actions: ssoProviders
|
||||
.map(
|
||||
(provider) =>
|
||||
AdaptiveModalAction(label: provider.name, value: provider),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
final url = client.homeserver!.replace(
|
||||
path:
|
||||
'/_matrix/client/v3/login/sso/redirect${provider == null ? '' : '/${provider.id}'}',
|
||||
path: '/_matrix/client/v3/login/sso/redirect',
|
||||
queryParameters: {
|
||||
'redirectUrl': redirectUrl.toString(),
|
||||
'action': signUp ? 'register' : 'login',
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class AdaptiveDialogAction extends StatelessWidget {
|
|||
|
||||
class AdaptiveDialogInkWell extends StatelessWidget {
|
||||
final Widget child;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback onTap;
|
||||
final EdgeInsets padding;
|
||||
|
||||
const AdaptiveDialogInkWell({
|
||||
|
|
@ -108,9 +108,7 @@ class AdaptiveDialogInkWell extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
return Material(
|
||||
color: onTap == null
|
||||
? theme.colorScheme.surfaceContainer
|
||||
: theme.colorScheme.surfaceBright,
|
||||
color: theme.colorScheme.surfaceBright,
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||
|
|
@ -127,7 +125,7 @@ class AdaptiveDialogInkWell extends StatelessWidget {
|
|||
class AdaptiveIconTextButton extends StatelessWidget {
|
||||
final String label;
|
||||
final IconData icon;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback onTap;
|
||||
const AdaptiveIconTextButton({
|
||||
super.key,
|
||||
required this.label,
|
||||
|
|
|
|||
|
|
@ -185,7 +185,6 @@ class PublicRoomDialog extends StatelessWidget {
|
|||
style: theme.textTheme.bodyMedium
|
||||
?.copyWith(fontSize: 10),
|
||||
),
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -195,39 +195,35 @@ class UserDialog extends StatelessWidget {
|
|||
AdaptiveIconTextButton(
|
||||
label: L10n.of(context).block,
|
||||
icon: Icons.block_outlined,
|
||||
onTap: client.userID == profile.userId
|
||||
? null
|
||||
: () {
|
||||
final router = GoRouter.of(context);
|
||||
Navigator.of(context).pop();
|
||||
router.go(
|
||||
'/rooms/settings/security/ignorelist',
|
||||
extra: profile.userId,
|
||||
);
|
||||
},
|
||||
onTap: () {
|
||||
final router = GoRouter.of(context);
|
||||
Navigator.of(context).pop();
|
||||
router.go(
|
||||
'/rooms/settings/security/ignorelist',
|
||||
extra: profile.userId,
|
||||
);
|
||||
},
|
||||
),
|
||||
AdaptiveIconTextButton(
|
||||
label: L10n.of(context).report,
|
||||
icon: Icons.gavel_outlined,
|
||||
onTap: client.userID == profile.userId
|
||||
? null
|
||||
: () async {
|
||||
Navigator.of(context).pop();
|
||||
final reason = await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).whyDoYouWantToReportThis,
|
||||
okLabel: L10n.of(context).report,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
hintText: L10n.of(context).reason,
|
||||
);
|
||||
if (reason == null || reason.isEmpty) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => Matrix.of(
|
||||
context,
|
||||
).client.reportUser(profile.userId, reason),
|
||||
);
|
||||
},
|
||||
onTap: () async {
|
||||
Navigator.of(context).pop();
|
||||
final reason = await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).whyDoYouWantToReportThis,
|
||||
okLabel: L10n.of(context).report,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
hintText: L10n.of(context).reason,
|
||||
);
|
||||
if (reason == null || reason.isEmpty) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => Matrix.of(
|
||||
context,
|
||||
).client.reportUser(profile.userId, reason),
|
||||
);
|
||||
},
|
||||
),
|
||||
AdaptiveIconTextButton(
|
||||
label: L10n.of(context).share,
|
||||
|
|
@ -240,19 +236,17 @@ class UserDialog extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
AdaptiveDialogInkWell(
|
||||
onTap: client.userID == profile.userId
|
||||
? null
|
||||
: () async {
|
||||
final router = GoRouter.of(context);
|
||||
final roomIdResult = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => client.startDirectChat(profile.userId),
|
||||
);
|
||||
final roomId = roomIdResult.result;
|
||||
if (roomId == null) return;
|
||||
if (context.mounted) Navigator.of(context).pop();
|
||||
router.go('/rooms/$roomId');
|
||||
},
|
||||
onTap: () async {
|
||||
final router = GoRouter.of(context);
|
||||
final roomIdResult = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => client.startDirectChat(profile.userId),
|
||||
);
|
||||
final roomId = roomIdResult.result;
|
||||
if (roomId == null) return;
|
||||
if (context.mounted) Navigator.of(context).pop();
|
||||
router.go('/rooms/$roomId');
|
||||
},
|
||||
child: Text(
|
||||
directChatRoomId == null
|
||||
? L10n.of(context).createNewChat
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ class ConfigViewer extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ConfigViewerState extends State<ConfigViewer> {
|
||||
String _searchQuery = '';
|
||||
|
||||
Future<void> _changeSetting(
|
||||
AppSettings appSetting,
|
||||
SharedPreferences store,
|
||||
|
|
@ -58,14 +56,6 @@ class _ConfigViewerState extends State<ConfigViewer> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final normalizedQuery = _searchQuery.trim().toLowerCase();
|
||||
final filteredSettings = AppSettings.values
|
||||
.where((setting) {
|
||||
if (normalizedQuery.isEmpty) return true;
|
||||
return setting.name.toLowerCase().contains(normalizedQuery);
|
||||
})
|
||||
.toList(growable: false);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(L10n.of(context).advancedConfigurations),
|
||||
|
|
@ -86,29 +76,12 @@ class _ConfigViewerState extends State<ConfigViewer> {
|
|||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: TextField(
|
||||
onChanged: (value) => setState(() => _searchQuery = value),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search config key',
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: theme.colorScheme.surfaceContainerHighest.withAlpha(
|
||||
128,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: filteredSettings.length,
|
||||
itemCount: AppSettings.values.length,
|
||||
itemBuilder: (context, i) {
|
||||
final store = Matrix.of(context).store;
|
||||
final appSetting = filteredSettings[i];
|
||||
final appSetting = AppSettings.values[i];
|
||||
var value = '';
|
||||
if (appSetting is AppSettings<String>) {
|
||||
value = appSetting.value;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/routes.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
|
|
@ -38,12 +37,6 @@ class FluffyChatApp extends StatelessWidget {
|
|||
static final GoRouter router = GoRouter(
|
||||
routes: AppRoutes.routes,
|
||||
debugLogDiagnostics: true,
|
||||
redirect: (context, state) {
|
||||
if (state.uri.toString().startsWith(AppConfig.deepLinkPrefix)) {
|
||||
return '/rooms/newprivatechat?deeplink=${state.uri}';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
}
|
||||
|
||||
Future<void> createVoipPlugin() async {
|
||||
if (!AppSettings.experimentalVoip.value) {
|
||||
if (AppSettings.experimentalVoip.value) {
|
||||
voipPlugin = null;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Future<int?> showPermissionChooser(
|
|||
child: Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .stretch,
|
||||
spacing: 16.0,
|
||||
spacing: 12.0,
|
||||
children: [
|
||||
Text(L10n.of(context).setPowerLevelDescription),
|
||||
ValueListenableBuilder(
|
||||
|
|
|
|||
|
|
@ -91,11 +91,7 @@ class QrCodeViewer extends StatelessWidget {
|
|||
margin: const EdgeInsets.all(32.0),
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
width: 4,
|
||||
),
|
||||
color: theme.colorScheme.surfaceBright,
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
),
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||
#include <gtk/gtk_plugin.h>
|
||||
#include <handy_window/handy_window_plugin.h>
|
||||
#include <record_linux/record_linux_plugin.h>
|
||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||
|
|
@ -44,6 +45,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin");
|
||||
flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar);
|
||||
g_autoptr(FlPluginRegistrar) gtk_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
|
||||
gtk_plugin_register_with_registrar(gtk_registrar);
|
||||
g_autoptr(FlPluginRegistrar) handy_window_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin");
|
||||
handy_window_plugin_register_with_registrar(handy_window_registrar);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
file_selector_linux
|
||||
flutter_secure_storage_linux
|
||||
flutter_webrtc
|
||||
gtk
|
||||
handy_window
|
||||
record_linux
|
||||
screen_retriever_linux
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import app_links
|
||||
import audio_session
|
||||
import desktop_drop
|
||||
import desktop_webview_window
|
||||
|
|
@ -35,6 +36,7 @@ import window_manager
|
|||
import window_to_front
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
|
||||
DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin"))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
PODS:
|
||||
- app_links (6.4.1):
|
||||
- FlutterMacOS
|
||||
- audio_session (0.0.1):
|
||||
- FlutterMacOS
|
||||
- desktop_drop (0.0.1):
|
||||
|
|
@ -74,6 +76,7 @@ PODS:
|
|||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
|
||||
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
||||
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
|
||||
- desktop_webview_window (from `Flutter/ephemeral/.symlinks/plugins/desktop_webview_window/macos`)
|
||||
|
|
@ -111,6 +114,8 @@ SPEC REPOS:
|
|||
- WebRTC-SDK
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
|
||||
audio_session:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
|
||||
desktop_drop:
|
||||
|
|
@ -173,6 +178,7 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f
|
||||
audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e
|
||||
desktop_drop: 10a3e6a7fa9dbe350541f2574092fecfa345a07b
|
||||
desktop_webview_window: 7e37af677d6d19294cb433d9b1d878ef78dffa4d
|
||||
|
|
@ -181,7 +187,7 @@ SPEC CHECKSUMS:
|
|||
emoji_picker_flutter: 51ca408e289d84d1e460016b2a28721ec754fcf7
|
||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
|
||||
flutter_local_notifications: 1fc7ffb10a83d6a2eeeeddb152d43f1944b0aad0
|
||||
flutter_local_notifications: 4bf37a31afde695b56091b4ae3e4d9c7a7e6cda0
|
||||
flutter_new_badger: 6fe9bf7e42793a164032c21f164c0ad9985cd0f2
|
||||
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
|
||||
flutter_vodozemac: fd2ea9cb3e2a37beaac883a369811fbfe042fc53
|
||||
|
|
|
|||
177
pubspec.lock
177
pubspec.lock
|
|
@ -25,6 +25,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.6"
|
||||
animations:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: animations
|
||||
sha256: "18938cefd7dcc04e1ecac0db78973761a01e4bc2d6bfae0cfa596bfeac9e96ab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
ansicolor:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -33,6 +41,38 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
app_links:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_linux
|
||||
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
app_links_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_web
|
||||
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -242,7 +282,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.0.2"
|
||||
cupertino_icons:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||
|
|
@ -462,6 +502,11 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_driver:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_foreground_task:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -490,34 +535,34 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: "0d9035862236fe38250fe1644d7ed3b8254e34a21b2c837c9f539fbb3bba5ef1"
|
||||
sha256: "2b50e938a275e1ad77352d6a25e25770f4130baa61eaf02de7a9a884680954ad"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "21.0.0"
|
||||
version: "20.1.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: e0f25e243c6c44c825bbbc6b2b2e76f7d9222362adcfe9fd780bf01923c840bd
|
||||
sha256: dce0116868cedd2cdf768af0365fc37ff1cbef7c02c4f51d0587482e625868d0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
version: "7.0.0"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: e7db3d5b49c2b7ecc68deba4aaaa67a348f92ee0fef34c8e4b4459dbef0d7307
|
||||
sha256: "23de31678a48c084169d7ae95866df9de5c9d2a44be3e5915a2ff067aeeba899"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.0.0"
|
||||
version: "10.0.0"
|
||||
flutter_local_notifications_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_windows
|
||||
sha256: "3a2654ba104fbb52c618ebed9def24ef270228470718c43b3a6afcd5c81bef0c"
|
||||
sha256: e97a1a3016512437d9c0b12fae7d1491c3c7b9aa7f03a69b974308840656b02a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "2.0.1"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -669,6 +714,11 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
geoclue:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -757,6 +807,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.8"
|
||||
gtk:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gtk
|
||||
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
handy_window:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -901,6 +959,11 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.0"
|
||||
integration_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -998,7 +1061,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.6.2"
|
||||
linkify:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: linkify
|
||||
sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832"
|
||||
|
|
@ -1065,10 +1128,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: matrix
|
||||
sha256: "5bb38e98212bc4c3244c762a1af787f7239a38d2cfdf44488258283ff899f77c"
|
||||
sha256: c0214ee99a73957d3c02d54a60afcf9acee577b0924749085d6fdf556e8eba42
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "6.1.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1237,6 +1300,54 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.0.1"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.1"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.7"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1738,6 +1849,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
sync_http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sync_http
|
||||
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1779,13 +1898,13 @@ packages:
|
|||
source: hosted
|
||||
version: "0.6.16"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: timezone
|
||||
sha256: "784a5e34d2eb62e1326f24d6f600aaaee452eb8ca8ef2f384a59244e292d158b"
|
||||
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.0"
|
||||
version: "0.10.1"
|
||||
tint:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1798,10 +1917,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: translations_cleaner
|
||||
sha256: c6e5051cb5d4fe4c5b2cc1ef83a6964f27063f9cf5b6166f445709bea8f81ad3
|
||||
sha256: "811f42be32f024fdf083903f198d3625f6ee6927601e3a53a29b85b90508b88c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
version: "0.1.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1990,10 +2109,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: video_player
|
||||
sha256: "48a7bdaa38a3d50ec10c78627abdbfad863fdf6f0d6e08c7c3c040cfd80ae36f"
|
||||
sha256: "08bfba72e311d48219acad4e191b1f9c27ff8cf928f2c7234874592d9c9d7341"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.1"
|
||||
version: "2.11.0"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2046,18 +2165,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: e4e125b7c1a2f0e491e5452afdc0e25ab77b2d2775a7caa231fcc1c1f2162c47
|
||||
sha256: "9296d40c9adbedaba95d1e704f4e0b434be446e2792948d0e4aa977048104228"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
version: "1.4.0"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "24b84143787220a403491c2e5de0877fbbb87baf3f0b18a2a988973863db4b03"
|
||||
sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.3.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2099,6 +2218,14 @@ packages:
|
|||
url: "https://github.com/google/webcrypto.dart.git"
|
||||
source: git
|
||||
version: "0.6.0"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webdriver
|
||||
sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2188,5 +2315,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.11.1 <4.0.0"
|
||||
flutter: ">=3.38.4"
|
||||
dart: ">=3.10.3 <4.0.0"
|
||||
flutter: "3.41.4"
|
||||
|
|
|
|||
23
pubspec.yaml
23
pubspec.yaml
|
|
@ -4,12 +4,15 @@ publish_to: none
|
|||
# On version bump please also increase:
|
||||
# 1. The build number (for F-Droid)
|
||||
# 2. The version in /snap/snapcraft.yaml
|
||||
version: 2.5.0+3547
|
||||
version: 2.4.0+3546
|
||||
|
||||
environment:
|
||||
sdk: ">=3.11.1 <4.0.0"
|
||||
sdk: ">=3.10.0 <4.0.0"
|
||||
flutter: 3.41.4
|
||||
|
||||
dependencies:
|
||||
animations: ^2.1.1
|
||||
app_links: ^6.4.1
|
||||
archive: ^4.0.7
|
||||
async: ^2.11.0
|
||||
badges: ^3.1.2
|
||||
|
|
@ -17,6 +20,7 @@ dependencies:
|
|||
chewie: ^1.13.0
|
||||
collection: ^1.18.0
|
||||
cross_file: ^0.3.5
|
||||
cupertino_icons: any
|
||||
desktop_drop: ^0.7.0
|
||||
desktop_notifications: ^0.6.3
|
||||
device_info_plus: ^12.3.0
|
||||
|
|
@ -28,7 +32,7 @@ dependencies:
|
|||
sdk: flutter
|
||||
flutter_foreground_task: ^9.2.1
|
||||
flutter_linkify: ^6.0.0
|
||||
flutter_local_notifications: ^21.0.0
|
||||
flutter_local_notifications: ^20.1.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_map: ^8.2.2
|
||||
|
|
@ -49,7 +53,8 @@ dependencies:
|
|||
intl: any
|
||||
just_audio: ^0.10.5
|
||||
latlong2: ^0.9.1
|
||||
matrix: ^6.2.0
|
||||
linkify: ^5.0.0
|
||||
matrix: ^6.1.1
|
||||
mime: ^2.0.0
|
||||
native_imaging: ^0.4.0
|
||||
opus_caf_converter_dart: ^1.0.1
|
||||
|
|
@ -57,6 +62,7 @@ dependencies:
|
|||
particles_network: ^1.9.3
|
||||
path: ^1.9.0
|
||||
path_provider: ^2.1.2
|
||||
permission_handler: ^12.0.1
|
||||
pretty_qr_code: ^3.6.0
|
||||
provider: ^6.0.2
|
||||
punycode: ^1.0.0
|
||||
|
|
@ -71,13 +77,14 @@ dependencies:
|
|||
sqflite_common_ffi: ^2.3.7+1
|
||||
sqlcipher_flutter_libs: ^0.6.8
|
||||
swipe_to_action: ^0.3.0
|
||||
timezone: ^0.10.1
|
||||
unifiedpush: ^6.2.0
|
||||
unifiedpush_ui: ^0.2.0
|
||||
universal_html: ^2.3.0
|
||||
url_launcher: ^6.3.2
|
||||
video_compress: ^3.1.4
|
||||
video_player: ^2.11.1
|
||||
wakelock_plus: ^1.5.0
|
||||
video_player: ^2.10.1
|
||||
wakelock_plus: ^1.3.3
|
||||
webrtc_interface: ^1.3.0
|
||||
|
||||
dev_dependencies:
|
||||
|
|
@ -87,8 +94,10 @@ dev_dependencies:
|
|||
flutter_test:
|
||||
sdk: flutter
|
||||
import_sorter: ^4.6.0
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
license_checker: ^1.6.2
|
||||
translations_cleaner: ^0.1.1
|
||||
translations_cleaner: ^0.1.0
|
||||
|
||||
import_sorter:
|
||||
ignored_files: # Optional, defaults to []
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@
|
|||
"English"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "converser.eu",
|
||||
"website": "https://converser.eu",
|
||||
"description": "A free and decentralized communication server.",
|
||||
"reg_method": "oidc",
|
||||
"languages": [
|
||||
"All",
|
||||
"Français"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mozilla.org",
|
||||
"website": "https://mozilla.org",
|
||||
|
|
@ -21,13 +31,11 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "tchncs.de",
|
||||
"website": "https://tchncs.de",
|
||||
"description": "A general homeserver. Owner also hosts other FOSS services.",
|
||||
"name": "magdeburg.jetzt",
|
||||
"website": "https://magdeburg.jetzt",
|
||||
"reg_method": "oidc",
|
||||
"languages": [
|
||||
"All",
|
||||
"English",
|
||||
"Deutsch"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
name: fluffychat
|
||||
title: FluffyChat
|
||||
base: core24
|
||||
version: 2.5.0
|
||||
version: 2.4.0
|
||||
license: AGPL-3.0
|
||||
summary: The cutest messenger in the Matrix network
|
||||
description: |
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <app_links/app_links_plugin_c_api.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <desktop_webview_window/desktop_webview_window_plugin.h>
|
||||
#include <dynamic_color/dynamic_color_plugin_c_api.h>
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||
#include <geolocator_windows/geolocator_windows.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <record_windows/record_windows_plugin_c_api.h>
|
||||
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||
|
|
@ -24,6 +26,8 @@
|
|||
#include <window_to_front/window_to_front_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AppLinksPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||
DesktopDropPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||
DesktopWebviewWindowPluginRegisterWithRegistrar(
|
||||
|
|
@ -40,6 +44,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
||||
GeolocatorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("GeolocatorWindows"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
RecordWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("RecordWindowsPluginCApi"));
|
||||
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
app_links
|
||||
desktop_drop
|
||||
desktop_webview_window
|
||||
dynamic_color
|
||||
|
|
@ -11,6 +12,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
flutter_secure_storage_windows
|
||||
flutter_webrtc
|
||||
geolocator_windows
|
||||
permission_handler_windows
|
||||
record_windows
|
||||
screen_retriever_windows
|
||||
share_plus
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue