Compare commits

..

20 Commits

Author SHA1 Message Date
chen08209
ba91fab2b5 Fix autoRun show issues
Fix Android 10 issues

Optimize ip show
2024-06-23 03:06:28 +08:00
chen08209
18add7fba3 Add intranet IP display
Add connections page

Add search in connections, requests

Add keyword search in connections, requests, logs

Add basic viewing editing capabilities

Optimize update profile
2024-06-22 03:01:07 +08:00
chen08209
0d3034f216 Update version
(cherry picked from commit afa1b4f424)
2024-06-19 13:13:16 +08:00
chen08209
313faa8cf3 Fix the problem of excessive memory usage in traffic usage.
Add lightBlue theme color

Fix start unable to update profile issues
2024-06-19 10:09:57 +08:00
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
20 changed files with 270 additions and 199 deletions

View File

@@ -64,7 +64,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
toast!!.show()
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"moveTaskToBack" -> {
@@ -151,7 +150,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
val message = call.argument<String>("message")
tip(message)
result.success(true)
}
else -> {

View File

@@ -2,20 +2,13 @@ import 'package:flutter/material.dart';
import 'color.dart';
extension TextStyleExtension on TextStyle {
toLight() {
return copyWith(color: color?.toLight());
}
TextStyle get toLight => copyWith(color: color?.toLight());
toLighter() {
return copyWith(color: color?.toLighter());
}
TextStyle get toLighter => copyWith(color: color?.toLighter());
TextStyle get toSoftBold => copyWith(fontWeight: FontWeight.w500);
toSoftBold() {
return copyWith(fontWeight: FontWeight.w500);
}
TextStyle get toBold => copyWith(fontWeight: FontWeight.bold);
toBold() {
return copyWith(fontWeight: FontWeight.bold);
}
}
TextStyle get toMinus => copyWith(fontSize: fontSize! - 1);
}

View File

@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -267,6 +266,7 @@ class AppController {
}
init() async {
updateLogStatus();
if (!config.silentLaunch) {
window?.show();
}
@@ -290,14 +290,13 @@ class AppController {
}
afterInit() async {
if (config.autoRun) {
await proxyManager.updateStartTime();
if (proxyManager.isStart) {
await updateSystemProxy(true);
} else {
await proxyManager.updateStartTime();
await updateSystemProxy(proxyManager.isStart);
await updateSystemProxy(config.autoRun);
}
autoUpdateProfiles();
updateLogStatus();
autoCheckUpdate();
}

View File

@@ -31,7 +31,7 @@ class CoreInfo extends StatelessWidget {
style: context
.textTheme
.titleMedium
?.toSoftBold(),
?.toSoftBold,
),
),
const SizedBox(
@@ -44,7 +44,7 @@ class CoreInfo extends StatelessWidget {
style: context
.textTheme
.titleLarge
?.toSoftBold(),
?.toSoftBold,
),
),
],

View File

