Add Settings Page

This commit is contained in:
2023-09-02 14:37:20 +08:00
parent f2025bfe6b
commit 8f90d2243b
7 changed files with 227 additions and 17 deletions

View File

@@ -14,6 +14,8 @@ class AuthInfo {
bool get isAuthed => (_user != null);
bool _checked = false;
bool get checked => _checked;
bool _isChecking = false;
bool get isChecking => _isChecking;
void clear() {
_user = null;
@@ -26,20 +28,25 @@ class AuthInfo {
}
Future<bool> checkAuth() async {
final re = await api.getUser();
if (re.ok) {
_user = re.data!;
final u = _user!;
_log.info(
"Logged in as ${u.username} (${u.id}). isAdmin: ${u.isAdmin}. permissions: ${u.permissions}");
} else if (re.status == 401 || re.status == 1 || re.status == 404) {
_user = null;
} else {
_user = null;
throw re.unwrapErr();
_isChecking = true;
try {
final re = await api.getUser();
if (re.ok) {
_user = re.data!;
final u = _user!;
_log.info(
"Logged in as ${u.username} (${u.id}). isAdmin: ${u.isAdmin}. permissions: ${u.permissions}");
} else if (re.status == 401 || re.status == 1 || re.status == 404) {
_user = null;
} else {
_user = null;
throw re.unwrapErr();
}
_checked = true;
await getServerStatus();
return re.ok;
} finally {
_isChecking = false;
}
_checked = true;
await getServerStatus();
return re.ok;
}
}

View File

@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -115,6 +116,7 @@ final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey =
enum MoreVertSettings {
setServerUrl,
createRootUser,
settings,
}
void onMoreVertSettingsSelected(BuildContext context, MoreVertSettings value) {
@@ -125,6 +127,9 @@ void onMoreVertSettingsSelected(BuildContext context, MoreVertSettings value) {
case MoreVertSettings.createRootUser:
context.push("/create_root_user");
break;
case MoreVertSettings.settings:
context.push("/settings");
break;
default:
break;
}
@@ -148,6 +153,11 @@ List<PopupMenuEntry<MoreVertSettings>> buildMoreVertSettings(
value: MoreVertSettings.createRootUser,
child: Text(AppLocalizations.of(context)!.createRootUser)));
}
if (path != "/settings") {
list.add(PopupMenuItem(
value: MoreVertSettings.settings,
child: Text(AppLocalizations.of(context)!.settings)));
}
return list;
}
@@ -184,3 +194,22 @@ mixin ThemeModeWidget<T extends StatefulWidget> on State<T> {
: Icons.light_mode));
}
}
enum Lang {
system("System"),
english("English"),
simplifiedChinese("简体中文");
const Lang(String lang) : langName = lang;
final String langName;
Locale toLocale() {
switch (this) {
case Lang.english:
return const Locale("en");
case Lang.simplifiedChinese:
return const Locale("zh");
default:
return PlatformDispatcher.instance.locale;
}
}
}

View File

