🗑️ Clean up about page

This commit is contained in:
2025-12-21 16:01:12 +08:00
parent 59c34ada40
commit 30b2c0a0b4
4 changed files with 280 additions and 286 deletions

View File

@@ -720,7 +720,7 @@
"aboutScreenDeveloperSectionTitle": "Developer", "aboutScreenDeveloperSectionTitle": "Developer",
"aboutScreenContactUsTitle": "Contact Us", "aboutScreenContactUsTitle": "Contact Us",
"aboutScreenLicenseTitle": "License", "aboutScreenLicenseTitle": "License",
"aboutScreenLicenseContent": "GNU Affero General Public License v3.0", "aboutScreenLicenseContent": "AGPLv3",
"aboutScreenCopyright": "All rights reserved © Solsynth {}", "aboutScreenCopyright": "All rights reserved © Solsynth {}",
"aboutScreenMadeWith": "Made with ❤︎️ by Solar Network Team", "aboutScreenMadeWith": "Made with ❤︎️ by Solar Network Team",
"aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}", "aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}",

View File

@@ -705,7 +705,7 @@
"aboutScreenDeveloperSectionTitle": "开发者", "aboutScreenDeveloperSectionTitle": "开发者",
"aboutScreenContactUsTitle": "联系我们", "aboutScreenContactUsTitle": "联系我们",
"aboutScreenLicenseTitle": "许可", "aboutScreenLicenseTitle": "许可",
"aboutScreenLicenseContent": "无法翻译", "aboutScreenLicenseContent": "AGPLv3",
"aboutScreenCopyright": "版权所有 © Solsynth {}", "aboutScreenCopyright": "版权所有 © Solsynth {}",
"aboutScreenMadeWith": "由 Solar Network 团队用 ❤︎️ 制作", "aboutScreenMadeWith": "由 Solar Network 团队用 ❤︎️ 制作",
"aboutScreenFailedToLoadPackageInfo": "无法加载包信息:{error}", "aboutScreenFailedToLoadPackageInfo": "无法加载包信息:{error}",

View File

