chore: Adjust support button design

This commit is contained in:
Christian Kußowski 2026-03-13 08:30:47 +01:00
parent eea4e431b4
commit 54ba19d39e
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
6 changed files with 83 additions and 14 deletions

View file

@ -37,8 +37,6 @@ abstract class AppConfig {
static const String supportUrl = static const String supportUrl =
'https://github.com/krille-chan/fluffychat/issues'; 'https://github.com/krille-chan/fluffychat/issues';
static const String changelogUrl = 'https://fluffy.chat/en/changelog/'; 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<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'}; static const Set<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'};

View file

@ -66,7 +66,9 @@ enum AppSettings<T> {
'https://fluffychat.im/en/privacy', 'https://fluffychat.im/en/privacy',
), ),
tos<String>('chat.fluffy.tos_url', 'https://fluffychat.im/en/tos'), tos<String>('chat.fluffy.tos_url', 'https://fluffychat.im/en/tos'),
sendTimelineEventTimeout<int>('chat.fluffy.send_timeline_event_timeout', 15); sendTimelineEventTimeout<int>('chat.fluffy.send_timeline_event_timeout', 15),
lastSeenSupportBanner<int>('chat.fluffy.last_seen_support_banner', 0),
supportBannerOptOut<bool>('chat.fluffy.support_banner_opt_out', false);
final String key; final String key;
final T defaultValue; final T defaultValue;

View file

@ -2782,5 +2782,10 @@
}, },
"createNewChat": "Create new chat", "createNewChat": "Create new chat",
"reset": "Reset", "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"
} }

View file

@ -10,6 +10,7 @@ import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart' as sdk;
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.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/config/app_config.dart';
import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/l10n/l10n.dart';
@ -366,6 +367,7 @@ class ChatListController extends State<ChatList>
_hackyWebRTCFixForWeb(); _hackyWebRTCFixForWeb();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
_showLastSeenSupportBanner();
searchServer = Matrix.of( searchServer = Matrix.of(
context, context,
).store.getString(_serverStoreNamespace); ).store.getString(_serverStoreNamespace);
@ -390,6 +392,73 @@ class ChatListController extends State<ChatList>
super.dispose(); super.dispose();
} }
Future<void> _showLastSeenSupportBanner() async {
if (AppSettings.supportBannerOptOut.value) return;
if (AppSettings.lastSeenSupportBanner.value == 0) {
await AppSettings.lastSeenSupportBanner.setItem(
DateTime.now().millisecondsSinceEpoch,
);
return;
}
final lastSeenSupportBanner = DateTime.fromMillisecondsSinceEpoch(
AppSettings.lastSeenSupportBanner.value,
);
if (DateTime.now().difference(lastSeenSupportBanner) >=
Duration(days: 6 * 7)) {
final 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<void> chatContextAction( Future<void> chatContextAction(
Room room, Room room,
BuildContext posContext, [ BuildContext posContext, [

View file

@ -4,7 +4,6 @@ import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:url_launcher/url_launcher_string.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/config/themes.dart';
import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
@ -83,7 +82,7 @@ class ClientChooserButton extends StatelessWidget {
value: SettingsAction.support, value: SettingsAction.support,
child: Row( child: Row(
children: [ children: [
Icon(Icons.volunteer_activism, color: Colors.red), Icon(Icons.favorite, color: Colors.red),
const SizedBox(width: 18), const SizedBox(width: 18),
Text(L10n.of(context).supportFluffyChat), Text(L10n.of(context).supportFluffyChat),
], ],
@ -223,7 +222,9 @@ class ClientChooserButton extends StatelessWidget {
FluffyShare.shareInviteLink(context); FluffyShare.shareInviteLink(context);
break; break;
case SettingsAction.support: case SettingsAction.support:
launchUrlString(AppConfig.donationUrl); launchUrlString(
'https://fluffychat.im/faq/#how_can_i_support_fluffychat',
);
break; break;
case SettingsAction.settings: case SettingsAction.settings:
context.go('/rooms/settings'); context.go('/rooms/settings');

View file

@ -1,6 +1,4 @@
PODS: PODS:
- app_links (6.4.1):
- FlutterMacOS
- audio_session (0.0.1): - audio_session (0.0.1):
- FlutterMacOS - FlutterMacOS
- desktop_drop (0.0.1): - desktop_drop (0.0.1):
@ -76,7 +74,6 @@ PODS:
- FlutterMacOS - FlutterMacOS
DEPENDENCIES: DEPENDENCIES:
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`) - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- desktop_webview_window (from `Flutter/ephemeral/.symlinks/plugins/desktop_webview_window/macos`) - desktop_webview_window (from `Flutter/ephemeral/.symlinks/plugins/desktop_webview_window/macos`)
@ -114,8 +111,6 @@ SPEC REPOS:
- WebRTC-SDK - WebRTC-SDK
EXTERNAL SOURCES: EXTERNAL SOURCES:
app_links:
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
audio_session: audio_session:
:path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos :path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
desktop_drop: desktop_drop:
@ -178,7 +173,6 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos :path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos
SPEC CHECKSUMS: SPEC CHECKSUMS:
app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f
audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e
desktop_drop: 10a3e6a7fa9dbe350541f2574092fecfa345a07b desktop_drop: 10a3e6a7fa9dbe350541f2574092fecfa345a07b
desktop_webview_window: 7e37af677d6d19294cb433d9b1d878ef78dffa4d desktop_webview_window: 7e37af677d6d19294cb433d9b1d878ef78dffa4d
@ -187,7 +181,7 @@ SPEC CHECKSUMS:
emoji_picker_flutter: 51ca408e289d84d1e460016b2a28721ec754fcf7 emoji_picker_flutter: 51ca408e289d84d1e460016b2a28721ec754fcf7
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7 file_selector_macos: 9e9e068e90ebee155097d00e89ae91edb2374db7
flutter_local_notifications: 4bf37a31afde695b56091b4ae3e4d9c7a7e6cda0 flutter_local_notifications: 1fc7ffb10a83d6a2eeeeddb152d43f1944b0aad0
flutter_new_badger: 6fe9bf7e42793a164032c21f164c0ad9985cd0f2 flutter_new_badger: 6fe9bf7e42793a164032c21f164c0ad9985cd0f2
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23 flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
flutter_vodozemac: fd2ea9cb3e2a37beaac883a369811fbfe042fc53 flutter_vodozemac: fd2ea9cb3e2a37beaac883a369811fbfe042fc53