mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Update state management.
This commit is contained in:
@@ -6,166 +6,99 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:venera/foundation/app.dart';
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
const _kTitleBarHeight = 36.0;
|
const _kTitleBarHeight = 36.0;
|
||||||
|
|
||||||
class WindowFrameController extends StateController {
|
class WindowFrame extends StatefulWidget {
|
||||||
bool useDarkTheme = false;
|
|
||||||
|
|
||||||
bool isHideWindowFrame = false;
|
|
||||||
|
|
||||||
void setDarkTheme() {
|
|
||||||
useDarkTheme = true;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetTheme() {
|
|
||||||
useDarkTheme = false;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
VoidCallback openSideBar = () {};
|
|
||||||
|
|
||||||
void hideWindowFrame() {
|
|
||||||
isHideWindowFrame = true;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void showWindowFrame() {
|
|
||||||
isHideWindowFrame = false;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WindowFrame extends StatelessWidget {
|
|
||||||
const WindowFrame(this.child, {super.key});
|
const WindowFrame(this.child, {super.key});
|
||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<WindowFrame> createState() => _WindowFrameState();
|
||||||
StateController.putIfNotExists<WindowFrameController>(
|
|
||||||
WindowFrameController());
|
|
||||||
if (App.isMobile) return child;
|
|
||||||
return StateBuilder<WindowFrameController>(builder: (controller) {
|
|
||||||
if (controller.isHideWindowFrame) return child;
|
|
||||||
|
|
||||||
var body = Stack(
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child: MediaQuery(
|
|
||||||
data: MediaQuery.of(context).copyWith(
|
|
||||||
padding: const EdgeInsets.only(top: _kTitleBarHeight)),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
child: Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: Theme(
|
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
brightness: controller.useDarkTheme ? Brightness.dark : null,
|
|
||||||
),
|
|
||||||
child: Builder(builder: (context) {
|
|
||||||
return SizedBox(
|
|
||||||
height: _kTitleBarHeight,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
if (App.isMacOS)
|
|
||||||
const DragToMoveArea(
|
|
||||||
child: SizedBox(
|
|
||||||
height: double.infinity,
|
|
||||||
width: 16,
|
|
||||||
),
|
|
||||||
).paddingRight(52)
|
|
||||||
else
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(
|
|
||||||
child: DragToMoveArea(
|
|
||||||
child: Text(
|
|
||||||
'Venera',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
color: (controller.useDarkTheme ||
|
|
||||||
context.brightness == Brightness.dark)
|
|
||||||
? Colors.white
|
|
||||||
: Colors.black,
|
|
||||||
),
|
|
||||||
).toAlign(Alignment.centerLeft).paddingLeft(4+(App.isMacOS?25:0)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (kDebugMode)
|
|
||||||
const TextButton(
|
|
||||||
onPressed: debug,
|
|
||||||
child: Text('Debug'),
|
|
||||||
),
|
|
||||||
if (!App.isMacOS) const WindowButtons()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (App.isLinux) {
|
|
||||||
return VirtualWindowFrame(child: body);
|
|
||||||
} else {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildMenuButton(
|
|
||||||
WindowFrameController controller, BuildContext context) {
|
|
||||||
return InkWell(
|
|
||||||
onTap: () {
|
|
||||||
controller.openSideBar();
|
|
||||||
},
|
|
||||||
child: SizedBox(
|
|
||||||
width: 42,
|
|
||||||
height: double.infinity,
|
|
||||||
child: Center(
|
|
||||||
child: CustomPaint(
|
|
||||||
size: const Size(18, 20),
|
|
||||||
painter: _MenuPainter(
|
|
||||||
color: (controller.useDarkTheme ||
|
|
||||||
Theme.of(context).brightness == Brightness.dark)
|
|
||||||
? Colors.white
|
|
||||||
: Colors.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MenuPainter extends CustomPainter {
|
class _WindowFrameState extends State<WindowFrame> {
|
||||||
final Color color;
|
bool isHideWindowFrame = false;
|
||||||
|
bool useDarkTheme = false;
|
||||||
_MenuPainter({this.color = Colors.black});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
Widget build(BuildContext context) {
|
||||||
final paint = getPaint(color);
|
if (App.isMobile) return widget.child;
|
||||||
final path = Path()
|
if (isHideWindowFrame) return widget.child;
|
||||||
..moveTo(0, size.height / 4)
|
|
||||||
..lineTo(size.width, size.height / 4)
|
var body = Stack(
|
||||||
..moveTo(0, size.height / 4 * 2)
|
children: [
|
||||||
..lineTo(size.width, size.height / 4 * 2)
|
Positioned.fill(
|
||||||
..moveTo(0, size.height / 4 * 3)
|
child: MediaQuery(
|
||||||
..lineTo(size.width, size.height / 4 * 3);
|
data: MediaQuery.of(context).copyWith(
|
||||||
canvas.drawPath(path, paint);
|
padding: const EdgeInsets.only(top: _kTitleBarHeight)),
|
||||||
|
child: widget.child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Theme(
|
||||||
|
data: Theme.of(context).copyWith(
|
||||||
|
brightness: useDarkTheme ? Brightness.dark : null,
|
||||||
|
),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: _kTitleBarHeight,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (App.isMacOS)
|
||||||
|
const DragToMoveArea(
|
||||||
|
child: SizedBox(
|
||||||
|
height: double.infinity,
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
).paddingRight(52)
|
||||||
|
else
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: DragToMoveArea(
|
||||||
|
child: Text(
|
||||||
|
'Venera',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: (useDarkTheme ||
|
||||||
|
context.brightness == Brightness.dark)
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toAlign(Alignment.centerLeft)
|
||||||
|
.paddingLeft(4 + (App.isMacOS ? 25 : 0)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (kDebugMode)
|
||||||
|
const TextButton(
|
||||||
|
onPressed: debug,
|
||||||
|
child: Text('Debug'),
|
||||||
|
),
|
||||||
|
if (!App.isMacOS) const WindowButtons()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (App.isLinux) {
|
||||||
|
return VirtualWindowFrame(child: body);
|
||||||
|
} else {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WindowButtons extends StatefulWidget {
|
class WindowButtons extends StatefulWidget {
|
||||||
@@ -489,7 +422,7 @@ class WindowPlacement {
|
|||||||
|
|
||||||
static Future<WindowPlacement> get current async {
|
static Future<WindowPlacement> get current async {
|
||||||
var rect = await windowManager.getBounds();
|
var rect = await windowManager.getBounds();
|
||||||
if(validate(rect)) {
|
if (validate(rect)) {
|
||||||
lastValidRect = rect;
|
lastValidRect = rect;
|
||||||
} else {
|
} else {
|
||||||
rect = lastValidRect ?? defaultPlacement.rect;
|
rect = lastValidRect ?? defaultPlacement.rect;
|
||||||
|
66
lib/foundation/global_state.dart
Normal file
66
lib/foundation/global_state.dart
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
abstract class GlobalState {
|
||||||
|
static final _state = <Pair<Object?, State>>[];
|
||||||
|
|
||||||
|
static void register(State state, [Object? key]) {
|
||||||
|
_state.add(Pair(key, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
static T find<T extends State>([Object? key]) {
|
||||||
|
for (var pair in _state) {
|
||||||
|
if (pair.left == key && pair.right is T) {
|
||||||
|
return pair.right as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Exception('State not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
static T? findOrNull<T extends State>([Object? key]) {
|
||||||
|
for (var pair in _state) {
|
||||||
|
if (pair.left == key && pair.right is T) {
|
||||||
|
return pair.right as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unregister(State state, [Object? key]) {
|
||||||
|
_state.removeWhere(
|
||||||
|
(pair) => (key == null || pair.left == key) && pair.right == state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Pair<K, V> {
|
||||||
|
K left;
|
||||||
|
V right;
|
||||||
|
|
||||||
|
Pair(this.left, this.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AutomaticGlobalState<T extends StatefulWidget>
|
||||||
|
extends State<T> {
|
||||||
|
@override
|
||||||
|
@mustCallSuper
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
GlobalState.register(this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@mustCallSuper
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
GlobalState.unregister(this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object? get key;
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,238 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class SimpleController extends StateController {
|
|
||||||
final void Function()? refreshFunction;
|
|
||||||
|
|
||||||
final Map<String, dynamic> Function()? control;
|
|
||||||
|
|
||||||
SimpleController({this.refreshFunction, this.control});
|
|
||||||
|
|
||||||
@override
|
|
||||||
void refresh() {
|
|
||||||
(refreshFunction ?? super.refresh)();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> get controlMap => control?.call() ?? {};
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class StateController {
|
|
||||||
static final _controllers = <StateControllerWrapped>[];
|
|
||||||
|
|
||||||
static T put<T extends StateController>(T controller,
|
|
||||||
{Object? tag, bool autoRemove = false}) {
|
|
||||||
_controllers.add(StateControllerWrapped(controller, autoRemove, tag));
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
static T putIfNotExists<T extends StateController>(T controller,
|
|
||||||
{Object? tag, bool autoRemove = false}) {
|
|
||||||
return findOrNull<T>(tag: tag) ??
|
|
||||||
put(controller, tag: tag, autoRemove: autoRemove);
|
|
||||||
}
|
|
||||||
|
|
||||||
static T find<T extends StateController>({Object? tag}) {
|
|
||||||
try {
|
|
||||||
return _controllers
|
|
||||||
.lastWhere((element) =>
|
|
||||||
element.controller is T && (tag == null || tag == element.tag))
|
|
||||||
.controller as T;
|
|
||||||
} catch (e) {
|
|
||||||
throw StateError("$T with tag $tag Not Found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<T> findAll<T extends StateController>({Object? tag}) {
|
|
||||||
return _controllers
|
|
||||||
.where((element) =>
|
|
||||||
element.controller is T && (tag == null || tag == element.tag))
|
|
||||||
.map((e) => e.controller as T)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
static T? findOrNull<T extends StateController>({Object? tag}) {
|
|
||||||
try {
|
|
||||||
return _controllers
|
|
||||||
.lastWhere((element) =>
|
|
||||||
element.controller is T && (tag == null || tag == element.tag))
|
|
||||||
.controller as T;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove<T>([Object? tag, bool check = false]) {
|
|
||||||
for (int i = _controllers.length - 1; i >= 0; i--) {
|
|
||||||
var element = _controllers[i];
|
|
||||||
if (element.controller is T && (tag == null || tag == element.tag)) {
|
|
||||||
if (check && !element.autoRemove) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_controllers.removeAt(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static SimpleController putSimpleController(
|
|
||||||
void Function() onUpdate, Object? tag,
|
|
||||||
{void Function()? refresh, Map<String, dynamic> Function()? control}) {
|
|
||||||
var controller = SimpleController(refreshFunction: refresh, control: control);
|
|
||||||
controller.stateUpdaters.add(Pair(null, onUpdate));
|
|
||||||
_controllers.add(StateControllerWrapped(controller, false, tag));
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Pair<Object?, void Function()>> stateUpdaters = [];
|
|
||||||
|
|
||||||
void update([List<Object>? ids]) {
|
|
||||||
if (ids == null) {
|
|
||||||
for (var element in stateUpdaters) {
|
|
||||||
element.right();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var element in stateUpdaters) {
|
|
||||||
if (ids.contains(element.left)) {
|
|
||||||
element.right();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispose() {
|
|
||||||
_controllers.removeWhere((element) => element.controller == this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void refresh() {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StateControllerWrapped {
|
|
||||||
StateController controller;
|
|
||||||
bool autoRemove;
|
|
||||||
Object? tag;
|
|
||||||
|
|
||||||
StateControllerWrapped(this.controller, this.autoRemove, this.tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
class StateBuilder<T extends StateController> extends StatefulWidget {
|
|
||||||
const StateBuilder({
|
|
||||||
super.key,
|
|
||||||
this.init,
|
|
||||||
this.dispose,
|
|
||||||
this.initState,
|
|
||||||
this.tag,
|
|
||||||
required this.builder,
|
|
||||||
this.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
final T? init;
|
|
||||||
|
|
||||||
final void Function(T controller)? dispose;
|
|
||||||
|
|
||||||
final void Function(T controller)? initState;
|
|
||||||
|
|
||||||
final Object? tag;
|
|
||||||
|
|
||||||
final Widget Function(T controller) builder;
|
|
||||||
|
|
||||||
Widget builderWrapped(StateController controller) {
|
|
||||||
return builder(controller as T);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initStateWrapped(StateController controller) {
|
|
||||||
return initState?.call(controller as T);
|
|
||||||
}
|
|
||||||
|
|
||||||
void disposeWrapped(StateController controller) {
|
|
||||||
return dispose?.call(controller as T);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object? id;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<StateBuilder> createState() => _StateBuilderState<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _StateBuilderState<T extends StateController>
|
|
||||||
extends State<StateBuilder> {
|
|
||||||
late T controller;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
if (widget.init != null) {
|
|
||||||
StateController.put(widget.init!, tag: widget.tag, autoRemove: true);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
controller = StateController.find<T>(tag: widget.tag);
|
|
||||||
} catch (e) {
|
|
||||||
throw "Controller Not Found";
|
|
||||||
}
|
|
||||||
controller.stateUpdaters.add(Pair(widget.id, () {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
widget.initStateWrapped(controller);
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
widget.disposeWrapped(controller);
|
|
||||||
StateController.remove<T>(widget.tag, true);
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) => widget.builderWrapped(controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class StateWithController<T extends StatefulWidget> extends State<T> {
|
|
||||||
late final SimpleController _controller;
|
|
||||||
|
|
||||||
void refresh() {
|
|
||||||
_controller.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@mustCallSuper
|
|
||||||
void initState() {
|
|
||||||
_controller = StateController.putSimpleController(
|
|
||||||
() {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tag,
|
|
||||||
refresh: refresh,
|
|
||||||
control: () => control,
|
|
||||||
);
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@mustCallSuper
|
|
||||||
void dispose() {
|
|
||||||
_controller.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
_controller.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
Object? get tag;
|
|
||||||
|
|
||||||
Map<String, dynamic> get control => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
class Pair<M, V>{
|
|
||||||
M left;
|
|
||||||
V right;
|
|
||||||
|
|
||||||
Pair(this.left, this.right);
|
|
||||||
|
|
||||||
Pair.fromMap(Map<M, V> map, M key): left = key, right = map[key]
|
|
||||||
?? (throw Exception("Pair not found"));
|
|
||||||
}
|
|
@@ -3,8 +3,8 @@ import 'package:venera/components/components.dart';
|
|||||||
import 'package:venera/foundation/app.dart';
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:venera/foundation/appdata.dart';
|
import 'package:venera/foundation/appdata.dart';
|
||||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||||
|
import 'package:venera/foundation/global_state.dart';
|
||||||
import 'package:venera/foundation/res.dart';
|
import 'package:venera/foundation/res.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
|
||||||
import 'package:venera/pages/comic_source_page.dart';
|
import 'package:venera/pages/comic_source_page.dart';
|
||||||
import 'package:venera/pages/search_result_page.dart';
|
import 'package:venera/pages/search_result_page.dart';
|
||||||
import 'package:venera/pages/settings/settings_page.dart';
|
import 'package:venera/pages/settings/settings_page.dart';
|
||||||
@@ -52,9 +52,7 @@ class _ExplorePageState extends State<ExplorePage>
|
|||||||
if (index == 2) {
|
if (index == 2) {
|
||||||
int page = controller.index;
|
int page = controller.index;
|
||||||
String currentPageId = pages[page];
|
String currentPageId = pages[page];
|
||||||
StateController.find<SimpleController>(tag: currentPageId)
|
GlobalState.find<_SingleExplorePageState>(currentPageId).toTop();
|
||||||
.control!()['toTop']
|
|
||||||
?.call();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +96,7 @@ class _ExplorePageState extends State<ExplorePage>
|
|||||||
void refresh() {
|
void refresh() {
|
||||||
int page = controller.index;
|
int page = controller.index;
|
||||||
String currentPageId = pages[page];
|
String currentPageId = pages[page];
|
||||||
StateController.find<SimpleController>(tag: currentPageId).refresh();
|
GlobalState.find<_SingleExplorePageState>(currentPageId).refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildFAB() => Material(
|
Widget buildFAB() => Material(
|
||||||
@@ -244,7 +242,7 @@ class _SingleExplorePage extends StatefulWidget {
|
|||||||
State<_SingleExplorePage> createState() => _SingleExplorePageState();
|
State<_SingleExplorePage> createState() => _SingleExplorePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SingleExplorePageState extends StateWithController<_SingleExplorePage>
|
class _SingleExplorePageState extends AutomaticGlobalState<_SingleExplorePage>
|
||||||
with AutomaticKeepAliveClientMixin<_SingleExplorePage> {
|
with AutomaticKeepAliveClientMixin<_SingleExplorePage> {
|
||||||
late final ExplorePageData data;
|
late final ExplorePageData data;
|
||||||
|
|
||||||
@@ -328,7 +326,7 @@ class _SingleExplorePageState extends StateWithController<_SingleExplorePage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Object? get tag => widget.title;
|
Object? get key => widget.title;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void refresh() {
|
void refresh() {
|
||||||
@@ -347,9 +345,6 @@ class _SingleExplorePageState extends StateWithController<_SingleExplorePage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> get control => {"toTop": toTop};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MixedExplorePage extends StatefulWidget {
|
class _MixedExplorePage extends StatefulWidget {
|
||||||
|
@@ -7,7 +7,7 @@ import 'package:venera/components/components.dart';
|
|||||||
import 'package:venera/foundation/app.dart';
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:venera/foundation/appdata.dart';
|
import 'package:venera/foundation/appdata.dart';
|
||||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
import 'package:venera/foundation/global_state.dart';
|
||||||
import 'package:venera/pages/aggregated_search_page.dart';
|
import 'package:venera/pages/aggregated_search_page.dart';
|
||||||
import 'package:venera/pages/search_result_page.dart';
|
import 'package:venera/pages/search_result_page.dart';
|
||||||
import 'package:venera/pages/settings/settings_page.dart';
|
import 'package:venera/pages/settings/settings_page.dart';
|
||||||
|
@@ -3,7 +3,7 @@ import 'package:venera/components/components.dart';
|
|||||||
import 'package:venera/foundation/app.dart';
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:venera/foundation/appdata.dart';
|
import 'package:venera/foundation/appdata.dart';
|
||||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
import 'package:venera/foundation/global_state.dart';
|
||||||
import 'package:venera/pages/search_page.dart';
|
import 'package:venera/pages/search_page.dart';
|
||||||
import 'package:venera/utils/ext.dart';
|
import 'package:venera/utils/ext.dart';
|
||||||
import 'package:venera/utils/tags_translation.dart';
|
import 'package:venera/utils/tags_translation.dart';
|
||||||
|
Reference in New Issue
Block a user