Optimize provider page
Optimize delay test Support local backup and recovery
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ScrollOverBuilder extends StatefulWidget {
|
||||
final Widget Function(bool isOver) builder;
|
||||
@@ -15,7 +17,6 @@ class ScrollOverBuilder extends StatefulWidget {
|
||||
class _ScrollOverBuilderState extends State<ScrollOverBuilder> {
|
||||
final isOverNotifier = ValueNotifier<bool>(false);
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
@@ -38,3 +39,29 @@ class _ScrollOverBuilderState extends State<ScrollOverBuilder> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ProxiesActionsBuilder extends StatelessWidget {
|
||||
final Widget? child;
|
||||
final Widget Function(
|
||||
ProxiesActionsState state,
|
||||
Widget? child,
|
||||
) builder;
|
||||
|
||||
const ProxiesActionsBuilder({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.builder,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<AppState, ProxiesActionsState>(
|
||||
selector: (_, appState) => ProxiesActionsState(
|
||||
isCurrent: appState.currentLabel == "proxies",
|
||||
hasProvider: appState.providers.isNotEmpty,
|
||||
),
|
||||
builder: (_, state, child) => builder(state, child),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,40 +32,39 @@ class InfoHeader extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (info.iconData != null) ...[
|
||||
Icon(
|
||||
info.iconData,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
],
|
||||
Flexible(
|
||||
child: TooltipText(
|
||||
text: Text(
|
||||
info.label,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
...actions,
|
||||
if (info.iconData != null) ...[
|
||||
Icon(
|
||||
info.iconData,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
],
|
||||
Flexible(
|
||||
child: TooltipText(
|
||||
text: Text(
|
||||
info.label,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
...actions,
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -146,13 +145,11 @@ class CommonCard extends StatelessWidget {
|
||||
childWidget = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 0,
|
||||
child: InfoHeader(
|
||||
info: info!,
|
||||
),
|
||||
InfoHeader(
|
||||
info: info!,
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -27,6 +27,8 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
systemProxy: config.systemProxy,
|
||||
mixedPort: clashConfig.mixedPort,
|
||||
onlyProxy: config.onlyProxy,
|
||||
currentProfileName:
|
||||
config.currentProfile?.label ?? config.currentProfileId ?? "",
|
||||
),
|
||||
builder: (__, state, child) {
|
||||
clashCore.setState(state);
|
||||
@@ -36,9 +38,32 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
);
|
||||
}
|
||||
|
||||
_changeProfileHandle() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final appController = globalState.appController;
|
||||
appController.appState.delayMap = {};
|
||||
await appController.applyProfile();
|
||||
});
|
||||
}
|
||||
|
||||
Widget _changeProfileContainer(Widget child) {
|
||||
return Selector<Config, String?>(
|
||||
selector: (_, config) => config.currentProfileId,
|
||||
builder: (__, state, child) {
|
||||
_changeProfileHandle();
|
||||
return child!;
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _updateCoreState(widget.child);
|
||||
return _changeProfileContainer(
|
||||
_updateCoreState(
|
||||
widget.child,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -73,16 +98,15 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
}
|
||||
|
||||
@override
|
||||
void onLoaded(String groupName) {
|
||||
void onLoaded(String providerName) {
|
||||
final appController = globalState.appController;
|
||||
final currentSelectedMap = appController.config.currentSelectedMap;
|
||||
final proxyName = currentSelectedMap[groupName];
|
||||
if (proxyName == null) return;
|
||||
appController.changeProxy(
|
||||
groupName: groupName,
|
||||
proxyName: proxyName,
|
||||
appController.appState.setProvider(
|
||||
clashCore.getExternalProvider(
|
||||
providerName,
|
||||
),
|
||||
);
|
||||
super.onLoaded(proxyName);
|
||||
appController.addCheckIpNumDebounce();
|
||||
super.onLoaded(providerName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -5,10 +5,12 @@ import 'package:fl_clash/widgets/scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'side_sheet.dart';
|
||||
|
||||
showExtendPage(BuildContext context, {
|
||||
showExtendPage(
|
||||
BuildContext context, {
|
||||
required Widget body,
|
||||
required String title,
|
||||
double? extendPageWidth,
|
||||
bool forceNotSide = false,
|
||||
Widget? action,
|
||||
}) {
|
||||
final NavigatorState navigator = Navigator.of(context);
|
||||
@@ -17,23 +19,24 @@ showExtendPage(BuildContext context, {
|
||||
key: globalKey,
|
||||
child: body,
|
||||
);
|
||||
final isMobile = globalState.appController.appState.viewMode ==
|
||||
ViewMode.mobile;
|
||||
final isMobile =
|
||||
globalState.appController.appState.viewMode == ViewMode.mobile;
|
||||
final isNotSide = isMobile || forceNotSide;
|
||||
navigator.push(
|
||||
ModalSideSheetRoute(
|
||||
modalBarrierColor: Colors.black38,
|
||||
builder: (context) {
|
||||
final commonScaffold = CommonScaffold(
|
||||
automaticallyImplyLeading: isMobile ? true : false,
|
||||
actions: isMobile
|
||||
automaticallyImplyLeading: isNotSide,
|
||||
actions: isNotSide
|
||||
? null
|
||||
: [
|
||||
const SizedBox(
|
||||
height: kToolbarHeight,
|
||||
width: kToolbarHeight,
|
||||
child: CloseButton(),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: kToolbarHeight,
|
||||
width: kToolbarHeight,
|
||||
child: CloseButton(),
|
||||
),
|
||||
],
|
||||
title: title,
|
||||
body: uniqueBody,
|
||||
);
|
||||
|
||||
@@ -220,16 +220,14 @@ class _WindowHeaderState extends State<WindowHeader> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!Platform.isMacOS) ...[
|
||||
const Positioned(
|
||||
left: 0,
|
||||
child: AppIcon(),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: _buildActions(),
|
||||
),
|
||||
]
|
||||
const Positioned(
|
||||
left: 0,
|
||||
child: AppIcon(),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: _buildActions(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user