├── lib ├── l10n │ ├── intl_be.arb │ ├── intl_te.arb │ ├── intl_da.arb │ └── intl_ia.arb ├── utils │ ├── matrix_sdk_extensions │ │ ├── flutter_matrix_dart_sdk_database │ │ │ └── sqlcipher_stub.dart │ │ ├── device_extension.dart │ │ └── event_extension.dart │ ├── tor_stub.dart │ ├── custom_scroll_behaviour.dart │ ├── color_value.dart │ ├── beautify_string_extension.dart │ ├── file_description.dart │ ├── size_string.dart │ ├── other_party_can_receive.dart │ ├── voip │ │ └── user_media_manager.dart │ ├── event_checkbox_extension.dart │ ├── custom_http_client.dart │ ├── string_color.dart │ ├── sync_status_localization.dart │ ├── show_scaffold_dialog.dart │ ├── fluffy_share.dart │ ├── show_update_snackbar.dart │ ├── resize_video.dart │ ├── stream_extension.dart │ └── client_download_content_extension.dart ├── pages │ ├── dialer │ │ └── pip │ │ │ └── dismiss_keyboard.dart │ ├── settings_chat │ │ └── settings_chat.dart │ ├── settings_multiple_emotes │ │ └── settings_multiple_emotes.dart │ ├── chat │ │ ├── events │ │ │ └── state_message.dart │ │ └── encryption_button.dart │ ├── settings_ignore_list │ │ └── settings_ignore_list.dart │ └── settings_homeserver │ │ └── settings_homeserver.dart ├── config │ └── app_emojis.dart └── widgets │ ├── hover_builder.dart │ ├── layouts │ ├── empty_page.dart │ └── two_column_layout.dart │ ├── settings_switch_list_tile.dart │ ├── error_widget.dart │ ├── unread_rooms_badge.dart │ ├── presence_builder.dart │ └── mxc_image_viewer.dart ├── winuwp ├── project_version ├── runner_uwp │ ├── resources.pri │ ├── Assets │ │ ├── StoreLogo.png │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── WideTile.scale-100.png │ │ ├── WideTile.scale-125.png │ │ ├── WideTile.scale-150.png │ │ ├── WideTile.scale-200.png │ │ ├── WideTile.scale-400.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ └── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Windows_TemporaryKey.pfx │ ├── main.cpp │ ├── CMakeSettings.json │ └── appxmanifest.in ├── flutter │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake └── .gitignore ├── assets ├── js │ └── package │ │ └── .gitkeep ├── logo.png ├── banner.png ├── favicon.png ├── info-logo.png ├── sounds │ ├── call.ogg │ ├── phone.ogg │ └── notification.ogg ├── logo_transparent.png └── banner_transparent.png ├── fastlane ├── ios ├── Runner │ ├── ar.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── ca.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── cs.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── de.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── eo.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── es.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── et.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── eu.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── fr.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── gl.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── hu.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── hy.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── it.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── ja.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── pl.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── pt.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── tr.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── uk.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── hr-HR.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── hu-HU.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── nb-NO.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── ru-RU.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── sk-SK.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── sv-SE.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── vi-VN.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── zh-Hans.lproj │ │ ├── Main.strings │ │ └── LaunchScreen.strings │ ├── Runner-Bridging-Header.h │ ├── notification.caf │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-50x50@1x.png │ │ │ ├── Icon-App-50x50@2x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchBackground.imageset │ │ │ ├── background.png │ │ │ ├── darkbackground.png │ │ │ └── Contents.json │ ├── Runner.entitlements │ ├── AppDelegate.swift │ ├── GoogleService-Info.plist │ └── Base.lproj │ │ └── Main.storyboard ├── Gemfile ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ ├── ephemeral │ │ ├── flutter_lldbinit │ │ └── flutter_lldb_helper.py │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── fastlane │ ├── Appfile │ ├── report.xml │ ├── README.md │ └── Fastfile ├── FluffyChat Share │ ├── FluffyChat Share.entitlements │ ├── ShareViewController.swift │ ├── Base.lproj │ │ └── MainInterface.storyboard │ └── Info.plist └── .gitignore ├── linux ├── .gitignore ├── main.cc ├── flutter │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake └── my_application.h ├── android ├── fastlane │ ├── metadata │ │ └── android │ │ │ └── en-US │ │ │ ├── video.txt │ │ │ ├── title.txt │ │ │ ├── short_description.txt │ │ │ ├── images │ │ │ ├── icon.png │ │ │ └── featureGraphic.png │ │ │ └── full_description.txt │ ├── Appfile │ ├── report.xml │ └── README.md ├── app │ ├── proguard-rules.pro │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── background.png │ │ │ │ └── launch_background.xml │ │ │ ├── drawable-hdpi │ │ │ │ ├── splash.png │ │ │ │ └── notifications_icon.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── splash.png │ │ │ │ └── notifications_icon.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── splash.png │ │ │ │ └── notifications_icon.png │ │ │ ├── drawable-v21 │ │ │ │ ├── background.png │ │ │ │ └── launch_background.xml │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── splash.png │ │ │ │ └── notifications_icon.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── splash.png │ │ │ │ └── notifications_icon.png │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-night │ │ │ │ ├── background.png │ │ │ │ └── launch_background.xml │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-night-v21 │ │ │ │ ├── background.png │ │ │ │ └── launch_background.xml │ │ │ ├── values │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ └── ic_launcher.xml │ │ │ └── values-night │ │ │ │ └── styles.xml │ │ │ └── kotlin │ │ │ └── chat │ │ │ └── fluffy │ │ │ └── fluffychat │ │ │ ├── UnifiedPushService.kt │ │ │ ├── FcmPushService.kt │ │ │ └── MainActivity.kt │ └── google-services.json ├── Gemfile ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── build.gradle └── settings.gradle ├── .github ├── CODEOWNERS ├── workflows │ ├── versions.env │ └── check_duplicates.yaml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.yml │ ├── issue_pr_management.yml │ ├── test_report.md │ └── bug_report.yml ├── dependabot.yml ├── FUNDING.yml └── pull_request_template.md ├── fdroid ├── .gitignore ├── fdroid-icon.png ├── config.stable.py ├── config.nightly.py └── metadata │ └── chat.fluffy.fluffychat.yml ├── appimage ├── .gitignore ├── AppRun ├── FluffyChat.desktop └── README.md ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ └── Icon-512.png ├── splash │ ├── img │ │ ├── dark-1x.png │ │ ├── dark-2x.png │ │ ├── dark-3x.png │ │ ├── dark-4x.png │ │ ├── light-1x.png │ │ ├── light-2x.png │ │ ├── light-3x.png │ │ └── light-4x.png │ └── style.css ├── auth.html └── manifest.json ├── docs ├── favicon.png ├── feature1.gif ├── feature2.gif ├── feature3.gif ├── feature4.gif ├── feature5.gif ├── feature6.gif ├── feature7.gif ├── feature8.gif ├── feature9.gif ├── info-logo.png ├── appstore-badge.png ├── browser-badge.png ├── fdroid_button.png ├── firefox_icon.png ├── flathub-badge-en.png ├── kofi_button_dark.png ├── .well-known │ └── org.flathub.VerifiedApps.txt ├── google-play-badge.png ├── screenshots │ ├── desktop.png │ ├── mobile.png │ ├── product.jpeg │ ├── screenshots.png │ ├── showcase1.jpeg │ ├── showcase2.jpeg │ ├── showcase3.jpeg │ ├── showcase4.jpeg │ └── showcase5.jpeg ├── tailwind.config.js └── LICENSE ├── snap └── gui │ ├── fluffychat.png │ └── fluffychat.desktop ├── integration_test ├── synapse │ └── data │ │ ├── localhost.signing.key │ │ └── localhost.log.config ├── .gitignore ├── users.dart └── extensions │ └── wait_for.dart ├── macos ├── Runner │ ├── Configs │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ ├── Warnings.xcconfig │ │ └── AppInfo.xcconfig │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── 16-mac.png │ │ │ ├── 32-mac.png │ │ │ ├── 64-mac.png │ │ │ ├── 1024-mac.png │ │ │ ├── 128-mac.png │ │ │ ├── 256-mac.png │ │ │ ├── 512-mac.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── MainFlutterWindow.swift │ ├── Release.entitlements │ ├── DebugProfile.entitlements │ └── Info.plist ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ └── Flutter-Release.xcconfig ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner.xcodeproj │ └── project.xcworkspace │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Podfile ├── windows ├── runner │ ├── resources │ │ └── app_icon.ico │ ├── resource.h │ ├── utils.h │ ├── runner.exe.manifest │ ├── flutter_window.h │ ├── CMakeLists.txt │ ├── main.cpp │ └── utils.cpp ├── .gitignore └── flutter │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake ├── scripts ├── prepare-macos.sh ├── build-windows.ps1 ├── update-dependencies.sh ├── integration-start-avd.sh ├── integration-create-environment-variables.sh ├── build-olm-windows.sh ├── prepare-windows.ps1 ├── integration-prepare-host.sh ├── package-windows.ps1 ├── integration-server-synapse.sh ├── prepare-web.sh ├── release-ios-testflight.sh ├── prepare-android-release.sh ├── integration-server-conduit.sh ├── prepare-fdroid.sh ├── integration-server-dendrite.sh ├── integration-check-release-build.sh ├── generate-locale-config.sh ├── generate_command_hints_glue.sh └── build-macos.sh ├── devtools_options.yaml ├── l10n.yaml ├── test ├── archive_test.dart ├── homeserver_picker_test.dart ├── widget_test.dart ├── command_hint_test.dart └── utils │ └── test_client.dart ├── config.sample.json ├── Dockerfile ├── .metadata ├── licenses.yaml ├── analysis_options.yaml └── .mailmap /lib/l10n/intl_be.arb: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /winuwp/project_version: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /assets/js/package/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fastlane: -------------------------------------------------------------------------------- 1 | ./android/fastlane -------------------------------------------------------------------------------- /ios/Runner/ar.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ca.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/cs.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/de.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/eo.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/es.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/et.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/eu.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/fr.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/gl.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hu.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hy.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/it.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ja.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/pl.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/pt.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/tr.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/uk.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /ios/Runner/hr-HR.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hu-HU.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/nb-NO.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ru-RU.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/sk-SK.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/sv-SE.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/vi-VN.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/zh-Hans.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ar.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ca.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/cs.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/de.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/eo.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/es.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/et.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/eu.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/fr.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/gl.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hr-HR.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hu-HU.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hu.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/hy.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/it.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ja.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/nb-NO.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/pl.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/pt.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/ru-RU.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/sk-SK.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/sv-SE.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/tr.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/uk.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Runner/vi-VN.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/video.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ios/Runner/zh-Hans.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @krille-chan 2 | lib/l10n/*.arb @weblate -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/title.txt: -------------------------------------------------------------------------------- 1 | FluffyChat -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keep class net.sqlcipher.** { *; } -------------------------------------------------------------------------------- /fdroid/.gitignore: -------------------------------------------------------------------------------- 1 | repo 2 | srclibs 3 | tmp 4 | chat.fluffy.fluffychat -------------------------------------------------------------------------------- /android/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /ios/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /.github/workflows/versions.env: -------------------------------------------------------------------------------- 1 | FLUTTER_VERSION=3.32.1 2 | JAVA_VERSION=17 3 | -------------------------------------------------------------------------------- /appimage/.gitignore: -------------------------------------------------------------------------------- 1 | FluffyChat.AppDir 2 | *.AppImage 3 | *.AppImage.zsync 4 | -------------------------------------------------------------------------------- /appimage/AppRun: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")" 4 | exec ./fluffychat -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/logo.png -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/favicon.png -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/banner.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /docs/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/favicon.png -------------------------------------------------------------------------------- /docs/feature1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature1.gif -------------------------------------------------------------------------------- /docs/feature2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature2.gif -------------------------------------------------------------------------------- /docs/feature3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature3.gif -------------------------------------------------------------------------------- /docs/feature4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature4.gif -------------------------------------------------------------------------------- /docs/feature5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature5.gif -------------------------------------------------------------------------------- /docs/feature6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature6.gif -------------------------------------------------------------------------------- /docs/feature7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature7.gif -------------------------------------------------------------------------------- /docs/feature8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature8.gif -------------------------------------------------------------------------------- /docs/feature9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/feature9.gif -------------------------------------------------------------------------------- /docs/info-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/info-logo.png -------------------------------------------------------------------------------- /assets/info-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/info-logo.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | Chat with your friends with FluffyChat. -------------------------------------------------------------------------------- /assets/sounds/call.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/sounds/call.ogg -------------------------------------------------------------------------------- /assets/sounds/phone.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/sounds/phone.ogg -------------------------------------------------------------------------------- /docs/appstore-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/appstore-badge.png -------------------------------------------------------------------------------- /docs/browser-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/browser-badge.png -------------------------------------------------------------------------------- /docs/fdroid_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/fdroid_button.png -------------------------------------------------------------------------------- /docs/firefox_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/firefox_icon.png -------------------------------------------------------------------------------- /fdroid/fdroid-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/fdroid/fdroid-icon.png -------------------------------------------------------------------------------- /snap/gui/fluffychat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/snap/gui/fluffychat.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /docs/flathub-badge-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/flathub-badge-en.png -------------------------------------------------------------------------------- /docs/kofi_button_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/kofi_button_dark.png -------------------------------------------------------------------------------- /assets/logo_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/logo_transparent.png -------------------------------------------------------------------------------- /docs/.well-known/org.flathub.VerifiedApps.txt: -------------------------------------------------------------------------------- 1 | # im.fluffychat.Fluffychat 2 | 8b25b37b-f160-4350-b4f6-9a04554e8f9e -------------------------------------------------------------------------------- /docs/google-play-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/google-play-badge.png -------------------------------------------------------------------------------- /docs/screenshots/desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/desktop.png -------------------------------------------------------------------------------- /docs/screenshots/mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/mobile.png -------------------------------------------------------------------------------- /ios/Runner/notification.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/notification.caf -------------------------------------------------------------------------------- /web/splash/img/dark-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/dark-1x.png -------------------------------------------------------------------------------- /web/splash/img/dark-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/dark-2x.png -------------------------------------------------------------------------------- /web/splash/img/dark-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/dark-3x.png -------------------------------------------------------------------------------- /web/splash/img/dark-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/dark-4x.png -------------------------------------------------------------------------------- /web/splash/img/light-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/light-1x.png -------------------------------------------------------------------------------- /web/splash/img/light-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/light-2x.png -------------------------------------------------------------------------------- /web/splash/img/light-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/light-3x.png -------------------------------------------------------------------------------- /web/splash/img/light-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/web/splash/img/light-4x.png -------------------------------------------------------------------------------- /assets/banner_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/banner_transparent.png -------------------------------------------------------------------------------- /assets/sounds/notification.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/assets/sounds/notification.ogg -------------------------------------------------------------------------------- /docs/screenshots/product.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/product.jpeg -------------------------------------------------------------------------------- /integration_test/synapse/data/localhost.signing.key: -------------------------------------------------------------------------------- 1 | ed25519 a_SLrz 0Ho/81rZZve88zdRxhaXWHUT6K3OqzmP35rNMZBUr6I 2 | -------------------------------------------------------------------------------- /docs/screenshots/screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/screenshots.png -------------------------------------------------------------------------------- /docs/screenshots/showcase1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/showcase1.jpeg -------------------------------------------------------------------------------- /docs/screenshots/showcase2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/showcase2.jpeg -------------------------------------------------------------------------------- /docs/screenshots/showcase3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/showcase3.jpeg -------------------------------------------------------------------------------- /docs/screenshots/showcase4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/showcase4.jpeg -------------------------------------------------------------------------------- /docs/screenshots/showcase5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/docs/screenshots/showcase5.jpeg -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/resources.pri: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/resources.pri -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.png -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/Windows_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Windows_TemporaryKey.pfx -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable/background.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/WideTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/WideTile.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/WideTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/WideTile.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/WideTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/WideTile.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/WideTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/WideTile.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/WideTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/WideTile.scale-400.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4608m 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | kotlin.jvm.target.validation.mode=IGNORE -------------------------------------------------------------------------------- /lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/sqlcipher_stub.dart: -------------------------------------------------------------------------------- 1 | Future applyWorkaroundToOpenSqlCipherOnOldAndroidVersions() async {} 2 | -------------------------------------------------------------------------------- /scripts/prepare-macos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! type "flutter" > /dev/null; then 4 | brew install flutter 5 | fi 6 | 7 | brew install libolm 8 | 9 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-night/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /ios/Flutter/ephemeral/flutter_lldbinit: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | command script import --relative-to-command-file flutter_lldb_helper.py 6 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-night-v21/background.png -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/16-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/16-mac.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/32-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/32-mac.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/64-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/64-mac.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/1024-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/1024-mac.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/128-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/128-mac.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/256-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/256-mac.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/512-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/512-mac.png -------------------------------------------------------------------------------- /scripts/build-windows.ps1: -------------------------------------------------------------------------------- 1 | flutter doctor 2 | flutter config --enable-windows-desktop 3 | flutter clean 4 | flutter pub get 5 | 6 | flutter build windows --release -v 7 | 8 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/notifications_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-hdpi/notifications_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/notifications_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-mdpi/notifications_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/notifications_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xhdpi/notifications_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/notifications_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xxhdpi/notifications_icon.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/notifications_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/app/src/main/res/drawable-xxxhdpi/notifications_icon.png -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/android/fastlane/metadata/android/en-US/images/featureGraphic.png -------------------------------------------------------------------------------- /integration_test/.gitignore: -------------------------------------------------------------------------------- 1 | synapse/data/homeserver.db 2 | dendrite/data/server.* 3 | dendrite/data/matrix_key.pem 4 | dendrite/data/logs 5 | dendrite/data/jetstream 6 | dendrite/data/*.db -------------------------------------------------------------------------------- /android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png -------------------------------------------------------------------------------- /lib/pages/dialer/pip/dismiss_keyboard.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void dismissKeyboard(BuildContext context) { 4 | FocusScope.of(context).requestFocus(FocusNode()); 5 | } 6 | -------------------------------------------------------------------------------- /scripts/update-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ve 2 | flutter pub upgrade --major-versions 3 | flutter pub get 4 | dart fix --apply 5 | flutter format lib test 6 | flutter pub run import_sorter:main --no-comments -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /scripts/integration-start-avd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | chmod 777 -R /dev/kvm 3 | adb start-server 4 | emulator -avd test -wipe-data -no-audio -no-boot-anim -no-window -accel on -gpu swiftshader_indirect 5 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingyicute/fluffychat/HEAD/winuwp/runner_uwp/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /devtools_options.yaml: -------------------------------------------------------------------------------- 1 | description: This file stores settings for Dart & Flutter DevTools. 2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states 3 | extensions: 4 | -------------------------------------------------------------------------------- /linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /scripts/integration-create-environment-variables.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export USER1_NAME="alice" 4 | export USER1_PW="AliceInWonderland" 5 | export USER2_NAME="bob" 6 | export USER2_PW="JoWirSchaffenDas" 7 | -------------------------------------------------------------------------------- /android/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | json_key_file("keys.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one 2 | package_name("chat.fluffy.fluffychat") # e.g. com.krausefx.app 3 | -------------------------------------------------------------------------------- /l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/l10n 2 | template-arb-file: intl_en.arb 3 | output-localization-file: l10n.dart 4 | output-class: L10n 5 | preferred-supported-locales: ["en"] 6 | use-deferred-loading: true 7 | nullable-getter: false -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 👬 FluffyChat Community 4 | url: https://matrix.to/#/#fluffychat:matrix.org 5 | about: Please ask and answer questions here. 6 | -------------------------------------------------------------------------------- /scripts/build-olm-windows.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git clone https://gitlab.matrix.org/matrix-org/olm.git -b 3.2.12 4 | cd olm 5 | cmake . -Bbuild -DCMAKE_TOOLCHAIN_FILE=Windows64.cmake 6 | cmake --build build 7 | cd .. 8 | -------------------------------------------------------------------------------- /scripts/prepare-windows.ps1: -------------------------------------------------------------------------------- 1 | choco install flutter cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y 2 | Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" 3 | refreshenv 4 | 5 | flutter config --no-analytics 6 | -------------------------------------------------------------------------------- /scripts/integration-prepare-host.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if ! command -v apk &>/dev/null; then 3 | apt update && apt install -y -qq docker.io ldnsutils grep scrcpy ffmpeg 4 | else 5 | apk update && apk add docker drill grep scrcpy ffmpeg 6 | fi 7 | -------------------------------------------------------------------------------- /appimage/FluffyChat.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Version=1.0 4 | Name=FluffyChat 5 | Comment=Matrix Client. Chat with your friends 6 | Exec=AppRun 7 | Icon=fluffychat 8 | Terminal=false 9 | Categories=Network;Chat;InstantMessaging;X-Matrix; -------------------------------------------------------------------------------- /winuwp/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /docs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: [ 3 | './index.html' 4 | ], 5 | darkMode: false, 6 | theme: { 7 | extend: {}, 8 | }, 9 | variants: { 10 | extend: {}, 11 | }, 12 | plugins: [], 13 | } 14 | -------------------------------------------------------------------------------- /lib/utils/tor_stub.dart: -------------------------------------------------------------------------------- 1 | /// Stub class for [TorBrowserDetector] 2 | /// 3 | /// statically returns false as Tor **browser** can only be detected in a 4 | /// **browser**. 5 | abstract class TorBrowserDetector { 6 | static Future get isTorBrowser => Future.value(false); 7 | } 8 | -------------------------------------------------------------------------------- /scripts/package-windows.ps1: -------------------------------------------------------------------------------- 1 | Write-Output "$WINDOWN_PFX" 2 | Move-Item -Path $WINDOWS_PFX -Destination fluffychat.pem 3 | certutil -decode fluffychat.pem fluffychat.pfx 4 | 5 | flutter pub run msix:create -c fluffychat.pfx -p $WINDOWS_PFX_PASS --sign-msix true --install-certificate false 6 | -------------------------------------------------------------------------------- /snap/gui/fluffychat.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=FluffyChat 3 | GenericName=Matrix Client 4 | Comment=Chat with your friends 5 | Exec=fluffychat 6 | Icon=${SNAP}/meta/gui/fluffychat.png 7 | Terminal=false 8 | Type=Application 9 | Categories=Network;Chat;InstantMessaging; 10 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 17 08:36:03 CET 2025 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /fdroid/config.stable.py: -------------------------------------------------------------------------------- 1 | repo_url = "https://fluffychat.im/repo/stable/repo" 2 | repo_name = "FluffyChat repo" 3 | repo_icon = "fdroid-icon.png" 4 | repo_description = """ 5 | FluffyChat repo 6 | """ 7 | 8 | archive_older = 0 9 | 10 | local_copy_dir = "/fdroid" 11 | 12 | keystore = "key.jks" 13 | repo_keyalias = "key" 14 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /scripts/integration-server-synapse.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker run -d --name synapse --tmpfs /data \ 3 | --volume="$(pwd)/integration_test/synapse/data/homeserver.yaml":/data/homeserver.yaml:rw \ 4 | --volume="$(pwd)/integration_test/synapse/data/localhost.log.config":/data/localhost.log.config:rw \ 5 | -p 80:80 matrixdotorg/synapse:latest 6 | -------------------------------------------------------------------------------- /test/archive_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | testWidgets('Test if the widget can be created', (WidgetTester tester) async { 5 | /*await tester.pumpWidget(FluffyChatApp( 6 | testWidget: Archive(), 7 | testClient: await testClient(loggedIn: true), 8 | ));*/ 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /lib/utils/custom_scroll_behaviour.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/gestures.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class CustomScrollBehavior extends MaterialScrollBehavior { 5 | @override 6 | Set get dragDevices => { 7 | PointerDeviceKind.touch, 8 | PointerDeviceKind.trackpad, 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /config.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "application_name": "FluffyChat", 3 | "application_welcome_message": null, 4 | "default_homeserver": "matrix.org", 5 | "web_base_url": "https://fluffychat.im/web", 6 | "privacy_url": "https://fluffychat.im/en/privacy.html", 7 | "render_html": false, 8 | "hide_redacted_events": false, 9 | "hide_unknown_events": false 10 | } -------------------------------------------------------------------------------- /fdroid/config.nightly.py: -------------------------------------------------------------------------------- 1 | repo_url = "https://fluffychat.im/repo/nightly/repo" 2 | repo_name = "FluffyChat nightly repo" 3 | repo_icon = "fdroid-icon.png" 4 | repo_description = """ 5 | FluffyChat nightly repo 6 | """ 7 | 8 | archive_older = 0 9 | 10 | local_copy_dir = "/fdroid" 11 | 12 | keystore = "key.nightly.jks" 13 | repo_keyalias = "vmd66783.contaboserver.net" 14 | -------------------------------------------------------------------------------- /ios/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier("im.fluffychat.app") # The bundle identifier of your app 2 | apple_id("christian-kussowski@posteo.de") # Your Apple email address 3 | 4 | itc_team_id("122628977") # App Store Connect Team ID 5 | team_id("4NXF6Z997G") # Developer Portal Team ID 6 | 7 | # For more information about the Appfile, see: 8 | # https://docs.fastlane.tools/advanced/#appfile 9 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /winuwp/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /ios/FluffyChat Share/FluffyChat Share.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.im.fluffychat.app 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/utils/color_value.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | extension ColorValue on Color { 4 | int get hexValue { 5 | return _floatToInt8(a) << 24 | 6 | _floatToInt8(r) << 16 | 7 | _floatToInt8(g) << 8 | 8 | _floatToInt8(b) << 0; 9 | } 10 | 11 | static int _floatToInt8(double x) { 12 | return (x * 255.0).round() & 0xff; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | 10 | subprojects { 11 | project.buildDir = "${rootProject.buildDir}/${project.name}" 12 | project.evaluationDependsOn(":app") 13 | } 14 | 15 | tasks.register("clean", Delete) { 16 | delete rootProject.buildDir 17 | } 18 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-night-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /winuwp/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /lib/utils/beautify_string_extension.dart: -------------------------------------------------------------------------------- 1 | extension BeautifyStringExtension on String { 2 | String get beautified { 3 | var beautifiedStr = ''; 4 | for (var i = 0; i < length; i++) { 5 | beautifiedStr += substring(i, i + 1); 6 | if (i % 4 == 3) { 7 | beautifiedStr += ' '; 8 | } 9 | if (i % 16 == 15) { 10 | beautifiedStr += '\n'; 11 | } 12 | } 13 | return beautifiedStr; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scripts/prepare-web.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ve 2 | rm -rf assets/js/package 3 | 4 | OLM_VERSION=$(cat pubspec.yaml | yq .dependencies.flutter_olm) 5 | DOWNLOAD_PATH="https://github.com/famedly/olm/releases/download/v$OLM_VERSION/olm.zip" 6 | 7 | cd assets/js/ && curl -L $DOWNLOAD_PATH > olm.zip && cd ../../ 8 | cd assets/js/ && unzip olm.zip && cd ../../ 9 | cd assets/js/ && rm olm.zip && cd ../../ 10 | cd assets/js/ && mv javascript package && cd ../../ 11 | -------------------------------------------------------------------------------- /scripts/release-ios-testflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ve 2 | git apply ./scripts/enable-android-google-services.patch 3 | yq eval '.dependencies.fcm_shared_isolate = "0.1.0"' -i pubspec.yaml # Workaround: 0.2.0 does not work on iOS 4 | flutter clean 5 | flutter pub get 6 | cd ios 7 | rm -rf Pods 8 | rm -f Podfile.lock 9 | pod install 10 | pod update 11 | cd .. 12 | flutter build ios --release 13 | cd ios 14 | bundle update fastlane 15 | bundle exec fastlane beta 16 | cd .. -------------------------------------------------------------------------------- /web/auth.html: -------------------------------------------------------------------------------- 1 | 2 | Authentication complete 3 |

Authentication is complete. If this does not happen automatically, please close the window.

4 | -------------------------------------------------------------------------------- /lib/pages/settings_chat/settings_chat.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'settings_chat_view.dart'; 4 | 5 | class SettingsChat extends StatefulWidget { 6 | const SettingsChat({super.key}); 7 | 8 | @override 9 | SettingsChatController createState() => SettingsChatController(); 10 | } 11 | 12 | class SettingsChatController extends State { 13 | @override 14 | Widget build(BuildContext context) => SettingsChatView(this); 15 | } 16 | -------------------------------------------------------------------------------- /linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/l10n/intl_te.arb: -------------------------------------------------------------------------------- 1 | { 2 | "alwaysUse24HourFormat": "తప్పుడు", 3 | "@alwaysUse24HourFormat": { 4 | "description": "Set to true to always display time of day in 24 hour format." 5 | }, 6 | "notAnImage": "ఇమేజ్ ఫైల్ కాదు.", 7 | "@notAnImage": {}, 8 | "repeatPassword": "పాస్‌వర్డ్‌ను పునరావృతం చేయండి", 9 | "@repeatPassword": {}, 10 | "remove": "తొలగించు", 11 | "@remove": { 12 | "type": "String", 13 | "placeholders": {} 14 | } 15 | } -------------------------------------------------------------------------------- /lib/config/app_emojis.dart: -------------------------------------------------------------------------------- 1 | abstract class AppEmojis { 2 | static const List emojis = [ 3 | '👍', 4 | '😊', 5 | '😀', 6 | '❤️', 7 | '😍', 8 | '😘', 9 | '😇', 10 | '😅', 11 | '😭', 12 | '😜', 13 | '😱', 14 | '😆', 15 | '😉', 16 | '😡', 17 | '👋', 18 | '🤔', 19 | '🙁', 20 | '🥳', 21 | '😟', 22 | '😄', 23 | '😁', 24 | '🙄', 25 | '😂', 26 | '🤣', 27 | '😌', 28 | '😬', 29 | ]; 30 | } 31 | -------------------------------------------------------------------------------- /scripts/prepare-android-release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd android 3 | echo $FDROID_KEY | base64 --decode --ignore-garbage > key.jks 4 | echo "storePassword=${FDROID_KEY_PASS}" >> key.properties 5 | echo "keyPassword=${FDROID_KEY_PASS}" >> key.properties 6 | echo "keyAlias=key" >> key.properties 7 | echo "storeFile=../key.jks" >> key.properties 8 | echo $PLAYSTORE_DEPLOY_KEY >> keys.json 9 | ls | grep key 10 | bundle install 11 | bundle update fastlane 12 | bundle exec fastlane set_build_code_internal 13 | cd .. 14 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pub" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | allow: 8 | - dependency-name: "*" 9 | commit-message: 10 | prefix: "build: " 11 | include: "scope" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" 16 | allow: 17 | - dependency-name: "*" 18 | commit-message: 19 | prefix: "build: " 20 | include: "scope" 21 | -------------------------------------------------------------------------------- /test/homeserver_picker_test.dart: -------------------------------------------------------------------------------- 1 | //import 'package:fluffychat/pages/homeserver_picker.dart'; 2 | //import 'package:fluffychat/main.dart'; 3 | 4 | import 'package:flutter_test/flutter_test.dart'; 5 | 6 | //import 'utils/test_client.dart'; 7 | 8 | void main() { 9 | testWidgets('Test if the widget can be created', (WidgetTester tester) async { 10 | /*await tester.pumpWidget( 11 | FluffyChatApp( 12 | client: await prepareTestClient(), 13 | testWidget: HomeserverPicker(), 14 | ), 15 | );*/ 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "LaunchImage.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "LaunchImage@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "LaunchImage@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scripts/integration-server-conduit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker run -d \ 3 | -e CONDUIT_SERVER_NAME="localhost" \ 4 | -e CONDUIT_PORT="8008" \ 5 | -e CONDUIT_DATABASE_BACKEND="rocksdb" \ 6 | -e CONDUIT_ALLOW_REGISTRATION=true \ 7 | -e CONDUIT_ALLOW_FEDERATION=true \ 8 | -e CONDUIT_MAX_REQUEST_SIZE="20000000" \ 9 | -e CONDUIT_TRUSTED_SERVERS="[\"conduit.rs\"]" \ 10 | -e CONDUIT_MAX_CONCURRENT_REQUESTS="100" \ 11 | -e CONDUIT_LOG="info,rocket=off,_=off,sled=off" \ 12 | --name conduit -p 80:8008 matrixconduit/matrix-conduit:latest 13 | -------------------------------------------------------------------------------- /winuwp/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | set(PLUGIN_BUNDLED_LIBRARIES) 9 | 10 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 11 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 12 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 13 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 14 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 15 | endforeach(plugin) 16 | -------------------------------------------------------------------------------- /ios/Runner/Runner.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | com.apple.developer.associated-domains 8 | 9 | applinks:example.com 10 | 11 | com.apple.security.application-groups 12 | 13 | group.im.fluffychat.app 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ios/FluffyChat Share/ShareViewController.swift: -------------------------------------------------------------------------------- 1 | // If you get no such module 'receive_sharing_intent' error. 2 | // Go to Build Phases of your Runner target and 3 | // move `Embed Foundation Extension` to the top of `Thin Binary`. 4 | import receive_sharing_intent 5 | 6 | class ShareViewController: RSIShareViewController { 7 | 8 | // Use this method to return false if you don't want to redirect to host app automatically. 9 | // Default is true 10 | override func shouldAutoRedirect() -> Bool { 11 | return false 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | if #available(iOS 10.0, *) { 12 | UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate 13 | } 14 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /integration_test/synapse/data/localhost.log.config: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | formatters: 4 | precise: 5 | format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' 6 | 7 | handlers: 8 | 9 | 10 | console: 11 | class: logging.StreamHandler 12 | formatter: precise 13 | 14 | loggers: 15 | synapse.storage.SQL: 16 | # beware: increasing this to DEBUG will make synapse log sensitive 17 | # information such as access tokens. 18 | level: INFO 19 | 20 | root: 21 | level: INFO 22 | 23 | 24 | handlers: [console] 25 | 26 | 27 | disable_existing_loggers: false -------------------------------------------------------------------------------- /scripts/prepare-fdroid.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cp -r android/fastlane fdroid/metadata/chat.fluffy.fluffychat 4 | cd fdroid 5 | echo $FDROID_KEY | base64 --decode --ignore-garbage > key.jks 6 | echo $FDROID_NIGHTLY_KEY | base64 --decode --ignore-garbage > key.nightly.jks 7 | echo "keypass=\"${FDROID_KEY_PASS}\"" >> config.stable.py 8 | echo "keystorepass=\"${FDROID_KEY_PASS}\"" >> config.stable.py 9 | echo "keypass=\"${FDROID_NIGHTLY_KEY_PASS}\"" >> config.nightly.py 10 | echo "keystorepass=\"${FDROID_NIGHTLY_KEY_PASS}\"" >> config.nightly.py 11 | chmod 600 config.stable.py key.jks config.nightly.py key.nightly.jks 12 | cd .. 13 | -------------------------------------------------------------------------------- /scripts/integration-server-dendrite.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | chown -R 991:991 integration_test/dendrite 3 | 4 | # creating integration test SSL certificates 5 | docker run --rm --entrypoint="" \ 6 | --volume="$(pwd)/integration_test/dendrite/data":/mnt:rw \ 7 | matrixdotorg/dendrite-monolith:latest \ 8 | /usr/bin/generate-keys \ 9 | -private-key /mnt/matrix_key.pem \ 10 | -tls-cert /mnt/server.crt \ 11 | -tls-key /mnt/server.key 12 | 13 | docker run -d --volume="$(pwd)/integration_test/dendrite/data":/etc/dendrite:rw \ 14 | --name dendrite -p 80:8008 matrixdotorg/dendrite-monolith:latest -really-enable-open-registration 15 | -------------------------------------------------------------------------------- /android/fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /appimage/README.md: -------------------------------------------------------------------------------- 1 | # FluffyChat AppImage 2 | 3 | FluffyChat is provided as AppImage too. To Download, visit fluffychat.im. 4 | 5 | ## Building 6 | 7 | - Ensure you install `appimagetool` 8 | 9 | ```shell 10 | flutter build linux 11 | 12 | # copy binaries to appimage dir 13 | cp -r build/linux/{x64,arm64}/release/bundle appimage/FluffyChat.AppDir 14 | cd appimage 15 | 16 | # prepare AppImage files 17 | cp FluffyChat.desktop FluffyChat.AppDir/ 18 | mkdir -p FluffyChat.AppDir/usr/share/icons 19 | cp ../assets/logo.svg FluffyChat.AppDir/fluffychat.svg 20 | cp AppRun FluffyChat.AppDir 21 | 22 | # build the AppImage 23 | appimagetool FluffyChat.AppDir 24 | ``` 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/cirruslabs/flutter as builder 2 | RUN sudo apt update && sudo apt install curl wget jq -y 3 | 4 | WORKDIR /tmp 5 | RUN wget https://github.com/mikefarah/yq/releases/download/v4.40.5/yq_linux_amd64.tar.gz 6 | RUN tar -xzvf ./yq_linux_amd64.tar.gz 7 | RUN mv yq_linux_amd64 /usr/bin/yq 8 | 9 | COPY . /app 10 | WORKDIR /app 11 | RUN ./scripts/prepare-web.sh 12 | COPY config.* /app/ 13 | RUN flutter pub get 14 | RUN flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --release --source-maps 15 | 16 | FROM docker.io/nginx:alpine 17 | RUN rm -rf /usr/share/nginx/html 18 | COPY --from=builder /app/build/web /usr/share/nginx/html 19 | -------------------------------------------------------------------------------- /lib/utils/file_description.dart: -------------------------------------------------------------------------------- 1 | import 'package:matrix/matrix.dart'; 2 | 3 | extension FileDescriptionExtension on Event { 4 | String? get fileDescription { 5 | if (!{ 6 | MessageTypes.File, 7 | MessageTypes.Image, 8 | }.contains(messageType)) { 9 | return null; 10 | } 11 | final formattedBody = content.tryGet('formatted_body'); 12 | if (formattedBody != null) return formattedBody; 13 | 14 | final filename = content.tryGet('filename'); 15 | final body = content.tryGet('body'); 16 | if (filename != body && body != null && filename != null) return body; 17 | return null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /lib/utils/size_string.dart: -------------------------------------------------------------------------------- 1 | extension SizeString on num { 2 | String get sizeString { 3 | var size = toDouble(); 4 | if (size < 1000) { 5 | return '${size.round()} Bytes'; 6 | } 7 | if (size < 1000 * 1000) { 8 | size = size / 1000; 9 | size = (size * 10).round() / 10; 10 | return '${size.toString()} KB'; 11 | } 12 | if (size < 1000 * 1000 * 1000) { 13 | size = size / 1000000; 14 | size = (size * 10).round() / 10; 15 | return '${size.toString()} MB'; 16 | } 17 | size = size / 1000 * 1000 * 1000 * 1000; 18 | size = (size * 10).round() / 10; 19 | return '${size.toString()} GB'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/utils/other_party_can_receive.dart: -------------------------------------------------------------------------------- 1 | import 'package:matrix/matrix.dart'; 2 | 3 | extension OtherPartyCanReceiveExtension on Room { 4 | bool get otherPartyCanReceiveMessages { 5 | if (!encrypted) return true; 6 | final users = getParticipants() 7 | .map((u) => u.id) 8 | .where((userId) => userId != client.userID) 9 | .toSet(); 10 | if (users.isEmpty) return true; 11 | 12 | for (final userId in users) { 13 | if (client.userDeviceKeys[userId]?.deviceKeys.values.isNotEmpty == true) { 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | } 20 | 21 | class OtherPartyCanNotReceiveMessages implements Exception {} 22 | -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = FluffyChat 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = im.fluffychat.fluffychat 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2023 FluffyChat authors. All rights reserved. 15 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FluffyChat", 3 | "short_name": "FluffyChat", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "The cutest messenger in the Matrix network", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | build/ 28 | 29 | # Exceptions to above rules. 30 | !default.mode1v3 31 | !default.mode2v3 32 | !default.pbxuser 33 | !default.perspectivev3 34 | -------------------------------------------------------------------------------- /lib/pages/settings_multiple_emotes/settings_multiple_emotes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:go_router/go_router.dart'; 4 | 5 | import 'settings_multiple_emotes_view.dart'; 6 | 7 | class MultipleEmotesSettings extends StatefulWidget { 8 | const MultipleEmotesSettings({super.key}); 9 | 10 | @override 11 | MultipleEmotesSettingsController createState() => 12 | MultipleEmotesSettingsController(); 13 | } 14 | 15 | class MultipleEmotesSettingsController extends State { 16 | String? get roomId => GoRouterState.of(context).pathParameters['roomid']; 17 | @override 18 | Widget build(BuildContext context) => MultipleEmotesSettingsView(this); 19 | } 20 | -------------------------------------------------------------------------------- /lib/utils/voip/user_media_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:just_audio/just_audio.dart'; 2 | 3 | class UserMediaManager { 4 | factory UserMediaManager() { 5 | return _instance; 6 | } 7 | 8 | UserMediaManager._internal(); 9 | 10 | static final UserMediaManager _instance = UserMediaManager._internal(); 11 | 12 | AudioPlayer? _assetsAudioPlayer; 13 | 14 | Future startRingingTone() async { 15 | const path = 'assets/sounds/phone.ogg'; 16 | final player = _assetsAudioPlayer = AudioPlayer(); 17 | player.setAsset(path); 18 | player.play(); 19 | 20 | return; 21 | } 22 | 23 | Future stopRingingTone() async { 24 | await _assetsAudioPlayer?.stop(); 25 | _assetsAudioPlayer = null; 26 | return; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | //import 'package:fluffychat/main.dart'; 9 | 10 | import 'package:flutter_test/flutter_test.dart'; 11 | 12 | //import 'utils/test_client.dart'; 13 | 14 | void main() { 15 | testWidgets('Test if the app starts', (WidgetTester tester) async { 16 | /* await tester.pumpWidget(FluffyChatApp( 17 | client: await prepareTestClient(), 18 | ));*/ 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /ios/fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.assets.pictures.read-only 8 | 9 | com.apple.security.device.audio-input 10 | 11 | com.apple.security.device.camera 12 | 13 | com.apple.security.files.user-selected.read-write 14 | 15 | com.apple.security.network.client 16 | 17 | com.apple.security.personal-information.location 18 | 19 | keychain-access-groups 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: krille 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: KrilleChritzelius 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /lib/utils/event_checkbox_extension.dart: -------------------------------------------------------------------------------- 1 | import 'package:matrix/matrix.dart'; 2 | 3 | extension EventCheckboxRoomExtension on Room { 4 | static const String relationshipType = 'im.fluffychat.checkboxes'; 5 | Future checkCheckbox( 6 | String eventId, 7 | int checkboxId, { 8 | String? txid, 9 | }) => 10 | sendEvent( 11 | { 12 | 'm.relates_to': { 13 | 'rel_type': relationshipType, 14 | 'event_id': eventId, 15 | 'checkbox_id': checkboxId, 16 | }, 17 | }, 18 | type: EventTypes.Reaction, 19 | txid: txid, 20 | ); 21 | } 22 | 23 | extension EventCheckboxExtension on Event { 24 | int? get checkedCheckboxId => content 25 | .tryGetMap('m.relates_to') 26 | ?.tryGet('checkbox_id'); 27 | } 28 | -------------------------------------------------------------------------------- /web/splash/style.css: -------------------------------------------------------------------------------- 1 | body, 2 | html { 3 | margin: 0; 4 | height: 100%; 5 | background: #ffffff; 6 | background-size: 100% 100%; 7 | } 8 | 9 | .center { 10 | margin: 0; 11 | position: absolute; 12 | top: 50%; 13 | left: 50%; 14 | -ms-transform: translate(-50%, -50%); 15 | transform: translate(-50%, -50%); 16 | } 17 | 18 | .contain { 19 | display: block; 20 | width: 100%; 21 | height: 100%; 22 | object-fit: contain; 23 | } 24 | 25 | .stretch { 26 | display: block; 27 | width: 100%; 28 | height: 100%; 29 | } 30 | 31 | .cover { 32 | display: block; 33 | width: 100%; 34 | height: 100%; 35 | object-fit: cover; 36 | } 37 | 38 | @media (prefers-color-scheme: dark) { 39 | body { 40 | margin: 0; 41 | height: 100%; 42 | background: #000000; 43 | background-size: 100% 100%; 44 | } 45 | } -------------------------------------------------------------------------------- /integration_test/users.dart: -------------------------------------------------------------------------------- 1 | abstract class Users { 2 | const Users._(); 3 | 4 | static const user1 = User( 5 | String.fromEnvironment( 6 | 'USER1_NAME', 7 | defaultValue: 'alice', 8 | ), 9 | String.fromEnvironment( 10 | 'USER1_PW', 11 | defaultValue: 'AliceInWonderland', 12 | ), 13 | ); 14 | static const user2 = User( 15 | String.fromEnvironment( 16 | 'USER2_NAME', 17 | defaultValue: 'bob', 18 | ), 19 | String.fromEnvironment( 20 | 'USER2_PW', 21 | defaultValue: 'JoWirSchaffenDas', 22 | ), 23 | ); 24 | } 25 | 26 | class User { 27 | final String name; 28 | final String password; 29 | 30 | const User(this.name, this.password); 31 | } 32 | 33 | const homeserver = 'http://${String.fromEnvironment( 34 | 'HOMESERVER', 35 | defaultValue: 'localhost', 36 | )}'; 37 | -------------------------------------------------------------------------------- /test/command_hint_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:flutter_test/flutter_test.dart'; 5 | 6 | import 'utils/test_client.dart'; 7 | 8 | void main() async { 9 | test('Check for missing /command hints', () async { 10 | final translated = 11 | jsonDecode(File('lib/l10n/intl_en.arb').readAsStringSync()) 12 | .keys 13 | .where((String k) => k.startsWith('commandHint_')) 14 | .map((k) => k.replaceFirst('commandHint_', '')); 15 | final commands = (await prepareTestClient()).commands.keys; 16 | final missing = commands.where((c) => !translated.contains(c)).toList(); 17 | 18 | expect( 19 | 0, 20 | missing.length, 21 | reason: 22 | 'missing hints for $missing\nAdding hints? See scripts/generate_command_hints_glue.sh', 23 | ); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /lib/widgets/hover_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class HoverBuilder extends StatefulWidget { 4 | final Widget Function(BuildContext context, bool hovered) builder; 5 | const HoverBuilder({required this.builder, super.key}); 6 | 7 | @override 8 | State createState() => _HoverBuilderState(); 9 | } 10 | 11 | class _HoverBuilderState extends State { 12 | bool hovered = false; 13 | @override 14 | Widget build(BuildContext context) { 15 | return MouseRegion( 16 | onEnter: (_) => hovered 17 | ? null 18 | : setState(() { 19 | hovered = true; 20 | }), 21 | onExit: (_) => !hovered 22 | ? null 23 | : setState(() { 24 | hovered = false; 25 | }), 26 | child: widget.builder(context, hovered), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/utils/custom_http_client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:http/http.dart' as http; 5 | import 'package:http/io_client.dart'; 6 | 7 | import 'package:fluffychat/config/isrg_x1.dart'; 8 | 9 | class CustomHttpClient { 10 | static HttpClient customHttpClient(String? cert) { 11 | final context = SecurityContext.defaultContext; 12 | 13 | try { 14 | if (cert != null) { 15 | final bytes = utf8.encode(cert); 16 | context.setTrustedCertificatesBytes(bytes); 17 | } 18 | } on TlsException catch (e) { 19 | if (e.osError != null && 20 | e.osError!.message.contains('CERT_ALREADY_IN_HASH_TABLE')) { 21 | } else { 22 | rethrow; 23 | } 24 | } 25 | 26 | return HttpClient(context: context); 27 | } 28 | 29 | static http.Client createHTTPClient() => IOClient(customHttpClient(ISRG_X1)); 30 | } 31 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.assets.pictures.read-only 8 | 9 | com.apple.security.cs.allow-jit 10 | 11 | com.apple.security.device.audio-input 12 | 13 | com.apple.security.device.camera 14 | 15 | com.apple.security.files.user-selected.read-write 16 | 17 | com.apple.security.network.client 18 | 19 | com.apple.security.network.server 20 | 21 | com.apple.security.personal-information.location 22 | 23 | keychain-access-groups 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/chat/fluffy/fluffychat/UnifiedPushService.kt: -------------------------------------------------------------------------------- 1 | package chat.fluffy.fluffychat 2 | 3 | import io.flutter.embedding.engine.FlutterEngine 4 | import io.flutter.embedding.engine.dart.DartExecutor 5 | import org.unifiedpush.flutter.connector.UnifiedPushReceiver 6 | 7 | import android.content.Context 8 | 9 | class UnifiedPushReceiver : UnifiedPushReceiver() { 10 | override fun getEngine(context: Context): FlutterEngine { 11 | var engine = MainActivity.engine 12 | if (engine == null) { 13 | engine = MainActivity.provideEngine(context) 14 | engine.localizationPlugin.sendLocalesToFlutter( 15 | context.resources.configuration 16 | ) 17 | engine.dartExecutor.executeDartEntrypoint( 18 | DartExecutor.DartEntrypoint.createDefault() 19 | ) 20 | } 21 | return engine 22 | } 23 | } -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.7.3" apply false 22 | id "org.jetbrains.kotlin.android" version "2.1.10" apply false 23 | // id "com.google.gms.google-services" version "4.3.8" apply false 24 | } 25 | 26 | include ":app" -------------------------------------------------------------------------------- /ios/fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | ``` 13 | [sudo] gem install fastlane -NV 14 | ``` 15 | or alternatively using `brew install fastlane` 16 | 17 | # Available Actions 18 | ### release 19 | ``` 20 | fastlane release 21 | ``` 22 | 23 | 24 | ---- 25 | 26 | ## iOS 27 | ### ios beta 28 | ``` 29 | fastlane ios beta 30 | ``` 31 | Push a new beta build to TestFlight 32 | 33 | ---- 34 | 35 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 36 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 37 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 38 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/utils/string_color.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension StringColor on String { 4 | static final _colorCache = >{}; 5 | 6 | Color _getColorLight(double light) { 7 | var number = 0.0; 8 | for (var i = 0; i < length; i++) { 9 | number += codeUnitAt(i); 10 | } 11 | number = (number % 12) * 25.5; 12 | return HSLColor.fromAHSL(0.75, number, 1, light).toColor(); 13 | } 14 | 15 | Color get color { 16 | _colorCache[this] ??= {}; 17 | return _colorCache[this]![0.3] ??= _getColorLight(0.3); 18 | } 19 | 20 | Color get darkColor { 21 | _colorCache[this] ??= {}; 22 | return _colorCache[this]![0.2] ??= _getColorLight(0.2); 23 | } 24 | 25 | Color get lightColorText { 26 | _colorCache[this] ??= {}; 27 | return _colorCache[this]![0.7] ??= _getColorLight(0.7); 28 | } 29 | 30 | Color get lightColorAvatar { 31 | _colorCache[this] ??= {}; 32 | return _colorCache[this]![0.45] ??= _getColorLight(0.45); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scripts/integration-check-release-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # generate a temporary signing key adn apply its configuration 4 | cd android 5 | KEYFILE="$(pwd)/key.jks" 6 | echo "Generating signing configuration with $KEYFILE..." 7 | keytool -genkey -keyalg RSA -alias key -keysize 4096 -dname "cn=FluffyChat CI, ou=Head of bad integration tests, o=FluffyChat HQ, c=TLH" -keypass FLUFFYCHAT -storepass FLUFFYCHAT -validity 1 -keystore "$KEYFILE" -storetype "pkcs12" 8 | echo "storePassword=FLUFFYCHAT" >> key.properties 9 | echo "keyPassword=FLUFFYCHAT" >> key.properties 10 | echo "keyAlias=key" >> key.properties 11 | echo "storeFile=$KEYFILE" >> key.properties 12 | ls | grep key 13 | cd .. 14 | 15 | # build release mode APK 16 | flutter pub get 17 | flutter build apk --release 18 | 19 | # install and launch APK 20 | flutter install 21 | adb shell am start -n chat.fluffy.fluffychat/chat.fluffy.fluffychat.MainActivity 22 | 23 | sleep 5 24 | 25 | # check whether FluffyChat runs 26 | adb shell ps | awk '{print $9}' | grep chat.fluffy.fluffychat 27 | -------------------------------------------------------------------------------- /lib/utils/sync_status_localization.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:matrix/matrix.dart'; 4 | 5 | import 'package:fluffychat/l10n/l10n.dart'; 6 | import 'package:fluffychat/utils/localized_exception_extension.dart'; 7 | 8 | extension SyncStatusLocalization on SyncStatusUpdate { 9 | String calcLocalizedString(BuildContext context) { 10 | final progress = this.progress; 11 | switch (status) { 12 | case SyncStatus.waitingForResponse: 13 | return L10n.of(context).waitingForServer; 14 | case SyncStatus.error: 15 | return ((error?.exception ?? Object()) as Object) 16 | .toLocalizedString(context); 17 | case SyncStatus.processing: 18 | case SyncStatus.cleaningUp: 19 | case SyncStatus.finished: 20 | return progress == null 21 | ? L10n.of(context).synchronizingPleaseWait 22 | : L10n.of(context).synchronizingPleaseWaitCounter( 23 | (progress * 100).round().toString(), 24 | ); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "winrt/Windows.ApplicationModel.Core.h" 5 | #include "winrt/Windows.Foundation.h" 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "flutter_frameworkview.cpp" 13 | 14 | struct App 15 | : winrt::implements< 16 | App, winrt::Windows::ApplicationModel::Core::IFrameworkViewSource> { 17 | App() { view_ = winrt::make_self(); } 18 | 19 | // |winrt::Windows::ApplicationModel::Core::IFrameworkViewSource| 20 | winrt::Windows::ApplicationModel::Core::IFrameworkView CreateView() { 21 | return view_.as(); 22 | } 23 | 24 | winrt::com_ptr view_; 25 | }; 26 | 27 | int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { 28 | winrt::Windows::ApplicationModel::Core::CoreApplication::Run( 29 | winrt::make()); 30 | } 31 | -------------------------------------------------------------------------------- /scripts/generate-locale-config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Directory containing the ARB files 4 | l10n_dir="./lib/l10n" 5 | # Target directory for the locale_config.xml file 6 | xml_dir="./android/app/src/main/res/xml" 7 | 8 | # Create the target directory if it does not exist 9 | mkdir -p "$xml_dir" 10 | 11 | # Output file name 12 | xml_file="$xml_dir/locale_config.xml" 13 | 14 | rm -rf "$xml_file" 15 | 16 | # XML Header 17 | echo '' > "$xml_file" 18 | echo '' >> "$xml_file" 19 | 20 | # Search for ARB files and extract language codes 21 | for file in "$l10n_dir"/intl_*.arb; do 22 | # Extract language code 23 | language_code=$(basename "$file" | cut -d'_' -f2 | cut -d'.' -f1) 24 | # Write language code to the XML file 25 | echo " " >> "$xml_file" 26 | done 27 | 28 | # XML Footer 29 | echo '' >> "$xml_file" 30 | 31 | echo "locale_config.xml file has been successfully created in the $xml_dir directory." 32 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "generator": "Visual Studio 15 2017 Win64", 7 | "configurationType": "Debug", 8 | "inheritEnvironments": [ "msvc_x64_x64" ], 9 | "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", 10 | "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", 11 | "cmakeCommandArgs": "", 12 | "buildCommandArgs": "", 13 | "ctestCommandArgs": "" 14 | }, 15 | { 16 | "name": "Release", 17 | "generator": "Visual Studio 15 2017 Win64", 18 | "configurationType": "Release", 19 | "inheritEnvironments": [ "msvc_x64_x64" ], 20 | "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", 21 | "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", 22 | "cmakeCommandArgs": "", 23 | "buildCommandArgs": "", 24 | "ctestCommandArgs": "" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "abb292a07e20d696c4568099f918f6c5f330e6b0" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 17 | base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 18 | - platform: linux 19 | create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 20 | base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /lib/widgets/layouts/empty_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class EmptyPage extends StatelessWidget { 6 | static const double _width = 400; 7 | const EmptyPage({super.key}); 8 | @override 9 | Widget build(BuildContext context) { 10 | final width = min(MediaQuery.of(context).size.width, EmptyPage._width) / 2; 11 | final theme = Theme.of(context); 12 | return Scaffold( 13 | // Add invisible appbar to make status bar on Android tablets bright. 14 | appBar: AppBar( 15 | automaticallyImplyLeading: false, 16 | elevation: 0, 17 | backgroundColor: Colors.transparent, 18 | ), 19 | extendBodyBehindAppBar: true, 20 | body: Container( 21 | alignment: Alignment.center, 22 | child: Image.asset( 23 | 'assets/logo_transparent.png', 24 | color: theme.colorScheme.surfaceContainerHigh, 25 | width: width, 26 | height: width, 27 | filterQuality: FilterQuality.medium, 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | *Thank you so much for your contribution to FluffyChat ❤️❤️❤️* 2 | 3 | Please make sure that your Pull Request meet the following **acceptance criteria**: 4 | 5 | - [ ] Code formatting and import sorting has been done with `dart format lib/ test/` and `dart run import_sorter:main --no-comments` 6 | - [ ] The commit message uses the format of [Conventional Commits](https://www.conventionalcommits.org) 7 | - [ ] The commit message describes what has been changed, why it has been changed and how it has been changed 8 | - [ ] Every new feature or change of the design/GUI is linked to an approved design proposal in an issue 9 | - [ ] Every new feature in the app or the build system has a strategy how this will be tested and maintained from now on for every release, e.g. a volunteer who takes over maintainership 10 | 11 | 12 | ### Pull Request has been tested on: 13 | 14 | - [ ] Android 15 | - [ ] iOS 16 | - [ ] Browser (Chromium based) 17 | - [ ] Browser (Firefox based) 18 | - [ ] Browser (WebKit based) 19 | - [ ] Desktop Linux 20 | - [ ] Desktop Windows 21 | - [ ] Desktop macOS -------------------------------------------------------------------------------- /android/app/src/main/kotlin/chat/fluffy/fluffychat/FcmPushService.kt: -------------------------------------------------------------------------------- 1 | /*package chat.fluffy.fluffychat 2 | 3 | import com.famedly.fcm_shared_isolate.FcmSharedIsolateService 4 | 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint 7 | import android.content.Context 8 | 9 | class FcmPushService : FcmSharedIsolateService() { 10 | override fun getEngine(): FlutterEngine { 11 | return provideEngine(getApplicationContext()) 12 | } 13 | 14 | companion object { 15 | fun provideEngine(context: Context): FlutterEngine { 16 | var engine = MainActivity.engine 17 | if (engine == null) { 18 | engine = MainActivity.provideEngine(context) 19 | engine.getLocalizationPlugin().sendLocalesToFlutter( 20 | context.getResources().getConfiguration()) 21 | engine.getDartExecutor().executeDartEntrypoint( 22 | DartEntrypoint.createDefault()) 23 | } 24 | return engine 25 | } 26 | } 27 | } 28 | */ -------------------------------------------------------------------------------- /android/app/src/main/kotlin/chat/fluffy/fluffychat/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package chat.fluffy.fluffychat 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | import io.flutter.embedding.engine.FlutterEngine 5 | 6 | import android.content.Context 7 | import androidx.multidex.MultiDex 8 | 9 | class MainActivity : FlutterActivity() { 10 | 11 | override fun attachBaseContext(base: Context) { 12 | super.attachBaseContext(base) 13 | MultiDex.install(this) 14 | } 15 | 16 | 17 | override fun provideFlutterEngine(context: Context): FlutterEngine? { 18 | return provideEngine(this) 19 | } 20 | 21 | override fun configureFlutterEngine(flutterEngine: FlutterEngine) { 22 | // do nothing, because the engine was been configured in provideEngine 23 | } 24 | 25 | companion object { 26 | var engine: FlutterEngine? = null 27 | fun provideEngine(context: Context): FlutterEngine { 28 | val eng = engine ?: FlutterEngine(context, emptyArray(), true, false) 29 | engine = eng 30 | return eng 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/l10n/intl_da.arb: -------------------------------------------------------------------------------- 1 | { 2 | "repeatPassword": "Gentag password", 3 | "@repeatPassword": {}, 4 | "notAnImage": "Ikke en billedfil.", 5 | "@notAnImage": {}, 6 | "setCustomPermissionLevel": "Indstil særligt tilladelsesniveau", 7 | "@setCustomPermissionLevel": {}, 8 | "setPermissionsLevelDescription": "Vælg en prædefineret rolle herunder eller indtaste et særligt tilladelsesniveau mellem 0 og 100.", 9 | "@setPermissionsLevelDescription": {}, 10 | "ignoreUser": "Ignorér bruger", 11 | "@ignoreUser": {}, 12 | "remove": "Fjern", 13 | "@remove": { 14 | "type": "String", 15 | "placeholders": {} 16 | }, 17 | "importNow": "Importer nu", 18 | "@importNow": {}, 19 | "importEmojis": "Importer emojis", 20 | "@importEmojis": {}, 21 | "normalUser": "Normal bruger", 22 | "@normalUser": {}, 23 | "importFromZipFile": "Importer fra .zip fil", 24 | "@importFromZipFile": {}, 25 | "alwaysUse24HourFormat": "true", 26 | "@alwaysUse24HourFormat": { 27 | "description": "Set to true to always display time of day in 24 hour format." 28 | } 29 | } -------------------------------------------------------------------------------- /android/fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | FluffyChat is an open, nonprofit and cute Matrix messenger app for Ubuntu Touch, Android and iOS. 2 | 3 | Open 4 | Opensource and open development where everyone can join. 5 | 6 | Nonprofit 7 | FluffyChat is donation funded. 8 | 9 | Cute ♥ 10 | Cute design and many theme settings including a dark mode. 11 | 12 | One-to-one and group chats 13 | Unlimited groups and direct chats. 14 | 15 | Easy 16 | FluffyChat is made as simple to use as possible. 17 | 18 | Free 19 | Free to use for everyone without ads. 20 | 21 | Decentralized 22 | There is no "FluffyChat server" you are forced to use. Use the server you find trustworthy or host your own. 23 | 24 | Compatible 25 | Compatible with Element, Fractal, Nheko and all Matrix messengers. 26 | 27 | 28 | FluffyChat comes with a dream 29 | 30 | Imagine a world where everyone can choose the messenger they like and is still able to chat with all of their friends. 31 | A world where there are no companies spying on you when you send selfies to friends and your loved. 32 | And a world where apps are made for fluffyness and not for profit. ♥ 33 | -------------------------------------------------------------------------------- /licenses.yaml: -------------------------------------------------------------------------------- 1 | # This is a config for a license compliance checker script. It runs in CI. 2 | # 3 | # To run locally: 4 | # dart run license_checker check-licenses -c licenses.yaml --problematic 5 | # 6 | # SPDX license list: https://spdx.org/licenses/ 7 | 8 | # Before you add a license here: Is it free software? Is it compatible with AGPL-3.0? 9 | permittedLicenses: 10 | - AGPL-3.0 11 | - Apache-2.0 12 | - BSD-2-Clause 13 | - BSD-3-Clause 14 | - EUPL-1.2 15 | - LGPL-3.0 16 | - MIT 17 | - MPL-2.0 18 | - Zlib 19 | 20 | packageLicenseOverride: 21 | dependency_validator: Apache-2.0 22 | flutter_gen: MIT 23 | hive: Apache-2.0 24 | hive_flutter: Apache-2.0 25 | latlong2: Apache-2.0 26 | platform_detect: Apache-2.0 27 | rxdart: Apache-2.0 28 | flutter_new_badger: MIT 29 | 30 | # flutter's internal packages 31 | flutter_driver: BSD-3-Clause 32 | flutter_localizations: BSD-3-Clause 33 | flutter_test: BSD-3-Clause 34 | flutter_web_plugins: BSD-3-Clause 35 | fuchsia_remote_debug_protocol: BSD-3-Clause 36 | integration_test: BSD-3-Clause 37 | sky_engine: BSD-3-Clause 38 | 39 | rejectedLicenses: 40 | - BUSL-1.1 41 | -------------------------------------------------------------------------------- /scripts/generate_command_hints_glue.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Generates some glue code for translation of /command hints. 3 | 4 | # How to use this: 5 | # - Add any new hints to assets/l10n/intl_en.arb 6 | # They must be of the form commandHint_ with in lowercase. 7 | # - Run this script to regenerate the glue code 8 | # - Run flutter test to see if you did everything right 9 | 10 | # Looking to add descriptions for a new command, but don't know what it does? 11 | # It is likely defined here (in registerDefaultCommands()): 12 | # https://gitlab.com/famedly/company/frontend/famedlysdk/-/blob/main/lib/src/utils/commands_extension.dart 13 | 14 | echo "\ 15 | // This file is auto-generated using scripts/generate_command_hints_glue.sh. 16 | 17 | import 'package:flutter_gen/gen_l10n/l10n.dart'; 18 | 19 | String commandHint(L10n l10n, String command) { 20 | switch (command) { 21 | $(sed -n \ 22 | 's/[[:blank:]]*\"\(commandHint_\([[:lower:]]*\)\)\".*/ case "\2":\ 23 | return l10n.\1;/p' \ 24 | lib/l10n/intl_en.arb 25 | ) 26 | default: 27 | return \"\"; 28 | } 29 | }\ 30 | " > lib/pages/chat/command_hints.dart 31 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 19 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tailwind Toolbox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | desktop_drop 7 | dynamic_color 8 | emoji_picker_flutter 9 | file_selector_linux 10 | flutter_secure_storage_linux 11 | flutter_webrtc 12 | gtk 13 | handy_window 14 | pasteboard 15 | record_linux 16 | sqlcipher_flutter_libs 17 | url_launcher_linux 18 | window_to_front 19 | ) 20 | 21 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 22 | ) 23 | 24 | set(PLUGIN_BUNDLED_LIBRARIES) 25 | 26 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 27 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 28 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 29 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 30 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 31 | endforeach(plugin) 32 | 33 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 34 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 35 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 36 | endforeach(ffi_plugin) 37 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "background.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "filename" : "darkbackground.png", 16 | "idiom" : "universal", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "appearances" : [ 25 | { 26 | "appearance" : "luminosity", 27 | "value" : "dark" 28 | } 29 | ], 30 | "idiom" : "universal", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "universal", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "dark" 42 | } 43 | ], 44 | "idiom" : "universal", 45 | "scale" : "3x" 46 | } 47 | ], 48 | "info" : { 49 | "author" : "xcode", 50 | "version" : 1 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 💡 Feature Request 2 | description: Suggest an idea for this project 3 | labels: enhancement 4 | body: 5 | - type: textarea 6 | id: feature-description 7 | attributes: 8 | label: "Feature Description" 9 | description: "Provide a clear and concise description of the feature." 10 | placeholder: "Describe the feature here..." 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: rationale 15 | attributes: 16 | label: "Rationale" 17 | description: "Explain why this feature should be added." 18 | placeholder: "Describe the rationale for the feature here..." 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: mockup 23 | attributes: 24 | label: "Mockup" 25 | description: "If applicable, add any visual mock-ups of the feature." 26 | validations: 27 | required: false 28 | - type: textarea 29 | id: additional-context 30 | attributes: 31 | label: "Additional Context" 32 | description: "Add any other context or screenshots about the feature request here." 33 | validations: 34 | required: false 35 | -------------------------------------------------------------------------------- /lib/widgets/layouts/two_column_layout.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:fluffychat/config/themes.dart'; 4 | 5 | class TwoColumnLayout extends StatelessWidget { 6 | final Widget mainView; 7 | final Widget sideView; 8 | 9 | const TwoColumnLayout({ 10 | super.key, 11 | required this.mainView, 12 | required this.sideView, 13 | }); 14 | @override 15 | Widget build(BuildContext context) { 16 | final theme = Theme.of(context); 17 | 18 | return ScaffoldMessenger( 19 | child: Scaffold( 20 | body: Row( 21 | children: [ 22 | Container( 23 | clipBehavior: Clip.antiAlias, 24 | decoration: const BoxDecoration(), 25 | width: FluffyThemes.columnWidth + FluffyThemes.navRailWidth, 26 | child: mainView, 27 | ), 28 | Container( 29 | width: 1.0, 30 | color: theme.dividerColor, 31 | ), 32 | Expanded( 33 | child: ClipRRect( 34 | child: sideView, 35 | ), 36 | ), 37 | ], 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_pr_management.yml: -------------------------------------------------------------------------------- 1 | name: Close Inactive Issues And PRs 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/stale@v9 14 | with: 15 | days-before-issue-stale: 365 16 | days-before-issue-close: 14 17 | stale-issue-label: "stale" 18 | stale-issue-message: "This issue is stale because it has been open for 365 days with no activity." 19 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." 20 | stale-pr-message: "This pull request is stale because it has been open for 365 days with no activity." 21 | close-pr-message: "This pull request was closed because it has been inactive for 14 days since being marked as stale." 22 | days-before-pr-stale: 365 23 | days-before-pr-close: 14 24 | exempt-milestones: true 25 | exempt-assignees: krille-chan 26 | operations-per-run: 500 27 | repo-token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/check_duplicates.yaml: -------------------------------------------------------------------------------- 1 | name: Check duplicates 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | jobs: 8 | check_duplicates: 9 | runs-on: ubuntu-latest 10 | env: 11 | title: ${{ github.event.issue.title }} 12 | author: ${{ github.event.issue.user.login }} 13 | number: ${{ github.event.issue.number }} 14 | GH_TOKEN: ${{ github.token }} 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Check duplicates 18 | run: | 19 | issues=$(gh issue list --search '${{ env.title }}' --json number,title,url) 20 | number=${{ env.number }} 21 | issues_filtered=$(echo "$issues" | jq --arg num "$number" 'map(select(.number != ($num | tonumber)))') 22 | if [ "$(echo "$issues_filtered" | jq length)" -eq 0 ]; then 23 | echo "No duplicates found." 24 | else 25 | issues_markdown=$(echo "$issues_filtered" | jq -r '.[] | "- [" + .title + "](" + .url + ")"') 26 | formatted_body=$(echo -e "@${{ env.author }}\nPossible duplication of:\n$issues_markdown") 27 | gh issue comment ${{ github.event.issue.number }} --body "$formatted_body" 28 | fi -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | app_links 7 | desktop_drop 8 | dynamic_color 9 | emoji_picker_flutter 10 | file_selector_windows 11 | flutter_secure_storage_windows 12 | flutter_webrtc 13 | geolocator_windows 14 | pasteboard 15 | permission_handler_windows 16 | record_windows 17 | share_plus 18 | sqlcipher_flutter_libs 19 | url_launcher_windows 20 | window_to_front 21 | ) 22 | 23 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 24 | ) 25 | 26 | set(PLUGIN_BUNDLED_LIBRARIES) 27 | 28 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 29 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 30 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 31 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 32 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 33 | endforeach(plugin) 34 | 35 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 36 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 37 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 38 | endforeach(ffi_plugin) 39 | -------------------------------------------------------------------------------- /ios/Runner/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CLIENT_ID 6 | 865731724731-ofdr7e6m04murgb1bvchlj9oaos0q5i3.apps.googleusercontent.com 7 | REVERSED_CLIENT_ID 8 | com.googleusercontent.apps.865731724731-ofdr7e6m04murgb1bvchlj9oaos0q5i3 9 | API_KEY 10 | AIzaSyA8ZUBcuny0HjPwF2Q2fvDyQTC5dG2VHlE 11 | GCM_SENDER_ID 12 | 865731724731 13 | PLIST_VERSION 14 | 1 15 | BUNDLE_ID 16 | im.fluffychat.app 17 | PROJECT_ID 18 | fluffychat-ef3e8 19 | STORAGE_BUCKET 20 | fluffychat-ef3e8.appspot.com 21 | IS_ADS_ENABLED 22 | 23 | IS_ANALYTICS_ENABLED 24 | 25 | IS_APPINVITE_ENABLED 26 | 27 | IS_GCM_ENABLED 28 | 29 | IS_SIGNIN_ENABLED 30 | 31 | GOOGLE_APP_ID 32 | 1:865731724731:ios:79fd983ce46cb40c64309e 33 | 34 | -------------------------------------------------------------------------------- /android/fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ## Android 17 | 18 | ### android set_build_code_internal 19 | 20 | ```sh 21 | [bundle exec] fastlane android set_build_code_internal 22 | ``` 23 | 24 | 25 | 26 | ### android deploy_internal_test 27 | 28 | ```sh 29 | [bundle exec] fastlane android deploy_internal_test 30 | ``` 31 | 32 | 33 | 34 | ### android deploy_candidate 35 | 36 | ```sh 37 | [bundle exec] fastlane android deploy_candidate 38 | ``` 39 | 40 | 41 | 42 | ### android deploy_release 43 | 44 | ```sh 45 | [bundle exec] fastlane android deploy_release 46 | ``` 47 | 48 | 49 | 50 | ---- 51 | 52 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 53 | 54 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 55 | 56 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/test_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 📝 Test 3 | about: A detailed protocol for testing all features 4 | title: 'Test Report' 5 | labels: test 6 | --- 7 | 8 | 1. App receives push notifications over Firebase Cloud Messaging when it is in background/terminated: 9 | - [ ] Android 10 | - [ ] iOS 11 | 2. App receives push notifications over Unified Push when it is in background/terminated: 12 | - [ ] Android 13 | 3. Notifications for rooms, which are not in foreground, are working: 14 | - [ ] Web 15 | - [ ] Linux 16 | 4. QR Code scanner can still scan links to start a new chat: 17 | - [ ] Android 18 | - [ ] iOS 19 | 5. Recording and playing voice messages works: 20 | - [ ] Android 21 | - [ ] iOS 22 | - [ ] Web (play only) 23 | 6. Sending and downloading files/images works: 24 | - [ ] Android 25 | - [ ] iOS 26 | - [ ] Web 27 | - [ ] Linux 28 | 7. Sharing texts/files/images from other apps to FluffyChat works: 29 | - [ ] Android 30 | - [ ] iOS 31 | 8. Login with single sign on works: 32 | - [ ] Android 33 | - [ ] iOS 34 | - [ ] Web 35 | - [ ] Linux 36 | 9. Test if the app lock works as intended and appears on opening/resuming the app: 37 | - [ ] Android 38 | - [ ] iOS 39 | 10. Drag&Drop to send a file into a chat still works: 40 | - [ ] Web 41 | - [ ] Linux 42 | -------------------------------------------------------------------------------- /lib/widgets/settings_switch_list_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'matrix.dart'; 4 | 5 | class SettingsSwitchListTile extends StatefulWidget { 6 | final bool defaultValue; 7 | final String storeKey; 8 | final String title; 9 | final String? subtitle; 10 | final Function(bool)? onChanged; 11 | 12 | const SettingsSwitchListTile.adaptive({ 13 | super.key, 14 | this.defaultValue = false, 15 | required this.storeKey, 16 | required this.title, 17 | this.subtitle, 18 | this.onChanged, 19 | }); 20 | 21 | @override 22 | SettingsSwitchListTileState createState() => SettingsSwitchListTileState(); 23 | } 24 | 25 | class SettingsSwitchListTileState extends State { 26 | @override 27 | Widget build(BuildContext context) { 28 | final subtitle = widget.subtitle; 29 | return SwitchListTile.adaptive( 30 | value: Matrix.of(context).store.getBool(widget.storeKey) ?? 31 | widget.defaultValue, 32 | title: Text(widget.title), 33 | subtitle: subtitle == null ? null : Text(subtitle), 34 | onChanged: (bool newValue) async { 35 | widget.onChanged?.call(newValue); 36 | await Matrix.of(context).store.setBool(widget.storeKey, newValue); 37 | setState(() {}); 38 | }, 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Disable Windows macros that collide with C++ standard library functions. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 25 | 26 | # Add dependency libraries and include directories. Add any application-specific 27 | # dependencies here. 28 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 29 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 30 | 31 | # Run the Flutter tool portions of the build. This must not be removed. 32 | add_dependencies(${BINARY_NAME} flutter_assemble) 33 | -------------------------------------------------------------------------------- /lib/utils/show_scaffold_dialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:fluffychat/config/app_config.dart'; 4 | import 'package:fluffychat/config/themes.dart'; 5 | 6 | Future showScaffoldDialog({ 7 | required BuildContext context, 8 | Color? barrierColor, 9 | Color? containerColor, 10 | double maxWidth = 480, 11 | double maxHeight = 720, 12 | required Widget Function(BuildContext context) builder, 13 | }) => 14 | showDialog( 15 | context: context, 16 | useSafeArea: false, 17 | builder: FluffyThemes.isColumnMode(context) 18 | ? (context) => Center( 19 | child: Container( 20 | decoration: BoxDecoration( 21 | borderRadius: BorderRadius.circular( 22 | AppConfig.borderRadius, 23 | ), 24 | color: containerColor ?? 25 | Theme.of(context).scaffoldBackgroundColor, 26 | ), 27 | clipBehavior: Clip.hardEdge, 28 | margin: const EdgeInsets.all(16), 29 | constraints: BoxConstraints( 30 | maxWidth: maxWidth, 31 | maxHeight: maxHeight, 32 | ), 33 | child: builder(context), 34 | ), 35 | ) 36 | : builder, 37 | ); 38 | -------------------------------------------------------------------------------- /lib/widgets/error_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:fluffychat/utils/error_reporter.dart'; 4 | 5 | class FluffyChatErrorWidget extends StatefulWidget { 6 | final FlutterErrorDetails details; 7 | const FluffyChatErrorWidget(this.details, {super.key}); 8 | 9 | @override 10 | State createState() => _FluffyChatErrorWidgetState(); 11 | } 12 | 13 | class _FluffyChatErrorWidgetState extends State { 14 | static final Set knownExceptions = {}; 15 | @override 16 | void initState() { 17 | super.initState(); 18 | 19 | if (knownExceptions.contains(widget.details.exception.toString())) { 20 | return; 21 | } 22 | knownExceptions.add(widget.details.exception.toString()); 23 | WidgetsBinding.instance.addPostFrameCallback((_) { 24 | ErrorReporter(context, 'Error Widget').onErrorCallback( 25 | widget.details.exception, 26 | widget.details.stack, 27 | ); 28 | }); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return Material( 34 | color: Colors.orange, 35 | child: Placeholder( 36 | child: Center( 37 | child: Material( 38 | color: Colors.white.withAlpha(230), 39 | borderRadius: BorderRadius.circular(8), 40 | ), 41 | ), 42 | ), 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/utils/test_client.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: depend_on_referenced_packages 2 | 3 | import 'package:matrix/encryption/utils/key_verification.dart'; 4 | import 'package:matrix/matrix.dart'; 5 | 6 | import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart'; 7 | 8 | Future prepareTestClient({ 9 | bool loggedIn = false, 10 | Uri? homeserver, 11 | String id = 'FluffyChat Widget Test', 12 | }) async { 13 | homeserver ??= Uri.parse('https://fakeserver.notexisting'); 14 | final client = Client( 15 | 'FluffyChat Widget Tests', 16 | httpClient: FakeMatrixApi() 17 | ..api['GET']!['/.well-known/matrix/client'] = (req) => {}, 18 | verificationMethods: { 19 | KeyVerificationMethod.numbers, 20 | KeyVerificationMethod.emoji, 21 | }, 22 | importantStateEvents: { 23 | 'im.ponies.room_emotes', // we want emotes to work properly 24 | }, 25 | databaseBuilder: flutterMatrixSdkDatabaseBuilder, 26 | supportedLoginTypes: { 27 | AuthenticationTypes.password, 28 | AuthenticationTypes.sso, 29 | }, 30 | ); 31 | await client.checkHomeserver(homeserver); 32 | if (loggedIn) { 33 | await client.login( 34 | LoginType.mLoginToken, 35 | identifier: AuthenticationUserIdentifier(user: '@alice:example.invalid'), 36 | password: '1234', 37 | ); 38 | } 39 | return client; 40 | } 41 | -------------------------------------------------------------------------------- /lib/utils/matrix_sdk_extensions/device_extension.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:matrix/matrix.dart'; 4 | 5 | IconData _getIconFromName(String displayname) { 6 | final name = displayname.toLowerCase(); 7 | if ({'android'}.any((s) => name.contains(s))) { 8 | return Icons.phone_android_outlined; 9 | } 10 | if ({'ios', 'ipad', 'iphone', 'ipod'}.any((s) => name.contains(s))) { 11 | return Icons.phone_iphone_outlined; 12 | } 13 | if ({ 14 | 'web', 15 | 'http://', 16 | 'https://', 17 | 'firefox', 18 | 'chrome', 19 | '/_matrix', 20 | 'safari', 21 | 'opera', 22 | }.any((s) => name.contains(s))) { 23 | return Icons.web_outlined; 24 | } 25 | if ({'desktop', 'windows', 'macos', 'linux', 'ubuntu'} 26 | .any((s) => name.contains(s))) { 27 | return Icons.desktop_mac_outlined; 28 | } 29 | return Icons.device_unknown_outlined; 30 | } 31 | 32 | extension DeviceExtension on Device { 33 | String get displayname => 34 | (displayName?.isNotEmpty ?? false) ? displayName! : 'Unknown device'; 35 | 36 | IconData get icon => _getIconFromName(displayname); 37 | } 38 | 39 | extension DeviceKeysExtension on DeviceKeys { 40 | String get displayname => (deviceDisplayName?.isNotEmpty ?? false) 41 | ? deviceDisplayName! 42 | : 'Unknown device'; 43 | 44 | IconData get icon => _getIconFromName(displayname); 45 | } 46 | -------------------------------------------------------------------------------- /ios/Flutter/ephemeral/flutter_lldb_helper.py: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | import lldb 6 | 7 | def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): 8 | """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" 9 | base = frame.register["x0"].GetValueAsAddress() 10 | page_len = frame.register["x1"].GetValueAsUnsigned() 11 | 12 | # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the 13 | # first page to see if handled it correctly. This makes diagnosing 14 | # misconfiguration (e.g. missing breakpoint) easier. 15 | data = bytearray(page_len) 16 | data[0:8] = b'IHELPED!' 17 | 18 | error = lldb.SBError() 19 | frame.GetThread().GetProcess().WriteMemory(base, data, error) 20 | if not error.Success(): 21 | print(f'Failed to write into {base}[+{page_len}]', error) 22 | return 23 | 24 | def __lldb_init_module(debugger: lldb.SBDebugger, _): 25 | target = debugger.GetDummyTarget() 26 | # Caveat: must use BreakpointCreateByRegEx here and not 27 | # BreakpointCreateByName. For some reasons callback function does not 28 | # get carried over from dummy target for the later. 29 | bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") 30 | bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) 31 | bp.SetAutoContinue(True) 32 | print("-- LLDB integration loaded --") 33 | -------------------------------------------------------------------------------- /lib/utils/fluffy_share.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'package:share_plus/share_plus.dart'; 5 | 6 | import 'package:fluffychat/l10n/l10n.dart'; 7 | import 'package:fluffychat/utils/platform_infos.dart'; 8 | import '../widgets/matrix.dart'; 9 | 10 | abstract class FluffyShare { 11 | static Future share( 12 | String text, 13 | BuildContext context, { 14 | bool copyOnly = false, 15 | }) async { 16 | if (PlatformInfos.isMobile && !copyOnly) { 17 | final box = context.findRenderObject() as RenderBox; 18 | await Share.share( 19 | text, 20 | sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size, 21 | ); 22 | return; 23 | } 24 | await Clipboard.setData( 25 | ClipboardData(text: text), 26 | ); 27 | ScaffoldMessenger.of(context).showSnackBar( 28 | SnackBar(content: Text(L10n.of(context).copiedToClipboard)), 29 | ); 30 | return; 31 | } 32 | 33 | static Future shareInviteLink(BuildContext context) async { 34 | final client = Matrix.of(context).client; 35 | final ownProfile = await client.fetchOwnProfile(); 36 | await FluffyShare.share( 37 | L10n.of(context).inviteText( 38 | ownProfile.displayName ?? client.userID!, 39 | 'https://matrix.to/#/${client.userID}?client=im.fluffychat', 40 | ), 41 | context, 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/utils/show_update_snackbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | import 'package:url_launcher/url_launcher_string.dart'; 5 | 6 | import 'package:fluffychat/config/app_config.dart'; 7 | import 'package:fluffychat/l10n/l10n.dart'; 8 | import 'package:fluffychat/utils/platform_infos.dart'; 9 | 10 | abstract class UpdateNotifier { 11 | static const String versionStoreKey = 'last_known_version'; 12 | 13 | static void showUpdateSnackBar(BuildContext context) async { 14 | final scaffoldMessenger = ScaffoldMessenger.of(context); 15 | final currentVersion = await PlatformInfos.getVersion(); 16 | final store = await SharedPreferences.getInstance(); 17 | final storedVersion = store.getString(versionStoreKey); 18 | 19 | if (currentVersion != storedVersion) { 20 | if (storedVersion != null) { 21 | scaffoldMessenger.showSnackBar( 22 | SnackBar( 23 | duration: const Duration(seconds: 30), 24 | showCloseIcon: true, 25 | content: Text(L10n.of(context).updateInstalled(currentVersion)), 26 | action: SnackBarAction( 27 | label: L10n.of(context).changelog, 28 | onPressed: () => launchUrlString(AppConfig.changelogUrl), 29 | ), 30 | ), 31 | ); 32 | } 33 | await store.setString(versionStoreKey, currentVersion); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"FluffyChat", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "865731724731", 4 | "project_id": "fluffychat-ef3e8", 5 | "storage_bucket": "fluffychat-ef3e8.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:865731724731:android:ec427b3b1dcd4a1e64309e", 11 | "android_client_info": { 12 | "package_name": "chat.fluffy.fluffychat" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "865731724731-od6969v178ul9970elgacpt936v5t7qg.apps.googleusercontent.com", 18 | "client_type": 3 19 | } 20 | ], 21 | "api_key": [ 22 | { 23 | "current_key": "AIzaSyBLdZpGSPjcinikB4lAU6awW_h88NG17Sg" 24 | } 25 | ], 26 | "services": { 27 | "appinvite_service": { 28 | "other_platform_oauth_client": [ 29 | { 30 | "client_id": "865731724731-od6969v178ul9970elgacpt936v5t7qg.apps.googleusercontent.com", 31 | "client_type": 3 32 | }, 33 | { 34 | "client_id": "865731724731-ofdr7e6m04murgb1bvchlj9oaos0q5i3.apps.googleusercontent.com", 35 | "client_type": 2, 36 | "ios_info": { 37 | "bundle_id": "im.fluffychat.app" 38 | } 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | ], 45 | "configuration_version": "1" 46 | } -------------------------------------------------------------------------------- /lib/utils/resize_video.dart: -------------------------------------------------------------------------------- 1 | import 'package:cross_file/cross_file.dart'; 2 | import 'package:matrix/matrix.dart'; 3 | import 'package:video_compress/video_compress.dart'; 4 | 5 | import 'package:fluffychat/utils/platform_infos.dart'; 6 | 7 | extension ResizeImage on XFile { 8 | static const int max = 1200; 9 | static const int quality = 40; 10 | 11 | Future resizeVideo() async { 12 | MediaInfo? mediaInfo; 13 | try { 14 | if (PlatformInfos.isMobile) { 15 | // will throw an error e.g. on Android SDK < 18 16 | mediaInfo = await VideoCompress.compressVideo(path); 17 | } 18 | } catch (e, s) { 19 | Logs().w('Error while compressing video', e, s); 20 | } 21 | return MatrixVideoFile( 22 | bytes: (await mediaInfo?.file?.readAsBytes()) ?? await readAsBytes(), 23 | name: name, 24 | mimeType: mimeType, 25 | width: mediaInfo?.width, 26 | height: mediaInfo?.height, 27 | duration: mediaInfo?.duration?.round(), 28 | ); 29 | } 30 | 31 | Future getVideoThumbnail() async { 32 | if (!PlatformInfos.isMobile) return null; 33 | 34 | try { 35 | final bytes = await VideoCompress.getByteThumbnail(path); 36 | if (bytes == null) return null; 37 | return MatrixImageFile( 38 | bytes: bytes, 39 | name: name, 40 | ); 41 | } catch (e, s) { 42 | Logs().w('Error while compressing video', e, s); 43 | } 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /integration_test/extensions/wait_for.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | /// Workaround for https://github.com/flutter/flutter/issues/88765 4 | extension WaitForExtension on WidgetTester { 5 | Future waitFor( 6 | Finder finder, { 7 | Duration timeout = const Duration(seconds: 20), 8 | bool skipPumpAndSettle = false, 9 | }) async { 10 | final end = DateTime.now().add(timeout); 11 | 12 | do { 13 | if (DateTime.now().isAfter(end)) { 14 | throw Exception('Timed out waiting for $finder'); 15 | } 16 | 17 | if (!skipPumpAndSettle) { 18 | await pumpAndSettle(); 19 | } 20 | await Future.delayed(const Duration(milliseconds: 100)); 21 | } while (finder.evaluate().isEmpty); 22 | } 23 | } 24 | 25 | extension MaybeUppercaseFinder on CommonFinders { 26 | /// On Android some button labels are in uppercase while on iOS they 27 | /// are not. This method tries both. 28 | Finder maybeUppercaseText( 29 | String text, { 30 | bool findRichText = false, 31 | bool skipOffstage = true, 32 | }) { 33 | try { 34 | final finder = find.text( 35 | text.toUpperCase(), 36 | findRichText: findRichText, 37 | skipOffstage: skipOffstage, 38 | ); 39 | expect(finder, findsOneWidget); 40 | return finder; 41 | } catch (_) { 42 | return find.text( 43 | text, 44 | findRichText: findRichText, 45 | skipOffstage: skipOffstage, 46 | ); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/widgets/unread_rooms_badge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:badges/badges.dart' as b; 4 | import 'package:matrix/matrix.dart'; 5 | 6 | import 'matrix.dart'; 7 | 8 | class UnreadRoomsBadge extends StatelessWidget { 9 | final bool Function(Room) filter; 10 | final b.BadgePosition? badgePosition; 11 | final Widget? child; 12 | 13 | const UnreadRoomsBadge({ 14 | super.key, 15 | required this.filter, 16 | this.badgePosition, 17 | this.child, 18 | }); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | final theme = Theme.of(context); 23 | 24 | final unreadCount = Matrix.of(context) 25 | .client 26 | .rooms 27 | .where(filter) 28 | .where((r) => (r.isUnread || r.membership == Membership.invite)) 29 | .length; 30 | return b.Badge( 31 | badgeStyle: b.BadgeStyle( 32 | badgeColor: theme.colorScheme.primary, 33 | elevation: 4, 34 | borderSide: BorderSide( 35 | color: theme.colorScheme.surface, 36 | width: 2, 37 | ), 38 | ), 39 | badgeContent: Text( 40 | unreadCount.toString(), 41 | style: TextStyle( 42 | color: theme.colorScheme.onPrimary, 43 | fontSize: 12, 44 | ), 45 | ), 46 | showBadge: unreadCount != 0, 47 | badgeAnimation: const b.BadgeAnimation.scale(), 48 | position: badgePosition ?? b.BadgePosition.bottomEnd(), 49 | child: child, 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - camel_case_types 6 | - avoid_print 7 | - constant_identifier_names 8 | - prefer_final_locals 9 | - prefer_final_in_for_each 10 | - sort_pub_dependencies 11 | - require_trailing_commas 12 | - omit_local_variable_types 13 | 14 | analyzer: 15 | errors: 16 | todo: ignore 17 | use_build_context_synchronously: ignore 18 | exclude: 19 | - lib/generated_plugin_registrant.dart 20 | - lib/l10n/*.dart 21 | 22 | dart_code_metrics: 23 | metrics: 24 | cyclomatic-complexity: 20 25 | number-of-arguments: 4 26 | maximum-nesting-level: 5 27 | source-lines-of-code: 50 28 | maintainability-index: 40 29 | rules: 30 | - no-boolean-literal-compare 31 | - no-empty-block 32 | - prefer-conditional-expressions 33 | - no-equal-then-else 34 | - no-magic-number: 35 | severity: style 36 | - avoid-late-keyword: 37 | severity: style 38 | - avoid-non-null-assertion: 39 | severity: style 40 | - avoid-unused-parameters 41 | - binary-expression-operand-order 42 | - avoid-unnecessary-setstate 43 | - avoid-wrapping-in-padding 44 | - prefer-const-border-radius 45 | - prefer-single-widget-per-file: 46 | ignore-private-widgets: true 47 | - prefer-extracting-callbacks 48 | metrics-exclude: 49 | - test/** 50 | rules-exclude: 51 | - test/** 52 | anti-patterns: 53 | - long-method 54 | - long-parameter-list 55 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"1024x1024","filename":"1024-mac.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} -------------------------------------------------------------------------------- /lib/widgets/presence_builder.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'package:matrix/matrix.dart'; 6 | 7 | import 'package:fluffychat/widgets/matrix.dart'; 8 | 9 | class PresenceBuilder extends StatefulWidget { 10 | final Widget Function(BuildContext context, CachedPresence? presence) builder; 11 | final String? userId; 12 | final Client? client; 13 | 14 | const PresenceBuilder({ 15 | required this.builder, 16 | this.userId, 17 | this.client, 18 | super.key, 19 | }); 20 | 21 | @override 22 | State createState() => _PresenceBuilderState(); 23 | } 24 | 25 | class _PresenceBuilderState extends State { 26 | CachedPresence? _presence; 27 | StreamSubscription? _sub; 28 | 29 | void _updatePresence(CachedPresence? presence) { 30 | setState(() { 31 | _presence = presence; 32 | }); 33 | } 34 | 35 | @override 36 | void initState() { 37 | super.initState(); 38 | final client = widget.client ?? Matrix.of(context).client; 39 | final userId = widget.userId; 40 | if (userId != null) { 41 | client.fetchCurrentPresence(userId).then(_updatePresence); 42 | _sub = client.onPresenceChanged.stream 43 | .where((presence) => presence.userid == userId) 44 | .listen(_updatePresence); 45 | } 46 | } 47 | 48 | @override 49 | void dispose() { 50 | _sub?.cancel(); 51 | super.dispose(); 52 | } 53 | 54 | @override 55 | Widget build(BuildContext context) => widget.builder(context, _presence); 56 | } 57 | -------------------------------------------------------------------------------- /scripts/build-macos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | git apply ./scripts/enable-android-google-services.patch 3 | FLUFFYCHAT_ORIG_GROUP="im.fluffychat" 4 | FLUFFYCHAT_ORIG_TEAM="4NXF6Z997G" 5 | #FLUFFYCHAT_NEW_GROUP="com.example.fluffychat" 6 | #FLUFFYCHAT_NEW_TEAM="ABCDE12345" 7 | 8 | # In some cases (ie: running beta XCode releases) some pods haven't updated their minimum version 9 | # but XCode will reject the package for using too old of a minimum version. 10 | # This will fix that, but. Well. Use at your own risk. 11 | # export I_PROMISE_IM_REALLY_SMART=1 12 | 13 | # If you want to automatically install the app 14 | # export FLUFFYCHAT_INSTALL_IPA=1 15 | 16 | ### Rotate IDs ### 17 | [ -n "${FLUFFYCHAT_NEW_GROUP}" ] && { 18 | # App group IDs 19 | sed -i "" "s/group.${FLUFFYCHAT_ORIG_GROUP}.app/group.${FLUFFYCHAT_NEW_GROUP}.app/g" "macos/Runner/Runner.entitlements" 20 | sed -i "" "s/group.${FLUFFYCHAT_ORIG_GROUP}.app/group.${FLUFFYCHAT_NEW_GROUP}.app/g" "macos/Runner.xcodeproj/project.pbxproj" 21 | # Bundle identifiers 22 | sed -i "" "s/${FLUFFYCHAT_ORIG_GROUP}.app/${FLUFFYCHAT_NEW_GROUP}.app/g" "macos/Runner.xcodeproj/project.pbxproj" 23 | } 24 | 25 | [ -n "${FLUFFYCHAT_NEW_TEAM}" ] && { 26 | # Code signing team 27 | sed -i "" "s/${FLUFFYCHAT_ORIG_TEAM}/${FLUFFYCHAT_NEW_TEAM}/g" "macos/Runner.xcodeproj/project.pbxproj" 28 | } 29 | 30 | ### Make release build ### 31 | flutter build macos --release 32 | 33 | cp /usr/local/Cellar/libolm/**/lib/libolm.3.dylib build/macos/Build/Products/Release/FluffyChat.app/Contents/Frameworks/libolm.3.dylib 34 | 35 | echo "Build build/macos/Build/Products/Release/FluffyChat.app" 36 | -------------------------------------------------------------------------------- /macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '12.2' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | end 35 | 36 | post_install do |installer| 37 | installer.pods_project.targets.each do |target| 38 | flutter_additional_macos_build_settings(target) 39 | target.build_configurations.each do |config| 40 | config.build_settings.delete 'MACOSX_DEPLOYMENT_TARGET' 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/pages/chat/events/state_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:matrix/matrix.dart'; 4 | 5 | import 'package:fluffychat/l10n/l10n.dart'; 6 | import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; 7 | import '../../../config/app_config.dart'; 8 | 9 | class StateMessage extends StatelessWidget { 10 | final Event event; 11 | const StateMessage(this.event, {super.key}); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | final theme = Theme.of(context); 16 | return Padding( 17 | padding: const EdgeInsets.symmetric(horizontal: 8.0), 18 | child: Center( 19 | child: Padding( 20 | padding: const EdgeInsets.all(4), 21 | child: Material( 22 | color: theme.colorScheme.surface.withAlpha(128), 23 | borderRadius: BorderRadius.circular(AppConfig.borderRadius / 3), 24 | child: Padding( 25 | padding: 26 | const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), 27 | child: Text( 28 | event.calcLocalizedBodyFallback( 29 | MatrixLocals(L10n.of(context)), 30 | ), 31 | textAlign: TextAlign.center, 32 | maxLines: 2, 33 | overflow: TextOverflow.ellipsis, 34 | style: TextStyle( 35 | fontSize: 12 * AppConfig.fontSizeFactor, 36 | decoration: 37 | event.redacted ? TextDecoration.lineThrough : null, 38 | ), 39 | ), 40 | ), 41 | ), 42 | ), 43 | ), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/pages/settings_ignore_list/settings_ignore_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:matrix/matrix.dart'; 4 | 5 | import 'package:fluffychat/l10n/l10n.dart'; 6 | import 'package:fluffychat/widgets/future_loading_dialog.dart'; 7 | import '../../widgets/matrix.dart'; 8 | import 'settings_ignore_list_view.dart'; 9 | 10 | class SettingsIgnoreList extends StatefulWidget { 11 | final String? initialUserId; 12 | 13 | const SettingsIgnoreList({super.key, this.initialUserId}); 14 | 15 | @override 16 | SettingsIgnoreListController createState() => SettingsIgnoreListController(); 17 | } 18 | 19 | class SettingsIgnoreListController extends State { 20 | final TextEditingController controller = TextEditingController(); 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | final initialUserId = widget.initialUserId; 26 | if (initialUserId != null) { 27 | controller.text = initialUserId; 28 | } 29 | } 30 | 31 | String? errorText; 32 | 33 | void ignoreUser(BuildContext context) { 34 | final userId = controller.text.trim(); 35 | if (userId.isEmpty) return; 36 | if (!userId.isValidMatrixId || userId.sigil != '@') { 37 | setState(() { 38 | errorText = L10n.of(context).invalidInput; 39 | }); 40 | return; 41 | } 42 | setState(() { 43 | errorText = null; 44 | }); 45 | 46 | showFutureLoadingDialog( 47 | context: context, 48 | future: () => Matrix.of(context).client.ignoreUser(userId), 49 | ); 50 | controller.clear(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) => SettingsIgnoreListView(this); 55 | } 56 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # This file contains the fastlane.tools configuration 2 | # You can find the documentation at https://docs.fastlane.tools 3 | # 4 | # For a list of all available actions, check out 5 | # 6 | # https://docs.fastlane.tools/actions 7 | # 8 | # For a list of all available plugins, check out 9 | # 10 | # https://docs.fastlane.tools/plugins/available-plugins 11 | # 12 | 13 | # Uncomment the line if you want fastlane to automatically update itself 14 | # update_fastlane 15 | 16 | default_platform(:ios) 17 | 18 | platform :ios do 19 | desc "Push a new beta build to TestFlight" 20 | lane :beta do 21 | increment_build_number( 22 | xcodeproj: "Runner.xcodeproj", 23 | build_number: latest_testflight_build_number + 1 24 | ) 25 | re = /version:\s([0-9]*\.[0-9]*\.[0-9]*)\+[0-9]*/i 26 | config = File.read("../../pubspec.yaml") 27 | version_name = config.match(re).captures[0] 28 | increment_version_number(version_number: version_name) 29 | build_app(workspace: "Runner.xcworkspace", scheme: "Runner") 30 | upload_to_testflight( 31 | distribute_external: true, 32 | groups: "FluffyChat Betatest", 33 | changelog: "This is a release candidate for FluffyChat. Please test if the app is overall in a good condition before we push this to production.", 34 | ) 35 | end 36 | end 37 | 38 | lane :release do 39 | capture_screenshots # generate new screenshots for the App Store 40 | sync_code_signing(type: "appstore") # see code signing guide for more information 41 | build_app(scheme: "Runner") 42 | upload_to_app_store # upload your app to App Store Connect 43 | slack(message: "Successfully uploaded a new App Store build") 44 | end 45 | -------------------------------------------------------------------------------- /lib/l10n/intl_ia.arb: -------------------------------------------------------------------------------- 1 | { 2 | "repeatPassword": "Repeter le contrasigno", 3 | "@repeatPassword": {}, 4 | "notAnImage": "Non es un file de imagine.", 5 | "@notAnImage": {}, 6 | "remove": "Remover", 7 | "@remove": { 8 | "type": "String", 9 | "placeholders": {} 10 | }, 11 | "importEmojis": "Importar emojis", 12 | "@importEmojis": {}, 13 | "importFromZipFile": "Importar ab un file .zip", 14 | "@importFromZipFile": {}, 15 | "importNow": "Importar ora", 16 | "@importNow": {}, 17 | "exportEmotePack": "Exportar pacchetto de emotes como un .zip", 18 | "@exportEmotePack": {}, 19 | "replace": "Reimplaciar", 20 | "@replace": {}, 21 | "about": "A proposito de", 22 | "@about": { 23 | "type": "String", 24 | "placeholders": {} 25 | }, 26 | "accept": "Acceptar", 27 | "@accept": { 28 | "type": "String", 29 | "placeholders": {} 30 | }, 31 | "acceptedTheInvitation": "👍 {username} acceptava tu invitation", 32 | "@acceptedTheInvitation": { 33 | "type": "String", 34 | "placeholders": { 35 | "username": { 36 | "type": "String" 37 | } 38 | } 39 | }, 40 | "account": "Conto", 41 | "@account": { 42 | "type": "String", 43 | "placeholders": {} 44 | }, 45 | "addEmail": "Adder email", 46 | "@addEmail": { 47 | "type": "String", 48 | "placeholders": {} 49 | }, 50 | "supposedMxid": "Isto deberea esser {mxid}", 51 | "@supposedMxid": { 52 | "type": "String", 53 | "placeholders": { 54 | "mxid": { 55 | "type": "String" 56 | } 57 | } 58 | }, 59 | "@custom": {} 60 | } -------------------------------------------------------------------------------- /ios/FluffyChat Share/Base.lproj/MainInterface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /winuwp/runner_uwp/appxmanifest.in: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | @SHORT_NAME@ 13 | CMake Test Cert 14 | Assets/StoreLogo.png 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Aminda Suomalainen Mikaela Suomalainen 2 | Aminda Suomalainen Mikaela Suomalainen 3 | Aminda Suomalainen Mikaela Suomalainen 4 | Anne Onyme 017 Anne017 5 | Brendan Abolivier Brendan Abolivier 6 | Christian Pauly Christian 7 | Christian Pauly Christian Pauly 8 | Christian Pauly Christian Pauly 9 | Christian Pauly Christian Pauly 10 | Christian Pauly Christian Pauly 11 | Christian Pauly Christian Pauly 12 | Christian Pauly Christian Pauly 13 | Christian Pauly Krille Fear 14 | CuteTadpole <61086561+CuteTadpole@users.noreply.github.com> CuteTadpole 15 | Drews Clausen Drews Clausen 16 | Jelv Jelv 17 | Kateřina Churanová Kateřina Churanová 18 | Kateřina Churanová Katerina 19 | NN708 NN708 20 | S1m S1m 21 | -------------------------------------------------------------------------------- /lib/utils/matrix_sdk_extensions/event_extension.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'package:async/async.dart' as async; 7 | import 'package:matrix/matrix.dart'; 8 | 9 | import 'package:fluffychat/utils/size_string.dart'; 10 | import 'package:fluffychat/widgets/future_loading_dialog.dart'; 11 | import 'matrix_file_extension.dart'; 12 | 13 | extension LocalizedBody on Event { 14 | Future> _getFile(BuildContext context) => 15 | showFutureLoadingDialog( 16 | context: context, 17 | future: downloadAndDecryptAttachment, 18 | ); 19 | 20 | void saveFile(BuildContext context) async { 21 | final matrixFile = await _getFile(context); 22 | 23 | matrixFile.result?.save(context); 24 | } 25 | 26 | void shareFile(BuildContext context) async { 27 | final matrixFile = await _getFile(context); 28 | inspect(matrixFile); 29 | 30 | matrixFile.result?.share(context); 31 | } 32 | 33 | bool get isAttachmentSmallEnough => 34 | infoMap['size'] is int && 35 | infoMap['size'] < room.client.database!.maxFileSize; 36 | 37 | bool get isThumbnailSmallEnough => 38 | thumbnailInfoMap['size'] is int && 39 | thumbnailInfoMap['size'] < room.client.database!.maxFileSize; 40 | 41 | bool get showThumbnail => 42 | [MessageTypes.Image, MessageTypes.Sticker, MessageTypes.Video] 43 | .contains(messageType) && 44 | (kIsWeb || 45 | isAttachmentSmallEnough || 46 | isThumbnailSmallEnough || 47 | (content['url'] is String)); 48 | 49 | String? get sizeString => content 50 | .tryGetMap('info') 51 | ?.tryGet('size') 52 | ?.sizeString; 53 | } 54 | -------------------------------------------------------------------------------- /lib/utils/stream_extension.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | extension StreamExtension on Stream { 4 | /// Returns a new Stream which outputs only `true` for every update of the original 5 | /// stream, ratelimited by the Duration t 6 | Stream rateLimit(Duration t) { 7 | final controller = StreamController(); 8 | Timer? timer; 9 | var gotMessage = false; 10 | // as we call our inline-defined function recursively we need to make sure that the 11 | // variable exists prior of creating the function. Silly dart. 12 | Function? onMessage; 13 | // callback to determine if we should send out an update 14 | onMessage = () { 15 | // do nothing if it is already closed 16 | if (controller.isClosed) { 17 | return; 18 | } 19 | if (timer == null) { 20 | // if we don't have a timer yet, send out the update and start a timer 21 | gotMessage = false; 22 | controller.add(true); 23 | timer = Timer(t, () { 24 | // the timer has ended...delete it and, if we got a message, re-run the 25 | // method to send out an update! 26 | timer = null; 27 | if (gotMessage) { 28 | onMessage?.call(); 29 | } 30 | }); 31 | } else { 32 | // set that we got a message 33 | gotMessage = true; 34 | } 35 | }; 36 | final subscription = listen( 37 | (_) => onMessage?.call(), 38 | onDone: () => controller.close(), 39 | onError: (e, s) => controller.addError(e, s), 40 | ); 41 | // add proper cleanup to the subscription and the controller, to not memory leak 42 | controller.onCancel = () { 43 | subscription.cancel(); 44 | controller.close(); 45 | }; 46 | return controller.stream; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/pages/chat/encryption_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:go_router/go_router.dart'; 4 | import 'package:matrix/matrix.dart'; 5 | 6 | import 'package:fluffychat/l10n/l10n.dart'; 7 | import '../../widgets/matrix.dart'; 8 | 9 | class EncryptionButton extends StatelessWidget { 10 | final Room room; 11 | const EncryptionButton(this.room, {super.key}); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return StreamBuilder( 16 | stream: Matrix.of(context) 17 | .client 18 | .onSync 19 | .stream 20 | .where((s) => s.deviceLists != null), 21 | builder: (context, snapshot) { 22 | return FutureBuilder( 23 | future: room.encrypted 24 | ? room.calcEncryptionHealthState() 25 | : Future.value(EncryptionHealthState.allVerified), 26 | builder: (BuildContext context, snapshot) => IconButton( 27 | tooltip: room.encrypted 28 | ? L10n.of(context).encrypted 29 | : L10n.of(context).encryptionNotEnabled, 30 | icon: Icon( 31 | room.encrypted ? Icons.lock_outlined : Icons.lock_open_outlined, 32 | size: 20, 33 | color: room.joinRules != JoinRules.public && !room.encrypted 34 | ? Colors.red 35 | : room.joinRules != JoinRules.public && 36 | snapshot.data == 37 | EncryptionHealthState.unverifiedDevices 38 | ? Colors.orange 39 | : null, 40 | ), 41 | onPressed: () => context.go('/rooms/${room.id}/encryption'), 42 | ), 43 | ); 44 | }, 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /fdroid/metadata/chat.fluffy.fluffychat.yml: -------------------------------------------------------------------------------- 1 | Categories: 2 | - Internet 3 | - Phone & SMS 4 | License: AGPL-3.0-only 5 | AuthorName: Famedly 6 | SourceCode: https://github.com/krille-chan/fluffychat 7 | IssueTracker: https://github.com/krille-chan/fluffychat/-/issues 8 | Translation: https://hosted.weblate.org/projects/fluffychat/ 9 | Changelog: https://gitlab.com/ChristianPauly/fluffychat-flutter/-/blob/main/CHANGELOG.md 10 | 11 | AutoName: FluffyChat 12 | Summary: "Chat with your friends with FluffyChat.\n" 13 | Description: | 14 | FluffyChat is an open, nonprofit and cute matrix messenger app for Ubuntu Touch, Android and iOS. 15 | 16 | Open 17 | Opensource and open development where everyone can join. 18 | 19 | Nonprofit 20 | FluffyChat is donation funded. 21 | 22 | Cute ♥ 23 | Cute design and many theme settings including a dark mode. 24 | 25 | One-to-one and groupchats 26 | Unlimited groups and direct chats. 27 | 28 | Easy 29 | FluffyChat is made as simple to use as possible. 30 | 31 | Free 32 | Free to use for everyone without ads. 33 | 34 | Decentralized 35 | There is no "FluffyChat server" you are forced to use. Use the server you find trustworthy or host 36 | your own. 37 | 38 | Compatible 39 | Compatible with Riot, Fractal, Nekho and all matrix messengers. 40 | 41 | 42 | FluffyChat comes with a dream 43 | 44 | Imagine a world where everyone can choose the messenger they like and is still able to chat with 45 | all of their friends. 46 | A world where there are no companies spying on you when you send selfies to friends and lovers. 47 | And a world where apps are made for fluffyness and not for profit. ♥ 48 | 49 | RepoType: git 50 | Repo: https://github.com/krille-chan/fluffychat.git 51 | 52 | AutoUpdateMode: None 53 | UpdateCheckMode: None 54 | -------------------------------------------------------------------------------- /lib/utils/client_download_content_extension.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:image/image.dart'; 4 | import 'package:matrix/matrix.dart'; 5 | 6 | extension ClientDownloadContentExtension on Client { 7 | Future downloadMxcCached( 8 | Uri mxc, { 9 | num? width, 10 | num? height, 11 | bool isThumbnail = false, 12 | bool? animated, 13 | ThumbnailMethod? thumbnailMethod, 14 | bool rounded = false, 15 | }) async { 16 | // To stay compatible with previous storeKeys: 17 | final cacheKey = isThumbnail 18 | // ignore: deprecated_member_use 19 | ? mxc.getThumbnail( 20 | this, 21 | width: width, 22 | height: height, 23 | animated: animated, 24 | method: thumbnailMethod!, 25 | ) 26 | : mxc; 27 | 28 | final cachedData = await database?.getFile(cacheKey); 29 | if (cachedData != null) return cachedData; 30 | 31 | final httpUri = isThumbnail 32 | ? await mxc.getThumbnailUri( 33 | this, 34 | width: width, 35 | height: height, 36 | animated: animated, 37 | method: thumbnailMethod, 38 | ) 39 | : await mxc.getDownloadUri(this); 40 | 41 | final response = await httpClient.get( 42 | httpUri, 43 | headers: 44 | accessToken == null ? null : {'authorization': 'Bearer $accessToken'}, 45 | ); 46 | if (response.statusCode != 200) { 47 | throw Exception(); 48 | } 49 | var imageData = response.bodyBytes; 50 | 51 | if (rounded) { 52 | final image = decodeImage(imageData); 53 | if (image != null) { 54 | imageData = encodePng(copyCropCircle(image)); 55 | } 56 | } 57 | 58 | await database?.storeFile(cacheKey, imageData, 0); 59 | 60 | return imageData; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ios/FluffyChat Share/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | FluffyChat Share 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSExtension 24 | 25 | NSExtensionAttributes 26 | 27 | NSExtensionActivationRule 28 | 29 | NSExtensionActivationSupportsFileWithMaxCount 30 | 10 31 | NSExtensionActivationSupportsImageWithMaxCount 32 | 10 33 | NSExtensionActivationSupportsMovieWithMaxCount 34 | 10 35 | NSExtensionActivationSupportsText 36 | 37 | NSExtensionActivationSupportsWebURLWithMaxCount 38 | 1 39 | 40 | PHSupportedMediaTypes 41 | 42 | Video 43 | Image 44 | 45 | 46 | NSExtensionMainStoryboard 47 | MainInterface 48 | NSExtensionPointIdentifier 49 | com.apple.share-services 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug report 2 | description: Create a report to help us improve 3 | labels: bug 4 | body: 5 | - type: textarea 6 | id: bug-description 7 | attributes: 8 | label: "Bug Description" 9 | description: "A clear and concise description of what the bug is. Please add screenshots if you have as they usually help us a lot." 10 | placeholder: "Describe the bug here..." 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: reproduce-steps 15 | attributes: 16 | label: "Steps to Reproduce" 17 | description: "Steps to reproduce the behavior:" 18 | placeholder: "1. Go to '...'\n2. Click on '...'\n3. Scroll down to '...'\n4. See error" 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: expected-behavior 23 | attributes: 24 | label: "Expected Behavior" 25 | description: "A clear and concise description of what you expected to happen." 26 | placeholder: "Describe what you expected to happen here..." 27 | validations: 28 | required: true 29 | - type: input 30 | id: app-version 31 | attributes: 32 | label: "App Version" 33 | description: "Please provide the version of the app you are using." 34 | placeholder: "e.g. 1.12.0" 35 | validations: 36 | required: true 37 | - type: input 38 | id: platform-info 39 | attributes: 40 | label: "Additional Platform Information" 41 | description: "Please provide the following information:" 42 | placeholder: "Device: [e.g. iPhone6, PC, Pixel 3]\nOS: [e.g. iOS, Android, Windows, Linux, macOS]\nBrowser (if applicable): [e.g. Chrome, Safari]" 43 | validations: 44 | required: true 45 | - type: textarea 46 | id: additional-context 47 | attributes: 48 | label: "Additional Context" 49 | description: "Add any other context about the problem here." 50 | validations: 51 | required: false 52 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | std::string utf8_string; 52 | if (target_length == 0 || target_length > utf8_string.max_size()) { 53 | return utf8_string; 54 | } 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /lib/pages/settings_homeserver/settings_homeserver.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'package:http/http.dart' as http; 6 | import 'package:matrix/matrix.dart'; 7 | 8 | import '../../widgets/matrix.dart'; 9 | import 'settings_homeserver_view.dart'; 10 | 11 | class SettingsHomeserver extends StatefulWidget { 12 | const SettingsHomeserver({super.key}); 13 | 14 | @override 15 | SettingsHomeserverController createState() => SettingsHomeserverController(); 16 | } 17 | 18 | class SettingsHomeserverController extends State { 19 | Future<({String name, String version, Uri federationBaseUrl})> 20 | fetchServerInfo() async { 21 | final client = Matrix.of(context).client; 22 | final domain = client.userID!.domain!; 23 | final httpClient = client.httpClient; 24 | var federationBaseUrl = Uri(host: domain, port: 8448, scheme: 'https'); 25 | try { 26 | final serverWellKnownResult = await httpClient.get( 27 | Uri.https(domain, '/.well-known/matrix/server'), 28 | ); 29 | final serverWellKnown = jsonDecode(serverWellKnownResult.body); 30 | federationBaseUrl = Uri.https(serverWellKnown['m.server']); 31 | } catch (e, s) { 32 | Logs().w( 33 | 'Unable to fetch federation base uri. Use $federationBaseUrl', 34 | e, 35 | s, 36 | ); 37 | } 38 | 39 | final serverVersionResult = await http.get( 40 | federationBaseUrl.resolveUri( 41 | Uri(path: '/_matrix/federation/v1/version'), 42 | ), 43 | ); 44 | final { 45 | 'server': { 46 | 'name': String name, 47 | 'version': String version, 48 | }, 49 | } = Map>.from( 50 | jsonDecode(serverVersionResult.body), 51 | ); 52 | 53 | return (name: name, version: version, federationBaseUrl: federationBaseUrl); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) => SettingsHomeserverView(this); 58 | } 59 | -------------------------------------------------------------------------------- /lib/widgets/mxc_image_viewer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:fluffychat/l10n/l10n.dart'; 4 | import 'mxc_image.dart'; 5 | 6 | class MxcImageViewer extends StatelessWidget { 7 | final Uri mxContent; 8 | 9 | const MxcImageViewer(this.mxContent, {super.key}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | final iconButtonStyle = IconButton.styleFrom( 14 | backgroundColor: Colors.black.withAlpha(200), 15 | foregroundColor: Colors.white, 16 | ); 17 | return GestureDetector( 18 | onTap: () => Navigator.of(context).pop(), 19 | child: Scaffold( 20 | backgroundColor: Colors.black.withAlpha(128), 21 | extendBodyBehindAppBar: true, 22 | appBar: AppBar( 23 | elevation: 0, 24 | leading: IconButton( 25 | style: iconButtonStyle, 26 | icon: const Icon(Icons.close), 27 | onPressed: Navigator.of(context).pop, 28 | color: Colors.white, 29 | tooltip: L10n.of(context).close, 30 | ), 31 | backgroundColor: Colors.transparent, 32 | ), 33 | body: InteractiveViewer( 34 | minScale: 1.0, 35 | maxScale: 10.0, 36 | onInteractionEnd: (endDetails) { 37 | if (endDetails.velocity.pixelsPerSecond.dy > 38 | MediaQuery.of(context).size.height * 1.5) { 39 | Navigator.of(context, rootNavigator: false).pop(); 40 | } 41 | }, 42 | child: Center( 43 | child: GestureDetector( 44 | // Ignore taps to not go back here: 45 | onTap: () {}, 46 | child: MxcImage( 47 | key: ValueKey(mxContent.toString()), 48 | uri: mxContent, 49 | fit: BoxFit.contain, 50 | isThumbnail: false, 51 | animated: true, 52 | ), 53 | ), 54 | ), 55 | ), 56 | ), 57 | ); 58 | } 59 | } 60 | --------------------------------------------------------------------------------