✨ Debug options
This commit is contained in:
@@ -102,235 +102,243 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: _errorMessage != null
|
||||
? Center(child: Text(_errorMessage!))
|
||||
: 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,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
_packageInfo.appName,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'aboutScreenVersionInfo'.tr(
|
||||
args: [_packageInfo.version, _packageInfo.buildNumber],
|
||||
),
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.textTheme.bodySmall?.color,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// App Info Card
|
||||
_buildSection(
|
||||
context,
|
||||
title: 'aboutScreenAppInfoSectionTitle'.tr(),
|
||||
: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 540),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (_deviceInfo != null) const SizedBox(height: 16),
|
||||
|
||||
if (_deviceInfo != null)
|
||||
_buildSection(
|
||||
context,
|
||||
title: 'Device Information',
|
||||
children: [
|
||||
_buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.label,
|
||||
label: 'aboutDeviceName'.tr(),
|
||||
value: _deviceInfo?.data['name'],
|
||||
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,
|
||||
),
|
||||
_buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.fingerprint,
|
||||
label: 'aboutDeviceIdentifier'.tr(),
|
||||
value: _deviceUdid ?? 'N/A',
|
||||
copyable: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
_packageInfo.appName,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'aboutScreenVersionInfo'.tr(
|
||||
args: [
|
||||
_packageInfo.version,
|
||||
_packageInfo.buildNumber,
|
||||
],
|
||||
),
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.textTheme.bodySmall?.color,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Links Card
|
||||
_buildSection(
|
||||
context,
|
||||
title: 'aboutScreenLinksSectionTitle'.tr(),
|
||||
children: [
|
||||
_buildListTile(
|
||||
// App Info Card
|
||||
_buildSection(
|
||||
context,
|
||||
icon: Symbols.system_update,
|
||||
title: 'Check for updates',
|
||||
onTap: () async {
|
||||
// Fetch latest release and show the unified sheet
|
||||
final svc = UpdateService();
|
||||
// Reuse service fetch + compare to decide content
|
||||
final release = await svc.fetchLatestRelease();
|
||||
if (release != null) {
|
||||
await svc.showUpdateSheet(context, release);
|
||||
} else {
|
||||
// Fallback: show a simple sheet indicating no info
|
||||
// Use your SheetScaffold for consistent styling
|
||||
// Show a minimal message
|
||||
// ignore: use_build_context_synchronously
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
showDragHandle: true,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.surface,
|
||||
builder:
|
||||
(_) => const SheetScaffold(
|
||||
titleText: 'Update',
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Text(
|
||||
'Unable to fetch release info at this time.',
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (_deviceInfo != null) const SizedBox(height: 16),
|
||||
|
||||
if (_deviceInfo != null)
|
||||
_buildSection(
|
||||
context,
|
||||
title: 'Device Information',
|
||||
children: [
|
||||
_buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.label,
|
||||
label: 'aboutDeviceName'.tr(),
|
||||
value: _deviceInfo?.data['name'],
|
||||
),
|
||||
_buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.fingerprint,
|
||||
label: 'aboutDeviceIdentifier'.tr(),
|
||||
value: _deviceUdid ?? 'N/A',
|
||||
copyable: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Links Card
|
||||
_buildSection(
|
||||
context,
|
||||
title: 'aboutScreenLinksSectionTitle'.tr(),
|
||||
children: [
|
||||
_buildListTile(
|
||||
context,
|
||||
icon: Symbols.system_update,
|
||||
title: 'Check for updates',
|
||||
onTap: () async {
|
||||
// Fetch latest release and show the unified sheet
|
||||
final svc = UpdateService();
|
||||
// Reuse service fetch + compare to decide content
|
||||
final release = await svc.fetchLatestRelease();
|
||||
if (release != null) {
|
||||
await svc.showUpdateSheet(context, release);
|
||||
} else {
|
||||
// Fallback: show a simple sheet indicating no info
|
||||
// Use your SheetScaffold for consistent styling
|
||||
// Show a minimal message
|
||||
// ignore: use_build_context_synchronously
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
showDragHandle: true,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.surface,
|
||||
builder:
|
||||
(_) => const SheetScaffold(
|
||||
titleText: 'Update',
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Text(
|
||||
'Unable to fetch release info at this time.',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
_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(
|
||||
args: [DateTime.now().year.toString()],
|
||||
),
|
||||
onTap:
|
||||
() => _launchURL(
|
||||
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
||||
),
|
||||
),
|
||||
if (kIsWeb || !(Platform.isMacOS || Platform.isIOS))
|
||||
_buildListTile(
|
||||
context,
|
||||
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()],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
style: theme.textTheme.bodySmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const Gap(1),
|
||||
Text(
|
||||
'aboutScreenMadeWith'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
).fontSize(10).opacity(0.8),
|
||||
],
|
||||
),
|
||||
),
|
||||
_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}',
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Gap(MediaQuery.of(context).padding.bottom + 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'),
|
||||
),
|
||||
_buildListTile(
|
||||
context,
|
||||
icon: Symbols.copyright,
|
||||
title: 'aboutScreenLicenseTitle'.tr(),
|
||||
subtitle: 'aboutScreenLicenseContent'.tr(
|
||||
args: [DateTime.now().year.toString()],
|
||||
),
|
||||
onTap:
|
||||
() => _launchURL(
|
||||
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
||||
),
|
||||
),
|
||||
if (kIsWeb || !(Platform.isMacOS || Platform.isIOS))
|
||||
_buildListTile(
|
||||
context,
|
||||
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()],
|
||||
),
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@@ -1,12 +1,8 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/message.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/screens/notification.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
@@ -15,6 +11,7 @@ import 'package:island/widgets/account/status.dart';
|
||||
import 'package:island/widgets/account/leveling_progress.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/debug_sheet.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
@@ -276,30 +273,6 @@ class AccountScreen extends HookConsumerWidget {
|
||||
context.pushNamed('accountSettings');
|
||||
},
|
||||
),
|
||||
if (kDebugMode) const Divider(height: 1).padding(vertical: 8),
|
||||
if (kDebugMode)
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.copy_all),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('Copy access token'),
|
||||
onTap: () async {
|
||||
final tk = ref.watch(tokenProvider);
|
||||
Clipboard.setData(ClipboardData(text: tk!.token));
|
||||
},
|
||||
),
|
||||
if (kDebugMode)
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.delete),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('Reset database'),
|
||||
onTap: () async {
|
||||
resetDatabase(ref);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1).padding(vertical: 8),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
@@ -311,6 +284,19 @@ class AccountScreen extends HookConsumerWidget {
|
||||
context.pushNamed('about');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.bug_report),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('debugOptions').tr(),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => DebugSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.logout),
|
||||
|
76
lib/widgets/debug_sheet.dart
Normal file
76
lib/widgets/debug_sheet.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/message.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/websocket.dart';
|
||||
import 'package:island/widgets/content/network_status_sheet.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
class DebugSheet extends HookConsumerWidget {
|
||||
const DebugSheet({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final wsNotifier = ref.watch(websocketStateProvider.notifier);
|
||||
|
||||
return SheetScaffold(
|
||||
titleText: 'Debug',
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.wifi),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
title: Text('Connection Status'),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder:
|
||||
(context) => NetworkStatusSheet(
|
||||
onReconnect: () => wsNotifier.connect(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.copy_all),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('Copy access token'),
|
||||
onTap: () async {
|
||||
final tk = ref.watch(tokenProvider);
|
||||
Clipboard.setData(ClipboardData(text: tk!.token));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.delete),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('Reset database'),
|
||||
onTap: () async {
|
||||
resetDatabase(ref);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.clear),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('Clear cache'),
|
||||
onTap: () async {
|
||||
DefaultCacheManager().emptyCache();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user