Files
FlClash/lib/views/proxies/common.dart
T
chen08209 2ea52fdfdc feat(proxies): show groups as cards and group tabs as chips
Changelog: Proxy groups as cards, group tabs as chips
2026-10-17 17:21:43 +08:00

81 lines
2.1 KiB
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/ui/typography.dart';
import 'package:flutter/widgets.dart';
const proxyGridSpacing = 8.0;
double get listHeaderHeight {
final measure = globalState.measure;
return 20 +
measure.textHeight(AppTextStyle.callout) +
2 +
measure.textHeight(AppTextStyle.caption1) +
2;
}
double getItemHeight(ProxyCardType proxyCardType) {
final measure = globalState.measure;
final baseHeight =
16 +
measure.textHeight(AppTextStyle.subheadline) * 2 +
measure.textHeight(AppTextStyle.footnote) +
8 +
4;
return switch (proxyCardType) {
ProxyCardType.loose =>
baseHeight + measure.textHeight(AppTextStyle.caption2) + 6,
ProxyCardType.standard => baseHeight,
ProxyCardType.compact =>
baseHeight - measure.textHeight(AppTextStyle.subheadline),
};
}
double getRowExtent(ProxyCardType proxyCardType) =>
getItemHeight(proxyCardType) + proxyGridSpacing;
class GroupOffsets {
const GroupOffsets(this.groups, this.offsets);
static const empty = GroupOffsets(<Group>[], <double>[]);
final List<Group> groups;
final List<double> offsets;
bool get isEmpty => offsets.isEmpty;
double offsetOf(String groupName) {
final index = groups.indexWhere((group) => group.name == groupName);
if (index < 0 || index >= offsets.length) {
return 0;
}
return offsets[index];
}
}
double? selectedRowOffset({
required List<Proxy> proxies,
required String? selectedProxyName,
required int columns,
required double rowExtent,
}) {
final index = proxies.indexWhere((proxy) => proxy.name == selectedProxyName);
if (index < 0) {
return null;
}
return (index ~/ columns) * rowExtent;
}
void animateScrollTo(ScrollController controller, double offset) {
if (!controller.hasClients) {
return;
}
final position = controller.position;
controller.animateTo(
offset.clamp(position.minScrollExtent, position.maxScrollExtent),
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
);
}