feat: use platform_ui widgets in option select page and use platform back button in title bar
This commit is contained in:
parent
3ed153fd37
commit
96e4f14e19
|
|
@ -1,14 +1,12 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
|
||||
import 'src/app.dart';
|
||||
import 'src/mixins/app_version.dart';
|
||||
import 'src/model/app_settings.dart';
|
||||
import 'src/model/operating_system.dart';
|
||||
import 'src/model/option.dart';
|
||||
|
|
@ -69,15 +67,12 @@ void main() async {
|
|||
skipTaskbar: false,
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
|
||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
});
|
||||
final foundQuickGet = await Process.run('which', ['quickget']);
|
||||
if (foundQuickGet.exitCode == 0) {
|
||||
gOperatingSystems = await loadOperatingSystems(false);
|
||||
AppVersion.packageInfo = await PackageInfo.fromPlatform();
|
||||
}
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
|
|
|
|||
190
lib/src/app.dart
190
lib/src/app.dart
|
|
@ -1,12 +1,16 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:adwaita/adwaita.dart';
|
||||
import 'package:fluent_ui/fluent_ui.dart' as fluent;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:gettext_i18n/gettext_i18n.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:platform_ui/platform_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:quickgui/main.dart';
|
||||
import 'package:quickgui/src/mixins/app_version.dart';
|
||||
import 'package:quickgui/src/model/operating_system.dart';
|
||||
import 'package:quickgui/src/pages/deget_not_found_page.dart';
|
||||
import 'package:quickgui/src/supported_locales.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
|
@ -24,78 +28,128 @@ class App extends StatefulWidget {
|
|||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> with PreferencesMixin, WindowListener {
|
||||
class _AppState extends State<App> with PreferencesMixin {
|
||||
bool isCheckingQuickemu = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
final foundQuickGet = await Process.run('which', ['quickget']);
|
||||
if (foundQuickGet.exitCode == 0) {
|
||||
gOperatingSystems = await loadOperatingSystems(false);
|
||||
AppVersion.packageInfo = await PackageInfo.fromPlatform();
|
||||
setState(() {
|
||||
isCheckingQuickemu = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
isCheckingQuickemu = false;
|
||||
});
|
||||
}
|
||||
|
||||
final pref = await SharedPreferences.getInstance();
|
||||
final appSettings = context.read<AppSettings>();
|
||||
appSettings.setActiveLocaleSilently(
|
||||
pref.getString(prefCurrentLocale) ?? Platform.localeName,
|
||||
);
|
||||
final cacheThemeMode = pref.getString(prefThemeMode);
|
||||
appSettings.themeModeSilently = ThemeMode.values.firstWhere((element) {
|
||||
return element.name == cacheThemeMode;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<SharedPreferences>(
|
||||
future: SharedPreferences.getInstance(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.data != null) {
|
||||
var appSettings = context.read<AppSettings>();
|
||||
appSettings.setActiveLocaleSilently(
|
||||
snapshot.data?.getString(prefCurrentLocale) ??
|
||||
Platform.localeName);
|
||||
var pref = snapshot.data!.getString(prefThemeMode);
|
||||
if (pref != null) {
|
||||
appSettings.themeModeSilently =
|
||||
ThemeMode.values.firstWhere((element) => element.name == pref);
|
||||
final appSettings = context.watch<AppSettings>();
|
||||
return PlatformApp(
|
||||
themeMode: appSettings.themeMode,
|
||||
home: isCheckingQuickemu
|
||||
? Column(
|
||||
children: [
|
||||
AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
actions: [
|
||||
Theme(
|
||||
data: AdwaitaThemeData.dark(),
|
||||
child: PlatformWindowButtons(
|
||||
isMaximized: () => windowManager.isMaximized(),
|
||||
onClose: windowManager.close,
|
||||
onMinimize: windowManager.minimize,
|
||||
onMaximize: windowManager.maximize,
|
||||
onRestore: windowManager.restore,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
PlatformText.subheading(
|
||||
"Checking Quickemu...",
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: LinearProgressIndicator(
|
||||
backgroundColor: Colors.grey[800]!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
)
|
||||
: AppVersion.packageInfo == null
|
||||
? const DebgetNotFoundPage()
|
||||
: const MainPage(),
|
||||
supportedLocales: supportedLocales.map(
|
||||
(s) => s.contains("_")
|
||||
? Locale(s.split("_")[0], s.split("_")[1])
|
||||
: Locale(s),
|
||||
),
|
||||
localizationsDelegates: [
|
||||
GettextLocalizationsDelegate(),
|
||||
...GlobalMaterialLocalizations.delegates,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
windowButtonConfig: PlatformWindowButtonConfig(
|
||||
isMaximized: () => windowManager.isMaximized(),
|
||||
onClose: windowManager.close,
|
||||
onMinimize: windowManager.minimize,
|
||||
onMaximize: windowManager.maximize,
|
||||
onRestore: windowManager.restore,
|
||||
showMaximizeButton: false,
|
||||
),
|
||||
windowsTheme: fluent.ThemeData(
|
||||
scaffoldBackgroundColor: fluent.Colors.grey[30],
|
||||
),
|
||||
windowsDarkTheme: fluent.ThemeData.dark().copyWith(
|
||||
scaffoldBackgroundColor: fluent.Colors.grey[200],
|
||||
),
|
||||
locale: appSettings.languageCode != null
|
||||
? Locale(appSettings.languageCode!, appSettings.countryCode)
|
||||
: null,
|
||||
localeListResolutionCallback: (locales, supportedLocales) {
|
||||
if (locales != null) {
|
||||
for (var locale in locales) {
|
||||
var supportedLocale = supportedLocales.where((element) =>
|
||||
element.languageCode == locale.languageCode &&
|
||||
element.countryCode == locale.countryCode);
|
||||
if (supportedLocale.isNotEmpty) {
|
||||
return supportedLocale.first;
|
||||
}
|
||||
supportedLocale = supportedLocales.where(
|
||||
(element) => element.languageCode == locale.languageCode);
|
||||
if (supportedLocale.isNotEmpty) {
|
||||
return supportedLocale.first;
|
||||
}
|
||||
}
|
||||
return Consumer<AppSettings>(
|
||||
builder: (context, appSettings, _) {
|
||||
return PlatformApp(
|
||||
themeMode: appSettings.themeMode,
|
||||
home: AppVersion.packageInfo == null
|
||||
? const DebgetNotFoundPage()
|
||||
: const MainPage(),
|
||||
supportedLocales: supportedLocales.map((s) => s.contains("_")
|
||||
? Locale(s.split("_")[0], s.split("_")[1])
|
||||
: Locale(s)),
|
||||
localizationsDelegates: [
|
||||
GettextLocalizationsDelegate(),
|
||||
...GlobalMaterialLocalizations.delegates,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
windowButtonConfig: PlatformWindowButtonConfig(
|
||||
isMaximized: () => windowManager.isMaximized(),
|
||||
onClose: windowManager.close,
|
||||
onMinimize: windowManager.minimize,
|
||||
onMaximize: windowManager.maximize,
|
||||
onRestore: windowManager.restore,
|
||||
showMaximizeButton: false,
|
||||
),
|
||||
windowsTheme: fluent.ThemeData(
|
||||
scaffoldBackgroundColor: fluent.Colors.grey[50],
|
||||
),
|
||||
windowsDarkTheme: fluent.ThemeData.dark(),
|
||||
locale:
|
||||
Locale(appSettings.languageCode!, appSettings.countryCode),
|
||||
localeListResolutionCallback: (locales, supportedLocales) {
|
||||
if (locales != null) {
|
||||
for (var locale in locales) {
|
||||
var supportedLocale = supportedLocales.where((element) =>
|
||||
element.languageCode == locale.languageCode &&
|
||||
element.countryCode == locale.countryCode);
|
||||
if (supportedLocale.isNotEmpty) {
|
||||
return supportedLocale.first;
|
||||
}
|
||||
supportedLocale = supportedLocales.where((element) =>
|
||||
element.languageCode == locale.languageCode);
|
||||
if (supportedLocale.isNotEmpty) {
|
||||
return supportedLocale.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class DownloaderPage extends StatelessWidget {
|
|||
return PlatformScaffold(
|
||||
appBar: TitleBar(
|
||||
title: PlatformText.subheading(context.t('Downloader')),
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: Column(
|
||||
children: const [
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ class _MainPageState extends State<MainPage> {
|
|||
appBar: TitleBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: PlatformText.subheading(context.t('Quickgui')),
|
||||
centerTitle: true,
|
||||
actions: [
|
||||
PlatformIconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
Widget build(BuildContext context) {
|
||||
return PlatformScaffold(
|
||||
appBar: TitleBar(
|
||||
leading: const PlatformBackButton(),
|
||||
title: PlatformText.subheading(context.t('Manager')),
|
||||
),
|
||||
body: _buildVmList(),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
|||
return PlatformScaffold(
|
||||
appBar: TitleBar(
|
||||
title: PlatformText.subheading(context.t('Select operating system')),
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gettext_i18n/gettext_i18n.dart';
|
||||
import 'package:platform_ui/platform_ui.dart';
|
||||
import 'package:quickgui/src/widgets/title_bar.dart';
|
||||
|
||||
import '../model/version.dart';
|
||||
|
||||
|
|
@ -29,49 +30,28 @@ class _OptionSelectionState extends State<OptionSelection> {
|
|||
.where((e) => e.option.toLowerCase().contains(term.toLowerCase()))
|
||||
.toList();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
return PlatformScaffold(
|
||||
appBar: TitleBar(
|
||||
title: PlatformText(context.t('Select option')),
|
||||
bottom: widget.version.options.length <= 6
|
||||
? null
|
||||
: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(kToolbarHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).canvasColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Material(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
const Icon(Icons.search),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration.collapsed(
|
||||
hintText: context.t('Search option')),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
term = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
if (widget.version.options.length > 6)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: PlatformTextField(
|
||||
focusNode: focusNode,
|
||||
prefixIcon: Icons.search,
|
||||
placeholder: context.t('Search option'),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
term = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: list.length,
|
||||
|
|
@ -80,7 +60,7 @@ class _OptionSelectionState extends State<OptionSelection> {
|
|||
return Card(
|
||||
color: PlatformTheme.of(context).secondaryBackgroundColor,
|
||||
elevation: platform == TargetPlatform.macOS ? 0 : null,
|
||||
child: ListTile(
|
||||
child: PlatformListTile(
|
||||
title: PlatformText(item.option),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop(item);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class _VersionSelectionState extends State<VersionSelection> {
|
|||
context
|
||||
.t('Select version for {0}', args: [widget.operatingSystem.name]),
|
||||
),
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class _SettingsPageState extends State<SettingsPage> with PreferencesMixin {
|
|||
return PlatformScaffold(
|
||||
appBar: TitleBar(
|
||||
title: PlatformText.subheading(context.t('Settings')),
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: Consumer<AppSettings>(
|
||||
builder: (context, appSettings, _) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class TitleBar extends StatelessWidget with PreferredSizeWidget {
|
|||
final TextStyle? titleTextStyle;
|
||||
final double? titleWidth;
|
||||
|
||||
const TitleBar({
|
||||
TitleBar({
|
||||
this.actions,
|
||||
this.leading,
|
||||
this.automaticallyImplyLeading = true,
|
||||
|
|
@ -38,7 +38,7 @@ class TitleBar extends StatelessWidget with PreferredSizeWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PlatformAppBar(
|
||||
var platformAppBar = PlatformAppBar(
|
||||
automaticallyImplyLeading: automaticallyImplyLeading,
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
|
|
@ -47,7 +47,7 @@ class TitleBar extends StatelessWidget with PreferredSizeWidget {
|
|||
leading: leading,
|
||||
leadingWidth: leadingWidth,
|
||||
title: title,
|
||||
titleSpacing: titleSpacing,
|
||||
titleSpacing: titleSpacing ?? (leading == null ? 16 : null),
|
||||
toolbarOpacity: toolbarOpacity,
|
||||
toolbarTextStyle: toolbarTextStyle,
|
||||
titleTextStyle: titleTextStyle,
|
||||
|
|
@ -58,8 +58,10 @@ class TitleBar extends StatelessWidget with PreferredSizeWidget {
|
|||
const PlatformWindowButtons(),
|
||||
],
|
||||
);
|
||||
return platformAppBar;
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
Size get preferredSize =>
|
||||
Size.fromHeight(platform == TargetPlatform.windows ? 35 : kToolbarHeight);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue