replace about dialog and FAQ tile with bottom-pinned author and version footer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Tommy Chow 2026-03-05 23:31:32 -08:00
parent d500119219
commit 4ff331ec98
2 changed files with 116 additions and 57 deletions

View file

@ -4,15 +4,12 @@ import 'package:firebase_performance/firebase_performance.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:frosty/cache_manager.dart';
import 'package:frosty/screens/settings/stores/settings_store.dart';
import 'package:frosty/screens/settings/widgets/release_notes.dart';
import 'package:frosty/screens/settings/widgets/settings_list_switch.dart';
import 'package:frosty/widgets/alert_message.dart';
import 'package:frosty/widgets/frosty_dialog.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class OtherSettings extends StatefulWidget {
final SettingsStore settingsStore;
@ -63,27 +60,6 @@ class _OtherSettingsState extends State<OtherSettings> {
Widget build(BuildContext context) {
return Column(
children: [
ListTile(
leading: const Icon(Icons.info_outline_rounded),
title: const Text('About Frosty'),
onTap: () async {
final packageInfo = await PackageInfo.fromPlatform();
if (!context.mounted) return;
showAboutDialog(
context: context,
applicationIcon: SvgPicture.asset(
'assets/icons/logo.svg',
height: 80,
),
applicationName: packageInfo.appName,
applicationVersion:
'Version ${packageInfo.version} (${packageInfo.buildNumber})',
applicationLegalese: '\u{a9} 2026 Tommy Chow',
);
},
),
ListTile(
leading: const Icon(Icons.notes_rounded),
title: const Text('Release notes'),
@ -91,16 +67,6 @@ class _OtherSettingsState extends State<OtherSettings> {
context,
).push(MaterialPageRoute(builder: (context) => const ReleaseNotes())),
),
ListTile(
leading: const Icon(Icons.launch_rounded),
title: const Text('FAQ'),
onTap: () => launchUrl(
Uri.parse('https://www.frostyapp.io/#faq'),
mode: widget.settingsStore.launchUrlExternal
? LaunchMode.externalApplication
: LaunchMode.inAppBrowserView,
),
),
ListTile(
leading: const Icon(Icons.delete_outline_rounded),
title: const Text('Clear image cache'),

View file

@ -13,6 +13,7 @@ import 'package:frosty/screens/settings/widgets/settings_tile_route.dart';
import 'package:frosty/widgets/blurred_container.dart';
import 'package:frosty/widgets/frosty_scrollbar.dart';
import 'package:frosty/widgets/section_header.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:simple_icons/simple_icons.dart';
import 'package:url_launcher/url_launcher.dart';
@ -81,31 +82,123 @@ class Settings extends StatelessWidget {
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + kToolbarHeight,
),
child: ListView(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + kToolbarHeight + 8,
),
children: [
const SectionHeader('Account', isFirst: true),
ProfileCard(authStore: context.read<AuthStore>()),
const SectionHeader('Customize'),
SettingsTileRoute(
leading: const Icon(Icons.settings_outlined),
title: 'General',
child: GeneralSettings(settingsStore: settingsStore),
child: CustomScrollView(
slivers: [
SliverPadding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top +
kToolbarHeight +
8,
),
sliver: SliverList.list(
children: [
const SectionHeader('Account', isFirst: true),
ProfileCard(authStore: context.read<AuthStore>()),
const SectionHeader('Customize'),
SettingsTileRoute(
leading: const Icon(Icons.settings_outlined),
title: 'General',
child: GeneralSettings(settingsStore: settingsStore),
),
SettingsTileRoute(
leading: const Icon(Icons.tv_rounded),
title: 'Video',
child: VideoSettings(settingsStore: settingsStore),
),
SettingsTileRoute(
leading: const Icon(Icons.chat_outlined),
title: 'Chat',
child: ChatSettings(settingsStore: settingsStore),
),
const SectionHeader('Other'),
OtherSettings(settingsStore: settingsStore),
],
),
),
SettingsTileRoute(
leading: const Icon(Icons.tv_rounded),
title: 'Video',
child: VideoSettings(settingsStore: settingsStore),
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.bottomCenter,
child: FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (context, snapshot) {
final version = snapshot.data?.version ?? '';
final buildNumber = snapshot.data?.buildNumber ?? '';
final mutedColor = theme.colorScheme.onSurfaceVariant
.withValues(alpha: 0.5);
return Padding(
padding: EdgeInsets.only(
top: 16,
bottom: MediaQuery.of(context).padding.bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text.rich(
TextSpan(
style:
theme.textTheme.bodySmall?.copyWith(
color: mutedColor,
),
children: [
const TextSpan(text: 'Made by '),
WidgetSpan(
alignment:
PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: GestureDetector(
onTap: () => launchUrl(
Uri.parse(
'https://tommychow.com',
),
mode: settingsStore
.launchUrlExternal
? LaunchMode
.externalApplication
: LaunchMode
.inAppBrowserView,
),
child: Text(
'Tommy Chow',
style: theme.textTheme.bodySmall
?.copyWith(
color: mutedColor,
decoration:
TextDecoration.underline,
decorationColor: mutedColor,
),
),
),
),
],
),
),
const SizedBox(height: 4),
if (snapshot.hasData)
GestureDetector(
onTap: () => launchUrl(
Uri.parse(
'https://github.com/tommyxchow/frosty/releases/tag/v$version',
),
mode: settingsStore.launchUrlExternal
? LaunchMode.externalApplication
: LaunchMode.inAppBrowserView,
),
child: Text(
'v$version ($buildNumber)',
style:
theme.textTheme.bodySmall?.copyWith(
color: mutedColor,
),
),
),
],
),
);
},
),
),
),
SettingsTileRoute(
leading: const Icon(Icons.chat_outlined),
title: 'Chat',
child: ChatSettings(settingsStore: settingsStore),
),
const SectionHeader('Other'),
OtherSettings(settingsStore: settingsStore),
],
),
),