Optimize proxies expansion panel 2
Fix android scan qrcode error
This commit is contained in:
@@ -150,7 +150,6 @@ class ApplicationState extends State<Application> {
|
|||||||
builder: (lightDynamic, darkDynamic) {
|
builder: (lightDynamic, darkDynamic) {
|
||||||
_updateSystemColorSchemes(lightDynamic, darkDynamic);
|
_updateSystemColorSchemes(lightDynamic, darkDynamic);
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
|
||||||
navigatorKey: globalState.navigatorKey,
|
navigatorKey: globalState.navigatorKey,
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
AppLocalizations.delegate,
|
AppLocalizations.delegate,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ class Android {
|
|||||||
init() async {
|
init() async {
|
||||||
app?.onExit = () {
|
app?.onExit = () {
|
||||||
clashCore.shutdown();
|
clashCore.shutdown();
|
||||||
print("adsadda==>");
|
|
||||||
exit(0);
|
exit(0);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,7 +359,9 @@ class AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addProfileFormURL(String url) async {
|
addProfileFormURL(String url) async {
|
||||||
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
|
if (globalState.navigatorKey.currentState?.canPop() ?? false) {
|
||||||
|
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
|
||||||
|
}
|
||||||
toProfiles();
|
toProfiles();
|
||||||
final commonScaffoldState = globalState.homeScaffoldKey.currentState;
|
final commonScaffoldState = globalState.homeScaffoldKey.currentState;
|
||||||
if (commonScaffoldState?.mounted != true) return;
|
if (commonScaffoldState?.mounted != true) return;
|
||||||
@@ -421,18 +423,17 @@ class AppController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Proxy> _sortOfName(List<Proxy> proxies) {
|
List<Proxy> _sortOfName(List<Proxy> proxies) {
|
||||||
return List.of(proxies)
|
return List.of(proxies)
|
||||||
..sort(
|
..sort(
|
||||||
(a, b) => other.sortByChar(a.name, b.name),
|
(a, b) => other.sortByChar(a.name, b.name),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Proxy> _sortOfDelay(List<Proxy> proxies) {
|
List<Proxy> _sortOfDelay(List<Proxy> proxies) {
|
||||||
return proxies = List.of(proxies)
|
return proxies = List.of(proxies)
|
||||||
..sort(
|
..sort(
|
||||||
(a, b) {
|
(a, b) {
|
||||||
final aDelay = appState.getDelay(a.name);
|
final aDelay = appState.getDelay(a.name);
|
||||||
final bDelay = appState.getDelay(b.name);
|
final bDelay = appState.getDelay(b.name);
|
||||||
if (aDelay == null && bDelay == null) {
|
if (aDelay == null && bDelay == null) {
|
||||||
@@ -449,11 +450,11 @@ class AppController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Proxy> getSortProxies(List<Proxy> proxies){
|
List<Proxy> getSortProxies(List<Proxy> proxies) {
|
||||||
return switch(config.proxiesSortType){
|
return switch (config.proxiesSortType) {
|
||||||
ProxiesSortType.none => proxies,
|
ProxiesSortType.none => proxies,
|
||||||
ProxiesSortType.delay => _sortOfDelay(proxies),
|
ProxiesSortType.delay => _sortOfDelay(proxies),
|
||||||
ProxiesSortType.name =>_sortOfName(proxies),
|
ProxiesSortType.name => _sortOfName(proxies),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ class AddProfile extends StatelessWidget {
|
|||||||
final url = await Navigator.of(context)
|
final url = await Navigator.of(context)
|
||||||
.push<String>(MaterialPageRoute(builder: (_) => const ScanPage()));
|
.push<String>(MaterialPageRoute(builder: (_) => const ScanPage()));
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
_handleAddProfileFormURL(url);
|
WidgetsBinding.instance.addPostFrameCallback((_){
|
||||||
|
_handleAddProfileFormURL(url);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -437,16 +437,16 @@ class _ProfileItemState extends State<ProfileItem> {
|
|||||||
label: appLocalizations.update,
|
label: appLocalizations.update,
|
||||||
iconData: Icons.sync,
|
iconData: Icons.sync,
|
||||||
),
|
),
|
||||||
CommonPopupMenuItem(
|
|
||||||
action: ProfileActions.delete,
|
|
||||||
label: appLocalizations.delete,
|
|
||||||
iconData: Icons.delete,
|
|
||||||
),
|
|
||||||
CommonPopupMenuItem(
|
CommonPopupMenuItem(
|
||||||
action: ProfileActions.view,
|
action: ProfileActions.view,
|
||||||
label: appLocalizations.view,
|
label: appLocalizations.view,
|
||||||
iconData: Icons.visibility,
|
iconData: Icons.visibility,
|
||||||
),
|
),
|
||||||
|
CommonPopupMenuItem(
|
||||||
|
action: ProfileActions.delete,
|
||||||
|
label: appLocalizations.delete,
|
||||||
|
iconData: Icons.delete,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
onSelected: (ProfileActions? action) async {
|
onSelected: (ProfileActions? action) async {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
|||||||
@@ -230,17 +230,6 @@ class ProxiesExpansionPanelFragment extends StatefulWidget {
|
|||||||
|
|
||||||
class _ProxiesExpansionPanelFragmentState
|
class _ProxiesExpansionPanelFragmentState
|
||||||
extends State<ProxiesExpansionPanelFragment> {
|
extends State<ProxiesExpansionPanelFragment> {
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Selector2<AppState, Config, ProxiesSelectorState>(
|
return Selector2<AppState, Config, ProxiesSelectorState>(
|
||||||
@@ -259,6 +248,7 @@ class _ProxiesExpansionPanelFragmentState
|
|||||||
itemBuilder: (_, index) {
|
itemBuilder: (_, index) {
|
||||||
final groupName = state.groupNames[index];
|
final groupName = state.groupNames[index];
|
||||||
return ProxyGroupView(
|
return ProxyGroupView(
|
||||||
|
key: PageStorageKey(groupName),
|
||||||
groupName: groupName,
|
groupName: groupName,
|
||||||
type: ProxiesType.expansion,
|
type: ProxiesType.expansion,
|
||||||
);
|
);
|
||||||
@@ -291,6 +281,7 @@ class ProxyGroupView extends StatefulWidget {
|
|||||||
class _ProxyGroupViewState extends State<ProxyGroupView> {
|
class _ProxyGroupViewState extends State<ProxyGroupView> {
|
||||||
var isLock = false;
|
var isLock = false;
|
||||||
final isBoundaryNotifier = ValueNotifier<bool>(false);
|
final isBoundaryNotifier = ValueNotifier<bool>(false);
|
||||||
|
final scrollController = ScrollController();
|
||||||
var isEnd = false;
|
var isEnd = false;
|
||||||
|
|
||||||
String get groupName => widget.groupName;
|
String get groupName => widget.groupName;
|
||||||
@@ -384,28 +375,49 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _androidExpansionHandle(Widget child) {
|
Widget _androidExpansionHandle(Widget child) {
|
||||||
return NotificationListener<ScrollNotification>(
|
// return NotificationListener<ScrollNotification>(
|
||||||
onNotification: (ScrollNotification notification) {
|
// onNotification: (ScrollNotification notification) {
|
||||||
if (notification is ScrollEndNotification) {
|
// if (notification is ScrollEndNotification) {
|
||||||
if (notification.metrics.atEdge) {
|
// if (notification.metrics.atEdge) {
|
||||||
isEnd = notification.metrics.pixels ==
|
// isEnd = notification.metrics.pixels ==
|
||||||
notification.metrics.maxScrollExtent;
|
// notification.metrics.maxScrollExtent;
|
||||||
isBoundaryNotifier.value = true;
|
// isBoundaryNotifier.value = true;
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// },
|
||||||
|
// child: Listener(
|
||||||
|
// onPointerMove: (details) {
|
||||||
|
// double yOffset = details.delta.dy;
|
||||||
|
// final isEnd = scrollController.position.maxScrollExtent == scrollController.position.pixels;
|
||||||
|
// final isTop = scrollController.position.minScrollExtent == scrollController.position.pixels;
|
||||||
|
// if(isEnd || isTop){
|
||||||
|
// isBoundaryNotifier.value = true;
|
||||||
|
// } else if (yOffset > 0 && scrollController.position.maxScrollExtent == scrollController.position.pixels) {
|
||||||
|
// isBoundaryNotifier.value = false;
|
||||||
|
// } else if (yOffset < 0 && !isEnd) {
|
||||||
|
// isBoundaryNotifier.value = false;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// child: child,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
return Listener(
|
||||||
|
onPointerMove: (details) {
|
||||||
|
double yOffset = details.delta.dy;
|
||||||
|
final isEnd = scrollController.position.maxScrollExtent ==
|
||||||
|
scrollController.position.pixels;
|
||||||
|
final isTop = scrollController.position.minScrollExtent ==
|
||||||
|
scrollController.position.pixels;
|
||||||
|
if (isEnd && yOffset < 0) {
|
||||||
|
isBoundaryNotifier.value = true;
|
||||||
|
} else if (isTop && yOffset > 0) {
|
||||||
|
isBoundaryNotifier.value = true;
|
||||||
|
} else {
|
||||||
|
isBoundaryNotifier.value = false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: Listener(
|
child: child,
|
||||||
onPointerMove: (details) {
|
|
||||||
double yOffset = details.delta.dy;
|
|
||||||
if (yOffset > 0 && isEnd) {
|
|
||||||
isBoundaryNotifier.value = false;
|
|
||||||
} else if (yOffset < 0 && !isEnd) {
|
|
||||||
isBoundaryNotifier.value = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +434,8 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
final itemHeight = _getItemHeight(proxyCardType);
|
final itemHeight = _getItemHeight(proxyCardType);
|
||||||
final innerHeight = context.appSize.height - 200;
|
final innerHeight = context.appSize.height - 200;
|
||||||
final lines = (sortedProxies.length / columns).ceil();
|
final lines = (sortedProxies.length / columns).ceil();
|
||||||
final minLines = innerHeight >= 200 ? (innerHeight / itemHeight).floor() : 3;
|
final minLines =
|
||||||
|
innerHeight >= 200 ? (innerHeight / itemHeight).floor() : 3;
|
||||||
final hasScrollable = lines > minLines;
|
final hasScrollable = lines > minLines;
|
||||||
final height = (itemHeight + 8) * min(lines, minLines) - 8;
|
final height = (itemHeight + 8) * min(lines, minLines) - 8;
|
||||||
return Selector<Config, Set<String>>(
|
return Selector<Config, Set<String>>(
|
||||||
@@ -430,6 +443,7 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
builder: (_, currentUnfoldSet, __) {
|
builder: (_, currentUnfoldSet, __) {
|
||||||
return CommonCard(
|
return CommonCard(
|
||||||
child: ExpansionTile(
|
child: ExpansionTile(
|
||||||
|
childrenPadding: const EdgeInsets.all(8),
|
||||||
initiallyExpanded: currentUnfoldSet.contains(groupName),
|
initiallyExpanded: currentUnfoldSet.contains(groupName),
|
||||||
iconColor: context.colorScheme.onSurfaceVariant,
|
iconColor: context.colorScheme.onSurfaceVariant,
|
||||||
onExpansionChanged: (value) {
|
onExpansionChanged: (value) {
|
||||||
@@ -527,12 +541,6 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
collapsedShape: const RoundedRectangleBorder(
|
collapsedShape: const RoundedRectangleBorder(
|
||||||
side: BorderSide.none,
|
side: BorderSide.none,
|
||||||
),
|
),
|
||||||
childrenPadding: const EdgeInsets.only(
|
|
||||||
top: 8,
|
|
||||||
bottom: 8,
|
|
||||||
left: 8,
|
|
||||||
right: 8,
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: height,
|
height: height,
|
||||||
@@ -541,62 +549,70 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
ValueListenableBuilder(
|
ValueListenableBuilder(
|
||||||
valueListenable: isBoundaryNotifier,
|
valueListenable: isBoundaryNotifier,
|
||||||
builder: (_, isBoundary, child) {
|
builder: (_, isBoundary, child) {
|
||||||
return GridView.builder(
|
return Scrollbar(
|
||||||
physics: isBoundary || !hasScrollable
|
thickness: 6,
|
||||||
? const NeverScrollableScrollPhysics()
|
interactive: true,
|
||||||
: const AlwaysScrollableScrollPhysics(),
|
radius: const Radius.circular(6),
|
||||||
gridDelegate:
|
child: GridView.builder(
|
||||||
SliverGridDelegateWithFixedCrossAxisCount(
|
key: widget.key,
|
||||||
crossAxisCount: columns,
|
controller: scrollController,
|
||||||
mainAxisSpacing: 8,
|
physics: isBoundary || !hasScrollable
|
||||||
crossAxisSpacing: 8,
|
? const NeverScrollableScrollPhysics()
|
||||||
mainAxisExtent: _getItemHeight(proxyCardType),
|
: const AlwaysScrollableScrollPhysics(),
|
||||||
|
gridDelegate:
|
||||||
|
SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: columns,
|
||||||
|
mainAxisSpacing: 8,
|
||||||
|
crossAxisSpacing: 8,
|
||||||
|
mainAxisExtent: _getItemHeight(proxyCardType),
|
||||||
|
),
|
||||||
|
itemCount: sortedProxies.length,
|
||||||
|
itemBuilder: (_, index) {
|
||||||
|
final proxy = sortedProxies[index];
|
||||||
|
return _currentProxyNameBuilder(
|
||||||
|
builder: (value) {
|
||||||
|
return ProxyCard(
|
||||||
|
style: CommonCardType.filled,
|
||||||
|
type: proxyCardType,
|
||||||
|
isSelected: value == proxy.name,
|
||||||
|
key: ValueKey('$groupName.${proxy.name}'),
|
||||||
|
proxy: proxy,
|
||||||
|
groupName: groupName,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
itemCount: sortedProxies.length,
|
|
||||||
itemBuilder: (_, index) {
|
|
||||||
final proxy = sortedProxies[index];
|
|
||||||
return _currentProxyNameBuilder(
|
|
||||||
builder: (value) {
|
|
||||||
return ProxyCard(
|
|
||||||
style: CommonCardType.filled,
|
|
||||||
type: proxyCardType,
|
|
||||||
isSelected: value == proxy.name,
|
|
||||||
key: ValueKey('$groupName.${proxy.name}'),
|
|
||||||
proxy: proxy,
|
|
||||||
groupName: groupName,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: GridView.builder(
|
: GridView.builder(
|
||||||
physics: !hasScrollable
|
key: widget.key,
|
||||||
? const NeverScrollableScrollPhysics()
|
controller: scrollController,
|
||||||
: const AlwaysScrollableScrollPhysics(),
|
physics: !hasScrollable
|
||||||
gridDelegate:
|
? const NeverScrollableScrollPhysics()
|
||||||
SliverGridDelegateWithFixedCrossAxisCount(
|
: const AlwaysScrollableScrollPhysics(),
|
||||||
crossAxisCount: columns,
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
mainAxisSpacing: 8,
|
crossAxisCount: columns,
|
||||||
crossAxisSpacing: 8,
|
mainAxisSpacing: 8,
|
||||||
mainAxisExtent: _getItemHeight(proxyCardType),
|
crossAxisSpacing: 8,
|
||||||
),
|
mainAxisExtent: _getItemHeight(proxyCardType),
|
||||||
itemCount: sortedProxies.length,
|
),
|
||||||
itemBuilder: (_, index) {
|
itemCount: sortedProxies.length,
|
||||||
final proxy = sortedProxies[index];
|
itemBuilder: (_, index) {
|
||||||
return _currentProxyNameBuilder(builder: (value) {
|
final proxy = sortedProxies[index];
|
||||||
return ProxyCard(
|
return _currentProxyNameBuilder(builder: (value) {
|
||||||
style: CommonCardType.filled,
|
return ProxyCard(
|
||||||
type: proxyCardType,
|
style: CommonCardType.filled,
|
||||||
isSelected: value == proxy.name,
|
type: proxyCardType,
|
||||||
key: ValueKey('$groupName.${proxy.name}'),
|
isSelected: value == proxy.name,
|
||||||
proxy: proxy,
|
key: ValueKey('$groupName.${proxy.name}'),
|
||||||
groupName: groupName,
|
proxy: proxy,
|
||||||
);
|
groupName: groupName,
|
||||||
});
|
);
|
||||||
},
|
});
|
||||||
),
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -609,6 +625,7 @@ class _ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
isBoundaryNotifier.dispose();
|
isBoundaryNotifier.dispose();
|
||||||
|
scrollController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: fl_clash
|
name: fl_clash
|
||||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.8.29
|
version: 0.8.30
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user