feat: add the function to hide records that are only valid for time.

This commit is contained in:
Nedifinita
2025-09-25 22:47:12 +08:00
parent 72f9dfe17b
commit 64401a6ce9
5 changed files with 164 additions and 6 deletions

View File

@@ -60,6 +60,10 @@ class HistoryScreenState extends State<HistoryScreen> {
});
}
Future<void> reloadRecords() async {
await loadRecords(scrollToTop: false);
}
@override
void initState() {
super.initState();
@@ -93,7 +97,71 @@ class HistoryScreenState extends State<HistoryScreen> {
final allRecords = await DatabaseService.instance.getAllRecords();
final settingsMap = await DatabaseService.instance.getAllSettings() ?? {};
_mergeSettings = MergeSettings.fromMap(settingsMap);
final items = MergeService.getMixedList(allRecords, _mergeSettings);
List<TrainRecord> filteredRecords = allRecords;
if ((settingsMap['hideTimeOnlyRecords'] ?? 0) == 1) {
int hiddenCount = 0;
int shownCount = 0;
filteredRecords = allRecords.where((record) {
bool isFieldMeaningful(String field) {
if (field.isEmpty) return false;
String cleaned = field.replaceAll('<NUL>', '').trim();
if (cleaned.isEmpty) return false;
if (cleaned.runes
.every((r) => r == '*'.runes.first || r == ' '.runes.first))
return false;
return true;
}
final hasTrainNumber = isFieldMeaningful(record.fullTrainNumber) &&
!record.fullTrainNumber.contains("-----");
final hasDirection = record.direction == 1 || record.direction == 3;
final hasLocoInfo = isFieldMeaningful(record.locoType) ||
isFieldMeaningful(record.loco);
final hasRoute = isFieldMeaningful(record.route);
final hasPosition = isFieldMeaningful(record.position);
final hasSpeed =
isFieldMeaningful(record.speed) && record.speed != "NUL";
final hasPositionInfo = isFieldMeaningful(record.positionInfo);
final hasTrainType =
isFieldMeaningful(record.trainType) && record.trainType != "未知";
final hasLbjClass =
isFieldMeaningful(record.lbjClass) && record.lbjClass != "NA";
final hasTrain = isFieldMeaningful(record.train) &&
!record.train.contains("-----");
final shouldShow = hasTrainNumber ||
hasDirection ||
hasLocoInfo ||
hasRoute ||
hasPosition ||
hasSpeed ||
hasPositionInfo ||
hasTrainType ||
hasLbjClass ||
hasTrain;
if (!shouldShow) {
hiddenCount++;
} else {
shownCount++;
}
return shouldShow;
}).toList();
}
final items = MergeService.getMixedList(filteredRecords, _mergeSettings);
if (mounted) {
final hasDataChanged = _hasDataChanged(items);
@@ -124,6 +192,58 @@ class HistoryScreenState extends State<HistoryScreen> {
final settingsMap = await DatabaseService.instance.getAllSettings() ?? {};
_mergeSettings = MergeSettings.fromMap(settingsMap);
if ((settingsMap['hideTimeOnlyRecords'] ?? 0) == 1) {
bool isFieldMeaningful(String field) {
if (field.isEmpty) return false;
String cleaned = field.replaceAll('<NUL>', '').trim();
if (cleaned.isEmpty) return false;
if (cleaned.runes
.every((r) => r == '*'.runes.first || r == ' '.runes.first))
return false;
return true;
}
final hasTrainNumber = isFieldMeaningful(newRecord.fullTrainNumber) &&
!newRecord.fullTrainNumber.contains("-----");
final hasDirection =
newRecord.direction == 1 || newRecord.direction == 3;
final hasLocoInfo = isFieldMeaningful(newRecord.locoType) ||
isFieldMeaningful(newRecord.loco);
final hasRoute = isFieldMeaningful(newRecord.route);
final hasPosition = isFieldMeaningful(newRecord.position);
final hasSpeed =
isFieldMeaningful(newRecord.speed) && newRecord.speed != "NUL";
final hasPositionInfo = isFieldMeaningful(newRecord.positionInfo);
final hasTrainType = isFieldMeaningful(newRecord.trainType) &&
newRecord.trainType != "未知";
final hasLbjClass =
isFieldMeaningful(newRecord.lbjClass) && newRecord.lbjClass != "NA";
final hasTrain = isFieldMeaningful(newRecord.train) &&
!newRecord.train.contains("-----");
if (!hasTrainNumber &&
!hasDirection &&
!hasLocoInfo &&
!hasRoute &&
!hasPosition &&
!hasSpeed &&
!hasPositionInfo &&
!hasTrainType &&
!hasLbjClass &&
!hasTrain) {
return;
}
}
final isNewRecord = !_displayItems.any((item) {
if (item is TrainRecord) {
return item.uniqueId == newRecord.uniqueId;
@@ -624,7 +744,8 @@ class HistoryScreenState extends State<HistoryScreen> {
final hasTrainNumber = record.fullTrainNumber.isNotEmpty;
final hasDirection = record.direction == 1 || record.direction == 3;
final hasLocoInfo = formattedLocoInfo.isNotEmpty && formattedLocoInfo != "<NUL>";
final hasLocoInfo =
formattedLocoInfo.isNotEmpty && formattedLocoInfo != "<NUL>";
final shouldShowTrainRow = hasTrainNumber || hasDirection || hasLocoInfo;
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
@@ -661,7 +782,8 @@ class HistoryScreenState extends State<HistoryScreen> {
fontWeight: FontWeight.bold,
color: Colors.white),
overflow: TextOverflow.ellipsis)),
if (hasTrainNumber && hasDirection) const SizedBox(width: 6),
if (hasTrainNumber && hasDirection)
const SizedBox(width: 6),
if (hasDirection)
Container(
width: 20,

View File

@@ -397,7 +397,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
selectedIndex: _currentIndex,
onDestinationSelected: (index) {
if (_currentIndex == 2 && index == 0) {
_historyScreenKey.currentState?.loadRecords();
_historyScreenKey.currentState?.reloadRecords();
}
setState(() {
if (_isHistoryEditMode) _isHistoryEditMode = false;

View File

@@ -32,6 +32,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
bool _notificationsEnabled = true;
int _recordCount = 0;
bool _mergeRecordsEnabled = false;
bool _hideTimeOnlyRecords = false;
GroupBy _groupBy = GroupBy.trainAndLoco;
TimeWindow _timeWindow = TimeWindow.unlimited;
@@ -61,6 +62,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
(settingsMap['backgroundServiceEnabled'] ?? 0) == 1;
_notificationsEnabled = (settingsMap['notificationEnabled'] ?? 1) == 1;
_mergeRecordsEnabled = settings.enabled;
_hideTimeOnlyRecords = (settingsMap['hideTimeOnlyRecords'] ?? 0) == 1;
_groupBy = settings.groupBy;
_timeWindow = settings.timeWindow;
});
@@ -82,6 +84,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
'backgroundServiceEnabled': _backgroundServiceEnabled ? 1 : 0,
'notificationEnabled': _notificationsEnabled ? 1 : 0,
'mergeRecordsEnabled': _mergeRecordsEnabled ? 1 : 0,
'hideTimeOnlyRecords': _hideTimeOnlyRecords ? 1 : 0,
'groupBy': _groupBy.name,
'timeWindow': _timeWindow.name,
});
@@ -236,6 +239,29 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
],
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('隐藏只有时间有效的记录', style: AppTheme.bodyLarge),
Text('不显示只有时间信息的记录', style: AppTheme.caption),
],
),
Switch(
value: _hideTimeOnlyRecords,
onChanged: (value) {
setState(() {
_hideTimeOnlyRecords = value;
});
_saveSettings();
},
activeColor: Theme.of(context).colorScheme.primary,
),
],
),
],
),
),