Compare commits

..

16 Commits

Author SHA1 Message Date
chen08209
4ba2f72b1a Fix flashback caused by process 2024-06-17 15:46:06 +08:00
chen08209
d6c22d4cca Add build version
Optimize quick start

Update system default option

(cherry picked from commit 05abf2d56d)
2024-06-16 18:54:22 +08:00
chen08209
614dfc841a Update build.yml
(cherry picked from commit 658727dd79)
2024-06-16 18:54:20 +08:00
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
chen08209
ee0e2a15a7 Fix externalController hot load error 2024-06-13 19:21:45 +08:00
chen08209
7b7fd084bf Add tcp concurrent switch
Add system proxy switch

Add geodata loader switch

Add external controller switch

Add auto gc on trim memory

Fix android notification error
2024-06-13 17:03:51 +08:00
chen08209
03c39bf4bf Fix ipv6 error
(cherry picked from commit 86572cc960)
2024-06-12 19:10:04 +08:00
chen08209
fd7c3be02f Fix android udp direct error
Add ipv6 switch

Add access all selected button

Remove android low version splash
2024-06-12 18:27:53 +08:00
chen08209
b67d221063 Fix search issues 2024-06-10 19:08:24 +08:00
chen08209
1a74c0a12f Fix LoadBalance, Relay load error
(cherry picked from commit 7acf9c6db3)
2024-06-10 19:07:28 +08:00
chen08209
9fc9c53427 Add allowBypass
Fix Android only pick .text file issues
2024-06-10 19:07:04 +08:00
chen08209
8954b88d7f Fix build.yml4 2024-06-09 19:55:59 +08:00
chen08209
3990f8d7fa Fix build.yml3
(cherry picked from commit 8a01e04871)
2024-06-09 19:53:02 +08:00
chen08209
98688bcd2a Fix build.yml2
(cherry picked from commit 7ddcdd9828)
2024-06-09 19:53:02 +08:00
chen08209
2957311682 Fix build.yml
(cherry picked from commit d89ed076fd)
2024-06-09 19:53:01 +08:00
chen08209
87a903af60 Add search function at access control
Fix the issues with the profile add button to cover the edit button

Adapt LoadBalance and Relay

Add arm

Fix android notification icon error
2024-06-09 19:22:49 +08:00
23 changed files with 91 additions and 379 deletions

View File