@@ -19,7 +19,7 @@ class _IntranetIpState extends State<IntranetIp> {
List<NetworkInterface> interfaces = await NetworkInterface.list();
for (final interface in interfaces) {
for (final address in interface.addresses) {
if (address.type == InternetAddressType.IPv4 && !address.isLoopback) {
if (!address.isLoopback) {
return address.address;
}
}
@@ -50,7 +50,7 @@ class _IntranetIpState extends State<IntranetIp> {
),
child: Container(
padding: const EdgeInsets.all(16).copyWith(top: 0),
height: globalState.appController.measure.titleLargeHeight + 16,
height: globalState.appController.measure.titleLargeHeight + 24 - 1,
child: ValueListenableBuilder(
valueListenable: ipNotifier,
builder: (_, value, __) {
@@ -65,7 +65,7 @@ class _IntranetIpState extends State<IntranetIp> {
child: TooltipText(
text: Text(
value,
style: context.textTheme.titleLarge?.toSoftBold(),
style: context.textTheme.titleLarge?.toSoftBold.toMinus,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@@ -74,8 +74,11 @@ class _IntranetIpState extends State<IntranetIp> {
],
)
: const Padding(
padding: EdgeInsets.all(4),
child: CircularProgressIndicator(),
padding: EdgeInsets.all(2),
child: AspectRatio(
aspectRatio: 1,
child: CircularProgressIndicator(),
),
),
);
},

View File

@@ -135,7 +135,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
),
Container(
height:
globalState.appController.measure.titleLargeHeight + 24,
globalState.appController.measure.titleLargeHeight + 24 - 1,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.all(16).copyWith(top: 0),
child: FadeBox(
@@ -150,7 +150,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
text: Text(
ipInfo.ip,
style: context.textTheme.titleLarge
?.toSoftBold(),
?.toSoftBold.toMinus,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@@ -164,9 +164,9 @@ class _NetworkDetectionState extends State<NetworkDetection> {
if (timeout) {
return Text(
"timeout",
style: context.textTheme.titleMedium
style: context.textTheme.titleLarge
?.copyWith(color: Colors.red)
.toSoftBold(),
.toSoftBold.toMinus,
maxLines: 1,
overflow: TextOverflow.ellipsis,
);

View File

@@ -47,8 +47,8 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
final showValue = value.showValue;
final showUnit = "${value.showUnit}/s";
final titleLargeSoftBold =
Theme.of(context).textTheme.titleLarge?.toSoftBold();
final bodyMedium = Theme.of(context).textTheme.bodySmall?.toLight();
Theme.of(context).textTheme.titleLarge?.toSoftBold;
final bodyMedium = Theme.of(context).textTheme.bodySmall?.toLight;
final valueText = Text(
showValue,
style: titleLargeSoftBold,
@@ -75,7 +75,7 @@ class _NetworkSpeedState extends State<NetworkSpeed> {
Flexible(
child: Text(
label,
style: Theme.of(context).textTheme.titleSmall?.toSoftBold(),
style: Theme.of(context).textTheme.titleSmall?.toSoftBold,
),
),
],

View File

@@ -67,7 +67,7 @@ class OutboundMode extends StatelessWidget {
.of(context)
.textTheme
.titleMedium
?.toSoftBold(),
?.toSoftBold,
),
),
],

View File

@@ -13,19 +13,17 @@ class StartButton extends StatefulWidget {
class _StartButtonState extends State<StartButton>
with SingleTickerProviderStateMixin {
bool isStart = false;
bool isInit = false;
late AnimationController _controller;
bool isStart = false;
@override
void initState() {
isStart = globalState.appController.appState.isStart;
super.initState();
_controller = AnimationController(
vsync: this,
value: isStart ? 1 : 0,
value: 0,
duration: const Duration(milliseconds: 200),
);
super.initState();
}
@override
@@ -35,9 +33,12 @@ class _StartButtonState extends State<StartButton>
}
handleSwitchStart() {
isStart = !isStart;
updateController();
updateSystemProxy();
final appController = globalState.appController;
if (isStart == appController.appState.isStart) {
isStart = !isStart;
updateController();
appController.updateSystemProxy(isStart);
}
}
updateController() {
@@ -48,11 +49,18 @@ class _StartButtonState extends State<StartButton>
}
}
updateSystemProxy() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final appController = globalState.appController;
await appController.updateSystemProxy(isStart);
});
Widget _updateControllerContainer(Widget child) {
return Selector<AppState, bool>(
selector: (_, appState) => appState.isStart,
builder: (_, isStart, child) {
if(isStart != this.isStart){
this.isStart = isStart;
updateController();
}
return child!;
},
child: child,
);
}
@override
@@ -72,8 +80,7 @@ class _StartButtonState extends State<StartButton>
other.getTimeDifference(
DateTime.now(),
),
style:
Theme.of(context).textTheme.titleMedium?.toSoftBold(),
style: Theme.of(context).textTheme.titleMedium?.toSoftBold,
),
)
.width +
@@ -119,24 +126,14 @@ class _StartButtonState extends State<StartButton>
child: child,
);
},
child: Selector<AppState, bool>(
selector: (_, appState) => appState.runTime != null,
builder: (_, isRun, child) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (isStart != isRun) {
isStart = isRun;
updateController();
}
});
return child!;
},
child: Selector<AppState, int?>(
child: _updateControllerContainer(
Selector<AppState, int?>(
selector: (_, appState) => appState.runTime,
builder: (_, int? value, __) {
final text = other.getTimeText(value);
return Text(
text,
style: Theme.of(context).textTheme.titleMedium?.toSoftBold(),
style: Theme.of(context).textTheme.titleMedium?.toSoftBold,
);
},
),

View File

@@ -42,7 +42,7 @@ class TrafficUsage extends StatelessWidget {
),
Text(
trafficValue.showUnit,
style: context.textTheme.labelMedium?.toLight(),
style: context.textTheme.labelMedium?.toLight,
),
],
);

View File

@@ -1,4 +1,4 @@
export 'proxies.dart';
export 'proxies/proxies.dart';
export 'dashboard/dashboard.dart';
export 'tools.dart';
export 'profiles/profiles.dart';

View File

@@ -253,7 +253,7 @@ class _ProfileItemState extends State<ProfileItem> {
),
Text(
profile.lastUpdateDate?.lastUpdateTimeDesc ?? '',
style: textTheme.labelMedium?.toLight(),
style: textTheme.labelMedium?.toLight,
),
],
),
@@ -284,7 +284,7 @@ class _ProfileItemState extends State<ProfileItem> {
),
Text(
"$useShow / $totalShow",
style: textTheme.labelMedium?.toLight(),
style: textTheme.labelMedium?.toLight,
),
const SizedBox(
height: 2,
@@ -293,14 +293,14 @@ class _ProfileItemState extends State<ProfileItem> {
children: [
Text(
appLocalizations.expirationTime,
style: textTheme.labelMedium?.toLighter(),
style: textTheme.labelMedium?.toLighter,
),
const SizedBox(
width: 4,
),
Text(
expireShow,
style: textTheme.labelMedium?.toLighter(),
style: textTheme.labelMedium?.toLighter,
),
],
)

View File

@@ -0,0 +1,59 @@
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/widgets/card.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProxiesExpansionPanelFragment extends StatefulWidget {
const ProxiesExpansionPanelFragment({super.key});
@override
State<ProxiesExpansionPanelFragment> createState() =>
_ProxiesExpansionPanelFragmentState();
}
class _ProxiesExpansionPanelFragmentState
extends State<ProxiesExpansionPanelFragment> {
@override
Widget build(BuildContext context) {
return Selector2<AppState, Config, ProxiesSelectorState>(
selector: (_, appState, config) {
final currentGroups = appState.currentGroups;
final groupNames = currentGroups.map((e) => e.name).toList();
return ProxiesSelectorState(
groupNames: groupNames,
currentGroupName: config.currentGroupName,
);
},
builder: (_, state, __) {
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: state.groupNames.length,
itemBuilder: (_, index) {
final groupName = state.groupNames[index];
return CommonCard(
child: ExpansionTile(
title: Text(groupName),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
side: const BorderSide(color: Colors.transparent),
),
collapsedShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
side: const BorderSide(color: Colors.transparent),
),
children: [
Text("1212313"),
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return const SizedBox(
height: 16,
);
},
);
},
);
}
}

View File

@@ -0,0 +1,72 @@
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/fragments/proxies/tabview.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProxiesFragment extends StatefulWidget {
const ProxiesFragment({super.key});
@override
State<ProxiesFragment> createState() => _ProxiesFragmentState();
}
class _ProxiesFragmentState extends State<ProxiesFragment> {
_initActions() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final commonScaffoldState =
context.findAncestorStateOfType<CommonScaffoldState>();
final items = [
CommonPopupMenuItem(
action: ProxiesSortType.none,
label: appLocalizations.defaultSort,
iconData: Icons.sort,
),
CommonPopupMenuItem(
action: ProxiesSortType.delay,
label: appLocalizations.delaySort,
iconData: Icons.network_ping),
CommonPopupMenuItem(
action: ProxiesSortType.name,
label: appLocalizations.nameSort,
iconData: Icons.sort_by_alpha),
];
commonScaffoldState?.actions = [
Selector<Config, ProxiesSortType>(
selector: (_, config) => config.proxiesSortType,
builder: (_, proxiesSortType, __) {
return CommonPopupMenu<ProxiesSortType>.radio(
items: items,
onSelected: (value) {
final config = context.read<Config>();
config.proxiesSortType = value;
},
selectedValue: proxiesSortType,
);
},
),
const SizedBox(
width: 8,
)
];
});
}
@override
Widget build(BuildContext context) {
return Selector<AppState, bool>(
selector: (_, appState) => appState.currentLabel == 'proxies',
builder: (_, isCurrent, child) {
if (isCurrent) {
_initActions();
}
return child!;
},
child: const ProxiesTabFragment(),
);
}
}