@@ -15,7 +15,10 @@ class HomePage extends HookWidget {
@override
Widget build(BuildContext context) {
if (tryInitApi(context) && !auth.isAuthed && !auth.checked) {
if (tryInitApi(context) &&
!auth.isAuthed &&
!auth.checked &&
!auth.isChecking) {
auth.checkAuth().then((re) {
if (!re) {
if (auth.status!.noUser &&

View File

@@ -13,5 +13,9 @@
"setServerUrl": "Server URL Settings",
"createRootUser": "Create Root User",
"skip": "Skip",
"create": "Create"
"create": "Create",
"settings": "Settings",
"lang": "Language",
"systemLang": "System Language",
"reset": "Reset"
}

View File

@@ -13,5 +13,9 @@
"setServerUrl": "服务器地址设置",
"createRootUser": "创建根用户",
"skip": "跳过",
"create": "创建"
"create": "创建",
"settings": "设置",
"lang": "语言",
"systemLang": "系统语言",
"reset": "重置"
}

View File

@@ -12,6 +12,7 @@ import 'home.dart';
import 'login.dart';
import 'logs/file.dart';
import 'set_server.dart';
import 'settings.dart';
import 'utils.dart';
final _router = GoRouter(
@@ -33,6 +34,10 @@ final _router = GoRouter(
GoRoute(
path: CreateRootUserPage.routeName,
builder: (context, state) => const CreateRootUserPage(),
),
GoRoute(
path: SettingsPage.routeName,
builder: (context, state) => const SettingsPage(),
)
],
);
@@ -99,6 +104,8 @@ class _MainApp extends State<MainApp> {
ThemeData _themeData = ThemeData();
ThemeData _darkThemeData = ThemeData.dark();
ThemeMode get themeMode => _themeMode;
Lang _lang = Lang.system;
Lang get lang => lang;
@override
void initState() {
@@ -108,6 +115,11 @@ class _MainApp extends State<MainApp> {
} catch (e) {
_log.warning("Failed to read themeMode from prefs:", e);
}
try {
_lang = Lang.values[prefs.getInt("lang") ?? 0];
} catch (e) {
_log.warning("Failed to read lang from prefs:", e);
}
if (kIsWeb || isWindows) {
_themeData = _themeData.useSystemChineseFont();
_darkThemeData = _darkThemeData.useSystemChineseFont();
@@ -125,6 +137,7 @@ class _MainApp extends State<MainApp> {
}
return title;
},
locale: _lang.toLocale(),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: _themeData,
@@ -141,4 +154,10 @@ class _MainApp extends State<MainApp> {
_themeMode = mode;
});
}
void changeLang(Lang lang) {
setState(() {
_lang = lang;
});
}
}

144
lib/settings.dart Normal file
View File

@@ -0,0 +1,144 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import 'globals.dart';
import 'main.dart';
final _log = Logger("SettingsPage");
class SettingsPage extends StatefulWidget {
const SettingsPage({Key? key}) : super(key: key);
static const String routeName = '/settings';
@override
State<SettingsPage> createState() => _SettingsPage();
}
class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
Lang _ori_lang = Lang.system;
Lang _lang = Lang.system;
@override
void initState() {
super.initState();
try {
_ori_lang = Lang.values[prefs.getInt("lang") ?? 0];
_lang = _ori_lang;
} catch (e) {
_log.warning("Failed to get lang:", e);
_ori_lang = Lang.system;
_lang = Lang.system;
}
}
void fallback(BuildContext context) {
if (_ori_lang != _lang) {
MainApp.of(context).changeLang(_ori_lang);
}
}
void reset(BuildContext context) {
if (_lang != Lang.system) MainApp.of(context).changeLang(Lang.system);
setState(() {
_lang = Lang.system;
});
}
Future<bool> save() async {
bool re = true;
if (!await prefs.setInt("lang", _lang.index)) {
re = false;
_log.warning("Failed to save lang.");
} else {
_ori_lang = _lang;
}
return re;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
fallback(context);
context.canPop() ? context.pop() : context.go("/");
},
icon: const Icon(Icons.arrow_back),
),
title: Text(AppLocalizations.of(context)!.settings),
actions: [
buildThemeModeIcon(context),
buildMoreVertSettingsButon(context),
],
),
body: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints:
BoxConstraints(minHeight: constraints.maxHeight),
child: Container(
padding: MediaQuery.of(context).size.width > 810
? const EdgeInsets.symmetric(horizontal: 100)
: null,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8),
child: DropdownMenu<Lang>(
initialSelection: _lang,
onSelected: (value) {
if (value != null) {
setState(() {
_lang = value;
});
MainApp.of(context).changeLang(_lang);
}
},
label:
Text(AppLocalizations.of(context)!.lang),
dropdownMenuEntries: Lang.values
.map((e) => DropdownMenuEntry(
value: e,
label: e == Lang.system
? AppLocalizations.of(context)!
.systemLang
: e.langName))
.toList(),
leadingIcon: const Icon(Icons.language),
)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8),
child: ElevatedButton(
onPressed: () {
reset(context);
},
child: Text(
AppLocalizations.of(context)!
.reset))),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8),
child: ElevatedButton(
onPressed: () {
save();
},
child: Text(
AppLocalizations.of(context)!.save),
))
],
),
],
))));
},
));
}
}