mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
fix #61
This commit is contained in:
@@ -1012,13 +1012,17 @@ class ComicListState extends State<ComicList> {
|
||||
while (_data[page] == null) {
|
||||
await _fetchNext();
|
||||
}
|
||||
if(mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
} catch (e) {
|
||||
if(mounted) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_loading[page] = false;
|
||||
}
|
||||
|
@@ -51,12 +51,10 @@ class _MenuRoute<T> extends PopupRoute<T> {
|
||||
],
|
||||
),
|
||||
child: BlurEffect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Material(
|
||||
color: context.brightness == Brightness.light
|
||||
? const Color(0xFFFAFAFA).withOpacity(0.82)
|
||||
: const Color(0xFF090909).withOpacity(0.82),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
color: context.colorScheme.surface.withOpacity(0.82),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
width: width,
|
||||
padding:
|
||||
|
@@ -23,7 +23,8 @@ class PaneActionEntry {
|
||||
}
|
||||
|
||||
class NaviPane extends StatefulWidget {
|
||||
const NaviPane({required this.paneItems,
|
||||
const NaviPane(
|
||||
{required this.paneItems,
|
||||
required this.paneActions,
|
||||
required this.pageBuilder,
|
||||
this.initialPage = 0,
|
||||
@@ -84,17 +85,14 @@ class NaviPaneState extends State<NaviPane>
|
||||
|
||||
static const _kBottomBarHeight = 58.0;
|
||||
|
||||
static const _kFoldedSideBarWidth = 80.0;
|
||||
static const _kFoldedSideBarWidth = 72.0;
|
||||
|
||||
static const _kSideBarWidth = 256.0;
|
||||
static const _kSideBarWidth = 224.0;
|
||||
|
||||
static const _kTopBarHeight = 48.0;
|
||||
|
||||
double get bottomBarHeight =>
|
||||
_kBottomBarHeight + MediaQuery
|
||||
.of(context)
|
||||
.padding
|
||||
.bottom;
|
||||
_kBottomBarHeight + MediaQuery.of(context).padding.bottom;
|
||||
|
||||
void onNavigatorStateChange() {
|
||||
onRebuild(context);
|
||||
@@ -136,10 +134,7 @@ class NaviPaneState extends State<NaviPane>
|
||||
}
|
||||
|
||||
double targetFormContext(BuildContext context) {
|
||||
var width = MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.width;
|
||||
var width = MediaQuery.of(context).size.width;
|
||||
double target = 0;
|
||||
if (width > changePoint) {
|
||||
target = 2;
|
||||
@@ -208,8 +203,7 @@ class NaviPaneState extends State<NaviPane>
|
||||
return Navigator(
|
||||
observers: [widget.observer],
|
||||
key: widget.navigatorKey,
|
||||
onGenerateRoute: (settings) =>
|
||||
AppPageRoute(
|
||||
onGenerateRoute: (settings) => AppPageRoute(
|
||||
preventRebuild: false,
|
||||
isRootRoute: true,
|
||||
builder: (context) {
|
||||
@@ -252,20 +246,14 @@ class NaviPaneState extends State<NaviPane>
|
||||
|
||||
Widget buildBottom() {
|
||||
return Material(
|
||||
textStyle: Theme
|
||||
.of(context)
|
||||
.textTheme
|
||||
.labelSmall,
|
||||
textStyle: Theme.of(context).textTheme.labelSmall,
|
||||
elevation: 0,
|
||||
child: Container(
|
||||
height: _kBottomBarHeight,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme
|
||||
.of(context)
|
||||
.colorScheme
|
||||
.outlineVariant,
|
||||
color: Theme.of(context).colorScheme.outlineVariant,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@@ -293,7 +281,7 @@ class NaviPaneState extends State<NaviPane>
|
||||
|
||||
Widget buildLeft() {
|
||||
final value = controller.value;
|
||||
const paddingHorizontal = 16.0;
|
||||
const paddingHorizontal = 12.0;
|
||||
return Material(
|
||||
child: Container(
|
||||
width: _kFoldedSideBarWidth +
|
||||
@@ -303,31 +291,18 @@ class NaviPaneState extends State<NaviPane>
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
right: BorderSide(
|
||||
color: Theme
|
||||
.of(context)
|
||||
.colorScheme
|
||||
.outlineVariant,
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.outlineVariant,
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: value == 3
|
||||
? (_kSideBarWidth - paddingHorizontal * 2 - 1)
|
||||
: (_kFoldedSideBarWidth - paddingHorizontal * 2 - 1),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: MediaQuery
|
||||
.of(context)
|
||||
.padding
|
||||
.top),
|
||||
SizedBox(height: MediaQuery.of(context).padding.top),
|
||||
...List<Widget>.generate(
|
||||
widget.paneItems.length,
|
||||
(index) =>
|
||||
_SideNaviWidget(
|
||||
(index) => _SideNaviWidget(
|
||||
enabled: currentPage == index,
|
||||
entry: widget.paneItems[index],
|
||||
showTitle: value == 3,
|
||||
@@ -340,8 +315,7 @@ class NaviPaneState extends State<NaviPane>
|
||||
const Spacer(),
|
||||
...List<Widget>.generate(
|
||||
widget.paneActions.length,
|
||||
(index) =>
|
||||
_PaneActionWidget(
|
||||
(index) => _PaneActionWidget(
|
||||
entry: widget.paneActions[index],
|
||||
showTitle: value == 3,
|
||||
key: ValueKey(index + widget.paneItems.length),
|
||||
@@ -353,16 +327,13 @@ class NaviPaneState extends State<NaviPane>
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SideNaviWidget extends StatefulWidget {
|
||||
const _SideNaviWidget({required this.enabled,
|
||||
class _SideNaviWidget extends StatelessWidget {
|
||||
const _SideNaviWidget(
|
||||
{required this.enabled,
|
||||
required this.entry,
|
||||
required this.onTap,
|
||||
required this.showTitle,
|
||||
@@ -376,60 +347,37 @@ class _SideNaviWidget extends StatefulWidget {
|
||||
|
||||
final bool showTitle;
|
||||
|
||||
@override
|
||||
State<_SideNaviWidget> createState() => _SideNaviWidgetState();
|
||||
}
|
||||
|
||||
class _SideNaviWidgetState extends State<_SideNaviWidget> {
|
||||
bool isHovering = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme
|
||||
.of(context)
|
||||
.colorScheme;
|
||||
final icon =
|
||||
Icon(widget.enabled ? widget.entry.activeIcon : widget.entry.icon);
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (details) => setState(() => isHovering = true),
|
||||
onExit: (details) => setState(() => isHovering = false),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: widget.onTap,
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final icon = Icon(enabled ? entry.activeIcon : entry.icon);
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 180),
|
||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
width: double.infinity,
|
||||
height: 42,
|
||||
height: 38,
|
||||
decoration: BoxDecoration(
|
||||
color: widget.enabled
|
||||
? colorScheme.primaryContainer
|
||||
: isHovering
|
||||
? colorScheme.surfaceContainerHigh
|
||||
: null,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: enabled ? colorScheme.primaryContainer : null,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: widget.showTitle
|
||||
? Row(
|
||||
child: showTitle ? Row(
|
||||
children: [
|
||||
icon,
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(widget.entry.label)
|
||||
const SizedBox(width: 12),
|
||||
Text(entry.label)
|
||||
],
|
||||
)
|
||||
: Center(
|
||||
) : Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: icon,
|
||||
)),
|
||||
),
|
||||
);
|
||||
),
|
||||
).paddingVertical(4);
|
||||
}
|
||||
}
|
||||
|
||||
class _PaneActionWidget extends StatefulWidget {
|
||||
class _PaneActionWidget extends StatelessWidget {
|
||||
const _PaneActionWidget(
|
||||
{required this.entry, required this.showTitle, super.key});
|
||||
|
||||
@@ -437,55 +385,34 @@ class _PaneActionWidget extends StatefulWidget {
|
||||
|
||||
final bool showTitle;
|
||||
|
||||
@override
|
||||
State<_PaneActionWidget> createState() => _PaneActionWidgetState();
|
||||
}
|
||||
|
||||
class _PaneActionWidgetState extends State<_PaneActionWidget> {
|
||||
bool isHovering = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme
|
||||
.of(context)
|
||||
.colorScheme;
|
||||
final icon = Icon(widget.entry.icon);
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (details) => setState(() => isHovering = true),
|
||||
onExit: (details) => setState(() => isHovering = false),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: widget.entry.onTap,
|
||||
final icon = Icon(entry.icon);
|
||||
return InkWell(
|
||||
onTap: entry.onTap,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 180),
|
||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
width: double.infinity,
|
||||
height: 42,
|
||||
decoration: BoxDecoration(
|
||||
color: isHovering ? colorScheme.surfaceContainerHigh : null,
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
child: widget.showTitle
|
||||
? Row(
|
||||
height: 38,
|
||||
child: showTitle ? Row(
|
||||
children: [
|
||||
icon,
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(widget.entry.label)
|
||||
const SizedBox(width: 12),
|
||||
Text(entry.label)
|
||||
],
|
||||
)
|
||||
: Center(
|
||||
) : Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: icon,
|
||||
)),
|
||||
),
|
||||
);
|
||||
),
|
||||
).paddingVertical(4);
|
||||
}
|
||||
}
|
||||
|
||||
class _SingleBottomNaviWidget extends StatefulWidget {
|
||||
const _SingleBottomNaviWidget({required this.enabled,
|
||||
const _SingleBottomNaviWidget(
|
||||
{required this.enabled,
|
||||
required this.entry,
|
||||
required this.onTap,
|
||||
super.key});
|
||||
@@ -556,9 +483,7 @@ class _SingleBottomNaviWidgetState extends State<_SingleBottomNaviWidget>
|
||||
|
||||
Widget buildContent() {
|
||||
final value = controller.value;
|
||||
final colorScheme = Theme
|
||||
.of(context)
|
||||
.colorScheme;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final icon =
|
||||
Icon(widget.enabled ? widget.entry.activeIcon : widget.entry.icon);
|
||||
return Center(
|
||||
@@ -725,8 +650,8 @@ class _NaviMainViewState extends State<_NaviMainView> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (shouldShowAppBar) state.buildBottom().paddingBottom(
|
||||
context.padding.bottom),
|
||||
if (shouldShowAppBar)
|
||||
state.buildBottom().paddingBottom(context.padding.bottom),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@@ -63,22 +63,9 @@ class _App {
|
||||
}
|
||||
}
|
||||
|
||||
var mainColor = Colors.blue;
|
||||
|
||||
Future<void> init() async {
|
||||
cachePath = (await getApplicationCacheDirectory()).path;
|
||||
dataPath = (await getApplicationSupportDirectory()).path;
|
||||
mainColor = switch (appdata.settings['color']) {
|
||||
'red' => Colors.red,
|
||||
'pink' => Colors.pink,
|
||||
'purple' => Colors.purple,
|
||||
'green' => Colors.green,
|
||||
'orange' => Colors.orange,
|
||||
'blue' => Colors.blue,
|
||||
'yellow' => Colors.yellow,
|
||||
'cyan' => Colors.cyan,
|
||||
_ => Colors.blue,
|
||||
};
|
||||
}
|
||||
|
||||
Function? _forceRebuildHandler;
|
||||
|
@@ -92,7 +92,7 @@ class _Settings with ChangeNotifier {
|
||||
final _data = <String, dynamic>{
|
||||
'comicDisplayMode': 'detailed', // detailed, brief
|
||||
'comicTileScale': 1.00, // 0.75-1.25
|
||||
'color': 'blue', // red, pink, purple, green, orange, blue
|
||||
'color': 'system', // red, pink, purple, green, orange, blue
|
||||
'theme_mode': 'system', // light, dark, system
|
||||
'newFavoriteAddTo': 'end', // start, end
|
||||
'moveFavoriteAfterRead': 'none', // none, end, start
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
@@ -128,6 +129,20 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Color translateColorSetting() {
|
||||
return switch (appdata.settings['color']) {
|
||||
'red' => Colors.red,
|
||||
'pink' => Colors.pink,
|
||||
'purple' => Colors.purple,
|
||||
'green' => Colors.green,
|
||||
'orange' => Colors.orange,
|
||||
'blue' => Colors.blue,
|
||||
'yellow' => Colors.yellow,
|
||||
'cyan' => Colors.cyan,
|
||||
_ => Colors.blue,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget home;
|
||||
@@ -140,27 +155,31 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
} else {
|
||||
home = const MainPage();
|
||||
}
|
||||
return DynamicColorBuilder(builder: (light, dark) {
|
||||
if (appdata.settings['color'] != 'system' || light == null || dark == null) {
|
||||
var color = translateColorSetting();
|
||||
light = ColorScheme.fromSeed(
|
||||
seedColor: color,
|
||||
);
|
||||
dark = ColorScheme.fromSeed(
|
||||
seedColor: color,
|
||||
brightness: Brightness.dark,
|
||||
);
|
||||
}
|
||||
return MaterialApp(
|
||||
home: home,
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: App.mainColor,
|
||||
colorScheme: light.copyWith(
|
||||
surface: Colors.white,
|
||||
primary: App.mainColor.shade600,
|
||||
// ignore: deprecated_member_use
|
||||
background: Colors.white,
|
||||
),
|
||||
fontFamily: App.isWindows ? "Microsoft YaHei" : null,
|
||||
),
|
||||
navigatorKey: App.rootNavigatorKey,
|
||||
darkTheme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: App.mainColor,
|
||||
brightness: Brightness.dark,
|
||||
colorScheme: dark.copyWith(
|
||||
surface: Colors.black,
|
||||
primary: App.mainColor.shade400,
|
||||
// ignore: deprecated_member_use
|
||||
background: Colors.black,
|
||||
),
|
||||
fontFamily: App.isWindows ? "Microsoft YaHei" : null,
|
||||
@@ -224,6 +243,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
throw ('widget is null');
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,6 +29,7 @@ class _AppearanceSettingsState extends State<AppearanceSettings> {
|
||||
title: "Theme Color".tl,
|
||||
settingKey: "color",
|
||||
optionTranslation: {
|
||||
"system": "System".tl,
|
||||
"red": "Red".tl,
|
||||
"pink": "Pink".tl,
|
||||
"purple": "Purple".tl,
|
||||
|
@@ -194,6 +194,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
dynamic_color:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dynamic_color
|
||||
sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@@ -70,6 +70,7 @@ dependencies:
|
||||
url: https://github.com/pkuislm/flutter_saf.git
|
||||
ref: 3315082b9f7055655610e4f6f136b69e48228c05
|
||||
pdf: ^3.11.1
|
||||
dynamic_color: ^1.7.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Reference in New Issue
Block a user