Fix list form input view issues

Fix traffic view issues
This commit is contained in:
chen08209
2025-03-05 15:11:19 +08:00
parent 5184ed6fc7
commit 5dda2854be
11 changed files with 248 additions and 211 deletions

View File

@@ -171,29 +171,34 @@ class FakeIpRangeItem extends ConsumerWidget {
}
}
class FakeIpFilterItem extends ConsumerWidget {
class FakeIpFilterItem extends StatelessWidget {
const FakeIpFilterItem({super.key});
@override
Widget build(BuildContext context, ref) {
final fakeIpFilter = ref.watch(
patchClashConfigProvider.select((state) => state.dns.fakeIpFilter),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.fakeipFilter),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.fakeipFilter,
widget: ListPage(
title: appLocalizations.fakeipFilter,
items: fakeIpFilter,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
fakeIpFilter: List.from(items),
));
widget: Consumer(
builder: (_, ref, __) {
final fakeIpFilter = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fakeIpFilter),
);
return ListPage(
title: appLocalizations.fakeipFilter,
items: fakeIpFilter,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
fakeIpFilter: List.from(items),
));
},
);
},
),
extendPageWidth: 360,
@@ -202,64 +207,69 @@ class FakeIpFilterItem extends ConsumerWidget {
}
}
class DefaultNameserverItem extends ConsumerWidget {
class DefaultNameserverItem extends StatelessWidget {
const DefaultNameserverItem({super.key});
@override
Widget build(BuildContext context, ref) {
final defaultNameserver = ref.watch(
patchClashConfigProvider.select((state) => state.dns.defaultNameserver),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.defaultNameserver),
subtitle: Text(appLocalizations.defaultNameserverDesc),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.defaultNameserver,
widget: ListPage(
title: appLocalizations.defaultNameserver,
items: defaultNameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
widget: Consumer(builder: (_, ref, __) {
final defaultNameserver = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.defaultNameserver),
);
return ListPage(
title: appLocalizations.defaultNameserver,
items: defaultNameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns(
defaultNameserver: List.from(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);
}
}
class NameserverItem extends ConsumerWidget {
class NameserverItem extends StatelessWidget {
const NameserverItem({super.key});
@override
Widget build(BuildContext context, ref) {
final nameserver = ref.watch(
patchClashConfigProvider.select((state) => state.dns.nameserver),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.nameserver),
subtitle: Text(appLocalizations.nameserverDesc),
delegate: OpenDelegate(
title: appLocalizations.nameserver,
isBlur: false,
widget: ListPage(
title: "域名服务器",
items: nameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
widget: Consumer(builder: (_, ref, __) {
final nameserver = ref.watch(
patchClashConfigProvider.select((state) => state.dns.nameserver),
);
return ListPage(
title: "域名服务器",
items: nameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns(
nameserver: List.from(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);
@@ -312,64 +322,71 @@ class UseSystemHostsItem extends ConsumerWidget {
}
}
class NameserverPolicyItem extends ConsumerWidget {
class NameserverPolicyItem extends StatelessWidget {
const NameserverPolicyItem({super.key});
@override
Widget build(BuildContext context, ref) {
final nameserverPolicy = ref.watch(
patchClashConfigProvider.select((state) => state.dns.nameserverPolicy),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.nameserverPolicy),
subtitle: Text(appLocalizations.nameserverPolicyDesc),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.nameserverPolicy,
widget: ListPage(
title: appLocalizations.nameserverPolicy,
items: nameserverPolicy.entries,
titleBuilder: (item) => Text(item.key),
subtitleBuilder: (item) => Text(item.value),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
widget: Consumer(builder: (_, ref, __) {
final nameserverPolicy = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.nameserverPolicy),
);
return ListPage(
title: appLocalizations.nameserverPolicy,
items: nameserverPolicy.entries,
titleBuilder: (item) => Text(item.key),
subtitleBuilder: (item) => Text(item.value),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns(
nameserverPolicy: Map.fromEntries(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);
}
}
class ProxyServerNameserverItem extends ConsumerWidget {
class ProxyServerNameserverItem extends StatelessWidget {
const ProxyServerNameserverItem({super.key});
@override
Widget build(BuildContext context, ref) {
final proxyServerNameserver = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.proxyServerNameserver),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.proxyNameserver),
subtitle: Text(appLocalizations.proxyNameserverDesc),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.proxyNameserver,
widget: ListPage(
title: appLocalizations.proxyNameserver,
items: proxyServerNameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
proxyServerNameserver: List.from(items),
));
widget: Consumer(
builder: (_, ref, __) {
final proxyServerNameserver = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.proxyServerNameserver),
);
return ListPage(
title: appLocalizations.proxyNameserver,
items: proxyServerNameserver,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns(
proxyServerNameserver: List.from(items),
),
);
},
);
},
),
extendPageWidth: 360,
@@ -378,32 +395,34 @@ class ProxyServerNameserverItem extends ConsumerWidget {
}
}
class FallbackItem extends ConsumerWidget {
class FallbackItem extends StatelessWidget {
const FallbackItem({super.key});
@override
Widget build(BuildContext context, ref) {
final fallback = ref.watch(
patchClashConfigProvider.select((state) => state.dns.fallback),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.fallback),
subtitle: Text(appLocalizations.fallbackDesc),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.fallback,
widget: ListPage(
title: appLocalizations.fallback,
items: fallback,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns(
widget: Consumer(builder: (_, ref, __) {
final fallback = ref.watch(
patchClashConfigProvider.select((state) => state.dns.fallback),
);
return ListPage(
title: appLocalizations.fallback,
items: fallback,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns(
fallback: List.from(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);
@@ -454,107 +473,113 @@ class GeoipCodeItem extends ConsumerWidget {
if (value == null) {
return;
}
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns.fallbackFilter(
geoipCode: value,
));
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns.fallbackFilter(
geoipCode: value,
),
);
},
),
);
}
}
class GeositeItem extends ConsumerWidget {
class GeositeItem extends StatelessWidget {
const GeositeItem({super.key});
@override
Widget build(BuildContext context, ref) {
final geosite = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.geosite),
);
Widget build(BuildContext context) {
return ListItem.open(
title: const Text("Geosite"),
delegate: OpenDelegate(
isBlur: false,
title: "Geosite",
widget: ListPage(
title: "Geosite",
items: geosite,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns.fallbackFilter(
widget: Consumer(builder: (_, ref, __) {
final geosite = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.geosite),
);
return ListPage(
title: "Geosite",
items: geosite,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns.fallbackFilter(
geosite: List.from(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);
}
}
class IpcidrItem extends ConsumerWidget {
class IpcidrItem extends StatelessWidget {
const IpcidrItem({super.key});
@override
Widget build(BuildContext context, ref) {
final ipcidr = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.ipcidr),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.ipcidr),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.ipcidr,
widget: ListPage(
title: appLocalizations.ipcidr,
items: ipcidr,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns.fallbackFilter(
ipcidr: List.from(items),
));
},
),
widget: Consumer(builder: (_, ref, ___) {
final ipcidr = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.ipcidr),
);
return ListPage(
title: appLocalizations.ipcidr,
items: ipcidr,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns.fallbackFilter(
ipcidr: List.from(items),
));
},
);
}),
extendPageWidth: 360,
),
);
}
}
class DomainItem extends ConsumerWidget {
class DomainItem extends StatelessWidget {
const DomainItem({super.key});
@override
Widget build(BuildContext context, ref) {
final domain = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.domain),
);
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.domain),
delegate: OpenDelegate(
isBlur: false,
title: appLocalizations.domain,
widget: ListPage(
title: appLocalizations.domain,
items: domain,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref
.read(patchClashConfigProvider.notifier)
.updateState((state) => state.copyWith.dns.fallbackFilter(
widget: Consumer(builder: (_, ref, __) {
final domain = ref.watch(
patchClashConfigProvider
.select((state) => state.dns.fallbackFilter.domain),
);
return ListPage(
title: appLocalizations.domain,
items: domain,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.dns.fallbackFilter(
domain: List.from(items),
));
},
),
),
);
},
);
}),
extendPageWidth: 360,
),
);

View File

@@ -189,13 +189,11 @@ class MixedPortItem extends ConsumerWidget {
}
}
class HostsItem extends ConsumerWidget {
class HostsItem extends StatelessWidget {
const HostsItem({super.key});
@override
Widget build(BuildContext context, ref) {
final hosts =
ref.watch(patchClashConfigProvider.select((state) => state.hosts));
Widget build(BuildContext context) {
return ListItem.open(
leading: const Icon(Icons.view_list_outlined),
title: const Text("Hosts"),
@@ -203,17 +201,23 @@ class HostsItem extends ConsumerWidget {
delegate: OpenDelegate(
isBlur: false,
title: "Hosts",
widget: ListPage(
title: "Hosts",
items: hosts.entries,
titleBuilder: (item) => Text(item.key),
subtitleBuilder: (item) => Text(item.value),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith(
hosts: Map.fromEntries(items),
),
);
widget: Consumer(
builder: (_, ref, __) {
final hosts = ref
.watch(patchClashConfigProvider.select((state) => state.hosts));
return ListPage(
title: "Hosts",
items: hosts.entries,
titleBuilder: (item) => Text(item.key),
subtitleBuilder: (item) => Text(item.value),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith(
hosts: Map.fromEntries(items),
),
);
},
);
},
),
extendPageWidth: 360,

View File

@@ -186,7 +186,7 @@ class TunStackItem extends ConsumerWidget {
}
}
class BypassDomainItem extends ConsumerWidget {
class BypassDomainItem extends StatelessWidget {
const BypassDomainItem({super.key});
_initActions(BuildContext context, WidgetRef ref) {
@@ -219,10 +219,7 @@ class BypassDomainItem extends ConsumerWidget {
}
@override
Widget build(BuildContext context, ref) {
final bypassDomain =
ref.watch(networkSettingProvider.select((state) => state.bypassDomain));
Widget build(BuildContext context) {
return ListItem.open(
title: Text(appLocalizations.bypassDomain),
subtitle: Text(appLocalizations.bypassDomainDesc),
@@ -230,21 +227,25 @@ class BypassDomainItem extends ConsumerWidget {
isBlur: false,
isScaffold: true,
title: appLocalizations.bypassDomain,
widget: Builder(builder: (context) {
_initActions(context, ref);
return ListPage(
title: appLocalizations.bypassDomain,
items: bypassDomain,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(networkSettingProvider.notifier).updateState(
(state) => state.copyWith(
bypassDomain: List.from(items),
),
);
},
);
}),
widget: Consumer(
builder: (_, ref, __) {
_initActions(context, ref);
final bypassDomain = ref.watch(
networkSettingProvider.select((state) => state.bypassDomain));
return ListPage(
title: appLocalizations.bypassDomain,
items: bypassDomain,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(networkSettingProvider.notifier).updateState(
(state) => state.copyWith(
bypassDomain: List.from(items),
),
);
},
);
},
),
extendPageWidth: 360,
),
);
@@ -293,8 +294,6 @@ class RouteAddressItem extends ConsumerWidget {
if (bypassPrivate) {
return Container();
}
final routeAddress = ref.watch(
patchClashConfigProvider.select((state) => state.tun.routeAddress));
return ListItem.open(
title: Text(appLocalizations.routeAddress),
subtitle: Text(appLocalizations.routeAddressDesc),
@@ -302,16 +301,22 @@ class RouteAddressItem extends ConsumerWidget {
isBlur: false,
isScaffold: true,
title: appLocalizations.routeAddress,
widget: ListPage(
title: appLocalizations.routeAddress,
items: routeAddress,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.tun(
routeAddress: List.from(items),
),
);
widget: Consumer(
builder: (_, ref, __) {
final routeAddress = ref.watch(patchClashConfigProvider
.select((state) => state.tun.routeAddress));
return ListPage(
title: appLocalizations.routeAddress,
items: routeAddress,
titleBuilder: (item) => Text(item),
onChange: (items) {
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith.tun(
routeAddress: List.from(items),
),
);
},
);
},
),
extendPageWidth: 360,

View File

@@ -343,5 +343,5 @@
"copyLink": "Copy link",
"exportFile": "Export file",
"cacheCorrupt": "The cache is corrupt. Do you want to clear it?",
"detectionTip": "Relying on third-party APIs is for reference only"
"detectionTip": "Relying on third-party api is for reference only"
}

View File

@@ -343,5 +343,5 @@
"copyLink": "复制链接",
"exportFile": "导出文件",
"cacheCorrupt": "缓存已损坏,是否清空?",
"detectionTip": "依赖第三方程序仅供参考"
"detectionTip": "依赖第三方api仅供参考"
}

View File

@@ -181,7 +181,7 @@ class MessageLookup extends MessageLookupByLibrary {
"A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.",
),
"detectionTip": MessageLookupByLibrary.simpleMessage(
"Relying on third-party APIs is for reference only",
"Relying on third-party api is for reference only",
),
"direct": MessageLookupByLibrary.simpleMessage("Direct"),
"disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"),

View File

@@ -122,7 +122,7 @@ class MessageLookup extends MessageLookupByLibrary {
"desc": MessageLookupByLibrary.simpleMessage(
"基于ClashMeta的多平台代理客户端简单易用开源无广告。",
),
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方程序仅供参考"),
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api仅供参考"),
"direct": MessageLookupByLibrary.simpleMessage("直连"),
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(

View File

@@ -2670,10 +2670,10 @@ class AppLocalizations {
);
}
/// `Relying on third-party APIs is for reference only`
/// `Relying on third-party api is for reference only`
String get detectionTip {
return Intl.message(
'Relying on third-party APIs is for reference only',
'Relying on third-party api is for reference only',
name: 'detectionTip',
desc: '',
args: [],

View File

@@ -334,7 +334,7 @@ class TrafficValue {
}
if (_value > pow(1024, 1)) {
return TrafficValueShow(
value: _value / pow(1024, 2),
value: _value / pow(1024, 1),
unit: TrafficUnit.KB,
);
}

View File

@@ -4,6 +4,7 @@ import 'package:fl_clash/models/common.dart';
import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/null_status.dart';
import 'package:flutter/material.dart';
import 'card.dart';
import 'float_layout.dart';
import 'list.dart';
@@ -118,7 +119,7 @@ class _InputDialogState extends State<InputDialog> {
border: const OutlineInputBorder(),
suffixText: suffixText,
),
onSubmitted: (_){
onSubmitted: (_) {
_handleUpdate();
},
),
@@ -256,7 +257,8 @@ class ListPage<T> extends StatelessWidget {
child: ListItem(
leading: leadingBuilder != null ? leadingBuilder!(e) : null,
title: titleBuilder(e),
subtitle: subtitleBuilder != null ? subtitleBuilder!(e) : null,
subtitle:
subtitleBuilder != null ? subtitleBuilder!(e) : null,
trailing: IconButton(
icon: const Icon(Icons.delete_outline),
onPressed: () {
@@ -318,6 +320,7 @@ class ListPage<T> extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("daad===>$items");
return FloatLayout(
floatingWidget: FloatWrapper(
child: FloatingActionButton(