View File

@@ -1,65 +1,23 @@
import 'package:collection/collection.dart';
import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../enum/enum.dart';
import '../models/models.dart';
import '../common/common.dart';
import '../widgets/widgets.dart';
class ProxiesFragment extends StatefulWidget {
const ProxiesFragment({super.key});
class ProxiesTabFragment extends StatefulWidget {
const ProxiesTabFragment({super.key});
@override
State<ProxiesFragment> createState() => _ProxiesFragmentState();
State<ProxiesTabFragment> createState() => _ProxiesTabFragmentState();
}
class _ProxiesFragmentState extends State<ProxiesFragment>
with TickerProviderStateMixin {
class _ProxiesTabFragmentState extends State<ProxiesTabFragment> with TickerProviderStateMixin {
TabController? _tabController;
_initActions() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final commonScaffoldState =
context.findAncestorStateOfType<CommonScaffoldState>();
final items = [
CommonPopupMenuItem(
action: ProxiesSortType.none,
label: appLocalizations.defaultSort,
iconData: Icons.sort,
),
CommonPopupMenuItem(
action: ProxiesSortType.delay,
label: appLocalizations.delaySort,
iconData: Icons.network_ping),
CommonPopupMenuItem(
action: ProxiesSortType.name,
label: appLocalizations.nameSort,
iconData: Icons.sort_by_alpha),
];
commonScaffoldState?.actions = [
Selector<Config, ProxiesSortType>(
selector: (_, config) => config.proxiesSortType,
builder: (_, proxiesSortType, __) {
return CommonPopupMenu<ProxiesSortType>.radio(
items: items,
onSelected: (value) {
final config = context.read<Config>();
config.proxiesSortType = value;
},
selectedValue: proxiesSortType,
);
},
),
const SizedBox(
width: 8,
)
];
});
}
_handleTabControllerChange() {
final indexIsChanging = _tabController?.indexIsChanging ?? false;
if (indexIsChanging) return;
@@ -71,6 +29,7 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
appController.config.updateCurrentGroupName(currentGroups[index].name);
}
}
@override
void dispose() {
super.dispose();
@@ -79,79 +38,70 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
@override
Widget build(BuildContext context) {
return Selector<AppState, bool>(
selector: (_, appState) => appState.currentLabel == 'proxies',
builder: (_, isCurrent, child) {
if (isCurrent) {
_initActions();
}
return child!;
return Selector2<AppState, Config, ProxiesSelectorState>(
selector: (_, appState, config) {
final currentGroups = appState.currentGroups;
final groupNames = currentGroups.map((e) => e.name).toList();
return ProxiesSelectorState(
groupNames: groupNames,
currentGroupName: config.currentGroupName,
);
},
child: Selector2<AppState, Config, ProxiesSelectorState>(
selector: (_, appState, config) {
final currentGroups = appState.currentGroups;
final groupNames = currentGroups.map((e) => e.name).toList();
return ProxiesSelectorState(
groupNames: groupNames,
currentGroupName: config.currentGroupName,
);
},
shouldRebuild: (prev, next) {
if (!const ListEquality<String>()
.equals(prev.groupNames, next.groupNames)) {
_tabController?.removeListener(_handleTabControllerChange);
_tabController?.dispose();
_tabController = null;
return true;
}
return false;
},
builder: (_, state, __) {
final index = state.groupNames.indexWhere(
(item) => item == state.currentGroupName,
);
_tabController ??= TabController(
length: state.groupNames.length,
initialIndex: index == -1 ? 0 : index,
vsync: this,
)..addListener(_handleTabControllerChange);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TabBar(
shouldRebuild: (prev, next) {
if (!const ListEquality<String>()
.equals(prev.groupNames, next.groupNames)) {
_tabController?.removeListener(_handleTabControllerChange);
_tabController?.dispose();
_tabController = null;
return true;
}
return false;
},
builder: (_, state, __) {
final index = state.groupNames.indexWhere(
(item) => item == state.currentGroupName,
);
_tabController ??= TabController(
length: state.groupNames.length,
initialIndex: index == -1 ? 0 : index,
vsync: this,
)..addListener(_handleTabControllerChange);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TabBar(
controller: _tabController,
padding: const EdgeInsets.symmetric(horizontal: 16),
dividerColor: Colors.transparent,
isScrollable: true,
tabAlignment: TabAlignment.start,
overlayColor:
const WidgetStatePropertyAll(Colors.transparent),
tabs: [
for (final groupName in state.groupNames)
Tab(
text: groupName,
),
],
),
Expanded(
child: TabBarView(
controller: _tabController,
padding: const EdgeInsets.symmetric(horizontal: 16),
dividerColor: Colors.transparent,
isScrollable: true,
tabAlignment: TabAlignment.start,
overlayColor:
const WidgetStatePropertyAll(Colors.transparent),
tabs: [
children: [
for (final groupName in state.groupNames)
Tab(
text: groupName,
KeepContainer(
key: ObjectKey(groupName),
child: ProxiesTabView(
groupName: groupName,
),
),
],
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
for (final groupName in state.groupNames)
KeepContainer(
key: ObjectKey(groupName),
child: ProxiesTabView(
groupName: groupName,
),
),
],
),
)
],
);
},
),
)
],
);
},
);
}
}
@@ -167,7 +117,7 @@ class ProxiesTabView extends StatelessWidget {
List<Proxy> _sortOfName(List<Proxy> proxies) {
return List.of(proxies)
..sort(
(a, b) => other.sortByChar(a.name, b.name),
(a, b) => other.sortByChar(a.name, b.name),
);
}
@@ -175,7 +125,7 @@ class ProxiesTabView extends StatelessWidget {
final appState = context.read<AppState>();
return proxies = List.of(proxies)
..sort(
(a, b) {
(a, b) {
final aDelay = appState.getDelay(a.name);
final bDelay = appState.getDelay(b.name);
if (aDelay == null && bDelay == null) {
@@ -193,10 +143,10 @@ class ProxiesTabView extends StatelessWidget {
}
_getProxies(
BuildContext context,
List<Proxy> proxies,
ProxiesSortType proxiesSortType,
) {
BuildContext context,
List<Proxy> proxies,
ProxiesSortType proxiesSortType,
) {
if (proxiesSortType == ProxiesSortType.delay) {
return _sortOfDelay(context, proxies);
}
@@ -379,7 +329,7 @@ class ProxyCard extends StatelessWidget {
style: context.textTheme.bodySmall?.copyWith(
overflow: TextOverflow.ellipsis,
color:
context.textTheme.bodySmall?.color?.toLight(),
context.textTheme.bodySmall?.color?.toLight(),
),
),
);

View File

@@ -187,7 +187,7 @@
"connections": "Connections",
"connectionsDesc": "View current connection",
"nullRequestsDesc": "No requests",
"nullConnectionsDesc": "No Connections",
"nullConnectionsDesc": "No connections",
"intranetIp": "Intranet IP",
"view": "View",
"cut": "Cut",

View File

@@ -186,7 +186,7 @@ class MessageLookup extends MessageLookupByLibrary {
"notSelectedTip": MessageLookupByLibrary.simpleMessage(
"The current proxy group cannot be selected."),
"nullConnectionsDesc":
MessageLookupByLibrary.simpleMessage("No Connections"),
MessageLookupByLibrary.simpleMessage("No connections"),
"nullCoreInfoDesc":
MessageLookupByLibrary.simpleMessage("Unable to obtain core info"),
"nullLogsDesc": MessageLookupByLibrary.simpleMessage("No logs"),

View File

@@ -1930,10 +1930,10 @@ class AppLocalizations {
);
}
/// `No Connections`
/// `No connections`
String get nullConnectionsDesc {
return Intl.message(
'No Connections',
'No connections',
name: 'nullConnectionsDesc',
desc: '',
args: [],

View File

@@ -11,7 +11,7 @@ class NullStatus extends StatelessWidget {
return Center(
child: Text(
label,
style: Theme.of(context).textTheme.titleMedium?.toBold(),
style: Theme.of(context).textTheme.titleMedium?.toBold,
),
);
}

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.26
version: 0.8.27
environment:
sdk: '>=3.1.0 <4.0.0'