diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 6e53d61ba..8eae9406c 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -37,8 +37,6 @@ abstract class AppConfig { static const String supportUrl = 'https://github.com/krille-chan/fluffychat/issues'; static const String changelogUrl = 'https://fluffy.chat/en/changelog/'; - static const String donationUrl = - 'https://fluffychat.im/faq/#how_can_i_support_fluffychat'; static const Set defaultReactions = {'👍', '❤️', '😂', '😮', '😢'}; diff --git a/lib/config/setting_keys.dart b/lib/config/setting_keys.dart index 471f88978..6cbc1127d 100644 --- a/lib/config/setting_keys.dart +++ b/lib/config/setting_keys.dart @@ -66,7 +66,9 @@ enum AppSettings { 'https://fluffychat.im/en/privacy', ), tos('chat.fluffy.tos_url', 'https://fluffychat.im/en/tos'), - sendTimelineEventTimeout('chat.fluffy.send_timeline_event_timeout', 15); + sendTimelineEventTimeout('chat.fluffy.send_timeline_event_timeout', 15), + lastSeenSupportBanner('chat.fluffy.last_seen_support_banner', 0), + supportBannerOptOut('chat.fluffy.support_banner_opt_out', false); final String key; final T defaultValue; diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index e88217c88..d99e59b84 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -2782,5 +2782,10 @@ }, "createNewChat": "Create new chat", "reset": "Reset", - "supportFluffyChat": "Support FluffyChat" + "supportFluffyChat": "Support FluffyChat", + "support": "Support", + "fluffyChatSupportBannerMessage": "FluffyChat needs YOUR help!\nFluffyChat will always be free, but development and hosting still cost money. The future of the project depends on support from people like you.", + "skipSupportingFluffyChat": "Skip supporting FluffyChat", + "iDoNotWantToSupport": "I do not want to support", + "iAlreadySupportFluffyChat": "I already support FluffyChat" } \ No newline at end of file diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 75181bf04..207050277 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -10,6 +10,7 @@ import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; +import 'package:url_launcher/url_launcher_string.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/l10n/l10n.dart'; @@ -366,6 +367,7 @@ class ChatListController extends State _hackyWebRTCFixForWeb(); WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { + _showLastSeenSupportBanner(); searchServer = Matrix.of( context, ).store.getString(_serverStoreNamespace); @@ -390,6 +392,73 @@ class ChatListController extends State super.dispose(); } + Future _showLastSeenSupportBanner() async { + if (AppSettings.supportBannerOptOut.value) return; + + if (AppSettings.lastSeenSupportBanner.value == 0) { + await AppSettings.lastSeenSupportBanner.setItem( + DateTime.now().millisecondsSinceEpoch, + ); + return; + } + + final lastSeenSupportBanner = DateTime.fromMillisecondsSinceEpoch( + AppSettings.lastSeenSupportBanner.value, + ); + + if (DateTime.now().difference(lastSeenSupportBanner) >= + Duration(days: 6 * 7)) { + final messenger = ScaffoldMessenger.of(context); + messenger.showMaterialBanner( + MaterialBanner( + leading: CloseButton( + onPressed: () async { + final okCancelResult = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context).skipSupportingFluffyChat, + message: L10n.of(context).fluffyChatSupportBannerMessage, + okLabel: L10n.of(context).iDoNotWantToSupport, + cancelLabel: L10n.of(context).iAlreadySupportFluffyChat, + isDestructive: true, + ); + switch (okCancelResult) { + case null: + return; + case OkCancelResult.ok: + messenger.clearMaterialBanners(); + return; + case OkCancelResult.cancel: + messenger.clearMaterialBanners(); + await AppSettings.supportBannerOptOut.setItem(true); + return; + } + }, + ), + content: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text(L10n.of(context).fluffyChatSupportBannerMessage), + ), + actions: [ + TextButton( + onPressed: () { + messenger.clearMaterialBanners(); + launchUrlString( + 'https://fluffychat.im/faq/#how_can_i_support_fluffychat', + ); + }, + child: Text(L10n.of(context).support), + ), + ], + ), + ); + await AppSettings.lastSeenSupportBanner.setItem( + DateTime.now().millisecondsSinceEpoch, + ); + } + + return; + } + Future chatContextAction( Room room, BuildContext posContext, [ diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index f4093cb0b..8cde34e19 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -4,7 +4,6 @@ import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import 'package:url_launcher/url_launcher_string.dart'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; @@ -83,7 +82,7 @@ class ClientChooserButton extends StatelessWidget { value: SettingsAction.support, child: Row( children: [ - Icon(Icons.volunteer_activism, color: Colors.red), + Icon(Icons.favorite, color: Colors.red), const SizedBox(width: 18), Text(L10n.of(context).supportFluffyChat), ], @@ -223,7 +222,9 @@ class ClientChooserButton extends StatelessWidget { FluffyShare.shareInviteLink(context); break; case SettingsAction.support: - launchUrlString(AppConfig.donationUrl); + launchUrlString( + 'https://fluffychat.im/faq/#how_can_i_support_fluffychat', + ); break; case SettingsAction.settings: context.go('/rooms/settings'); diff --git a/macos/Podfile.lock b/macos/Podfile.lock index a4387410d..e803f9595 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,6 +1,4 @@ PODS: - - app_links (6.4.1): - - FlutterMacOS - audio_session (0.0.1): - FlutterMacOS - desktop_drop (0.0.1): @@ -76,7 +74,6 @@ PODS: - FlutterMacOS DEPENDENCIES: - - app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`) - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - desktop_webview_window (from `Flutter/ephemeral/.symlinks/plugins/desktop_webview_window/macos`) @@ -114,8 +111,6 @@ SPEC REPOS: - WebRTC-SDK EXTERNAL SOURCES: - app_links: - :path: Flutter/ephemeral/.symlinks/plugins/app_links/macos audio_session: :path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos desktop_drop: @@ -178,7 +173,6 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos SPEC CHECKSUMS: - app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e desktop_drop: 10a3e6a7fa9dbe350541f2574092fecfa345a07b desktop_webview_window: 7e37af677d6d19294cb433d9b1d878ef78dffa4d @@ -187,7 +181,7 @@ SPEC CHECKSUMS: emoji_picker_flutter: 51ca408e289d84d1e460016b2a28721ec754fcf7 file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7 - flutter_local_notifications: 4bf37a31afde695b56091b4ae3e4d9c7a7e6cda0 + flutter_local_notifications: 1fc7ffb10a83d6a2eeeeddb152d43f1944b0aad0 flutter_new_badger: 6fe9bf7e42793a164032c21f164c0ad9985cd0f2 flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23 flutter_vodozemac: fd2ea9cb3e2a37beaac883a369811fbfe042fc53