From 30b2c0a0b47417b2d520379c365f0890c9652794 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 21 Dec 2025 16:01:12 +0800 Subject: [PATCH] :wastebasket: Clean up about page --- assets/i18n/en-US.json | 2 +- assets/i18n/zh-CN.json | 2 +- lib/screens/about.dart | 370 ++++++++++++++++++--------------------- lib/screens/account.dart | 192 ++++++++++---------- 4 files changed, 280 insertions(+), 286 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index d56953a9..93896417 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -720,7 +720,7 @@ "aboutScreenDeveloperSectionTitle": "Developer", "aboutScreenContactUsTitle": "Contact Us", "aboutScreenLicenseTitle": "License", - "aboutScreenLicenseContent": "GNU Affero General Public License v3.0", + "aboutScreenLicenseContent": "AGPLv3", "aboutScreenCopyright": "All rights reserved © Solsynth {}", "aboutScreenMadeWith": "Made with ❤︎️ by Solar Network Team", "aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}", diff --git a/assets/i18n/zh-CN.json b/assets/i18n/zh-CN.json index 9c5e99ae..fd83f2da 100644 --- a/assets/i18n/zh-CN.json +++ b/assets/i18n/zh-CN.json @@ -705,7 +705,7 @@ "aboutScreenDeveloperSectionTitle": "开发者", "aboutScreenContactUsTitle": "联系我们", "aboutScreenLicenseTitle": "许可", - "aboutScreenLicenseContent": "无法翻译", + "aboutScreenLicenseContent": "AGPLv3", "aboutScreenCopyright": "版权所有 © Solsynth {}", "aboutScreenMadeWith": "由 Solar Network 团队用 ❤︎️ 制作", "aboutScreenFailedToLoadPackageInfo": "无法加载包信息:{error}", diff --git a/lib/screens/about.dart b/lib/screens/about.dart index 2c1c02ea..e063e47c 100644 --- a/lib/screens/about.dart +++ b/lib/screens/about.dart @@ -12,7 +12,6 @@ import 'package:island/widgets/app_scaffold.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:styled_widget/styled_widget.dart'; -import 'package:island/services/update_service.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -97,232 +96,213 @@ class _AboutScreenState extends ConsumerState { return AppScaffold( isNoBackground: false, appBar: AppBar(title: Text('about'.tr()), elevation: 0), - body: - _isLoading - ? const Center(child: CircularProgressIndicator()) - : _errorMessage != null - ? Center(child: Text(_errorMessage!)) - : Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 540), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 24), - // App Icon and Name - CircleAvatar( - radius: 50, - backgroundColor: theme.colorScheme.primary - .withOpacity(0.1), - child: Image.asset( - 'assets/icons/icon.png', - width: 56, - height: 56, - ), + body: _isLoading + ? const Center(child: CircularProgressIndicator()) + : _errorMessage != null + ? Center(child: Text(_errorMessage!)) + : Center( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 540), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 24), + // App Icon and Name + CircleAvatar( + radius: 50, + backgroundColor: theme.colorScheme.primary.withOpacity( + 0.1, ), - const SizedBox(height: 16), - Text( - _packageInfo.appName, - style: theme.textTheme.headlineSmall?.copyWith( - fontWeight: FontWeight.bold, - ), + child: Image.asset( + 'assets/icons/icon.png', + width: 56, + height: 56, ), - Text( - 'aboutScreenVersionInfo'.tr( - args: [ - _packageInfo.version, - _packageInfo.buildNumber, - ], - ), - style: theme.textTheme.bodyMedium?.copyWith( - color: theme.textTheme.bodySmall?.color, - ), + ), + const SizedBox(height: 16), + Text( + _packageInfo.appName, + style: theme.textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.bold, ), - const SizedBox(height: 32), - - // App Info Card - _buildSection( - context, - title: 'aboutScreenAppInfoSectionTitle'.tr(), - children: [ - _buildInfoItem( - context, - icon: Symbols.info, - label: 'aboutScreenPackageNameLabel'.tr(), - value: _packageInfo.packageName, - ), - _buildInfoItem( - context, - icon: Symbols.update, - label: 'aboutScreenVersionLabel'.tr(), - value: _packageInfo.version, - ), - _buildInfoItem( - context, - icon: Symbols.build, - label: 'aboutScreenBuildNumberLabel'.tr(), - value: _packageInfo.buildNumber, - ), + ), + Text( + 'aboutScreenVersionInfo'.tr( + args: [ + _packageInfo.version, + _packageInfo.buildNumber, ], ), + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.textTheme.bodySmall?.color, + ), + ), + const SizedBox(height: 32), - if (_deviceInfo != null) const SizedBox(height: 16), - - if (_deviceInfo != null) - _buildSection( + // App Info Card + _buildSection( + context, + title: 'aboutScreenAppInfoSectionTitle'.tr(), + children: [ + _buildInfoItem( context, - title: 'Device Information', - children: [ - FutureBuilder( - future: udid.getDeviceName(), - builder: (context, snapshot) { - final value = - snapshot.hasData - ? snapshot.data! - : 'unknown'.tr(); - return _buildInfoItem( - context, - icon: Symbols.label, - label: 'aboutDeviceName'.tr(), - value: value, - ); - }, - ), - _buildInfoItem( - context, - icon: Symbols.fingerprint, - label: 'aboutDeviceIdentifier'.tr(), - value: _deviceUdid ?? 'N/A', - copyable: true, - ), - ], + icon: Symbols.info, + label: 'aboutScreenPackageNameLabel'.tr(), + value: _packageInfo.packageName, ), + _buildInfoItem( + context, + icon: Symbols.update, + label: 'aboutScreenVersionLabel'.tr(), + value: _packageInfo.version, + ), + _buildInfoItem( + context, + icon: Symbols.build, + label: 'aboutScreenBuildNumberLabel'.tr(), + value: _packageInfo.buildNumber, + ), + ], + ), - const SizedBox(height: 16), + if (_deviceInfo != null) const SizedBox(height: 16), - // Links Card + if (_deviceInfo != null) _buildSection( context, - title: 'aboutScreenLinksSectionTitle'.tr(), + title: 'Device Information', children: [ - _buildListTile( - context, - icon: Symbols.system_update, - title: 'Check for updates', - onTap: () async { - final svc = UpdateService(); - showLoadingModal(context); - svc.checkForUpdates(context); - if (!context.mounted) return; - hideLoadingModal(context); - }, - ), - _buildListTile( - context, - icon: Symbols.privacy_tip, - title: 'aboutScreenPrivacyPolicyTitle'.tr(), - onTap: - () => _launchURL( - 'https://solsynth.dev/terms/privacy-policy', - ), - ), - _buildListTile( - context, - icon: Symbols.description, - title: 'aboutScreenTermsOfServiceTitle'.tr(), - onTap: - () => _launchURL( - 'https://solsynth.dev/terms/user-agreement', - ), - ), - _buildListTile( - context, - icon: Symbols.code, - title: 'aboutScreenOpenSourceLicensesTitle'.tr(), - onTap: () { - showLicensePage( - context: context, - applicationName: _packageInfo.appName, - applicationVersion: - 'Version ${_packageInfo.version}', + FutureBuilder( + future: udid.getDeviceName(), + builder: (context, snapshot) { + final value = snapshot.hasData + ? snapshot.data! + : 'unknown'.tr(); + return _buildInfoItem( + context, + icon: Symbols.label, + label: 'aboutDeviceName'.tr(), + value: value, ); }, ), + _buildInfoItem( + context, + icon: Symbols.fingerprint, + label: 'aboutDeviceIdentifier'.tr(), + value: _deviceUdid ?? 'N/A', + copyable: true, + ), ], ), - const SizedBox(height: 16), + const SizedBox(height: 16), - // Developer Info - _buildSection( - context, - title: 'aboutScreenDeveloperSectionTitle'.tr(), - children: [ - _buildListTile( - context, - icon: Symbols.email, - title: 'aboutScreenContactUsTitle'.tr(), - subtitle: 'lily@solsynth.dev', - onTap: - () => _launchURL('mailto:lily@solsynth.dev'), + // Links Card + _buildSection( + context, + title: 'aboutScreenLinksSectionTitle'.tr(), + children: [ + _buildListTile( + context, + icon: Symbols.privacy_tip, + title: 'aboutScreenPrivacyPolicyTitle'.tr(), + onTap: () => _launchURL( + 'https://solsynth.dev/terms/privacy-policy', ), + ), + _buildListTile( + context, + icon: Symbols.description, + title: 'aboutScreenTermsOfServiceTitle'.tr(), + onTap: () => _launchURL( + 'https://solsynth.dev/terms/user-agreement', + ), + ), + _buildListTile( + context, + icon: Symbols.code, + title: 'aboutScreenOpenSourceLicensesTitle'.tr(), + onTap: () { + showLicensePage( + context: context, + applicationName: _packageInfo.appName, + applicationVersion: + 'Version ${_packageInfo.version}', + ); + }, + ), + ], + ), + + const SizedBox(height: 16), + + // Developer Info + _buildSection( + context, + title: 'aboutScreenDeveloperSectionTitle'.tr(), + children: [ + _buildListTile( + context, + icon: Symbols.email, + title: 'aboutScreenContactUsTitle'.tr(), + subtitle: 'lily@solsynth.dev', + onTap: () => _launchURL('mailto:lily@solsynth.dev'), + ), + _buildListTile( + context, + icon: Symbols.copyright, + title: 'aboutScreenLicenseTitle'.tr(), + subtitle: 'aboutScreenLicenseContent'.tr(), + onTap: () => _launchURL( + 'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt', + ), + ), + if (kIsWeb || !(Platform.isMacOS || Platform.isIOS)) _buildListTile( context, - icon: Symbols.copyright, - title: 'aboutScreenLicenseTitle'.tr(), - subtitle: 'aboutScreenLicenseContent'.tr( + icon: Symbols.favorite, + title: 'donate'.tr(), + subtitle: 'donateDescription'.tr(), + onTap: () { + launchUrlString( + 'https://afdian.com/@littlesheep', + ); + }, + ), + ], + ), + + const SizedBox(height: 32), + + // Copyright + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Text( + 'aboutScreenCopyright'.tr( args: [DateTime.now().year.toString()], ), - onTap: - () => _launchURL( - 'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt', - ), + style: theme.textTheme.bodySmall, + textAlign: TextAlign.center, ), - if (kIsWeb || !(Platform.isMacOS || Platform.isIOS)) - _buildListTile( - context, - icon: Symbols.favorite, - title: 'donate'.tr(), - subtitle: 'donateDescription'.tr(), - onTap: () { - launchUrlString( - 'https://afdian.com/@littlesheep', - ); - }, - ), + const Gap(1), + Text( + 'aboutScreenMadeWith'.tr(), + textAlign: TextAlign.center, + ).fontSize(10).opacity(0.8), ], ), + ), - const SizedBox(height: 32), - - // Copyright - Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - Text( - 'aboutScreenCopyright'.tr( - args: [DateTime.now().year.toString()], - ), - style: theme.textTheme.bodySmall, - textAlign: TextAlign.center, - ), - const Gap(1), - Text( - 'aboutScreenMadeWith'.tr(), - textAlign: TextAlign.center, - ).fontSize(10).opacity(0.8), - ], - ), - ), - - Gap(MediaQuery.of(context).padding.bottom + 16), - ], - ), + Gap(MediaQuery.of(context).padding.bottom + 16), + ], ), ), ), + ), ); } diff --git a/lib/screens/account.dart b/lib/screens/account.dart index d026cd8b..2a166bbc 100644 --- a/lib/screens/account.dart +++ b/lib/screens/account.dart @@ -352,99 +352,113 @@ class AccountScreen extends HookConsumerWidget { }, ), ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.notifications), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Row( - children: [ - Expanded(child: Text('notifications').tr()), - Badge.count( - count: notificationUnreadCount.value ?? 0, - isLabelVisible: (notificationUnreadCount.value ?? 0) > 0, + Builder( + builder: (context) { + final menuItems = [ + { + 'icon': Symbols.notifications, + 'title': 'notifications', + 'badgeCount': notificationUnreadCount.value ?? 0, + 'onTap': () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => const NotificationSheet(), + ); + }, + }, + { + 'icon': Symbols.files, + 'title': 'files', + 'onTap': () { + context.goNamed('files'); + }, + }, + { + 'icon': Symbols.group, + 'title': 'realms', + 'onTap': () { + context.goNamed('realmList'); + }, + }, + { + 'icon': Symbols.wallet, + 'title': 'wallet', + 'onTap': () { + context.pushNamed('wallet'); + }, + }, + { + 'icon': Symbols.people, + 'title': 'relationships', + 'onTap': () { + context.pushNamed('relationships'); + }, + }, + { + 'icon': Symbols.sticker_rounded, + 'title': 'stickers', + 'onTap': () { + context.pushNamed('stickerMarketplace'); + }, + }, + { + 'icon': Symbols.rss_feed, + 'title': 'webFeeds', + 'onTap': () { + context.pushNamed('webFeedMarketplace'); + }, + }, + { + 'icon': Symbols.gavel, + 'title': 'abuseReport', + 'onTap': () { + context.pushNamed('reportList'); + }, + }, + ]; + return GridView.builder( + padding: const EdgeInsets.symmetric(horizontal: 12), + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 80, + crossAxisSpacing: 8, + mainAxisSpacing: 8, ), - ], - ), - onTap: () { - showModalBottomSheet( - context: context, - isScrollControlled: true, - useRootNavigator: true, - builder: (context) => const NotificationSheet(), + itemCount: menuItems.length, + itemBuilder: (context, index) { + final item = menuItems[index]; + final icon = item['icon'] as IconData; + final title = item['title'] as String; + final badgeCount = item['badgeCount'] as int?; + final onTap = item['onTap'] as VoidCallback?; + return Card( + margin: EdgeInsets.zero, + child: Tooltip( + message: title.tr(), + child: InkWell( + borderRadius: BorderRadius.circular(8), + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, size: 28), + if (badgeCount != null && badgeCount > 0) + Badge.count(count: badgeCount), + ], + ), + ), + ), + ), + ); + }, ); }, ), - if (!isWideScreen(context)) - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.files), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('files').tr(), - onTap: () { - context.goNamed('files'); - }, - ), - if (!isWideScreen(context)) - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.group), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('realms').tr(), - onTap: () { - context.goNamed('realmList'); - }, - ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.wallet), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('wallet').tr(), - onTap: () { - context.pushNamed('wallet'); - }, - ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.people), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('relationships').tr(), - onTap: () { - context.pushNamed('relationships'); - }, - ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.sticker_rounded), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('stickers').tr(), - onTap: () { - context.pushNamed('stickerMarketplace'); - }, - ), - ListTile( - minTileHeight: 48, - leading: const Icon(Symbols.rss_feed), - trailing: const Icon(Symbols.chevron_right), - contentPadding: EdgeInsets.symmetric(horizontal: 24), - title: Text('webFeeds').tr(), - onTap: () { - context.pushNamed('webFeedMarketplace'); - }, - ), - ListTile( - minTileHeight: 48, - title: Text('abuseReport').tr(), - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.gavel), - trailing: const Icon(Symbols.chevron_right), - onTap: () => context.pushNamed('reportList'), - ), const Divider(height: 1).padding(vertical: 8), ListTile( minTileHeight: 48,