Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/core/bus_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class BusRepository {
_stationPassbyInFlight.clear();
_routeRealtimeBusesCache.clear();
_routeRealtimeBusesInFlight.clear();
_routeAlertsCache.clear();
_routeAlertsInFlight.clear();
_routeDetailCache.clear();
_routeDetailInFlight.clear();
_routeStopsApiCache.clear();
Expand Down Expand Up @@ -132,7 +134,7 @@ class BusRepository {
final Map<String, Future<List<CancelledDeparture>>>
_taichungCancelledDepartureInFlight =
<String, Future<List<CancelledDeparture>>>{};
static const _routeAlertsCacheTtl = Duration(hours: 2);
static const _routeAlertsCacheTtl = Duration(minutes: 5);
final Map<String, _TimedValue<List<RouteAlert>>> _routeAlertsCache =
<String, _TimedValue<List<RouteAlert>>>{};
final Map<String, Future<List<RouteAlert>>> _routeAlertsInFlight =
Expand Down Expand Up @@ -3375,10 +3377,13 @@ class BusRepository {
}

final future = _loadRouteAlerts(routeId);
final generation = _routeDataGeneration;
_routeAlertsInFlight[routeId] = future;
try {
final alerts = await future;
_routeAlertsCache[routeId] = _TimedValue<List<RouteAlert>>(alerts);
if (generation == _routeDataGeneration) {
_routeAlertsCache[routeId] = _TimedValue<List<RouteAlert>>(alerts);
}
return alerts;
} finally {
if (identical(_routeAlertsInFlight[routeId], future)) {
Expand Down
68 changes: 59 additions & 9 deletions lib/core/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2504,30 +2504,78 @@ class RouteAlert {
required this.endTime,
required this.publishTime,
required this.updatedTime,
this.source,
this.sourceUrl,
});

factory RouteAlert.fromJson(Map<String, dynamic> json) {
final rawSource = json['source'];
final source = rawSource is Map
? _firstString(rawSource, const ['name', 'title', 'label'])
: _firstString(json, const ['source', 'source_name', 'provider']);
final sourceUrl = rawSource is Map
? _firstString(rawSource, const ['url', 'uri', 'link'])
: _firstString(json, const [
'source_url',
'official_url',
'info_url',
'url',
]) ??
(source != null && Uri.tryParse(source)?.hasScheme == true
? source
: null);
return RouteAlert(
alertId: json['alert_id']?.toString() ?? '',
title: json['title']?.toString() ?? '',
description: json['description']?.toString() ?? '',
status: (json['status'] as num?)?.toInt(),
cause: (json['cause'] as num?)?.toInt(),
effect: (json['effect'] as num?)?.toInt(),
direction: (json['direction'] as num?)?.toInt(),
scope: json['scope']?.toString(),
status: _intValue(json['status']),
cause: _intValue(json['cause']),
effect: _intValue(json['effect']),
direction: _intValue(json['direction']),
scope: _scopeString(json['scope']),
stopIds:
(json['stop_ids'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??
const <String>[],
startTime: (json['start_time'] as num?)?.toInt(),
endTime: (json['end_time'] as num?)?.toInt(),
publishTime: (json['publish_time'] as num?)?.toInt(),
updatedTime: (json['updated_time'] as num?)?.toInt(),
startTime: _intValue(json['start_time']),
endTime: _intValue(json['end_time']),
publishTime: _intValue(json['publish_time']),
updatedTime: _intValue(json['updated_time']),
source: source,
sourceUrl: sourceUrl,
);
}

static String? _firstString(Map<dynamic, dynamic> json, List<String> keys) {
for (final key in keys) {
final value = json[key]?.toString().trim();
if (value != null && value.isNotEmpty) {
return value;
}
}
return null;
}

static int? _intValue(Object? value) {
if (value is num) {
return value.toInt();
}
return int.tryParse(value?.toString().trim() ?? '');
}

static String? _scopeString(Object? value) {
if (value is List) {
final values = value
.map((item) => item.toString().trim())
.where((item) => item.isNotEmpty)
.toList();
return values.isEmpty ? null : values.join('、');
}
final text = value?.toString().trim();
return text == null || text.isEmpty ? null : text;
}

final String alertId;
final String title;
final String description;
Expand All @@ -2541,6 +2589,8 @@ class RouteAlert {
final int? endTime;
final int? publishTime;
final int? updatedTime;
final String? source;
final String? sourceUrl;

String get statusText => switch (status) {
0 => '全部營運停止',
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,12 @@
"routeDetailDirectionHeading": "{direction}:",
"@routeDetailDirectionHeading": {"placeholders": {"direction": {"type": "String"}}},
"routeDetailOperationsNotice": "Service notice",
"routeAlertAffectedRoute": "Affected route",
"routeAlertType": "Type",
"routeAlertTime": "Time",
"routeAlertImpact": "Impact",
"routeAlertSource": "Official source",
"routeAlertOpenSource": "Open official source",
"routeDetailViewRoutePresence": "Viewing route",
"routeDetailBackgroundPromptTitle": "Enable background trip alerts?",
"routeDetailBackgroundPromptMessage": "YABus can keep tracking this route in the background and alert you as you approach your destination.",
Expand Down
18 changes: 18 additions & 0 deletions lib/l10n/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2761,6 +2761,24 @@ abstract class AppLocalizations {
/// **'Service notice'**
String get routeDetailOperationsNotice;

/// No description provided for @routeAlertAffectedRoute.
String get routeAlertAffectedRoute;

/// No description provided for @routeAlertType.
String get routeAlertType;

/// No description provided for @routeAlertTime.
String get routeAlertTime;

/// No description provided for @routeAlertImpact.
String get routeAlertImpact;

/// No description provided for @routeAlertSource.
String get routeAlertSource;

/// No description provided for @routeAlertOpenSource.
String get routeAlertOpenSource;

/// No description provided for @routeDetailViewRoutePresence.
///
/// In en, this message translates to:
Expand Down
18 changes: 18 additions & 0 deletions lib/l10n/app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,24 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get routeDetailOperationsNotice => 'Service notice';

@override
String get routeAlertAffectedRoute => 'Affected route';

@override
String get routeAlertType => 'Type';

@override
String get routeAlertTime => 'Time';

@override
String get routeAlertImpact => 'Impact';

@override
String get routeAlertSource => 'Official source';

@override
String get routeAlertOpenSource => 'Open official source';

@override
String get routeDetailViewRoutePresence => 'Viewing route';

Expand Down
36 changes: 36 additions & 0 deletions lib/l10n/app_localizations_zh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,24 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get routeDetailOperationsNotice => '營運通知';

@override
String get routeAlertAffectedRoute => '受影響路線';

@override
String get routeAlertType => '異常類型';

@override
String get routeAlertTime => '發生時間';

@override
String get routeAlertImpact => '影響範圍';

@override
String get routeAlertSource => '官方公告來源';

@override
String get routeAlertOpenSource => '開啟官方公告';

@override
String get routeDetailViewRoutePresence => '查看路線';

Expand Down Expand Up @@ -4748,6 +4766,24 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override
String get routeDetailOperationsNotice => '營運通知';

@override
String get routeAlertAffectedRoute => '受影響路線';

@override
String get routeAlertType => '異常類型';

@override
String get routeAlertTime => '發生時間';

@override
String get routeAlertImpact => '影響範圍';

@override
String get routeAlertSource => '官方公告來源';

@override
String get routeAlertOpenSource => '開啟官方公告';

@override
String get routeDetailViewRoutePresence => '查看路線';

Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,12 @@
"routeDetailDirectionHeading": "{direction}:",
"@routeDetailDirectionHeading": {"placeholders": {"direction": {"type": "String"}}},
"routeDetailOperationsNotice": "營運通知",
"routeAlertAffectedRoute": "受影響路線",
"routeAlertType": "異常類型",
"routeAlertTime": "發生時間",
"routeAlertImpact": "影響範圍",
"routeAlertSource": "官方公告來源",
"routeAlertOpenSource": "開啟官方公告",
"routeDetailViewRoutePresence": "查看路線",
"routeDetailBackgroundPromptTitle": "啓用背景乘車提醒?",
"routeDetailBackgroundPromptMessage": "YABus 可以在你把 app 丟到背景後繼續追蹤這條路線,並在接近目的地下車前提醒你。",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/app_zh_TW.arb
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,12 @@
"routeDetailDirectionHeading": "{direction}:",
"@routeDetailDirectionHeading": {"placeholders": {"direction": {"type": "String"}}},
"routeDetailOperationsNotice": "營運通知",
"routeAlertAffectedRoute": "受影響路線",
"routeAlertType": "異常類型",
"routeAlertTime": "發生時間",
"routeAlertImpact": "影響範圍",
"routeAlertSource": "官方公告來源",
"routeAlertOpenSource": "開啟官方公告",
"routeDetailViewRoutePresence": "查看路線",
"routeDetailBackgroundPromptTitle": "啓用背景乘車提醒?",
"routeDetailBackgroundPromptMessage": "YABus 可以在你把 app 丟到背景後繼續追蹤這條路線,並在接近目的地下車前提醒你。",
Expand Down
Loading
Loading