💄 Localized about page
This commit is contained in:
parent
14183a7316
commit
13ea182707
@ -587,7 +587,7 @@
|
|||||||
"no": "No",
|
"no": "No",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"navigateToChat": "Navigate to Chat",
|
"navigateToChat": "Navigate to Chat",
|
||||||
"wouldYouLikeToNavigateToChat": "Would you like to navigate to the chat?",
|
"wouldYouLikeToNavigateToChat": "Would You like to navigate to the chat?",
|
||||||
"abuseReport": "Report",
|
"abuseReport": "Report",
|
||||||
"abuseReportTitle": "Report Content",
|
"abuseReportTitle": "Report Content",
|
||||||
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
||||||
@ -672,5 +672,23 @@
|
|||||||
"membershipCancel": "Cancel Membership",
|
"membershipCancel": "Cancel Membership",
|
||||||
"membershipCancelConfirm": "Are you sure to cancel your membership?",
|
"membershipCancelConfirm": "Are you sure to cancel your membership?",
|
||||||
"membershipCancelHint": "Are you sure to cancel your membership? You will not be charged again. Your membership will remain active until the end of the current billing period. And you will not able to resubscribe until the end of the current subscription ends.",
|
"membershipCancelHint": "Are you sure to cancel your membership? You will not be charged again. Your membership will remain active until the end of the current billing period. And you will not able to resubscribe until the end of the current subscription ends.",
|
||||||
"membershipCancelSuccess": "Your membership has been successfully canceled."
|
"membershipCancelSuccess": "Your membership has been successfully canceled.",
|
||||||
|
"aboutScreenTitle": "About",
|
||||||
|
"aboutScreenVersionInfo": "Version {} ({})",
|
||||||
|
"aboutScreenAppInfoSectionTitle": "App Information",
|
||||||
|
"aboutScreenPackageNameLabel": "Package Name",
|
||||||
|
"aboutScreenVersionLabel": "Version",
|
||||||
|
"aboutScreenBuildNumberLabel": "Build Number",
|
||||||
|
"aboutScreenLinksSectionTitle": "Links",
|
||||||
|
"aboutScreenPrivacyPolicyTitle": "Privacy Policy",
|
||||||
|
"aboutScreenTermsOfServiceTitle": "Terms of Service",
|
||||||
|
"aboutScreenOpenSourceLicensesTitle": "Open Source Licenses",
|
||||||
|
"aboutScreenDeveloperSectionTitle": "Developer",
|
||||||
|
"aboutScreenContactUsTitle": "Contact Us",
|
||||||
|
"aboutScreenLicenseTitle": "License",
|
||||||
|
"aboutScreenLicenseContent": "All copyright reserved © {} Solsynth\nOpen-sourced under license GNU AGPL v3.0",
|
||||||
|
"aboutScreenCopyright": "© {} {}. All rights reserved.",
|
||||||
|
"aboutScreenFailedToLoadPackageInfo": "Failed to load package info: {error}",
|
||||||
|
"copiedToClipboard": "Copied to clipboard",
|
||||||
|
"copyToClipboardTooltip": "Copy to clipboard"
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.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:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
class AboutScreen extends StatefulWidget {
|
class AboutScreen extends StatefulWidget {
|
||||||
const AboutScreen({super.key});
|
const AboutScreen({super.key});
|
||||||
@ -12,8 +14,8 @@ class AboutScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _AboutScreenState extends State<AboutScreen> {
|
class _AboutScreenState extends State<AboutScreen> {
|
||||||
PackageInfo _packageInfo = PackageInfo(
|
PackageInfo _packageInfo = PackageInfo(
|
||||||
appName: 'Island',
|
appName: 'Solian',
|
||||||
packageName: 'com.example.island',
|
packageName: 'dev.solsynth.solian',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
buildNumber: '1',
|
buildNumber: '1',
|
||||||
);
|
);
|
||||||
@ -38,7 +40,9 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_errorMessage = 'Failed to load package info: $e';
|
_errorMessage = 'aboutScreenFailedToLoadPackageInfo'.tr(
|
||||||
|
args: [e.toString()],
|
||||||
|
);
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -57,7 +61,7 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('About'), elevation: 0),
|
appBar: AppBar(title: Text('about'.tr()), elevation: 0),
|
||||||
body:
|
body:
|
||||||
_isLoading
|
_isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
@ -88,7 +92,9 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Version ${_packageInfo.version} (${_packageInfo.buildNumber})',
|
'aboutScreenVersionInfo'.tr(
|
||||||
|
args: [_packageInfo.version, _packageInfo.buildNumber],
|
||||||
|
),
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
color: theme.textTheme.bodySmall?.color,
|
color: theme.textTheme.bodySmall?.color,
|
||||||
),
|
),
|
||||||
@ -98,24 +104,24 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
// App Info Card
|
// App Info Card
|
||||||
_buildSection(
|
_buildSection(
|
||||||
context,
|
context,
|
||||||
title: 'App Information',
|
title: 'aboutScreenAppInfoSectionTitle'.tr(),
|
||||||
children: [
|
children: [
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
context,
|
context,
|
||||||
icon: Icons.info_outline,
|
icon: Icons.info_outline,
|
||||||
label: 'Package Name',
|
label: 'aboutScreenPackageNameLabel'.tr(),
|
||||||
value: _packageInfo.packageName,
|
value: _packageInfo.packageName,
|
||||||
),
|
),
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
context,
|
context,
|
||||||
icon: Icons.update,
|
icon: Icons.update,
|
||||||
label: 'Version',
|
label: 'aboutScreenVersionLabel'.tr(),
|
||||||
value: _packageInfo.version,
|
value: _packageInfo.version,
|
||||||
),
|
),
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
context,
|
context,
|
||||||
icon: Icons.build,
|
icon: Icons.build,
|
||||||
label: 'Build Number',
|
label: 'aboutScreenBuildNumberLabel'.tr(),
|
||||||
value: _packageInfo.buildNumber,
|
value: _packageInfo.buildNumber,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -126,12 +132,12 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
// Links Card
|
// Links Card
|
||||||
_buildSection(
|
_buildSection(
|
||||||
context,
|
context,
|
||||||
title: 'Links',
|
title: 'aboutScreenLinksSectionTitle'.tr(),
|
||||||
children: [
|
children: [
|
||||||
_buildListTile(
|
_buildListTile(
|
||||||
context,
|
context,
|
||||||
icon: Icons.privacy_tip_outlined,
|
icon: Icons.privacy_tip_outlined,
|
||||||
title: 'Privacy Policy',
|
title: 'aboutScreenPrivacyPolicyTitle'.tr(),
|
||||||
onTap:
|
onTap:
|
||||||
() => _launchURL(
|
() => _launchURL(
|
||||||
'https://solsynth.dev/terms/privacy-policy',
|
'https://solsynth.dev/terms/privacy-policy',
|
||||||
@ -140,16 +146,16 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
_buildListTile(
|
_buildListTile(
|
||||||
context,
|
context,
|
||||||
icon: Icons.description_outlined,
|
icon: Icons.description_outlined,
|
||||||
title: 'Terms of Service',
|
title: 'aboutScreenTermsOfServiceTitle'.tr(),
|
||||||
onTap:
|
onTap:
|
||||||
() => _launchURL(
|
() => _launchURL(
|
||||||
'https://example.com/terms/basic-law',
|
'https://solsynth.dev/terms/basic-law',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_buildListTile(
|
_buildListTile(
|
||||||
context,
|
context,
|
||||||
icon: Icons.code,
|
icon: Icons.code,
|
||||||
title: 'Open Source Licenses',
|
title: 'aboutScreenOpenSourceLicensesTitle'.tr(),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showLicensePage(
|
showLicensePage(
|
||||||
context: context,
|
context: context,
|
||||||
@ -167,21 +173,22 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
// Developer Info
|
// Developer Info
|
||||||
_buildSection(
|
_buildSection(
|
||||||
context,
|
context,
|
||||||
title: 'Developer',
|
title: 'aboutScreenDeveloperSectionTitle'.tr(),
|
||||||
children: [
|
children: [
|
||||||
_buildListTile(
|
_buildListTile(
|
||||||
context,
|
context,
|
||||||
icon: Icons.email_outlined,
|
icon: Icons.email_outlined,
|
||||||
title: 'Contact Us',
|
title: 'aboutScreenContactUsTitle'.tr(),
|
||||||
subtitle: 'lily@solsynth.dev',
|
subtitle: 'lily@solsynth.dev',
|
||||||
onTap: () => _launchURL('mailto:lily@solsynth.dev'),
|
onTap: () => _launchURL('mailto:lily@solsynth.dev'),
|
||||||
),
|
),
|
||||||
_buildListTile(
|
_buildListTile(
|
||||||
context,
|
context,
|
||||||
icon: Icons.copyright,
|
icon: Icons.copyright,
|
||||||
title: 'License',
|
title: 'aboutScreenLicenseTitle'.tr(),
|
||||||
subtitle:
|
subtitle: 'aboutScreenLicenseContent'.tr(
|
||||||
'Copyright reserved © ${DateTime.now().year} Solsynth\nGNU Affero General Public License v3.0',
|
args: [DateTime.now().year.toString()],
|
||||||
|
),
|
||||||
onTap:
|
onTap:
|
||||||
() => _launchURL(
|
() => _launchURL(
|
||||||
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
||||||
@ -196,7 +203,9 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'© ${DateTime.now().year} ${_packageInfo.appName}. All rights reserved.',
|
'aboutScreenCopyright'.tr(
|
||||||
|
args: [DateTime.now().year.toString(), "Solsynth"],
|
||||||
|
),
|
||||||
style: theme.textTheme.bodySmall,
|
style: theme.textTheme.bodySmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
@ -264,12 +273,12 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Clipboard.setData(ClipboardData(text: value));
|
Clipboard.setData(ClipboardData(text: value));
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Copied to clipboard')),
|
SnackBar(content: Text('copiedToClipboard'.tr())),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
constraints: const BoxConstraints(),
|
constraints: const BoxConstraints(),
|
||||||
tooltip: 'Copy to clipboard',
|
tooltip: 'copyToClipboardTooltip'.tr(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -283,13 +292,18 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||||||
String? subtitle,
|
String? subtitle,
|
||||||
required VoidCallback onTap,
|
required VoidCallback onTap,
|
||||||
}) {
|
}) {
|
||||||
|
final multipleLines = subtitle?.contains('\n') ?? false;
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(icon),
|
leading: Icon(icon).padding(top: multipleLines ? 8 : 0),
|
||||||
title: Text(title),
|
title: Text(title),
|
||||||
subtitle: subtitle != null ? Text(subtitle) : null,
|
subtitle: subtitle != null ? Text(subtitle) : null,
|
||||||
trailing: const Icon(Icons.chevron_right),
|
isThreeLine: multipleLines,
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.chevron_right,
|
||||||
|
).padding(top: multipleLines ? 8 : 0),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
minLeadingWidth: 24,
|
minLeadingWidth: 24,
|
||||||
|
@ -9,7 +9,6 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:island/widgets/post/post_quick_reply.dart';
|
import 'package:island/widgets/post/post_quick_reply.dart';
|
||||||
import 'package:island/widgets/post/post_replies.dart';
|
import 'package:island/widgets/post/post_replies.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _formatFileSize(int bytes) {
|
String formatFileSize(int bytes) {
|
||||||
if (bytes <= 0) return '0 B';
|
if (bytes <= 0) return '0 B';
|
||||||
if (bytes < 1024) return '$bytes B';
|
if (bytes < 1024) return '$bytes B';
|
||||||
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB';
|
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB';
|
||||||
@ -274,7 +274,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
buildInfoRow(
|
buildInfoRow(
|
||||||
Icons.storage,
|
Icons.storage,
|
||||||
'Size',
|
'Size',
|
||||||
_formatFileSize(item.size),
|
formatFileSize(item.size),
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
buildInfoRow(
|
buildInfoRow(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user