Optimize app logic

Support windows administrator auto launch

Support android close vpn
This commit is contained in:
chen08209
2024-08-15 16:18:00 +08:00
parent 0f8cfa20b2
commit 5dfb95a22d
65 changed files with 2784 additions and 1020 deletions

View File

@@ -1,5 +1,6 @@
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'text.dart';
@@ -29,12 +30,13 @@ class InfoHeader extends StatelessWidget {
return Container(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
Flexible(
flex: 1,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.max,
children: [
if (info.iconData != null) ...[
Icon(
@@ -46,6 +48,7 @@ class InfoHeader extends StatelessWidget {
),
],
Flexible(
flex: 1,
child: TooltipText(
text: Text(
info.label,
@@ -58,6 +61,9 @@ class InfoHeader extends StatelessWidget {
],
),
),
const SizedBox(
width: 8,
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
@@ -155,6 +161,18 @@ class CommonCard extends StatelessWidget {
],
);
}
if (selectWidget != null && isSelected) {
final List<Widget> children = [];
children.add(childWidget);
children.add(
Positioned.fill(
child: selectWidget!,
),
);
childWidget = Stack(
children: children,
);
}
return OutlinedButton(
clipBehavior: Clip.antiAlias,
style: ButtonStyle(
@@ -172,25 +190,7 @@ class CommonCard extends StatelessWidget {
),
),
onPressed: onPressed,
child: Builder(
builder: (_) {
if (selectWidget == null) {
return childWidget;
}
List<Widget> children = [];
children.add(childWidget);
if (isSelected) {
children.add(
Positioned.fill(
child: selectWidget!,
),
);
}
return Stack(
children: children,
);
},
),
child: childWidget,
);
}
}

View File

@@ -1,10 +1,11 @@
import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/plugins/proxy.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../common/function.dart';
class ClashContainer extends StatefulWidget {
final Widget child;
@@ -19,12 +20,49 @@ class ClashContainer extends StatefulWidget {
class _ClashContainerState extends State<ClashContainer>
with AppMessageListener {
Function? updateClashConfigDebounce;
Widget _updateContainer(Widget child) {
return Selector<ClashConfig, ClashConfigState>(
selector: (_, clashConfig) => ClashConfigState(
mixedPort: clashConfig.mixedPort,
allowLan: clashConfig.allowLan,
ipv6: clashConfig.ipv6,
logLevel: clashConfig.logLevel,
geodataLoader: clashConfig.geodataLoader,
externalController: clashConfig.externalController,
mode: clashConfig.mode,
findProcessMode: clashConfig.findProcessMode,
keepAliveInterval: clashConfig.keepAliveInterval,
unifiedDelay: clashConfig.unifiedDelay,
tcpConcurrent: clashConfig.tcpConcurrent,
tun: clashConfig.tun,
dns: clashConfig.dns,
geoXUrl: clashConfig.geoXUrl,
rules: clashConfig.rules,
globalRealUa: clashConfig.globalRealUa,
),
builder: (__, state, child) {
if (updateClashConfigDebounce == null) {
updateClashConfigDebounce = debounce<Function()>(() async {
await globalState.appController.updateClashConfig();
});
} else {
updateClashConfigDebounce!();
}
return child!;
},
child: child,
);
}
Widget _updateCoreState(Widget child) {
return Selector2<Config, ClashConfig, CoreState>(
selector: (_, config, clashConfig) => CoreState(
accessControl: config.isAccessControl ? config.accessControl : null,
allowBypass: config.allowBypass,
systemProxy: config.systemProxy,
enable: config.vpnProps.enable,
allowBypass: config.vpnProps.allowBypass,
systemProxy: config.vpnProps.systemProxy,
mixedPort: clashConfig.mixedPort,
onlyProxy: config.onlyProxy,
currentProfileName:
@@ -61,7 +99,9 @@ class _ClashContainerState extends State<ClashContainer>
Widget build(BuildContext context) {
return _changeProfileContainer(
_updateCoreState(
widget.child,
_updateContainer(
widget.child,
),
),
);
}
@@ -89,6 +129,7 @@ class _ClashContainerState extends State<ClashContainer>
@override
void onLog(Log log) {
globalState.appController.appState.addLog(log);
debugPrint("$log");
super.onLog(log);
}
@@ -113,9 +154,7 @@ class _ClashContainerState extends State<ClashContainer>
@override
Future<void> onStarted(String runTime) async {
super.onStarted(runTime);
proxy?.updateStartTime();
final appController = globalState.appController;
await appController.applyProfile(isPrue: true);
appController.addCheckIpNumDebounce();
}
}

View File

@@ -0,0 +1,37 @@
import 'package:fl_clash/common/proxy.dart';
import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProxyContainer extends StatelessWidget {
final Widget child;
const ProxyContainer({super.key, required this.child});
_updateProxy(ProxyState proxyState) {
final isStart = proxyState.isStart;
final systemProxy = proxyState.systemProxy;
final port = proxyState.port;
if (isStart && systemProxy) {
proxy?.startProxy(port);
}else{
proxy?.stopProxy();
}
}
@override
Widget build(BuildContext context) {
return Selector3<AppState, Config, ClashConfig, ProxyState>(
selector: (_, appState, config, clashConfig) => ProxyState(
isStart: appState.isStart,
systemProxy: config.desktopProps.systemProxy,
port: clashConfig.mixedPort,
),
builder: (_, state, child) {
_updateProxy(state);
return child!;
},
child: child,
);
}
}

View File

@@ -109,7 +109,7 @@ class CommonScaffoldState extends State<CommonScaffold> {
valueListenable: _actions,
builder: (_, actions, __) {
final realActions =
actions.isNotEmpty ? actions : widget.actions;
actions.isNotEmpty ? actions : widget.actions;
return AppBar(
centerTitle: false,
automaticallyImplyLeading: widget.automaticallyImplyLeading,

View File

@@ -24,13 +24,13 @@ class _TileContainerState extends State<TileContainer> with TileListener {
@override
void onStart() {
globalState.appController.updateSystemProxy(true);
globalState.appController.updateStatus(true);
super.onStart();
}
@override
void onStop() {
globalState.appController.updateSystemProxy(false);
globalState.appController.updateStatus(false);
super.onStop();
}

View File

@@ -32,12 +32,12 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
_updateOtherTray() async {
if (isTrayInit == false) {
await trayManager.setIcon(
other.getTrayIconPath(),
);
await trayManager.setToolTip(
appName,
);
await trayManager.setIcon(
other.getTrayIconPath(),
);
isTrayInit = true;
}
}
@@ -110,7 +110,7 @@ class _TrayContainerState extends State<TrayContainer> with TrayListener {
final proxyMenuItem = MenuItem.checkbox(
label: appLocalizations.systemProxy,
onClick: (_) async {
globalState.appController.updateSystemProxy(!state.isRun);
globalState.appController.updateStatus(!state.isRun);
},
checked: state.isRun,
);

View File

@@ -23,8 +23,8 @@ class _WindowContainerState extends State<WindowContainer> with WindowListener {
_autoLaunchContainer(Widget child) {
return Selector<Config, bool>(
selector: (_, config) => config.autoLaunch,
builder: (_, isAutoLaunch, child) {
autoLaunch?.updateStatus(isAutoLaunch);
builder: (_, state, child) {
autoLaunch?.updateStatus(state);
return child!;
},
child: child,
@@ -33,22 +33,7 @@ class _WindowContainerState extends State<WindowContainer> with WindowListener {
@override
Widget build(BuildContext context) {
return Stack(
children: [
Column(
children: [
SizedBox(
height: kHeaderHeight,
),
Expanded(
flex: 1,
child: _autoLaunchContainer(widget.child),
),
],
),
const WindowHeader(),
],
);
return _autoLaunchContainer(widget.child);
}
@override
@@ -98,6 +83,35 @@ class _WindowContainerState extends State<WindowContainer> with WindowListener {
}
}
class WindowHeaderContainer extends StatelessWidget {
final Widget child;
const WindowHeaderContainer({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
return Stack(
children: [
Column(
children: [
SizedBox(
height: kHeaderHeight,
),
Expanded(
flex: 1,
child: child,
),
],
),
const WindowHeader(),
],
);
}
}
class WindowHeader extends StatefulWidget {
const WindowHeader({super.key});
@@ -188,7 +202,7 @@ class _WindowHeaderState extends State<WindowHeader> {
),
IconButton(
onPressed: () {
windowManager.close();
globalState.appController.handleBackOrExit();
},
icon: const Icon(Icons.close),
),
@@ -214,7 +228,7 @@ class _WindowHeaderState extends State<WindowHeader> {
_updateMaximized();
},
child: Container(
color: context.colorScheme.surface,
color: context.colorScheme.secondary.toSoft(),
alignment: Alignment.centerLeft,
height: kHeaderHeight,
),