@@ -12,7 +12,6 @@ import 'package:island/widgets/app_scaffold.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:island/services/update_service.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@@ -97,232 +96,213 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
return AppScaffold( return AppScaffold(
isNoBackground: false, isNoBackground: false,
appBar: AppBar(title: Text('about'.tr()), elevation: 0), appBar: AppBar(title: Text('about'.tr()), elevation: 0),
body: body: _isLoading
_isLoading ? const Center(child: CircularProgressIndicator())
? const Center(child: CircularProgressIndicator()) : _errorMessage != null
: _errorMessage != null ? Center(child: Text(_errorMessage!))
? Center(child: Text(_errorMessage!)) : Center(
: Center( child: ConstrainedBox(
child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 540),
constraints: const BoxConstraints(maxWidth: 540), child: SingleChildScrollView(
child: SingleChildScrollView( child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, children: [
children: [ const SizedBox(height: 24),
const SizedBox(height: 24), // App Icon and Name
// App Icon and Name CircleAvatar(
CircleAvatar( radius: 50,
radius: 50, backgroundColor: theme.colorScheme.primary.withOpacity(
backgroundColor: theme.colorScheme.primary 0.1,
.withOpacity(0.1),
child: Image.asset(
'assets/icons/icon.png',
width: 56,
height: 56,
),
), ),
const SizedBox(height: 16), child: Image.asset(
Text( 'assets/icons/icon.png',
_packageInfo.appName, width: 56,
style: theme.textTheme.headlineSmall?.copyWith( height: 56,
fontWeight: FontWeight.bold,
),
), ),
Text( ),
'aboutScreenVersionInfo'.tr( const SizedBox(height: 16),
args: [ Text(
_packageInfo.version, _packageInfo.appName,
_packageInfo.buildNumber, style: theme.textTheme.headlineSmall?.copyWith(
], fontWeight: FontWeight.bold,
),
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.textTheme.bodySmall?.color,
),
), ),
const SizedBox(height: 32), ),
Text(
// App Info Card 'aboutScreenVersionInfo'.tr(
_buildSection( args: [
context, _packageInfo.version,
title: 'aboutScreenAppInfoSectionTitle'.tr(), _packageInfo.buildNumber,
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,
),
], ],
), ),
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.textTheme.bodySmall?.color,
),
),
const SizedBox(height: 32),
if (_deviceInfo != null) const SizedBox(height: 16), // App Info Card
_buildSection(
if (_deviceInfo != null) context,
_buildSection( title: 'aboutScreenAppInfoSectionTitle'.tr(),
children: [
_buildInfoItem(
context, context,
title: 'Device Information', icon: Symbols.info,
children: [ label: 'aboutScreenPackageNameLabel'.tr(),
FutureBuilder<String>( value: _packageInfo.packageName,
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,
),
],
), ),
_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( _buildSection(
context, context,
title: 'aboutScreenLinksSectionTitle'.tr(), title: 'Device Information',
children: [ children: [
_buildListTile( FutureBuilder<String>(
context, future: udid.getDeviceName(),
icon: Symbols.system_update, builder: (context, snapshot) {
title: 'Check for updates', final value = snapshot.hasData
onTap: () async { ? snapshot.data!
final svc = UpdateService(); : 'unknown'.tr();
showLoadingModal(context); return _buildInfoItem(
svc.checkForUpdates(context); context,
if (!context.mounted) return; icon: Symbols.label,
hideLoadingModal(context); label: 'aboutDeviceName'.tr(),
}, value: value,
),
_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}',
); );
}, },
), ),
_buildInfoItem(
context,
icon: Symbols.fingerprint,
label: 'aboutDeviceIdentifier'.tr(),
value: _deviceUdid ?? 'N/A',
copyable: true,
),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// Developer Info // Links Card
_buildSection( _buildSection(
context, context,
title: 'aboutScreenDeveloperSectionTitle'.tr(), title: 'aboutScreenLinksSectionTitle'.tr(),
children: [ children: [
_buildListTile( _buildListTile(
context, context,
icon: Symbols.email, icon: Symbols.privacy_tip,
title: 'aboutScreenContactUsTitle'.tr(), title: 'aboutScreenPrivacyPolicyTitle'.tr(),
subtitle: 'lily@solsynth.dev', onTap: () => _launchURL(
onTap: 'https://solsynth.dev/terms/privacy-policy',
() => _launchURL('mailto:lily@solsynth.dev'),
), ),
),
_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( _buildListTile(
context, context,
icon: Symbols.copyright, icon: Symbols.favorite,
title: 'aboutScreenLicenseTitle'.tr(), title: 'donate'.tr(),
subtitle: 'aboutScreenLicenseContent'.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()], args: [DateTime.now().year.toString()],
), ),
onTap: style: theme.textTheme.bodySmall,
() => _launchURL( textAlign: TextAlign.center,
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
),
), ),
if (kIsWeb || !(Platform.isMacOS || Platform.isIOS)) const Gap(1),
_buildListTile( Text(
context, 'aboutScreenMadeWith'.tr(),
icon: Symbols.favorite, textAlign: TextAlign.center,
title: 'donate'.tr(), ).fontSize(10).opacity(0.8),
subtitle: 'donateDescription'.tr(),
onTap: () {
launchUrlString(
'https://afdian.com/@littlesheep',
);
},
),
], ],
), ),
),
const SizedBox(height: 32), Gap(MediaQuery.of(context).padding.bottom + 16),
],
// 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),
],
),
), ),
), ),
), ),
),
); );
} }

View File

@@ -352,99 +352,113 @@ class AccountScreen extends HookConsumerWidget {
}, },
), ),
), ),
ListTile( Builder(
minTileHeight: 48, builder: (context) {
leading: const Icon(Symbols.notifications), final menuItems = [
trailing: const Icon(Symbols.chevron_right), {
contentPadding: EdgeInsets.symmetric(horizontal: 24), 'icon': Symbols.notifications,
title: Row( 'title': 'notifications',
children: [ 'badgeCount': notificationUnreadCount.value ?? 0,
Expanded(child: Text('notifications').tr()), 'onTap': () {
Badge.count( showModalBottomSheet(
count: notificationUnreadCount.value ?? 0, context: context,
isLabelVisible: (notificationUnreadCount.value ?? 0) > 0, 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,
), ),
], itemCount: menuItems.length,
), itemBuilder: (context, index) {
onTap: () { final item = menuItems[index];
showModalBottomSheet( final icon = item['icon'] as IconData;
context: context, final title = item['title'] as String;
isScrollControlled: true, final badgeCount = item['badgeCount'] as int?;
useRootNavigator: true, final onTap = item['onTap'] as VoidCallback?;
builder: (context) => const NotificationSheet(), 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), const Divider(height: 1).padding(vertical: 8),
ListTile( ListTile(
minTileHeight: 48, minTileHeight: 48,