add build step for flutter web, add persistent pagination in the traction list
Some checks failed
Release / meta (push) Successful in 14s
Release / web-build (push) Has been cancelled
Release / release-dev (push) Has been cancelled
Release / release-master (push) Has been cancelled
Release / linux-build (push) Has been cancelled
Release / android-build (push) Has been cancelled

This commit is contained in:
2026-01-01 23:08:22 +00:00
parent 648872acf1
commit 59458484aa
13 changed files with 326 additions and 58 deletions

View File

@@ -37,6 +37,9 @@ class _TractionPageState extends State<TractionPage> {
final Map<String, TextEditingController> _dynamicControllers = {};
final Map<String, String?> _enumSelections = {};
bool _restoredFromPrefs = false;
static const int _pageSize = 100;
int _lastTractionOffset = 0;
String? _lastQuerySignature;
@override
void initState() {
@@ -59,6 +62,9 @@ class _TractionPageState extends State<TractionPage> {
Future<void> _initialLoad() async {
final data = context.read<DataService>();
await _restoreSearchState();
if (_lastTractionOffset == 0 && data.traction.length > _pageSize) {
_lastTractionOffset = data.traction.length - _pageSize;
}
data.fetchClassList();
data.fetchEventFields();
await _refreshTraction();
@@ -103,7 +109,29 @@ class _TractionPageState extends State<TractionPage> {
dynamicFieldsUsed;
}
Future<void> _refreshTraction({bool append = false}) async {
String _tractionQuerySignature(
Map<String, dynamic> filters,
bool hadOnly,
) {
final sortedKeys = filters.keys.toList()..sort();
final filterSignature = sortedKeys
.map((key) => '$key=${filters[key]}')
.join('|');
final classQuery = (_selectedClass ?? _classController.text).trim();
return [
'class=$classQuery',
'number=${_numberController.text.trim()}',
'name=${_nameController.text.trim()}',
'mileageFirst=$_mileageFirst',
'hadOnly=$hadOnly',
'filters=$filterSignature',
].join(';');
}
Future<void> _refreshTraction({
bool append = false,
bool preservePosition = true,
}) async {
final data = context.read<DataService>();
final filters = <String, dynamic>{};
final name = _nameController.text.trim();
@@ -118,15 +146,49 @@ class _TractionPageState extends State<TractionPage> {
}
});
final hadOnly = !_hasFilters;
final signature = _tractionQuerySignature(filters, hadOnly);
final queryChanged =
_lastQuerySignature != null && signature != _lastQuerySignature;
_lastQuerySignature = signature;
if (queryChanged && !append) {
_lastTractionOffset = 0;
}
final shouldPreservePosition = preservePosition &&
!append &&
!queryChanged &&
_lastTractionOffset > 0;
int limit;
int offset;
if (append) {
offset = data.traction.length;
limit = _pageSize;
_lastTractionOffset = offset;
} else if (shouldPreservePosition) {
offset = 0;
limit = _pageSize + _lastTractionOffset;
} else {
offset = 0;
limit = _pageSize;
}
await data.fetchTraction(
hadOnly: hadOnly,
locoClass: _selectedClass ?? _classController.text.trim(),
locoNumber: _numberController.text.trim(),
offset: append ? data.traction.length : 0,
offset: offset,
limit: limit,
append: append,
filters: filters,
mileageFirst: _mileageFirst,
);
if (!append && !shouldPreservePosition) {
_lastTractionOffset = 0;
}
await _persistSearchState();
}

View File

@@ -39,6 +39,16 @@ extension _TractionPersistence on _TractionPageState {
enumValues[entry.key.toString()] = entry.value?.toString();
}
}
final lastOffsetRaw = decoded['lastOffset'];
if (lastOffsetRaw is int) {
_lastTractionOffset = lastOffsetRaw;
} else if (lastOffsetRaw is num) {
_lastTractionOffset = lastOffsetRaw.toInt();
}
final lastSig = decoded['querySignature']?.toString();
if (lastSig != null && lastSig.isNotEmpty) {
_lastQuerySignature = lastSig;
}
for (final entry in dynamicValues.entries) {
_dynamicControllers.putIfAbsent(
@@ -76,6 +86,8 @@ extension _TractionPersistence on _TractionPageState {
'showAdvancedFilters': _showAdvancedFilters,
'dynamic': _dynamicControllers.map((k, v) => MapEntry(k, v.text)),
'enum': _enumSelections,
'lastOffset': _lastTractionOffset,
'querySignature': _lastQuerySignature,
};
try {