@@ -188,21 +188,6 @@ func getTraffic() *C.char {
return C.CString(string(data))
}
//export getTotalTraffic
func getTotalTraffic() *C.char {
up, down := statistic.DefaultManager.Total()
traffic := map[string]int64{
"up": up,
"down": down,
}
data, err := json.Marshal(traffic)
if err != nil {
fmt.Println("Error:", err)
return C.CString("")
}
return C.CString(string(data))
}
//export asyncTestDelay
func asyncTestDelay(s *C.char, port C.longlong) {
i := int64(port)

View File

@@ -35,6 +35,8 @@ func startTUN(fd C.int) {
closer, err := t.Start(f, gateway, portal, dns)
applyConfig(true)
if err != nil {
log.Errorln("startTUN error: %v", err)
tempTun.Close()
@@ -54,6 +56,7 @@ func stopTun() {
if tun != nil {
tun.Close()
applyConfig(true)
tun = nil
}
}()

View File

@@ -46,8 +46,8 @@ class ClashCore {
bool init(String homeDir) {
return clashFFI.initClash(
homeDir.toNativeUtf8().cast(),
) ==
homeDir.toNativeUtf8().cast(),
) ==
1;
}
@@ -100,8 +100,7 @@ class ClashCore {
UsedProxy.GLOBAL.name,
...(proxies[UsedProxy.GLOBAL.name]["all"] as List).where((e) {
final proxy = proxies[e] ?? {};
return GroupTypeExtension.valueList.contains(proxy['type']) &&
proxy['hidden'] != true;
return GroupTypeExtension.valueList.contains(proxy['type']) && proxy['hidden'] != true;
})
];
final groupsRaw = groupNames.map((groupName) {
@@ -109,7 +108,7 @@ class ClashCore {
group["all"] = ((group["all"] ?? []) as List)
.map(
(name) => proxies[name],
)
)
.toList();
return group;
}).toList();
@@ -120,14 +119,14 @@ class ClashCore {
Future<List<ExternalProvider>> getExternalProviders() {
final externalProvidersRaw = clashFFI.getExternalProviders();
final externalProvidersRawString =
externalProvidersRaw.cast<Utf8>().toDartString();
externalProvidersRaw.cast<Utf8>().toDartString();
return Isolate.run<List<ExternalProvider>>(() {
final externalProviders =
(json.decode(externalProvidersRawString) as List<dynamic>)
.map(
(item) => ExternalProvider.fromJson(item),
)
.toList();
(json.decode(externalProvidersRawString) as List<dynamic>)
.map(
(item) => ExternalProvider.fromJson(item),
)
.toList();
return externalProviders;
});
}
@@ -199,13 +198,6 @@ class ClashCore {
return Traffic.fromMap(trafficMap);
}
Traffic getTotalTraffic() {
final trafficRaw = clashFFI.getTotalTraffic();
final trafficMap = json.decode(trafficRaw.cast<Utf8>().toDartString());
return Traffic.fromMap(trafficMap);
}
void startLog() {
clashFFI.startLog();
}
@@ -230,16 +222,16 @@ class ClashCore {
clashFFI.setProcessMap(json.encode(processMapItem).toNativeUtf8().cast());
}
// DateTime? getRunTime() {
// final runTimeString = clashFFI.getRunTime().cast<Utf8>().toDartString();
// if (runTimeString.isEmpty) return null;
// return DateTime.fromMillisecondsSinceEpoch(int.parse(runTimeString));
// }
DateTime? getRunTime() {
final runTimeString = clashFFI.getRunTime().cast<Utf8>().toDartString();
if (runTimeString.isEmpty) return null;
return DateTime.fromMillisecondsSinceEpoch(int.parse(runTimeString));
}
List<Connection> getConnections() {
final connectionsDataRaw = clashFFI.getConnections();
final connectionsData =
json.decode(connectionsDataRaw.cast<Utf8>().toDartString()) as Map;
json.decode(connectionsDataRaw.cast<Utf8>().toDartString()) as Map;
final connectionsRaw = connectionsData['connections'] as List? ?? [];
return connectionsRaw.map((e) => Connection.fromJson(e)).toList();
}

View File

@@ -983,16 +983,6 @@ class ClashFFI {
late final _getTraffic =
_getTrafficPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
ffi.Pointer<ffi.Char> getTotalTraffic() {
return _getTotalTraffic();
}
late final _getTotalTrafficPtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
'getTotalTraffic');
late final _getTotalTraffic =
_getTotalTrafficPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
void asyncTestDelay(
ffi.Pointer<ffi.Char> s,
int port,
@@ -1166,6 +1156,16 @@ class ClashFFI {
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('startTUN');
late final _startTUN = _startTUNPtr.asFunction<void Function(int)>();
ffi.Pointer<ffi.Char> getRunTime() {
return _getRunTime();
}
late final _getRunTimePtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
'getRunTime');
late final _getRunTime =
_getRunTimePtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
void stopTun() {
return _stopTun();
}

View File

@@ -31,7 +31,6 @@ class AppController {
Future<void> updateSystemProxy(bool isStart) async {
if (isStart) {
await globalState.startSystemProxy(
appState: appState,
config: config,
clashConfig: clashConfig,
);

View File

@@ -21,17 +21,26 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
.asMap()
.map(
(index, e) => MapEntry(
index,
Point(
(index + initPoints.length).toDouble(),
e.speed.toDouble(),
),
),
)
index,
Point(
(index + initPoints.length).toDouble(),
e.speed.toDouble(),
),
),
)
.values
.toList();
var pointsRaw = [...initPoints, ...trafficPoints];
List<Point> points;
if (pointsRaw.length > 60) {
points = pointsRaw
.getRange(pointsRaw.length - 61, pointsRaw.length - 1)
.toList();
} else {
points = pointsRaw;
}
return [...initPoints, ...trafficPoints];
return points;
}
Traffic _getLastTraffic(List<Traffic> traffics) {
@@ -44,10 +53,11 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
required IconData iconData,
required TrafficValue value,
}) {
final showValue = value.showValue;
final showUnit = "${value.showUnit}/s";
final titleLargeSoftBold =
Theme.of(context).textTheme.titleLarge?.toSoftBold();
Theme.of(context).textTheme.titleLarge?.toSoftBold();
final bodyMedium = Theme.of(context).textTheme.bodySmall?.toLight();
final valueText = Text(
showValue,
@@ -111,7 +121,7 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
@override
Widget build(BuildContext context) {
return CommonCard(
info: Info(
info: Info(
label: appLocalizations.networkSpeed,
iconData: Icons.speed,
),
@@ -162,4 +172,4 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
),
);
}
}
}

View File

@@ -55,11 +55,21 @@ class TrafficUsage extends StatelessWidget {
label: appLocalizations.trafficUsage,
iconData: Icons.data_saver_off,
),
child: Selector<AppState, Traffic>(
selector: (_, appState) => appState.totalTraffic,
builder: (_, totalTraffic, __) {
final upTotalTrafficValue = totalTraffic.up;
final downTotalTrafficValue = totalTraffic.down;
child: Selector<AppState, List<Traffic>>(
selector: (_, appState) => appState.traffics,
builder: (_, traffics, __) {
final trafficTotal = traffics.isNotEmpty
? traffics.reduce(
(value, element) {
return Traffic(
up: element.up.value + value.up.value,
down: element.down.value + value.down.value,
);
},
)
: Traffic();
final upTrafficValue = trafficTotal.up;
final downTrafficValue = trafficTotal.down;
return Padding(
padding: const EdgeInsets.all(16).copyWith(top: 0),
child: Column(
@@ -70,7 +80,7 @@ class TrafficUsage extends StatelessWidget {
child: getTrafficDataItem(
context,
Icons.arrow_upward,
upTotalTrafficValue,
upTrafficValue,
),
),
const SizedBox(
@@ -81,7 +91,7 @@ class TrafficUsage extends StatelessWidget {
child: getTrafficDataItem(
context,
Icons.arrow_downward,
downTotalTrafficValue,
downTrafficValue,
),
),
],

View File

@@ -1,6 +1,5 @@
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/fragments/profiles/edit_profile.dart';
import 'package:fl_clash/fragments/profiles/view_profile.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/state.dart';
@@ -16,7 +15,6 @@ enum ProfileActions {
edit,
update,
delete,
view,
}
class ProfilesFragment extends StatefulWidget {
@@ -200,16 +198,6 @@ class _ProfileItemState extends State<ProfileItem> {
);
}
_handleViewProfile(Profile profile) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ViewProfile(
profile: profile.copyWith(),
),
),
);
}
_buildTitle(Profile profile) {
final textTheme = context.textTheme;
final userInfo = profile.userInfo ?? UserInfo();
@@ -219,7 +207,7 @@ class _ProfileItemState extends State<ProfileItem> {
final totalShow = TrafficValue(value: total).show;
final progress = total == 0 ? 0.0 : use / total;
final expireShow = userInfo.expire == 0
? appLocalizations.infiniteTime
? "长期有效"
: DateTime.fromMillisecondsSinceEpoch(userInfo.expire * 1000).show;
return Container(
padding: const EdgeInsets.symmetric(vertical: 4),
@@ -267,7 +255,7 @@ class _ProfileItemState extends State<ProfileItem> {
Row(
children: [
Text(
appLocalizations.expirationTime,
"到期时间:",
style: textTheme.labelMedium?.toLighter(),
),
const SizedBox(
@@ -328,11 +316,6 @@ class _ProfileItemState extends State<ProfileItem> {
label: appLocalizations.delete,
iconData: Icons.delete,
),
// CommonPopupMenuItem(
// action: ProfileActions.view,
// label: "查看",
// iconData: Icons.visibility,
// ),
],
onSelected: (ProfileActions? action) async {
switch (action) {
@@ -345,9 +328,6 @@ class _ProfileItemState extends State<ProfileItem> {
case ProfileActions.update:
_handleUpdateProfile(profile.id);
break;
case ProfileActions.view:
_handleViewProfile(profile);
break;
case null:
break;
}

View File

@@ -1,171 +0,0 @@
import 'dart:io';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/widgets/scaffold.dart';
import 'package:flutter/material.dart';
import 'package:re_editor/re_editor.dart';
import 'package:re_highlight/languages/yaml.dart';
import 'package:re_highlight/styles/intellij-light.dart';
class ViewProfile extends StatefulWidget {
final Profile profile;
const ViewProfile({
super.key,
required this.profile,
});
@override
State<ViewProfile> createState() => _ViewProfileState();
}
class _ViewProfileState extends State<ViewProfile> {
bool readOnly = true;
final controller = CodeLineEditingController();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final profilePath = await appPath.getProfilePath(widget.profile.id);
if (profilePath == null) {
return;
}
final file = File(profilePath);
final text = await file.readAsString();
controller.text = text;
// _codeController.text = text;
});
}
@override
Widget build(BuildContext context) {
return CommonScaffold(
actions: [
IconButton(
onPressed: controller.undo,
icon: const Icon(Icons.undo),
),
IconButton(
onPressed: controller.redo,
icon: const Icon(Icons.redo),
),
const SizedBox(
width: 8,
)
],
body: CodeEditor(
autofocus: false,
readOnly: readOnly,
scrollbarBuilder: (context, child, details) {
return Scrollbar(
controller: details.controller,
thumbVisibility: true,
interactive: true,
child: child,
);
},
showCursorWhenReadOnly: false,
controller: controller,
toolbarController: const ContextMenuControllerImpl(),
shortcutsActivatorsBuilder:
const DefaultCodeShortcutsActivatorsBuilder(),
indicatorBuilder:
(context, editingController, chunkController, notifier) {
return Row(
children: [
DefaultCodeLineNumber(
controller: editingController,
notifier: notifier,
),
DefaultCodeChunkIndicator(
width: 20,
controller: chunkController,
notifier: notifier,
)
],
);
},
style: CodeEditorStyle(
fontSize: 14,
codeTheme: CodeHighlightTheme(
languages: {
'yaml': CodeHighlightThemeMode(
mode: langYaml,
)
},
theme: intellijLightTheme,
),
),
),
title: "查看",
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
readOnly = !readOnly;
});
},
child: readOnly ? const Icon(Icons.edit) : const Icon(Icons.save),
),
);
}
}
class ContextMenuItemWidget extends PopupMenuItem<void> {
ContextMenuItemWidget({
super.key,
required String text,
required VoidCallback super.onTap,
}) : super(child: Text(text));
}
class ContextMenuControllerImpl implements SelectionToolbarController {
const ContextMenuControllerImpl();
@override
void hide(BuildContext context) {}
@override
void show({
required BuildContext context,
required CodeLineEditingController controller,
required TextSelectionToolbarAnchors anchors,
Rect? renderRect,
required LayerLink layerLink,
required ValueNotifier<bool> visibility,
}) {
if (controller.selectedText.isEmpty) {
return;
}
showMenu(
context: context,
popUpAnimationStyle: AnimationStyle.noAnimation,
position: RelativeRect.fromSize(
(anchors.secondaryAnchor ?? anchors.primaryAnchor) &
const Size(150, double.infinity),
MediaQuery.of(context).size,
),
items: [
ContextMenuItemWidget(
text: 'Cut',
onTap: () {
controller.cut();
},
),
ContextMenuItemWidget(
text: 'Copy',
onTap: () {
controller.copy();
},
),
ContextMenuItemWidget(
text: 'Paste',
onTap: () {
controller.paste();
},
),
],
);
}
}

View File

@@ -64,18 +64,13 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
final indexIsChanging = _tabController?.indexIsChanging ?? false;
if (indexIsChanging) return;
final index = _tabController?.index;
if (index == null) return;
if(index == null) return;
final appController = globalState.appController;
final currentGroups = appController.appState.currentGroups;
if (currentGroups.length > index) {
appController.config.updateCurrentGroupName(currentGroups[index].name);
}
}
@override
void dispose() {
super.dispose();
_tabController?.dispose();
}
@override
Widget build(BuildContext context) {
@@ -125,8 +120,7 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
dividerColor: Colors.transparent,
isScrollable: true,
tabAlignment: TabAlignment.start,
overlayColor:
const WidgetStatePropertyAll(Colors.transparent),
overlayColor: const WidgetStatePropertyAll(Colors.transparent),
tabs: [
for (final groupName in state.groupNames)
Tab(

View File

@@ -111,10 +111,9 @@ class ThemeFragment extends StatelessWidget {
null,
defaultPrimaryColor,
Colors.pinkAccent,
Colors.lightBlue,
Colors.greenAccent,
Colors.yellowAccent,
Colors.purple,
Colors.purple
];
return Column(
children: [

View File

@@ -182,7 +182,5 @@
"nullRequestsDesc": "No proxy or no request",
"findProcessMode": "Find process",
"findProcessModeDesc": "There is a risk of flashback after opening",
"init": "Init",
"infiniteTime": "Long term effective",
"expirationTime": "Expiration time"
"init": "Init"
}

View File

@@ -182,7 +182,5 @@
"nullRequestsDesc": "未开启代理或者没有请求",
"findProcessMode": "查找进程",
"findProcessModeDesc": "开启后存在闪退风险",
"init": "初始化",
"infiniteTime": "长期有效",
"expirationTime": "到期时间"
"init": "初始化"
}

View File

@@ -117,8 +117,6 @@ class MessageLookup extends MessageLookupByLibrary {
"edit": MessageLookupByLibrary.simpleMessage("Edit"),
"en": MessageLookupByLibrary.simpleMessage("English"),
"exit": MessageLookupByLibrary.simpleMessage("Exit"),
"expirationTime":
MessageLookupByLibrary.simpleMessage("Expiration time"),
"externalController":
MessageLookupByLibrary.simpleMessage("ExternalController"),
"externalControllerDesc": MessageLookupByLibrary.simpleMessage(
@@ -144,8 +142,6 @@ class MessageLookup extends MessageLookupByLibrary {
"hours": MessageLookupByLibrary.simpleMessage("Hours"),
"importFromURL":
MessageLookupByLibrary.simpleMessage("Import from URL"),
"infiniteTime":
MessageLookupByLibrary.simpleMessage("Long term effective"),
"init": MessageLookupByLibrary.simpleMessage("Init"),
"ipCheckTimeout":
MessageLookupByLibrary.simpleMessage("Ip check timeout"),

View File

@@ -97,7 +97,6 @@ class MessageLookup extends MessageLookupByLibrary {
"edit": MessageLookupByLibrary.simpleMessage("编辑"),
"en": MessageLookupByLibrary.simpleMessage("英语"),
"exit": MessageLookupByLibrary.simpleMessage("退出"),
"expirationTime": MessageLookupByLibrary.simpleMessage("到期时间"),
"externalController": MessageLookupByLibrary.simpleMessage("外部控制器"),
"externalControllerDesc":
MessageLookupByLibrary.simpleMessage("开启后将可以通过9090端口控制clash内核"),
@@ -117,7 +116,6 @@ class MessageLookup extends MessageLookupByLibrary {
"goDownload": MessageLookupByLibrary.simpleMessage("前往下载"),
"hours": MessageLookupByLibrary.simpleMessage("小时"),
"importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"),
"infiniteTime": MessageLookupByLibrary.simpleMessage("长期有效"),
"init": MessageLookupByLibrary.simpleMessage("初始化"),
"ipCheckTimeout": MessageLookupByLibrary.simpleMessage("Ip检测超时"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收ipv6流量"),

View File

@@ -1889,26 +1889,6 @@ class AppLocalizations {
args: [],
);
}
/// `Long term effective`
String get infiniteTime {
return Intl.message(
'Long term effective',
name: 'infiniteTime',
desc: '',
args: [],
);
}
/// `Expiration time`
String get expirationTime {
return Intl.message(
'Expiration time',
name: 'expirationTime',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -75,7 +75,6 @@ Future<void> vpnService() async {
handleStart() async {
await app?.tip(appLocalizations.startVpn);
await globalState.startSystemProxy(
appState: appState,
config: config,
clashConfig: clashConfig,
);

View File

@@ -22,7 +22,6 @@ class AppState with ChangeNotifier {
bool _isInit;
VersionInfo? _versionInfo;
List<Traffic> _traffics;
Traffic _totalTraffic;
List<Log> _logs;
String _currentLabel;
SystemColorSchemes _systemColorSchemes;
@@ -49,7 +48,6 @@ class AppState with ChangeNotifier {
_sortNum = 0,
_requests = [],
_mode = mode,
_totalTraffic = Traffic(),
_delayMap = {},
_groups = [],
_isCompatible = isCompatible,
@@ -159,24 +157,11 @@ class AppState with ChangeNotifier {
}
}
addTraffic(Traffic traffic) {
_traffics = List.from(_traffics)..add(traffic);
const maxLength = 60;
if (_traffics.length > maxLength) {
_traffics = _traffics.sublist(_traffics.length - maxLength);
}
addTraffic(Traffic value) {
_traffics = List.from(_traffics)..add(value);
notifyListeners();
}
Traffic get totalTraffic => _totalTraffic;
set totalTraffic(Traffic value) {
if (_totalTraffic != value) {
_totalTraffic = value;
notifyListeners();
}
}
List<Connection> get requests => _requests;
set requests(List<Connection> value) {
@@ -206,9 +191,10 @@ class AppState with ChangeNotifier {
addLog(Log log) {
_logs.add(log);
final maxLength = Platform.isAndroid ? 1000 : 60;
if (_logs.length > maxLength) {
_logs = _logs.sublist(_logs.length - maxLength);
if (!Platform.isAndroid) {
if (_logs.length > 60) {
_logs = _logs.sublist(_logs.length - 60);
}
}
notifyListeners();
}

View File

@@ -57,7 +57,6 @@ class GlobalState {
}
Future<void> startSystemProxy({
required AppState appState,
required Config config,
required ClashConfig clashConfig,
}) async {
@@ -74,11 +73,6 @@ class GlobalState {
args: args,
);
startListenUpdate();
applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
}
Future<void> stopSystemProxy() async {
@@ -201,7 +195,6 @@ class GlobalState {
final traffic = clashCore.getTraffic();
if (appState != null) {
appState.addTraffic(traffic);
appState.totalTraffic = clashCore.getTotalTraffic();
}
if (Platform.isAndroid) {
final currentProfile = config.currentProfile;

View File

@@ -7,7 +7,6 @@ import 'package:flutter/services.dart';
class CommonScaffold extends StatefulWidget {
final Widget body;
final Widget? bottomNavigationBar;
final Widget? floatingActionButton;
final String title;
final Widget? leading;
final List<Widget>? actions;
@@ -20,7 +19,6 @@ class CommonScaffold extends StatefulWidget {
this.leading,
required this.title,
this.actions,
this.floatingActionButton,
this.automaticallyImplyLeading = true,
});
@@ -118,13 +116,12 @@ class CommonScaffoldState extends State<CommonScaffold> {
Widget build(BuildContext context) {
return _platformContainer(
child: Scaffold(
floatingActionButton: widget.floatingActionButton ??
ValueListenableBuilder(
valueListenable: _floatingActionButton,
builder: (_, floatingActionButton, __) {
return floatingActionButton ?? Container();
},
),
floatingActionButton: ValueListenableBuilder(
valueListenable: _floatingActionButton,
builder: (_, floatingActionButton, __) {
return floatingActionButton ?? Container();
},
),
resizeToAvoidBottomInset: true,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),

View File

@@ -517,22 +517,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.4"
isolate_contactor:
dependency: transitive
description:
name: isolate_contactor
sha256: f1be0a90f91e4309ef37cc45280b2a84e769e848aae378318dd3dd263cfc482a
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.2.0"
isolate_manager:
dependency: transitive
description:
name: isolate_manager
sha256: "8fb916c4444fd408f089448f904f083ac3e169ea1789fd4d987b25809af92188"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.3.1"
jovial_misc:
dependency: transitive
description:
@@ -553,10 +537,10 @@ packages:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.6.7"
version: "0.7.1"
json_annotation:
dependency: "direct main"
description:
@@ -836,22 +820,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.1"
re_editor:
dependency: "direct main"
description:
name: re_editor
sha256: db7a82e95f0f74301e85d4d5c805a8b8a5ba43d6c0d26673b7e35dc011f06635
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.0"
re_highlight:
dependency: "direct main"
description:
name: re_highlight
sha256: "6c4ac3f76f939fb7ca9df013df98526634e17d8f7460e028bd23a035870024f2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.3"
screen_retriever:
dependency: transitive
description:

View File

@@ -1,7 +1,7 @@
name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none'
version: 0.8.25
version: 0.8.24
environment:
sdk: '>=3.1.0 <4.0.0'
@@ -17,7 +17,7 @@ dependencies:
provider: ^6.0.5
window_manager: ^0.3.8
ffi: ^2.1.0
dynamic_color: ^1.7.0
dynamic_color: ^1.6.0
proxy:
path: plugins/proxy
launch_at_startup: ^0.2.2
@@ -39,8 +39,6 @@ dependencies:
webdav_client: ^1.2.2
dio: ^5.4.3+1
country_flags: ^2.2.0
re_editor: ^0.3.0
re_highlight: ^0.0.3
dev_dependencies:
flutter_test:
sdk: flutter