Files
MWClash/lib/widgets/scaffold.dart
chen08209 5afa552b6c Fix android vpn close issues
Add requests page

Fix checkUpdate dark mode style error

Fix quickStart error open app

Add memory proxies tab index

Support hidden group

Optimize logs
2024-06-16 13:05:46 +08:00

179 lines
4.8 KiB
Dart

import 'package:fl_clash/common/app_localizations.dart';
import 'package:fl_clash/common/system.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class CommonScaffold extends StatefulWidget {
final Widget body;
final Widget? bottomNavigationBar;
final String title;
final Widget? leading;
final List<Widget>? actions;
final bool automaticallyImplyLeading;
const CommonScaffold({
super.key,
required this.body,
this.bottomNavigationBar,
this.leading,
required this.title,
this.actions,
this.automaticallyImplyLeading = true,
});
CommonScaffold.open({
Key? key,
required Widget body,
required String title,
required Function onBack,
}) : this(
key: key,
body: body,
title: title,
automaticallyImplyLeading: false,
leading: SizedBox(
height: kToolbarHeight,
child: IconButton(
icon: const BackButtonIcon(),
onPressed: () {
onBack();
},
),
),
);
@override
State<CommonScaffold> createState() => CommonScaffoldState();
}
class CommonScaffoldState extends State<CommonScaffold> {
final ValueNotifier<List<Widget>> _actions = ValueNotifier([]);
final ValueNotifier<Widget?> _floatingActionButton = ValueNotifier(null);
final ValueNotifier<bool> _loading = ValueNotifier(false);
set actions(List<Widget> actions) {
if (_actions.value != actions) {
_actions.value = actions;
}
}
set floatingActionButton(Widget? actions) {
if (_floatingActionButton.value != actions) {
_floatingActionButton.value = actions;
}
}
Future<T?> loadingRun<T>(
Future<T> Function() futureFunction, {
String? title,
}) async {
_loading.value = true;
try {
final res = await futureFunction();
_loading.value = false;
return res;
} catch (e) {
globalState.showMessage(
title: title ?? appLocalizations.tip,
message: TextSpan(
text: e.toString(),
),
);
_loading.value = false;
return null;
}
}
@override
void didUpdateWidget(covariant CommonScaffold oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.title != widget.title) {
_actions.value = [];
_floatingActionButton.value = null;
}
}
_platformContainer({required Widget child}) {
if (system.isDesktop) {
return child;
}
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Theme.of(context).brightness == Brightness.dark
? Brightness.light
: Brightness.dark,
systemNavigationBarColor: Colors.transparent,
systemNavigationBarDividerColor: Colors.transparent,
),
child: child,
);
}
@override
Widget build(BuildContext context) {
return _platformContainer(
child: Scaffold(
floatingActionButton: ValueListenableBuilder(
valueListenable: _floatingActionButton,
builder: (_, floatingActionButton, __) {
return floatingActionButton ?? Container();
},
),
resizeToAvoidBottomInset: true,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: Stack(
alignment: Alignment.bottomCenter,
children: [
ValueListenableBuilder(
valueListenable: _actions,
builder: (_, actions, __) {
return AppBar(
automaticallyImplyLeading: widget.automaticallyImplyLeading,
leading: widget.leading,
title: Text(widget.title),
actions: actions.isNotEmpty ? actions : widget.actions,
);
},
),
ValueListenableBuilder(
valueListenable: _loading,
builder: (_, value, __) {
return value == true
? const LinearProgressIndicator()
: Container();
},
),
],
),
),
body: widget.body,
bottomNavigationBar: widget.bottomNavigationBar,
),
);
}
}
class AppIcon extends StatelessWidget {
const AppIcon({super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
width: 30,
height: 30,
child: const CircleAvatar(
foregroundImage: AssetImage("assets/images/launch_icon.png"),
backgroundColor: Colors.transparent,
),
);
}
}