diff --git a/.crowdin/strings.pot b/.crowdin/strings.pot
index 0c93b9b6f..aafc7d610 100644
--- a/.crowdin/strings.pot
+++ b/.crowdin/strings.pot
@@ -1,338 +1,338 @@
-#: ./lib/core/service.dart:291
+#: ./lib/core/service.dart:285
msgid "正在更新位置"
msgstr ""
-#: ./lib/core/service.dart:292
+#: ./lib/core/service.dart:286
msgid "取得 GPS 位置中..."
msgstr ""
-#: ./lib/app/settings/notify/page.dart:51
+#: ./lib/app/settings/notify/page.dart:56
msgid "接收全部"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:50
+#: ./lib/app/settings/notify/page.dart:65
msgid "關閉"
msgstr ""
-#: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:51
+#: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:70
msgid "接收類別"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:35
+#: ./lib/app/settings/notify/page.dart:55
msgid "所在地震度1以上"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:46
+#: ./lib/app/settings/notify/page.dart:61
msgid "海嘯消息、海嘯警報"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:45
+#: ./lib/app/settings/notify/page.dart:60
msgid "只接收海嘯警報"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:41
+#: ./lib/app/settings/notify/page.dart:66
msgid "接收所在地"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:27
+#: ./lib/app/settings/notify/page.dart:54
msgid "所在地震度4以上"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:28
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:33
msgid "音效測試"
msgstr ""
-#: ./lib/route/announcement/announcement.dart:81
+#: ./lib/route/announcement/announcement.dart:80
msgid "公告"
msgstr ""
-#: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:32
+#: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:37
msgid "發送公告時"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:46
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:51
msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:82
+#: ./lib/app/settings/notify/page.dart:104
msgid "伺服器排隊中,請稍候…"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:166
+#: ./lib/app/welcome/4-permissions/page.dart:111
msgid "通知"
msgstr ""
-#: ./lib/app/settings/page.dart:182
+#: ./lib/app/settings/page.dart:189
msgid "推播通知設定與通知音效測試"
msgstr ""
-#: ./lib/app/home/_widgets/location_not_set_card.dart:33
+#: ./lib/app/home_old/_widgets/location_not_set_card.dart:41
msgid "尚未設定所在地"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:201
+#: ./lib/app/settings/notify/page.dart:208
msgid "請先設定所在地來使用通知功能"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:211
+#: ./lib/app/settings/notify/page.dart:217
msgid "設定所在地"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:209
+#: ./lib/app/settings/experimental/page.dart:215
msgid "地震速報"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:232
+#: ./lib/app/settings/notify/page.dart:238
msgid "緊急地震速報"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:113
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:125
msgid "地震"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1579
+#: ./lib/app/map/_lib/managers/monitor.dart:1584
msgid "強震監視器"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1302
+#: ./lib/app/map/_lib/managers/report.dart:1294
msgid "地震報告"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:290
+#: ./lib/app/settings/notify/page.dart:297
msgid "震度速報"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:304
+#: ./lib/app/settings/notify/page.dart:310
msgid "天氣"
msgstr ""
-#: ./lib/app/home/_widgets/thunderstorm_card.dart:63
+#: ./lib/app/home_old/_widgets/thunderstorm_card.dart:72
msgid "雷雨即時訊息"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:334
+#: ./lib/app/settings/notify/page.dart:339
msgid "天氣警特報"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:354
+#: ./lib/app/settings/notify/page.dart:358
msgid "防災資訊"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:129
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:141
msgid "海嘯"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:378
+#: ./lib/app/settings/notify/page.dart:383
msgid "海嘯資訊"
msgstr ""
-#: ./lib/app/settings/notify/page.dart:390
+#: ./lib/app/settings/notify/page.dart:394
msgid "其他"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:36
msgid "重大"
msgstr ""
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:31
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:36
msgid "海嘯警報發布時"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:37
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42
msgid "一般"
msgstr ""
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:37
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:42
msgid "海嘯消息發布時"
msgstr ""
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:41
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:46
msgid "太平洋海嘯消息(無聲通知)"
msgstr ""
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:42
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:47
msgid "太平洋海嘯消息發布時"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:35
msgid "強震監視器(一般)"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:36
msgid "偵測到晃動"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35
msgid "震度速報(一般)"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36
msgid "所在地(鄉鎮)實測震度 3 以上"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:41
msgid "震度速報(無聲通知)"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:37
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:42
msgid "所在地(鄉鎮)實測震度 1 以上"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:35
msgid "地震報告(一般)"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:36
msgid "所在地(縣市)實測震度 3 以上"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:36
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:41
msgid "地震報告(無聲通知)"
msgstr ""
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:37
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:42
msgid "所在地(縣市)實測震度 1 以上"
msgstr ""
-#: ./lib/app/settings/notify/_lib/utils.dart:15
+#: ./lib/app/settings/notify/_lib/utils.dart:29
msgid "已更新通知設定"
msgstr ""
-#: ./lib/app/settings/notify/_lib/utils.dart:22
+#: ./lib/app/settings/notify/_lib/utils.dart:40
msgid "更新通知設定失敗"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:30
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:35
msgid "緊急地震速報(重大)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:31
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:36
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 4 以上"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:36
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:41
msgid "緊急地震速報(一般)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:37
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:42
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 2 以上"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:41
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:46
msgid "緊急地震速報(無聲)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:42
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:47
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 1 以上"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:46
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:51
msgid "地震速報(重大)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:47
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:52
msgid "所在地(鄉鎮)預估震度 4 以上"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:51
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:56
msgid "地震速報(一般)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:52
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:57
msgid "所在地(鄉鎮)預估震度 2 以上"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:56
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:61
msgid "地震速報(無聲)"
msgstr ""
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:57
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:62
msgid "所在地(鄉鎮)預估震度 1 以上"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:36
msgid "所在地(鄉鎮)發布防災警訊時"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:42
msgid "所在地(鄉鎮)發布防災資訊時"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:37
msgid ""
"所在地(鄉鎮)發布紅色燈號之\n"
"天氣警特報"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:43
msgid ""
"所在地(鄉鎮)發布上述除外燈號之\n"
"天氣警特報"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:37
msgid "所在地(鄉鎮)發布山區暴雨時"
msgstr ""
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:43
msgid "所在地(鄉鎮)發布雷雨即時訊息時"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:197
-msgid "啟動時進入強震監視器"
+#: ./lib/app/settings/experimental/page.dart:48
+msgid "地震速報不限制非 CWA 來源"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:57
-msgid "地震速報不限制非 CWA 來源"
+#: ./lib/app/settings/experimental/page.dart:203
+msgid "啟動時進入強震監視器"
msgstr ""
-#: ./lib/app/settings/page.dart:428
+#: ./lib/app/settings/page.dart:430
msgid "實驗性功能"
msgstr ""
-#: ./lib/app/settings/page.dart:429
+#: ./lib/app/settings/page.dart:431
msgid "搶先體驗開發中的新功能"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:154
+#: ./lib/app/settings/experimental/page.dart:160
msgid "注意"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:162
+#: ./lib/app/settings/experimental/page.dart:168
msgid "這些功能仍在開發中,可能會不穩定或在未來的版本中變更。"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:188
+#: ./lib/app/settings/experimental/page.dart:194
msgid "啟動行為"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:198
+#: ./lib/app/settings/experimental/page.dart:204
msgid "開啟 App 時直接進入強震監視器地圖"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:218
+#: ./lib/app/settings/experimental/page.dart:224
msgid "不限制非 CWA 來源"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:219
+#: ./lib/app/settings/experimental/page.dart:225
msgid "顯示所有來源的地震速報資料"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:280
+#: ./lib/app/settings/experimental/page.dart:281
msgid "啟用實驗性功能"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:286
+#: ./lib/app/settings/experimental/page.dart:287
msgid "你即將啟用:"
msgstr ""
-#: ./lib/app/settings/experimental/page.dart:317
+#: ./lib/app/settings/experimental/page.dart:318
msgid "此功能為實驗性質,可能會造成應用程式不穩定或行為異常。如遇問題,請至設定中關閉此功能。"
msgstr ""
@@ -340,15 +340,15 @@ msgstr ""
msgid "取消"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:272
+#: ./lib/app/settings/layout/page.dart:163
msgid "啟用"
msgstr ""
-#: ./lib/app/settings/page.dart:151
+#: ./lib/app/settings/page.dart:158
msgid "單位"
msgstr ""
-#: ./lib/app/settings/page.dart:152
+#: ./lib/app/settings/page.dart:159
msgid "調整 DPIP 顯示數值時使用的單位"
msgstr ""
@@ -360,131 +360,131 @@ msgstr ""
msgid "切換溫度顯示單位為華氏度 (℉)"
msgstr ""
-#: ./lib/app/settings/page.dart:141
+#: ./lib/app/settings/page.dart:148
msgid "語言"
msgstr ""
-#: ./lib/app/settings/page.dart:142
+#: ./lib/app/settings/page.dart:149
msgid "調整 DPIP 的顯示語言"
msgstr ""
-#: ./lib/app/settings/locale/page.dart:41
+#: ./lib/app/settings/locale/page.dart:49
msgid "顯示語言"
msgstr ""
-#: ./lib/app/settings/locale/page.dart:42
+#: ./lib/app/settings/locale/page.dart:50
msgid "系統語言"
msgstr ""
-#: ./lib/app/settings/locale/page.dart:52
+#: ./lib/app/settings/locale/page.dart:60
msgid "協助翻譯"
msgstr ""
-#: ./lib/app/settings/locale/page.dart:53
+#: ./lib/app/settings/locale/page.dart:61
msgid "點擊這裡來幫助我們改進 DPIP 的翻譯"
msgstr ""
-#: ./lib/app/settings/locale/select/page.dart:116
+#: ./lib/app/settings/locale/select/page.dart:122
msgid "已翻譯 {translated}・已校對 {approved}"
msgstr ""
-#: ./lib/app/settings/locale/select/page.dart:129
+#: ./lib/app/settings/locale/select/page.dart:135
msgid "來源語言"
msgstr ""
-#: ./lib/app/settings/locale/select/page.dart:163
+#: ./lib/app/settings/locale/select/page.dart:172
msgid "選擇語言"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:52
+#: ./lib/app/settings/donate/page.dart:59
msgid "無法連線至商店,請稍後再試"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:59
+#: ./lib/app/settings/donate/page.dart:65
msgid "找不到商品,請稍候再試"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:521
-msgid "重新載入"
-msgstr ""
-
-#: ./lib/app/settings/donate/page.dart:171
-msgid "正在載入商店物品中"
-msgstr ""
-
-#: ./lib/app/settings/donate/page.dart:225
+#: ./lib/app/settings/donate/page.dart:136
msgid "支持 DPIP"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:233
+#: ./lib/app/settings/donate/page.dart:144
msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。您的支持將幫助我們維持伺服器運行與持續開發。"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:260
+#: ./lib/app/settings/donate/page.dart:170
msgid "訂閱制"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:276
+#: ./lib/app/settings/donate/page.dart:189
msgid "推薦"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:443
+#: ./lib/app/settings/donate/page.dart:353
msgid "{price}/月"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:475
+#: ./lib/app/settings/donate/page.dart:385
msgid "單次支援"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:615
+#: ./lib/app/settings/donate/page.dart:520
msgid "恢復購買"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:628
+#: ./lib/app/settings/donate/page.dart:530
msgid "無法連線至 {store},請稍後再試。"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:639
+#: ./lib/app/settings/donate/page.dart:541
msgid "正在恢復您購買的訂閱"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:644
+#: ./lib/app/settings/donate/page.dart:546
msgid "使用條款"
msgstr ""
-#: ./lib/app/settings/donate/page.dart:648
+#: ./lib/app/settings/donate/page.dart:550
msgid "隱私權政策"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:51
+#: ./lib/app/map/_lib/managers/report.dart:546
+msgid "重新載入"
+msgstr ""
+
+#: ./lib/app/settings/donate/page.dart:636
+msgid "正在載入商店物品中"
+msgstr ""
+
+#: ./lib/app/settings/proxy/page.dart:38
msgid "設定已儲存"
msgstr ""
-#: ./lib/app/settings/page.dart:200
+#: ./lib/app/settings/page.dart:207
msgid "HTTP 代理"
msgstr ""
-#: ./lib/app/settings/page.dart:201
+#: ./lib/app/settings/page.dart:208
msgid "調整 HTTP 代理伺服器設定"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:75
+#: ./lib/app/settings/proxy/page.dart:74
msgid "啟用代理"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:76
+#: ./lib/app/settings/proxy/page.dart:75
msgid "透過代理伺服器發送所有網路請求"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:88
+#: ./lib/app/settings/proxy/page.dart:87
msgid "代理主機"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:102
+#: ./lib/app/settings/proxy/page.dart:101
msgid "代理端口"
msgstr ""
-#: ./lib/app/settings/proxy/page.dart:117
+#: ./lib/app/settings/proxy/page.dart:116
msgid "設定儲存後,需要重新啟動應用程式才能生效"
msgstr ""
@@ -492,123 +492,123 @@ msgstr ""
msgid "設定"
msgstr ""
-#: ./lib/app/settings/page.dart:71
+#: ./lib/app/settings/page.dart:79
msgid "自訂你的 DPIP 使用體驗"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:174
+#: ./lib/app/welcome/4-permissions/page.dart:119
msgid "位置"
msgstr ""
-#: ./lib/app/settings/location/page.dart:417
+#: ./lib/app/settings/location/page.dart:421
msgid "所在地"
msgstr ""
-#: ./lib/app/settings/location/page.dart:241
+#: ./lib/app/settings/location/page.dart:245
msgid "設定你的所在地來接收當地的即時資訊"
msgstr ""
-#: ./lib/app/settings/page.dart:113
+#: ./lib/app/settings/page.dart:120
msgid "介面"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:47
+#: ./lib/app/settings/layout/page.dart:183
msgid "版面"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:48
+#: ./lib/app/settings/layout/page.dart:184
msgid "調整首頁的版面樣式"
msgstr ""
-#: ./lib/app/settings/theme/page.dart:25
+#: ./lib/app/settings/theme/page.dart:32
msgid "主題"
msgstr ""
-#: ./lib/app/settings/theme/page.dart:26
+#: ./lib/app/settings/theme/page.dart:33
msgid "調整 DPIP 整體的外觀與顏色"
msgstr ""
-#: ./lib/app/settings/map/page.dart:49
+#: ./lib/app/home/layout.dart:93
msgid "地圖"
msgstr ""
-#: ./lib/app/settings/map/page.dart:50
+#: ./lib/app/settings/map/page.dart:59
msgid "調整地圖的顯示樣式"
msgstr ""
-#: ./lib/app/settings/page.dart:191
+#: ./lib/app/settings/page.dart:198
msgid "網路"
msgstr ""
-#: ./lib/app/settings/page.dart:210
+#: ./lib/app/settings/page.dart:217
msgid "資訊"
msgstr ""
-#: ./lib/app/changelog/page.dart:54
+#: ./lib/app/home_old/page.dart:163
msgid "更新日誌"
msgstr ""
-#: ./lib/app/settings/page.dart:230
+#: ./lib/app/settings/page.dart:237
msgid "瀏覽 DPIP 的歷次更新紀錄"
msgstr ""
-#: ./lib/app/settings/page.dart:240
+#: ./lib/app/settings/page.dart:247
msgid "第三方套件授權"
msgstr ""
-#: ./lib/app/settings/page.dart:241
+#: ./lib/app/settings/page.dart:248
msgid "DPIP 的實現歸功於開放原始碼"
msgstr ""
-#: ./lib/app/settings/page.dart:264
+#: ./lib/app/settings/page.dart:271
msgid "贊助我們"
msgstr ""
-#: ./lib/app/settings/page.dart:267
+#: ./lib/app/settings/page.dart:274
msgid "幫助我們維護伺服器的穩定和長久發展"
msgstr ""
-#: ./lib/app/settings/page.dart:343
+#: ./lib/app/settings/page.dart:349
msgid "下載"
msgstr ""
-#: ./lib/app/settings/page.dart:383
+#: ./lib/app/settings/page.dart:385
msgid "除錯"
msgstr ""
-#: ./lib/app/settings/page.dart:391
+#: ./lib/app/settings/page.dart:393
msgid "應用程式版本"
msgstr ""
-#: ./lib/app/settings/page.dart:400
+#: ./lib/app/settings/page.dart:402
msgid "裝置資訊"
msgstr ""
-#: ./lib/app/settings/page.dart:409
+#: ./lib/app/settings/page.dart:411
msgid "複製通知 Token"
msgstr ""
-#: ./lib/app/debug/logs/page.dart:16
+#: ./lib/app/debug/logs/page.dart:22
msgid "App 日誌"
msgstr ""
-#: ./lib/app/settings/page.dart:463
+#: ./lib/app/settings/page.dart:465
msgid "任何資訊應以中央氣象署發布之內容為準"
msgstr ""
-#: ./lib/app/settings/location/page.dart:74
+#: ./lib/app/settings/location/page.dart:85
msgid "無法取得通知權限"
msgstr ""
-#: ./lib/app/settings/location/page.dart:76
+#: ./lib/app/settings/location/page.dart:87
msgid "無法取得位置權限"
msgstr ""
-#: ./lib/app/settings/location/page.dart:77
+#: ./lib/app/settings/location/page.dart:88
msgid "無法取得自啟動權限"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:180
+#: ./lib/app/welcome/4-permissions/page.dart:125
msgid "省電策略"
msgstr ""
@@ -616,782 +616,810 @@ msgstr ""
msgid "無法取得權限"
msgstr ""
-#: ./lib/app/settings/location/page.dart:84
+#: ./lib/app/settings/location/page.dart:94
msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:86
+#: ./lib/app/settings/location/page.dart:95
msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:89
+#: ./lib/app/settings/location/page.dart:98
msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:91
+#: ./lib/app/settings/location/page.dart:99
msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:93
+#: ./lib/app/settings/location/page.dart:100
msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:95
+#: ./lib/app/settings/location/page.dart:101
msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:96
+#: ./lib/app/settings/location/page.dart:102
msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:174
+#: ./lib/app/settings/location/page.dart:180
msgid "自動啟動"
msgstr ""
-#: ./lib/app/settings/location/page.dart:175
+#: ./lib/app/settings/location/page.dart:181
msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:199
+#: ./lib/app/settings/location/page.dart:203
msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:233
+#: ./lib/app/settings/location/page.dart:237
msgid "一律允許"
msgstr ""
-#: ./lib/app/settings/location/page.dart:233
+#: ./lib/app/settings/location/page.dart:237
msgid "永遠"
msgstr ""
-#: ./lib/app/settings/location/page.dart:253
+#: ./lib/app/settings/location/page.dart:257
msgid "自動更新"
msgstr ""
-#: ./lib/app/settings/location/page.dart:254
+#: ./lib/app/settings/location/page.dart:258
msgid "定期更新目前的所在地"
msgstr ""
-#: ./lib/app/settings/location/page.dart:263
+#: ./lib/app/settings/location/page.dart:267
msgid ""
"自動定位功能將使用您的裝置上的 GPS,即使 DPIP "
"關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:334
+#: ./lib/app/settings/location/page.dart:338
msgid "通知功能已被拒絕,請移至設定允許權限。"
msgstr ""
-#: ./lib/app/settings/location/page.dart:395
+#: ./lib/app/settings/location/page.dart:399
msgid "省電策略已被拒絕,請移至設定允許權限。"
msgstr ""
-#: ./lib/app/settings/location/select/[city]/page.dart:98
+#: ./lib/app/settings/location/select/[city]/page.dart:109
msgid "設定所在地時發生錯誤,請稍候再試一次。"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:233
+#: ./lib/app/home_old/_widgets/location_button.dart:204
msgid "新增地點"
msgstr ""
-#: ./lib/app/settings/location/select/page.dart:33
+#: ./lib/app/home/_widgets/location_chip.dart:148
msgid "縣市"
msgstr ""
-#: ./lib/app/settings/location/select/page.dart:44
+#: ./lib/app/settings/location/select/page.dart:49
msgid "目前所在地"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:56
+#: ./lib/app/settings/layout/page.dart:90
+msgid "停用"
+msgstr ""
+
+#: ./lib/app/settings/layout/page.dart:192
msgid "拖曳調整順序"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:100
+#: ./lib/app/settings/layout/page.dart:236
msgid "已停用"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:135
+#: ./lib/app/settings/layout/page.dart:271
msgid "所有區塊皆已啟用"
msgstr ""
-#: ./lib/app/settings/layout/page.dart:202
-msgid "停用"
-msgstr ""
-
-#: ./lib/app/settings/map/page.dart:61
+#: ./lib/app/settings/map/page.dart:70
msgid "初始圖層"
msgstr ""
-#: ./lib/app/settings/map/page.dart:62
+#: ./lib/app/settings/map/page.dart:71
msgid "調整地圖的底圖以及初始顯示的圖層"
msgstr ""
-#: ./lib/app/settings/map/page.dart:74
+#: ./lib/app/settings/map/page.dart:83
msgid "自動縮放"
msgstr ""
-#: ./lib/app/settings/map/page.dart:75
+#: ./lib/app/settings/map/page.dart:84
msgid "接收到檢知時自動縮放地圖"
msgstr ""
-#: ./lib/app/settings/map/page.dart:101
+#: ./lib/app/settings/map/page.dart:110
msgid "動畫幀率"
msgstr ""
-#: ./lib/app/settings/map/page.dart:102
+#: ./lib/app/settings/map/page.dart:111
msgid "調整強震監視器震波模擬動畫的流暢度"
msgstr ""
-#: ./lib/app/settings/map/page.dart:136
+#: ./lib/app/settings/map/page.dart:144
msgid "過高的動畫幀率可能會造成卡頓或裝置發熱"
msgstr ""
-#: ./lib/app/settings/theme/page.dart:46
+#: ./lib/app/settings/theme/page.dart:53
msgid "主題模式"
msgstr ""
-#: ./lib/app/settings/theme/mode/page.dart:63
+#: ./lib/app/settings/theme/mode/page.dart:69
msgid "淺色"
msgstr ""
-#: ./lib/app/settings/theme/mode/page.dart:64
+#: ./lib/app/settings/theme/mode/page.dart:70
msgid "深色"
msgstr ""
-#: ./lib/app/settings/theme/mode/page.dart:59
+#: ./lib/app/settings/theme/mode/page.dart:67
msgid "跟隨系統主題"
msgstr ""
-#: ./lib/app/settings/theme/color/page.dart:22
+#: ./lib/app/settings/theme/color/page.dart:30
msgid "主題色彩"
msgstr ""
-#: ./lib/app/settings/theme/color/page.dart:43
+#: ./lib/app/settings/theme/color/page.dart:51
msgid "使用系統配色"
msgstr ""
-#: ./lib/app/settings/theme/color/page.dart:62
+#: ./lib/app/settings/theme/color/page.dart:70
msgid "自訂"
msgstr ""
-#: ./lib/app/settings/theme/color/page.dart:72
+#: ./lib/app/settings/theme/color/page.dart:79
msgid "自訂色彩"
msgstr ""
-#: ./lib/app/home/_widgets/thunderstorm_card.dart:84
-msgid "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。"
+#: ./lib/app/map/_lib/managers/radar.dart:614
+msgid "雷達回波"
msgstr ""
-#: ./lib/app/home/_widgets/forecast_card.dart:59
-msgid "天氣預報(24h)"
+#: ./lib/app/home/_widgets/weather_parameters.dart:52
+msgid "相對溼度"
msgstr ""
-#: ./lib/app/home/_widgets/location_out_of_service.dart:28
-msgid "服務區域外,僅在臺灣各地可用"
+#: ./lib/app/home/_widgets/weather_parameters.dart:57
+msgid "空氣品質"
msgstr ""
-#: ./lib/app/map/_lib/managers/radar.dart:587
-msgid "雷達回波"
+#: ./lib/app/map/_lib/managers/wind.dart:343
+msgid "風向/風速"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:497
-msgid "無資料"
+#: ./lib/app/home/_widgets/weather_parameters.dart:68
+msgid "降水量"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:372
-msgid "{wind}級 {Desc}"
+#: ./lib/app/home/_widgets/location_chip.dart:84
+msgid "清除暫時位置"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:389
-msgid "陣風 {speed} m/s"
+#: ./lib/app/home/_widgets/location_chip.dart:159
+msgid "目前選擇地區"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:471
-msgid "無法測量"
+#: ./lib/app/home_old/_widgets/location_button.dart:170
+msgid "快速切換"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:492
-msgid "指北針不可靠"
+#: ./lib/app/home/layout.dart:88
+msgid "首頁"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:494
-msgid "指北針準確度下降"
+#: ./lib/app/home/layout.dart:98
+msgid "小工具"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:495
-msgid "指北針正常"
+#: ./lib/app/changelog/page.dart:86
+msgid "發生錯誤"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:502
-msgid "方向精確度"
+#: ./lib/route/image_viewer/image_viewer.dart:85
+msgid "再試一次"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:521
-msgid "正常範圍:±0-15°"
+#: ./lib/app/changelog/page.dart:217
+msgid "目前版本"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:538
-msgid "附近有強磁場干擾,指北針方向可能完全不準確。請遠離磁鐵、電子裝置或金屬物品。"
+#: ./lib/app/welcome/4-permissions/page.dart:383
+msgid "下一步"
msgstr ""
-#: ./lib/app/home/_widgets/wind_card.dart:539
-msgid "附近可能有磁場干擾,指北針方向可能有偏差。"
+#: ./lib/app/welcome/1-about/page.dart:73
+msgid "防災資訊平台"
msgstr ""
-#: ./lib/route/image_viewer/image_viewer.dart:145
-msgid "確定"
+#: ./lib/app/welcome/2-exptech/page.dart:98
+msgid "我們是誰?"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:29
-msgid "尚未設定"
+#: ./lib/app/welcome/2-exptech/page.dart:105
+msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:138
-msgid "切換區域"
+#: ./lib/app/welcome/2-exptech/page.dart:111
+msgid "我們的初衷"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:144
-msgid "位置設定"
+#: ./lib/app/welcome/2-exptech/page.dart:118
+msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:195
-msgid "快速切換"
+#: ./lib/app/welcome/3-notice/page.dart:50
+msgid "注意事項"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:240
-msgid "選擇縣市"
+#: ./lib/app/welcome/3-notice/page.dart:70
+msgid "任何資訊應以中央氣象署發布之內容為準。"
msgstr ""
-#: ./lib/app/home/_widgets/location_button.dart:250
-msgid "目前選擇"
+#: ./lib/app/welcome/3-notice/page.dart:87
+msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
msgstr ""
-#: ./lib/app/home/page.dart:888
-msgid "濕度"
+#: ./lib/app/welcome/3-notice/page.dart:101
+msgid "強烈搖晃有機率比通知早抵達使用者所在地。"
msgstr ""
-#: ./lib/app/home/page.dart:916
-msgid "風速"
+#: ./lib/app/welcome/3-notice/page.dart:115
+msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
msgstr ""
-#: ./lib/app/home/_widgets/weather_header.dart:181
-msgid "風向"
+#: ./lib/app/welcome/3-notice/page.dart:129
+msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
msgstr ""
-#: ./lib/app/home/_widgets/weather_header.dart:190
-msgid "風級"
+#: ./lib/app/welcome/1-about/page.dart:51
+msgid "歡迎使用 DPIP"
msgstr ""
-#: ./lib/app/home/page.dart:895
-msgid "氣壓"
+#: ./lib/app/welcome/1-about/page.dart:96
+msgid ""
+"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
+"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
msgstr ""
-#: ./lib/app/home/page.dart:902
-msgid "降雨"
+#: ./lib/app/welcome/4-permissions/page.dart:112
+msgid "在重大災害發生時以通知來傳遞即時防災資訊"
msgstr ""
-#: ./lib/app/home/page.dart:909
-msgid "能見度"
+#: ./lib/app/welcome/4-permissions/page.dart:120
+msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
msgstr ""
-#: ./lib/app/home/page.dart:923
-msgid "陣風"
+#: ./lib/app/welcome/4-permissions/page.dart:126
+msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
msgstr ""
-#: ./lib/app/home/_widgets/weather_header.dart:233
-msgid "陣風級"
+#: ./lib/route/image_viewer/image_viewer.dart:254
+msgid "儲存"
msgstr ""
-#: ./lib/app/home/_widgets/weather_header.dart:241
-msgid "日照"
+#: ./lib/app/welcome/4-permissions/page.dart:133
+msgid "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
msgstr ""
-#: ./lib/app/home/_widgets/hero_weather.dart:142
-msgid "體感 {feelsLike}°"
+#: ./lib/app/welcome/4-permissions/page.dart:293
+msgid "權限請求"
msgstr ""
-#: ./lib/app/home/_widgets/hero_weather.dart:185
-msgid "無天氣資料"
+#: ./lib/app/welcome/4-permissions/page.dart:294
+msgid "需要使用者手動到設定開啟相關權限。"
msgstr ""
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:14
-msgid "全國 · 生效中"
+#: ./lib/route/image_viewer/image_viewer.dart:145
+msgid "確定"
msgstr ""
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:16
-msgid "全國 · 歷史"
+#: ./lib/app/welcome/4-permissions/page.dart:317
+msgid "需要背景位置權限"
msgstr ""
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:18
-msgid "所在地 · 生效中"
+#: ./lib/app/welcome/4-permissions/page.dart:319
+msgid ""
+"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
+"\n"
+"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
msgstr ""
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:20
-msgid "所在地 · 歷史"
+#: ./lib/app/welcome/4-permissions/page.dart:325
+msgid "稍後"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1258
-msgid "EEW"
+#: ./lib/app/welcome/4-permissions/page.dart:329
+msgid "前往設定"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1397
-msgid "第 {serial} 報"
+#: ./lib/app/welcome/4-permissions/page.dart:406
+msgid "權限"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1415
-msgid ""
-"{time} 左右,{location}附近發生有感地震,預估規模 "
-"M{magnitude}、所在地最大震度{intensity}。"
+#: ./lib/app/welcome/4-permissions/page.dart:419
+msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1423
-msgid ""
-"{time} 左右,{location}附近發生有感地震,預估規模 "
-"M{magnitude}、深度{depth}公里。"
+#: ./lib/app/home_old/_widgets/thunderstorm_card.dart:93
+msgid "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1469
-msgid "所在地預估"
+#: ./lib/app/home_old/_widgets/forecast_card.dart:68
+msgid "天氣預報(24h)"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1505
-msgid "震波"
+#: ./lib/app/home_old/_widgets/location_out_of_service.dart:34
+msgid "服務區域外,僅在臺灣各地可用"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1527
-msgid " 秒"
+#: ./lib/app/map/_lib/managers/monitor.dart:518
+msgid "無資料"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1544
-msgid "抵達"
+#: ./lib/app/home_old/_widgets/wind_card.dart:329
+msgid "{wind}級 {Desc}"
msgstr ""
-#: ./lib/app/home/page.dart:195
-msgid "已更新至 {version}"
+#: ./lib/app/home_old/_widgets/wind_card.dart:346
+msgid "陣風 {speed} m/s"
msgstr ""
-#: ./lib/utils/weather_icon.dart:284
-msgid "取得天氣異常"
+#: ./lib/app/home_old/_widgets/wind_card.dart:408
+msgid "無法測量"
msgstr ""
-#: ./lib/app/home/page.dart:366
-msgid "取得歷史資訊異常"
+#: ./lib/app/home_old/_widgets/wind_card.dart:429
+msgid "指北針不可靠"
msgstr ""
-#: ./lib/app/home/page.dart:777
-msgid "上午"
+#: ./lib/app/home_old/_widgets/wind_card.dart:431
+msgid "指北針準確度下降"
msgstr ""
-#: ./lib/app/home/page.dart:777
-msgid "下午"
+#: ./lib/app/home_old/_widgets/wind_card.dart:432
+msgid "指北針正常"
msgstr ""
-#: ./lib/app/changelog/page.dart:76
-msgid "發生錯誤"
+#: ./lib/app/home_old/_widgets/wind_card.dart:439
+msgid "方向精確度"
msgstr ""
-#: ./lib/route/image_viewer/image_viewer.dart:85
-msgid "再試一次"
+#: ./lib/app/home_old/_widgets/wind_card.dart:458
+msgid "正常範圍:±0-15°"
msgstr ""
-#: ./lib/app/changelog/page.dart:203
-msgid "目前版本"
+#: ./lib/app/home_old/_widgets/wind_card.dart:475
+msgid "附近有強磁場干擾,指北針方向可能完全不準確。請遠離磁鐵、電子裝置或金屬物品。"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:403
-msgid "下一步"
+#: ./lib/app/home_old/_widgets/wind_card.dart:476
+msgid "附近可能有磁場干擾,指北針方向可能有偏差。"
msgstr ""
-#: ./lib/app/welcome/1-about/page.dart:68
-msgid "防災資訊平台"
+#: ./lib/app/home_old/_widgets/location_button.dart:38
+msgid "尚未設定"
msgstr ""
-#: ./lib/app/welcome/2-exptech/page.dart:93
-msgid "我們是誰?"
+#: ./lib/app/home_old/_widgets/location_button.dart:211
+msgid "選擇縣市"
msgstr ""
-#: ./lib/app/welcome/2-exptech/page.dart:100
-msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
+#: ./lib/app/home_old/_widgets/location_button.dart:221
+msgid "目前選擇"
msgstr ""
-#: ./lib/app/welcome/2-exptech/page.dart:106
-msgid "我們的初衷"
+#: ./lib/app/home_old/_widgets/location_button.dart:279
+msgid "切換區域"
msgstr ""
-#: ./lib/app/welcome/2-exptech/page.dart:113
-msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
+#: ./lib/app/home_old/_widgets/location_button.dart:285
+msgid "位置設定"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:45
-msgid "注意事項"
+#: ./lib/app/home_old/page.dart:630
+msgid "濕度"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:65
-msgid "任何資訊應以中央氣象署發布之內容為準。"
+#: ./lib/app/home_old/page.dart:658
+msgid "風速"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:82
-msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
+#: ./lib/app/home_old/_widgets/weather_header.dart:199
+msgid "風向"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:97
-msgid "強烈搖晃有機率比通知早抵達使用者所在地。"
+#: ./lib/app/home_old/_widgets/weather_header.dart:206
+msgid "風級"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:111
-msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
+#: ./lib/app/home_old/page.dart:637
+msgid "氣壓"
msgstr ""
-#: ./lib/app/welcome/3-notice/page.dart:125
-msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
+#: ./lib/app/home_old/page.dart:644
+msgid "降雨"
msgstr ""
-#: ./lib/app/welcome/1-about/page.dart:46
-msgid "歡迎使用 DPIP"
+#: ./lib/app/home_old/page.dart:651
+msgid "能見度"
msgstr ""
-#: ./lib/app/welcome/1-about/page.dart:91
-msgid ""
-"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
-"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
+#: ./lib/app/home_old/page.dart:665
+msgid "陣風"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:167
-msgid "在重大災害發生時以通知來傳遞即時防災資訊"
+#: ./lib/app/home_old/_widgets/weather_header.dart:243
+msgid "陣風級"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:175
-msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
+#: ./lib/app/home_old/_widgets/weather_header.dart:251
+msgid "日照"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:181
-msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
+#: ./lib/app/home_old/_widgets/hero_weather.dart:151
+msgid "體感 {feelsLike}°"
msgstr ""
-#: ./lib/route/image_viewer/image_viewer.dart:255
-msgid "儲存"
+#: ./lib/app/home_old/_widgets/hero_weather.dart:194
+msgid "無天氣資料"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:188
-msgid "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:32
+msgid "全國 · 生效中"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:352
-msgid "權限請求"
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:34
+msgid "全國 · 歷史"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:353
-msgid "需要使用者手動到設定開啟相關權限。"
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:36
+msgid "所在地 · 生效中"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:376
-msgid "需要背景位置權限"
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:38
+msgid "所在地 · 歷史"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:378
+#: ./lib/app/map/_lib/managers/monitor.dart:1274
+msgid "EEW"
+msgstr ""
+
+#: ./lib/app/map/_lib/managers/monitor.dart:1407
+msgid "第 {serial} 報"
+msgstr ""
+
+#: ./lib/app/map/_lib/managers/monitor.dart:1425
msgid ""
-"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
-"\n"
-"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
+"{time} 左右,{location}附近發生有感地震,預估規模 "
+"M{magnitude}、所在地最大震度{intensity}。"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:384
-msgid "稍後"
+#: ./lib/app/map/_lib/managers/monitor.dart:1433
+msgid ""
+"{time} 左右,{location}附近發生有感地震,預估規模 "
+"M{magnitude}、深度{depth}公里。"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:388
-msgid "前往設定"
+#: ./lib/app/map/_lib/managers/monitor.dart:1479
+msgid "所在地預估"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:426
-msgid "權限"
+#: ./lib/app/map/_lib/managers/monitor.dart:1515
+msgid "震波"
msgstr ""
-#: ./lib/app/welcome/4-permissions/page.dart:439
-msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
+#: ./lib/app/map/_lib/managers/monitor.dart:1535
+msgid " 秒"
+msgstr ""
+
+#: ./lib/app/map/_lib/managers/monitor.dart:1551
+msgid "抵達"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:84
+#: ./lib/app/home_old/page.dart:158
+msgid "已更新至 {version}"
+msgstr ""
+
+#: ./lib/utils/weather_icon.dart:282
+msgid "取得天氣異常"
+msgstr ""
+
+#: ./lib/app/home_old/page.dart:331
+msgid "取得歷史資訊異常"
+msgstr ""
+
+#: ./lib/app/home_old/page.dart:571
+msgid "上午"
+msgstr ""
+
+#: ./lib/app/home_old/page.dart:571
+msgid "下午"
+msgstr ""
+
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:96
msgid "地圖圖層"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:85
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:97
msgid "選擇要顯示的地圖圖層"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:91
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:103
msgid "底圖"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:97
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:109
msgid "簡單"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:119
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131
msgid "監視器"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:124
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:136
msgid "報告"
msgstr ""
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:135
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:147
msgid "氣象"
msgstr ""
-#: ./lib/app/map/_lib/managers/temperature.dart:453
+#: ./lib/app/map/_lib/managers/temperature.dart:480
msgid "氣溫"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:577
+#: ./lib/app/map/_lib/managers/precipitation.dart:587
msgid "降水"
msgstr ""
-#: ./lib/app/map/_lib/managers/wind.dart:320
-msgid "風向/風速"
-msgstr ""
-
-#: ./lib/app/map/_lib/managers/lightning.dart:294
+#: ./lib/app/map/_lib/managers/lightning.dart:302
msgid "閃電"
msgstr ""
-#: ./lib/app/map/_widgets/map_legend.dart:202
+#: ./lib/app/map/_widgets/map_legend.dart:250
msgid "單位:{unit}"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:485
+#: ./lib/app/map/_lib/managers/tsunami.dart:494
msgid "近期無海嘯資訊"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:486
+#: ./lib/app/map/_lib/managers/tsunami.dart:494
msgid "海嘯警報"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:496
+#: ./lib/app/map/_lib/managers/tsunami.dart:504
msgid "{id}號 第{serial}報"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:551
+#: ./lib/app/map/_lib/managers/tsunami.dart:558
msgid "發布"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:553
+#: ./lib/app/map/_lib/managers/tsunami.dart:560
msgid "更新"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:554
+#: ./lib/app/map/_lib/managers/tsunami.dart:561
msgid "解除"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:607
+#: ./lib/app/map/_lib/managers/tsunami.dart:612
msgid "預估海嘯到達時間及波高"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:626
+#: ./lib/app/map/_lib/managers/tsunami.dart:630
msgid "各地觀測到的海嘯"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:641
+#: ./lib/app/map/_lib/managers/tsunami.dart:645
msgid "地震資訊"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:654
+#: ./lib/app/map/_lib/managers/tsunami.dart:657
msgid "發生時間"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1072
+#: ./lib/app/map/_lib/managers/report.dart:1069
msgid "位於"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:736
+#: ./lib/app/map/_lib/managers/tsunami.dart:730
msgid "規模"
msgstr ""
-#: ./lib/app/map/_lib/managers/tsunami.dart:765
+#: ./lib/app/map/_lib/managers/tsunami.dart:753
msgid "深度"
msgstr ""
-#: ./lib/app/map/_lib/managers/radar.dart:744
+#: ./lib/app/map/_lib/managers/radar.dart:750
msgid "長按設定播放起點"
msgstr ""
-#: ./lib/app/map/_lib/managers/radar.dart:760
+#: ./lib/app/map/_lib/managers/radar.dart:766
msgid "目前時間"
msgstr ""
-#: ./lib/app/map/_lib/managers/radar.dart:765
+#: ./lib/app/map/_lib/managers/radar.dart:771
msgid "播放起點"
msgstr ""
-#: ./lib/app/map/_lib/managers/radar.dart:1099
+#: ./lib/app/map/_lib/managers/radar.dart:1100
msgid "播放進度"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:393
+#: ./lib/app/map/_lib/managers/lightning.dart:399
msgid "5 分鐘內對地閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:401
+#: ./lib/app/map/_lib/managers/lightning.dart:407
msgid "10 分鐘內對地閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:409
+#: ./lib/app/map/_lib/managers/lightning.dart:415
msgid "30 分鐘內對地閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:417
+#: ./lib/app/map/_lib/managers/lightning.dart:423
msgid "60 分鐘內對地閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:425
+#: ./lib/app/map/_lib/managers/lightning.dart:431
msgid "5 分鐘內雲間閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:433
+#: ./lib/app/map/_lib/managers/lightning.dart:439
msgid "10 分鐘內雲間閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:441
+#: ./lib/app/map/_lib/managers/lightning.dart:447
msgid "30 分鐘內雲間閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/lightning.dart:449
+#: ./lib/app/map/_lib/managers/lightning.dart:455
msgid "60 分鐘內雲間閃電"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:396
+#: ./lib/app/map/_lib/managers/precipitation.dart:420
msgid "今日"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:397
+#: ./lib/app/map/_lib/managers/precipitation.dart:421
msgid "10 分鐘"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:398
+#: ./lib/app/map/_lib/managers/precipitation.dart:422
msgid "1 小時"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:399
+#: ./lib/app/map/_lib/managers/precipitation.dart:423
msgid "3 小時"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:400
+#: ./lib/app/map/_lib/managers/precipitation.dart:424
msgid "6 小時"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:401
+#: ./lib/app/map/_lib/managers/precipitation.dart:425
msgid "12 小時"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:402
+#: ./lib/app/map/_lib/managers/precipitation.dart:426
msgid "24 小時"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:403
+#: ./lib/app/map/_lib/managers/precipitation.dart:427
msgid "2 天"
msgstr ""
-#: ./lib/app/map/_lib/managers/precipitation.dart:404
+#: ./lib/app/map/_lib/managers/precipitation.dart:428
msgid "3 天"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:474
+#: ./lib/app/map/_lib/managers/monitor.dart:495
msgid "海外測站"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:494
+#: ./lib/app/map/_lib/managers/monitor.dart:515
msgid "即時震度:"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:517
+#: ./lib/app/map/_lib/managers/monitor.dart:538
msgid "地動加速度:"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:541
+#: ./lib/app/map/_lib/managers/monitor.dart:562
msgid "地動速度:"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1331
+#: ./lib/app/map/_lib/managers/monitor.dart:1346
msgid "規模 M{magnitude},所在地預估{intensity}"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1349
+#: ./lib/app/map/_lib/managers/monitor.dart:1362
msgid "{countdown}秒後抵達"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1352
+#: ./lib/app/map/_lib/managers/monitor.dart:1365
msgid "已抵達"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1364
+#: ./lib/app/map/_lib/managers/monitor.dart:1376
msgid "規模 M{magnitude},深度{depth}公里"
msgstr ""
-#: ./lib/app/map/_lib/managers/monitor.dart:1591
+#: ./lib/app/map/_lib/managers/monitor.dart:1594
msgid "目前沒有生效中的地震速報"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:516
+#: ./lib/app/map/_lib/managers/report.dart:541
msgid "CWA 正在製圖中"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:639
+#: ./lib/app/map/_lib/managers/report.dart:660
msgid "近期的地震報告"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:647
+#: ./lib/app/map/_lib/managers/report.dart:667
msgid "更多"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:995
+#: ./lib/app/map/_lib/managers/report.dart:994
msgid "編號 {number} 顯著有感地震"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:998
+#: ./lib/app/map/_lib/managers/report.dart:997
msgid "小區域有感地震"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1083
+#: ./lib/app/map/_lib/managers/report.dart:1080
msgid "地震規模"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1110
+#: ./lib/app/map/_lib/managers/report.dart:1107
msgid "震源深度"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:886
+#: ./lib/app/map/_lib/managers/report.dart:893
msgid "沒有更多資料"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1030
+#: ./lib/app/map/_lib/managers/report.dart:1029
msgid "報告頁面"
msgstr ""
-#: ./lib/route/report/report_sheet_content.dart:90
+#: ./lib/route/report/report_sheet_content.dart:88
msgid "重播"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1064
+#: ./lib/app/map/_lib/managers/report.dart:1061
msgid "發震時間"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1132
+#: ./lib/app/map/_lib/managers/report.dart:1129
msgid "各地震度"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1212
+#: ./lib/app/map/_lib/managers/report.dart:1205
msgid "地震報告圖"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1228
+#: ./lib/app/map/_lib/managers/report.dart:1220
msgid "震度圖"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1248
+#: ./lib/app/map/_lib/managers/report.dart:1240
msgid "最大地動加速度圖"
msgstr ""
-#: ./lib/app/map/_lib/managers/report.dart:1268
+#: ./lib/app/map/_lib/managers/report.dart:1260
msgid "最大地動速度圖"
msgstr ""
@@ -1443,11 +1471,11 @@ msgstr ""
msgid "未知"
msgstr ""
-#: ./lib/route/announcement/announcement.dart:105
+#: ./lib/route/announcement/announcement.dart:104
msgid "目前沒有公告"
msgstr ""
-#: ./lib/route/announcement/announcement.dart:246
+#: ./lib/route/announcement/announcement.dart:245
msgid "公告詳情"
msgstr ""
@@ -1463,302 +1491,302 @@ msgstr ""
msgid "儲存圖片時發生錯誤"
msgstr ""
-#: ./lib/utils/extensions/number.dart:26
+#: ./lib/utils/extensions/number.dart:25
msgid "0級"
msgstr ""
-#: ./lib/utils/extensions/number.dart:27
+#: ./lib/utils/extensions/number.dart:26
msgid "1級"
msgstr ""
-#: ./lib/utils/extensions/number.dart:28
+#: ./lib/utils/extensions/number.dart:27
msgid "2級"
msgstr ""
-#: ./lib/utils/extensions/number.dart:29
+#: ./lib/utils/extensions/number.dart:28
msgid "3級"
msgstr ""
-#: ./lib/utils/extensions/number.dart:30
+#: ./lib/utils/extensions/number.dart:29
msgid "4級"
msgstr ""
-#: ./lib/utils/extensions/number.dart:31
+#: ./lib/utils/extensions/number.dart:30
msgid "5弱"
msgstr ""
-#: ./lib/utils/extensions/number.dart:32
+#: ./lib/utils/extensions/number.dart:31
msgid "5強"
msgstr ""
-#: ./lib/utils/extensions/number.dart:33
+#: ./lib/utils/extensions/number.dart:32
msgid "6弱"
msgstr ""
-#: ./lib/utils/extensions/number.dart:34
+#: ./lib/utils/extensions/number.dart:33
msgid "6強"
msgstr ""
-#: ./lib/utils/extensions/number.dart:35
+#: ./lib/utils/extensions/number.dart:34
msgid "7級"
msgstr ""
-#: ./lib/utils/weather_icon.dart:285
+#: ./lib/utils/weather_icon.dart:283
msgid "晴"
msgstr ""
-#: ./lib/utils/weather_icon.dart:286
+#: ./lib/utils/weather_icon.dart:284
msgid "晴有霾"
msgstr ""
-#: ./lib/utils/weather_icon.dart:287
+#: ./lib/utils/weather_icon.dart:285
msgid "晴有靄"
msgstr ""
-#: ./lib/utils/weather_icon.dart:288
+#: ./lib/utils/weather_icon.dart:286
msgid "晴有閃電"
msgstr ""
-#: ./lib/utils/weather_icon.dart:304
+#: ./lib/utils/weather_icon.dart:302
msgid "晴天伴有雷"
msgstr ""
-#: ./lib/utils/weather_icon.dart:290
+#: ./lib/utils/weather_icon.dart:288
msgid "晴有霧"
msgstr ""
-#: ./lib/utils/weather_icon.dart:291
+#: ./lib/utils/weather_icon.dart:289
msgid "晴有雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:292
+#: ./lib/utils/weather_icon.dart:290
msgid "晴有雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:293
+#: ./lib/utils/weather_icon.dart:291
msgid "晴有大雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:294
+#: ./lib/utils/weather_icon.dart:292
msgid "晴有雪珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:295
+#: ./lib/utils/weather_icon.dart:293
msgid "晴有冰珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:296
+#: ./lib/utils/weather_icon.dart:294
msgid "晴有陣雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:297
+#: ./lib/utils/weather_icon.dart:295
msgid "晴陣雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:298
+#: ./lib/utils/weather_icon.dart:296
msgid "晴有雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:299
+#: ./lib/utils/weather_icon.dart:297
msgid "晴有雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:300
+#: ./lib/utils/weather_icon.dart:298
msgid "晴有雷雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:301
+#: ./lib/utils/weather_icon.dart:299
msgid "晴有雷雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:302
+#: ./lib/utils/weather_icon.dart:300
msgid "晴大雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:303
+#: ./lib/utils/weather_icon.dart:301
msgid "晴大雷雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:305
+#: ./lib/utils/weather_icon.dart:303
msgid "多雲"
msgstr ""
-#: ./lib/utils/weather_icon.dart:306
+#: ./lib/utils/weather_icon.dart:304
msgid "多雲有霾"
msgstr ""
-#: ./lib/utils/weather_icon.dart:307
+#: ./lib/utils/weather_icon.dart:305
msgid "多雲有靄"
msgstr ""
-#: ./lib/utils/weather_icon.dart:308
+#: ./lib/utils/weather_icon.dart:306
msgid "多雲有閃電"
msgstr ""
-#: ./lib/utils/weather_icon.dart:324
+#: ./lib/utils/weather_icon.dart:322
msgid "多雲伴有雷"
msgstr ""
-#: ./lib/utils/weather_icon.dart:310
+#: ./lib/utils/weather_icon.dart:308
msgid "多雲有霧"
msgstr ""
-#: ./lib/utils/weather_icon.dart:311
+#: ./lib/utils/weather_icon.dart:309
msgid "多雲有雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:312
+#: ./lib/utils/weather_icon.dart:310
msgid "多雲有雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:313
+#: ./lib/utils/weather_icon.dart:311
msgid "多雲有大雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:314
+#: ./lib/utils/weather_icon.dart:312
msgid "多雲有雪珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:315
+#: ./lib/utils/weather_icon.dart:313
msgid "多雲有冰珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:316
+#: ./lib/utils/weather_icon.dart:314
msgid "多雲有陣雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:317
+#: ./lib/utils/weather_icon.dart:315
msgid "多雲陣雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:318
+#: ./lib/utils/weather_icon.dart:316
msgid "多雲有雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:319
+#: ./lib/utils/weather_icon.dart:317
msgid "多雲有雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:320
+#: ./lib/utils/weather_icon.dart:318
msgid "多雲有雷雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:321
+#: ./lib/utils/weather_icon.dart:319
msgid "多雲有雷雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:322
+#: ./lib/utils/weather_icon.dart:320
msgid "多雲大雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:323
+#: ./lib/utils/weather_icon.dart:321
msgid "多雲大雷雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:325
+#: ./lib/utils/weather_icon.dart:323
msgid "陰"
msgstr ""
-#: ./lib/utils/weather_icon.dart:326
+#: ./lib/utils/weather_icon.dart:324
msgid "陰有霾"
msgstr ""
-#: ./lib/utils/weather_icon.dart:327
+#: ./lib/utils/weather_icon.dart:325
msgid "陰有靄"
msgstr ""
-#: ./lib/utils/weather_icon.dart:328
+#: ./lib/utils/weather_icon.dart:326
msgid "陰有閃電"
msgstr ""
-#: ./lib/utils/weather_icon.dart:344
+#: ./lib/utils/weather_icon.dart:342
msgid "陰天伴有雷"
msgstr ""
-#: ./lib/utils/weather_icon.dart:330
+#: ./lib/utils/weather_icon.dart:328
msgid "陰有霧"
msgstr ""
-#: ./lib/utils/weather_icon.dart:331
+#: ./lib/utils/weather_icon.dart:329
msgid "陰有雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:332
+#: ./lib/utils/weather_icon.dart:330
msgid "陰有雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:333
+#: ./lib/utils/weather_icon.dart:331
msgid "陰有大雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:334
+#: ./lib/utils/weather_icon.dart:332
msgid "陰有雪珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:335
+#: ./lib/utils/weather_icon.dart:333
msgid "陰有冰珠"
msgstr ""
-#: ./lib/utils/weather_icon.dart:336
+#: ./lib/utils/weather_icon.dart:334
msgid "陰有陣雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:337
+#: ./lib/utils/weather_icon.dart:335
msgid "陰陣雨雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:338
+#: ./lib/utils/weather_icon.dart:336
msgid "陰有雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:339
+#: ./lib/utils/weather_icon.dart:337
msgid "陰有雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:340
+#: ./lib/utils/weather_icon.dart:338
msgid "陰有雷雪"
msgstr ""
-#: ./lib/utils/weather_icon.dart:341
+#: ./lib/utils/weather_icon.dart:339
msgid "陰有雷雹"
msgstr ""
-#: ./lib/utils/weather_icon.dart:342
+#: ./lib/utils/weather_icon.dart:340
msgid "陰大雷雨"
msgstr ""
-#: ./lib/utils/weather_icon.dart:343
+#: ./lib/utils/weather_icon.dart:341
msgid "陰大雷雹"
msgstr ""
-#: ./lib/api/model/location/location.dart:85
+#: ./lib/api/model/location/location.dart:84
msgid "{city}{cityLevel} {town}{townLevel}"
msgstr ""
-#: ./lib/api/model/location/location.dart:98
+#: ./lib/api/model/location/location.dart:97
msgid "{city} {town}"
msgstr ""
-#: ./lib/api/model/location/location.dart:113
+#: ./lib/api/model/location/location.dart:112
msgid "{city}{cityLevel}"
msgstr ""
-#: ./lib/api/model/location/location.dart:130
+#: ./lib/api/model/location/location.dart:129
msgid "{town}{townLevel}"
msgstr ""
-#: ./lib/widgets/ui/color_picker.dart:363
+#: ./lib/widgets/ui/color_picker.dart:361
msgid "色相"
msgstr ""
-#: ./lib/widgets/ui/color_picker.dart:379
+#: ./lib/widgets/ui/color_picker.dart:377
msgid "彩度"
msgstr ""
-#: ./lib/widgets/ui/color_picker.dart:395
+#: ./lib/widgets/ui/color_picker.dart:393
msgid "明度"
msgstr ""
-#: ./lib/widgets/ui/color_picker.dart:415
+#: ./lib/widgets/ui/color_picker.dart:413
msgid "十六進位值"
msgstr ""
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
index c20a06e4b..726c8e47b 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -12,7 +12,9 @@ linter:
flutter_style_todos: error
prefer_single_quotes: warning
avoid_annotating_with_dynamic: error
- public_member_api_docs: warning
+ prefer_const_constructors: info
+ prefer_const_constructors_in_immutables: info
+ prefer_const_declarations: info
formatter:
page_width: 100
diff --git a/android/gradle.properties b/android/gradle.properties
index 9b2416014..540567a6c 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -2,3 +2,7 @@ org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true
kotlin.jvm.target.validation.mode = IGNORE
+# This builtInKotlin flag was added automatically by Flutter migrator
+android.builtInKotlin=false
+# This newDsl flag was added automatically by Flutter migrator
+android.newDsl=false
diff --git a/assets/fonts/GoogleSansFlex.ttf b/assets/fonts/GoogleSansFlex.ttf
new file mode 100644
index 000000000..6cd6eaf58
Binary files /dev/null and b/assets/fonts/GoogleSansFlex.ttf differ
diff --git a/assets/fonts/NotoSansTC.ttf b/assets/fonts/NotoSansTC.ttf
new file mode 100644
index 000000000..2defdb937
Binary files /dev/null and b/assets/fonts/NotoSansTC.ttf differ
diff --git a/assets/translations/zh-Hant.po b/assets/translations/zh-Hant.po
index 6753f1f6d..2ec760e6d 100644
--- a/assets/translations/zh-Hant.po
+++ b/assets/translations/zh-Hant.po
@@ -11,215 +11,215 @@ msgstr ""
"Language-Team: Chinese Traditional\n"
"Language: zh_TW\n"
-#: ./lib/core/service.dart:291
+#: ./lib/core/service.dart:285
msgid "正在更新位置"
msgstr "正在更新位置"
-#: ./lib/core/service.dart:292
+#: ./lib/core/service.dart:286
msgid "取得 GPS 位置中..."
msgstr "取得 GPS 位置中..."
-#: ./lib/app/settings/notify/page.dart:51
+#: ./lib/app/settings/notify/page.dart:56
msgid "接收全部"
msgstr "接收全部"
-#: ./lib/app/settings/notify/page.dart:50
+#: ./lib/app/settings/notify/page.dart:65
msgid "關閉"
msgstr "關閉"
-#: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:51
+#: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:70
msgid "接收類別"
msgstr "接收類別"
-#: ./lib/app/settings/notify/page.dart:35
+#: ./lib/app/settings/notify/page.dart:55
msgid "所在地震度1以上"
msgstr "所在地震度1以上"
-#: ./lib/app/settings/notify/page.dart:46
+#: ./lib/app/settings/notify/page.dart:61
msgid "海嘯消息、海嘯警報"
msgstr "海嘯消息、海嘯警報"
-#: ./lib/app/settings/notify/page.dart:45
+#: ./lib/app/settings/notify/page.dart:60
msgid "只接收海嘯警報"
msgstr "只接收海嘯警報"
-#: ./lib/app/settings/notify/page.dart:41
+#: ./lib/app/settings/notify/page.dart:66
msgid "接收所在地"
msgstr "接收所在地"
-#: ./lib/app/settings/notify/page.dart:27
+#: ./lib/app/settings/notify/page.dart:54
msgid "所在地震度4以上"
msgstr "所在地震度4以上"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:28
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:33
msgid "音效測試"
msgstr "音效測試"
-#: ./lib/route/announcement/announcement.dart:81
+#: ./lib/route/announcement/announcement.dart:80
msgid "公告"
msgstr "公告"
-#: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:32
+#: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:37
msgid "發送公告時"
msgstr "發送公告時"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:46
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:51
msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求"
msgstr "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求"
-#: ./lib/app/settings/notify/page.dart:82
+#: ./lib/app/settings/notify/page.dart:104
msgid "伺服器排隊中,請稍候…"
msgstr "伺服器排隊中,請稍候…"
-#: ./lib/app/welcome/4-permissions/page.dart:166
+#: ./lib/app/welcome/4-permissions/page.dart:111
msgid "通知"
msgstr "通知"
-#: ./lib/app/settings/page.dart:182
+#: ./lib/app/settings/page.dart:189
msgid "推播通知設定與通知音效測試"
msgstr "推播通知設定與通知音效測試"
-#: ./lib/app/home/_widgets/location_not_set_card.dart:33
+#: ./lib/app/home_old/_widgets/location_not_set_card.dart:41
msgid "尚未設定所在地"
msgstr "尚未設定所在地"
-#: ./lib/app/settings/notify/page.dart:201
+#: ./lib/app/settings/notify/page.dart:208
msgid "請先設定所在地來使用通知功能"
msgstr "請先設定所在地來使用通知功能"
-#: ./lib/app/settings/notify/page.dart:211
+#: ./lib/app/settings/notify/page.dart:217
msgid "設定所在地"
msgstr "設定所在地"
-#: ./lib/app/settings/experimental/page.dart:209
+#: ./lib/app/settings/experimental/page.dart:215
msgid "地震速報"
msgstr "地震速報"
-#: ./lib/app/settings/notify/page.dart:232
+#: ./lib/app/settings/notify/page.dart:238
msgid "緊急地震速報"
msgstr "緊急地震速報"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:113
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:125
msgid "地震"
msgstr "地震"
-#: ./lib/app/map/_lib/managers/monitor.dart:1579
+#: ./lib/app/map/_lib/managers/monitor.dart:1584
msgid "強震監視器"
msgstr "強震監視器"
-#: ./lib/app/map/_lib/managers/report.dart:1302
+#: ./lib/app/map/_lib/managers/report.dart:1294
msgid "地震報告"
msgstr "地震報告"
-#: ./lib/app/settings/notify/page.dart:290
+#: ./lib/app/settings/notify/page.dart:297
msgid "震度速報"
msgstr "震度速報"
-#: ./lib/app/settings/notify/page.dart:304
+#: ./lib/app/settings/notify/page.dart:310
msgid "天氣"
msgstr "天氣"
-#: ./lib/app/home/_widgets/thunderstorm_card.dart:63
+#: ./lib/app/home_old/_widgets/thunderstorm_card.dart:72
msgid "雷雨即時訊息"
msgstr "雷雨即時訊息"
-#: ./lib/app/settings/notify/page.dart:334
+#: ./lib/app/settings/notify/page.dart:339
msgid "天氣警特報"
msgstr "天氣警特報"
-#: ./lib/app/settings/notify/page.dart:354
+#: ./lib/app/settings/notify/page.dart:358
msgid "防災資訊"
msgstr "防災資訊"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:129
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:141
msgid "海嘯"
msgstr "海嘯"
-#: ./lib/app/settings/notify/page.dart:378
+#: ./lib/app/settings/notify/page.dart:383
msgid "海嘯資訊"
msgstr "海嘯資訊"
-#: ./lib/app/settings/notify/page.dart:390
+#: ./lib/app/settings/notify/page.dart:394
msgid "其他"
msgstr "其他"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:36
msgid "重大"
msgstr "重大"
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:31
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:36
msgid "海嘯警報發布時"
msgstr "海嘯警報發布時"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:37
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42
msgid "一般"
msgstr "一般"
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:37
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:42
msgid "海嘯消息發布時"
msgstr "海嘯消息發布時"
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:41
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:46
msgid "太平洋海嘯消息(無聲通知)"
msgstr "太平洋海嘯消息(無聲通知)"
-#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:42
+#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:47
msgid "太平洋海嘯消息發布時"
msgstr "太平洋海嘯消息發布時"
-#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:35
msgid "強震監視器(一般)"
msgstr "強震監視器(一般)"
-#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:36
msgid "偵測到晃動"
msgstr "偵測到晃動"
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35
msgid "震度速報(一般)"
msgstr "震度速報(一般)"
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36
msgid "所在地(鄉鎮)實測震度 3 以上"
msgstr "所在地(鄉鎮)實測震度 3 以上"
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:41
msgid "震度速報(無聲通知)"
msgstr "震度速報(無聲通知)"
-#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:37
+#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:42
msgid "所在地(鄉鎮)實測震度 1 以上"
msgstr "所在地(鄉鎮)實測震度 1 以上"
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:30
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:35
msgid "地震報告(一般)"
msgstr "地震報告(一般)"
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:31
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:36
msgid "所在地(縣市)實測震度 3 以上"
msgstr "所在地(縣市)實測震度 3 以上"
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:36
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:41
msgid "地震報告(無聲通知)"
msgstr "地震報告(無聲通知)"
-#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:37
+#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:42
msgid "所在地(縣市)實測震度 1 以上"
msgstr "所在地(縣市)實測震度 1 以上"
-#: ./lib/app/settings/notify/_lib/utils.dart:15
+#: ./lib/app/settings/notify/_lib/utils.dart:29
msgid "已更新通知設定"
msgstr "已更新通知設定"
-#: ./lib/app/settings/notify/_lib/utils.dart:22
+#: ./lib/app/settings/notify/_lib/utils.dart:40
msgid "更新通知設定失敗"
msgstr "更新通知設定失敗"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:30
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:35
msgid "緊急地震速報(重大)"
msgstr "緊急地震速報(重大)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:31
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:36
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 4 以上"
@@ -227,11 +227,11 @@ msgstr ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 4 以上"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:36
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:41
msgid "緊急地震速報(一般)"
msgstr "緊急地震速報(一般)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:37
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:42
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 2 以上"
@@ -239,11 +239,11 @@ msgstr ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 2 以上"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:41
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:46
msgid "緊急地震速報(無聲)"
msgstr "緊急地震速報(無聲)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:42
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:47
msgid ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 1 以上"
@@ -251,39 +251,39 @@ msgstr ""
"最大震度 5 弱以上 且\n"
"所在地(鄉鎮)預估震度 1 以上"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:46
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:51
msgid "地震速報(重大)"
msgstr "地震速報(重大)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:47
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:52
msgid "所在地(鄉鎮)預估震度 4 以上"
msgstr "所在地(鄉鎮)預估震度 4 以上"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:51
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:56
msgid "地震速報(一般)"
msgstr "地震速報(一般)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:52
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:57
msgid "所在地(鄉鎮)預估震度 2 以上"
msgstr "所在地(鄉鎮)預估震度 2 以上"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:56
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:61
msgid "地震速報(無聲)"
msgstr "地震速報(無聲)"
-#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:57
+#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:62
msgid "所在地(鄉鎮)預估震度 1 以上"
msgstr "所在地(鄉鎮)預估震度 1 以上"
-#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:36
msgid "所在地(鄉鎮)發布防災警訊時"
msgstr "所在地(鄉鎮)發布防災警訊時"
-#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:42
msgid "所在地(鄉鎮)發布防災資訊時"
msgstr "所在地(鄉鎮)發布防災資訊時"
-#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:37
msgid ""
"所在地(鄉鎮)發布紅色燈號之\n"
"天氣警特報"
@@ -291,7 +291,7 @@ msgstr ""
"所在地(鄉鎮)發布紅色燈號之\n"
"天氣警特報"
-#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:43
msgid ""
"所在地(鄉鎮)發布上述除外燈號之\n"
"天氣警特報"
@@ -299,63 +299,63 @@ msgstr ""
"所在地(鄉鎮)發布上述除外燈號之\n"
"天氣警特報"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:32
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:37
msgid "所在地(鄉鎮)發布山區暴雨時"
msgstr "所在地(鄉鎮)發布山區暴雨時"
-#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:38
+#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:43
msgid "所在地(鄉鎮)發布雷雨即時訊息時"
msgstr "所在地(鄉鎮)發布雷雨即時訊息時"
-#: ./lib/app/settings/experimental/page.dart:197
-msgid "啟動時進入強震監視器"
-msgstr "啟動時進入強震監視器"
-
-#: ./lib/app/settings/experimental/page.dart:57
+#: ./lib/app/settings/experimental/page.dart:48
msgid "地震速報不限制非 CWA 來源"
msgstr "地震速報不限制非 CWA 來源"
-#: ./lib/app/settings/page.dart:428
+#: ./lib/app/settings/experimental/page.dart:203
+msgid "啟動時進入強震監視器"
+msgstr "啟動時進入強震監視器"
+
+#: ./lib/app/settings/page.dart:430
msgid "實驗性功能"
msgstr "實驗性功能"
-#: ./lib/app/settings/page.dart:429
+#: ./lib/app/settings/page.dart:431
msgid "搶先體驗開發中的新功能"
msgstr "搶先體驗開發中的新功能"
-#: ./lib/app/settings/experimental/page.dart:154
+#: ./lib/app/settings/experimental/page.dart:160
msgid "注意"
msgstr "注意"
-#: ./lib/app/settings/experimental/page.dart:162
+#: ./lib/app/settings/experimental/page.dart:168
msgid "這些功能仍在開發中,可能會不穩定或在未來的版本中變更。"
msgstr "這些功能仍在開發中,可能會不穩定或在未來的版本中變更。"
-#: ./lib/app/settings/experimental/page.dart:188
+#: ./lib/app/settings/experimental/page.dart:194
msgid "啟動行為"
msgstr "啟動行為"
-#: ./lib/app/settings/experimental/page.dart:198
+#: ./lib/app/settings/experimental/page.dart:204
msgid "開啟 App 時直接進入強震監視器地圖"
msgstr "開啟 App 時直接進入強震監視器地圖"
-#: ./lib/app/settings/experimental/page.dart:218
+#: ./lib/app/settings/experimental/page.dart:224
msgid "不限制非 CWA 來源"
msgstr "不限制非 CWA 來源"
-#: ./lib/app/settings/experimental/page.dart:219
+#: ./lib/app/settings/experimental/page.dart:225
msgid "顯示所有來源的地震速報資料"
msgstr "顯示所有來源的地震速報資料"
-#: ./lib/app/settings/experimental/page.dart:280
+#: ./lib/app/settings/experimental/page.dart:281
msgid "啟用實驗性功能"
msgstr "啟用實驗性功能"
-#: ./lib/app/settings/experimental/page.dart:286
+#: ./lib/app/settings/experimental/page.dart:287
msgid "你即將啟用:"
msgstr "你即將啟用:"
-#: ./lib/app/settings/experimental/page.dart:317
+#: ./lib/app/settings/experimental/page.dart:318
msgid "此功能為實驗性質,可能會造成應用程式不穩定或行為異常。如遇問題,請至設定中關閉此功能。"
msgstr "此功能為實驗性質,可能會造成應用程式不穩定或行為異常。如遇問題,請至設定中關閉此功能。"
@@ -363,15 +363,15 @@ msgstr "此功能為實驗性質,可能會造成應用程式不穩定或行為
msgid "取消"
msgstr "取消"
-#: ./lib/app/settings/layout/page.dart:272
+#: ./lib/app/settings/layout/page.dart:163
msgid "啟用"
msgstr "啟用"
-#: ./lib/app/settings/page.dart:151
+#: ./lib/app/settings/page.dart:158
msgid "單位"
msgstr "單位"
-#: ./lib/app/settings/page.dart:152
+#: ./lib/app/settings/page.dart:159
msgid "調整 DPIP 顯示數值時使用的單位"
msgstr "調整 DPIP 顯示數值時使用的單位"
@@ -383,131 +383,131 @@ msgstr "使用華氏度"
msgid "切換溫度顯示單位為華氏度 (℉)"
msgstr "切換溫度顯示單位為華氏度 (℉)"
-#: ./lib/app/settings/page.dart:141
+#: ./lib/app/settings/page.dart:148
msgid "語言"
msgstr "語言"
-#: ./lib/app/settings/page.dart:142
+#: ./lib/app/settings/page.dart:149
msgid "調整 DPIP 的顯示語言"
msgstr "調整 DPIP 的顯示語言"
-#: ./lib/app/settings/locale/page.dart:41
+#: ./lib/app/settings/locale/page.dart:49
msgid "顯示語言"
msgstr "顯示語言"
-#: ./lib/app/settings/locale/page.dart:42
+#: ./lib/app/settings/locale/page.dart:50
msgid "系統語言"
msgstr "系統語言"
-#: ./lib/app/settings/locale/page.dart:52
+#: ./lib/app/settings/locale/page.dart:60
msgid "協助翻譯"
msgstr "協助翻譯"
-#: ./lib/app/settings/locale/page.dart:53
+#: ./lib/app/settings/locale/page.dart:61
msgid "點擊這裡來幫助我們改進 DPIP 的翻譯"
msgstr "點擊這裡來幫助我們改進 DPIP 的翻譯"
-#: ./lib/app/settings/locale/select/page.dart:116
+#: ./lib/app/settings/locale/select/page.dart:122
msgid "已翻譯 {translated}・已校對 {approved}"
msgstr "已翻譯 {translated}・已校對 {approved}"
-#: ./lib/app/settings/locale/select/page.dart:129
+#: ./lib/app/settings/locale/select/page.dart:135
msgid "來源語言"
msgstr "來源語言"
-#: ./lib/app/settings/locale/select/page.dart:163
+#: ./lib/app/settings/locale/select/page.dart:172
msgid "選擇語言"
msgstr "選擇語言"
-#: ./lib/app/settings/donate/page.dart:52
+#: ./lib/app/settings/donate/page.dart:59
msgid "無法連線至商店,請稍後再試"
msgstr "無法連線至商店,請稍後再試"
-#: ./lib/app/settings/donate/page.dart:59
+#: ./lib/app/settings/donate/page.dart:65
msgid "找不到商品,請稍候再試"
msgstr "找不到商品,請稍候再試"
-#: ./lib/app/map/_lib/managers/report.dart:521
-msgid "重新載入"
-msgstr "重新載入"
-
-#: ./lib/app/settings/donate/page.dart:171
-msgid "正在載入商店物品中"
-msgstr "正在載入商店物品中"
-
-#: ./lib/app/settings/donate/page.dart:225
+#: ./lib/app/settings/donate/page.dart:136
msgid "支持 DPIP"
msgstr "支持 DPIP"
-#: ./lib/app/settings/donate/page.dart:233
+#: ./lib/app/settings/donate/page.dart:144
msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。您的支持將幫助我們維持伺服器運行與持續開發。"
msgstr "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。您的支持將幫助我們維持伺服器運行與持續開發。"
-#: ./lib/app/settings/donate/page.dart:260
+#: ./lib/app/settings/donate/page.dart:170
msgid "訂閱制"
msgstr "訂閱制"
-#: ./lib/app/settings/donate/page.dart:276
+#: ./lib/app/settings/donate/page.dart:189
msgid "推薦"
msgstr "推薦"
-#: ./lib/app/settings/donate/page.dart:443
+#: ./lib/app/settings/donate/page.dart:353
msgid "{price}/月"
msgstr "{price}/月"
-#: ./lib/app/settings/donate/page.dart:475
+#: ./lib/app/settings/donate/page.dart:385
msgid "單次支援"
msgstr "單次支援"
-#: ./lib/app/settings/donate/page.dart:615
+#: ./lib/app/settings/donate/page.dart:520
msgid "恢復購買"
msgstr "恢復購買"
-#: ./lib/app/settings/donate/page.dart:628
+#: ./lib/app/settings/donate/page.dart:530
msgid "無法連線至 {store},請稍後再試。"
msgstr "無法連線至 {store},請稍後再試。"
-#: ./lib/app/settings/donate/page.dart:639
+#: ./lib/app/settings/donate/page.dart:541
msgid "正在恢復您購買的訂閱"
msgstr "正在恢復您購買的訂閱"
-#: ./lib/app/settings/donate/page.dart:644
+#: ./lib/app/settings/donate/page.dart:546
msgid "使用條款"
msgstr "使用條款"
-#: ./lib/app/settings/donate/page.dart:648
+#: ./lib/app/settings/donate/page.dart:550
msgid "隱私權政策"
msgstr "隱私權政策"
-#: ./lib/app/settings/proxy/page.dart:51
+#: ./lib/app/map/_lib/managers/report.dart:546
+msgid "重新載入"
+msgstr "重新載入"
+
+#: ./lib/app/settings/donate/page.dart:636
+msgid "正在載入商店物品中"
+msgstr "正在載入商店物品中"
+
+#: ./lib/app/settings/proxy/page.dart:38
msgid "設定已儲存"
msgstr "設定已儲存"
-#: ./lib/app/settings/page.dart:200
+#: ./lib/app/settings/page.dart:207
msgid "HTTP 代理"
msgstr "HTTP 代理"
-#: ./lib/app/settings/page.dart:201
+#: ./lib/app/settings/page.dart:208
msgid "調整 HTTP 代理伺服器設定"
msgstr "調整 HTTP 代理伺服器設定"
-#: ./lib/app/settings/proxy/page.dart:75
+#: ./lib/app/settings/proxy/page.dart:74
msgid "啟用代理"
msgstr "啟用代理"
-#: ./lib/app/settings/proxy/page.dart:76
+#: ./lib/app/settings/proxy/page.dart:75
msgid "透過代理伺服器發送所有網路請求"
msgstr "透過代理伺服器發送所有網路請求"
-#: ./lib/app/settings/proxy/page.dart:88
+#: ./lib/app/settings/proxy/page.dart:87
msgid "代理主機"
msgstr "代理主機"
-#: ./lib/app/settings/proxy/page.dart:102
+#: ./lib/app/settings/proxy/page.dart:101
msgid "代理端口"
msgstr "代理端口"
-#: ./lib/app/settings/proxy/page.dart:117
+#: ./lib/app/settings/proxy/page.dart:116
msgid "設定儲存後,需要重新啟動應用程式才能生效"
msgstr "設定儲存後,需要重新啟動應用程式才能生效"
@@ -515,123 +515,123 @@ msgstr "設定儲存後,需要重新啟動應用程式才能生效"
msgid "設定"
msgstr "設定"
-#: ./lib/app/settings/page.dart:71
+#: ./lib/app/settings/page.dart:79
msgid "自訂你的 DPIP 使用體驗"
msgstr "自訂你的 DPIP 使用體驗"
-#: ./lib/app/welcome/4-permissions/page.dart:174
+#: ./lib/app/welcome/4-permissions/page.dart:119
msgid "位置"
msgstr "位置"
-#: ./lib/app/settings/location/page.dart:417
+#: ./lib/app/settings/location/page.dart:421
msgid "所在地"
msgstr "所在地"
-#: ./lib/app/settings/location/page.dart:241
+#: ./lib/app/settings/location/page.dart:245
msgid "設定你的所在地來接收當地的即時資訊"
msgstr "設定你的所在地來接收當地的即時資訊"
-#: ./lib/app/settings/page.dart:113
+#: ./lib/app/settings/page.dart:120
msgid "介面"
msgstr "介面"
-#: ./lib/app/settings/layout/page.dart:47
+#: ./lib/app/settings/layout/page.dart:183
msgid "版面"
msgstr "版面"
-#: ./lib/app/settings/layout/page.dart:48
+#: ./lib/app/settings/layout/page.dart:184
msgid "調整首頁的版面樣式"
msgstr "調整首頁的版面樣式"
-#: ./lib/app/settings/theme/page.dart:25
+#: ./lib/app/settings/theme/page.dart:32
msgid "主題"
msgstr "主題"
-#: ./lib/app/settings/theme/page.dart:26
+#: ./lib/app/settings/theme/page.dart:33
msgid "調整 DPIP 整體的外觀與顏色"
msgstr "調整 DPIP 整體的外觀與顏色"
-#: ./lib/app/settings/map/page.dart:49
+#: ./lib/app/home/layout.dart:93
msgid "地圖"
msgstr "地圖"
-#: ./lib/app/settings/map/page.dart:50
+#: ./lib/app/settings/map/page.dart:59
msgid "調整地圖的顯示樣式"
msgstr "調整地圖的顯示樣式"
-#: ./lib/app/settings/page.dart:191
+#: ./lib/app/settings/page.dart:198
msgid "網路"
msgstr "網路"
-#: ./lib/app/settings/page.dart:210
+#: ./lib/app/settings/page.dart:217
msgid "資訊"
msgstr "資訊"
-#: ./lib/app/changelog/page.dart:54
+#: ./lib/app/home_old/page.dart:163
msgid "更新日誌"
msgstr "更新日誌"
-#: ./lib/app/settings/page.dart:230
+#: ./lib/app/settings/page.dart:237
msgid "瀏覽 DPIP 的歷次更新紀錄"
msgstr "瀏覽 DPIP 的歷次更新紀錄"
-#: ./lib/app/settings/page.dart:240
+#: ./lib/app/settings/page.dart:247
msgid "第三方套件授權"
msgstr "第三方套件授權"
-#: ./lib/app/settings/page.dart:241
+#: ./lib/app/settings/page.dart:248
msgid "DPIP 的實現歸功於開放原始碼"
msgstr "DPIP 的實現歸功於開放原始碼"
-#: ./lib/app/settings/page.dart:264
+#: ./lib/app/settings/page.dart:271
msgid "贊助我們"
msgstr "贊助我們"
-#: ./lib/app/settings/page.dart:267
+#: ./lib/app/settings/page.dart:274
msgid "幫助我們維護伺服器的穩定和長久發展"
msgstr "幫助我們維護伺服器的穩定和長久發展"
-#: ./lib/app/settings/page.dart:343
+#: ./lib/app/settings/page.dart:349
msgid "下載"
msgstr "下載"
-#: ./lib/app/settings/page.dart:383
+#: ./lib/app/settings/page.dart:385
msgid "除錯"
msgstr "除錯"
-#: ./lib/app/settings/page.dart:391
+#: ./lib/app/settings/page.dart:393
msgid "應用程式版本"
msgstr "應用程式版本"
-#: ./lib/app/settings/page.dart:400
+#: ./lib/app/settings/page.dart:402
msgid "裝置資訊"
msgstr "裝置資訊"
-#: ./lib/app/settings/page.dart:409
+#: ./lib/app/settings/page.dart:411
msgid "複製通知 Token"
msgstr "複製通知 Token"
-#: ./lib/app/debug/logs/page.dart:16
+#: ./lib/app/debug/logs/page.dart:22
msgid "App 日誌"
msgstr "App 日誌"
-#: ./lib/app/settings/page.dart:463
+#: ./lib/app/settings/page.dart:465
msgid "任何資訊應以中央氣象署發布之內容為準"
msgstr "任何資訊應以中央氣象署發布之內容為準"
-#: ./lib/app/settings/location/page.dart:74
+#: ./lib/app/settings/location/page.dart:85
msgid "無法取得通知權限"
msgstr "無法取得通知權限"
-#: ./lib/app/settings/location/page.dart:76
+#: ./lib/app/settings/location/page.dart:87
msgid "無法取得位置權限"
msgstr "無法取得位置權限"
-#: ./lib/app/settings/location/page.dart:77
+#: ./lib/app/settings/location/page.dart:88
msgid "無法取得自啟動權限"
msgstr "無法取得自啟動權限"
-#: ./lib/app/welcome/4-permissions/page.dart:180
+#: ./lib/app/welcome/4-permissions/page.dart:125
msgid "省電策略"
msgstr "省電策略"
@@ -639,63 +639,63 @@ msgstr "省電策略"
msgid "無法取得權限"
msgstr "無法取得權限"
-#: ./lib/app/settings/location/page.dart:84
+#: ./lib/app/settings/location/page.dart:94
msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。"
msgstr "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。"
-#: ./lib/app/settings/location/page.dart:86
+#: ./lib/app/settings/location/page.dart:95
msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。"
msgstr "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。"
-#: ./lib/app/settings/location/page.dart:89
+#: ./lib/app/settings/location/page.dart:98
msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。"
msgstr "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。"
-#: ./lib/app/settings/location/page.dart:91
+#: ./lib/app/settings/location/page.dart:99
msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。"
msgstr "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。"
-#: ./lib/app/settings/location/page.dart:93
+#: ./lib/app/settings/location/page.dart:100
msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。"
msgstr "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。"
-#: ./lib/app/settings/location/page.dart:95
+#: ./lib/app/settings/location/page.dart:101
msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。"
msgstr "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。"
-#: ./lib/app/settings/location/page.dart:96
+#: ./lib/app/settings/location/page.dart:102
msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。"
msgstr "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。"
-#: ./lib/app/settings/location/page.dart:174
+#: ./lib/app/settings/location/page.dart:180
msgid "自動啟動"
msgstr "自動啟動"
-#: ./lib/app/settings/location/page.dart:175
+#: ./lib/app/settings/location/page.dart:181
msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
msgstr "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
-#: ./lib/app/settings/location/page.dart:199
+#: ./lib/app/settings/location/page.dart:203
msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
msgstr "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。"
-#: ./lib/app/settings/location/page.dart:233
+#: ./lib/app/settings/location/page.dart:237
msgid "一律允許"
msgstr "一律允許"
-#: ./lib/app/settings/location/page.dart:233
+#: ./lib/app/settings/location/page.dart:237
msgid "永遠"
msgstr "永遠"
-#: ./lib/app/settings/location/page.dart:253
+#: ./lib/app/settings/location/page.dart:257
msgid "自動更新"
msgstr "自動更新"
-#: ./lib/app/settings/location/page.dart:254
+#: ./lib/app/settings/location/page.dart:258
msgid "定期更新目前的所在地"
msgstr "定期更新目前的所在地"
-#: ./lib/app/settings/location/page.dart:263
+#: ./lib/app/settings/location/page.dart:267
msgid ""
"自動定位功能將使用您的裝置上的 GPS,即使 DPIP "
"關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。"
@@ -703,267 +703,429 @@ msgstr ""
"自動定位功能將使用您的裝置上的 GPS,即使 DPIP "
"關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。"
-#: ./lib/app/settings/location/page.dart:334
+#: ./lib/app/settings/location/page.dart:338
msgid "通知功能已被拒絕,請移至設定允許權限。"
msgstr "通知功能已被拒絕,請移至設定允許權限。"
-#: ./lib/app/settings/location/page.dart:395
+#: ./lib/app/settings/location/page.dart:399
msgid "省電策略已被拒絕,請移至設定允許權限。"
msgstr "省電策略已被拒絕,請移至設定允許權限。"
-#: ./lib/app/settings/location/select/[city]/page.dart:98
+#: ./lib/app/settings/location/select/[city]/page.dart:109
msgid "設定所在地時發生錯誤,請稍候再試一次。"
msgstr "設定所在地時發生錯誤,請稍候再試一次。"
-#: ./lib/app/home/_widgets/location_button.dart:233
+#: ./lib/app/home_old/_widgets/location_button.dart:204
msgid "新增地點"
msgstr "新增地點"
-#: ./lib/app/settings/location/select/page.dart:33
+#: ./lib/app/home/_widgets/location_chip.dart:148
msgid "縣市"
msgstr "縣市"
-#: ./lib/app/settings/location/select/page.dart:44
+#: ./lib/app/settings/location/select/page.dart:49
msgid "目前所在地"
msgstr "目前所在地"
-#: ./lib/app/settings/layout/page.dart:56
+#: ./lib/app/settings/layout/page.dart:90
+msgid "停用"
+msgstr "停用"
+
+#: ./lib/app/settings/layout/page.dart:192
msgid "拖曳調整順序"
msgstr "拖曳調整順序"
-#: ./lib/app/settings/layout/page.dart:100
+#: ./lib/app/settings/layout/page.dart:236
msgid "已停用"
msgstr "已停用"
-#: ./lib/app/settings/layout/page.dart:135
+#: ./lib/app/settings/layout/page.dart:271
msgid "所有區塊皆已啟用"
msgstr "所有區塊皆已啟用"
-#: ./lib/app/settings/layout/page.dart:202
-msgid "停用"
-msgstr "停用"
-
-#: ./lib/app/settings/map/page.dart:61
+#: ./lib/app/settings/map/page.dart:70
msgid "初始圖層"
msgstr "初始圖層"
-#: ./lib/app/settings/map/page.dart:62
+#: ./lib/app/settings/map/page.dart:71
msgid "調整地圖的底圖以及初始顯示的圖層"
msgstr "調整地圖的底圖以及初始顯示的圖層"
-#: ./lib/app/settings/map/page.dart:74
+#: ./lib/app/settings/map/page.dart:83
msgid "自動縮放"
msgstr "自動縮放"
-#: ./lib/app/settings/map/page.dart:75
+#: ./lib/app/settings/map/page.dart:84
msgid "接收到檢知時自動縮放地圖"
msgstr "接收到檢知時自動縮放地圖"
-#: ./lib/app/settings/map/page.dart:101
+#: ./lib/app/settings/map/page.dart:110
msgid "動畫幀率"
msgstr "動畫幀率"
-#: ./lib/app/settings/map/page.dart:102
+#: ./lib/app/settings/map/page.dart:111
msgid "調整強震監視器震波模擬動畫的流暢度"
msgstr "調整強震監視器震波模擬動畫的流暢度"
-#: ./lib/app/settings/map/page.dart:136
+#: ./lib/app/settings/map/page.dart:144
msgid "過高的動畫幀率可能會造成卡頓或裝置發熱"
msgstr "過高的動畫幀率可能會造成卡頓或裝置發熱"
-#: ./lib/app/settings/theme/page.dart:46
+#: ./lib/app/settings/theme/page.dart:53
msgid "主題模式"
msgstr "主題模式"
-#: ./lib/app/settings/theme/mode/page.dart:63
+#: ./lib/app/settings/theme/mode/page.dart:69
msgid "淺色"
msgstr "淺色"
-#: ./lib/app/settings/theme/mode/page.dart:64
+#: ./lib/app/settings/theme/mode/page.dart:70
msgid "深色"
msgstr "深色"
-#: ./lib/app/settings/theme/mode/page.dart:59
+#: ./lib/app/settings/theme/mode/page.dart:67
msgid "跟隨系統主題"
msgstr "跟隨系統主題"
-#: ./lib/app/settings/theme/color/page.dart:22
+#: ./lib/app/settings/theme/color/page.dart:30
msgid "主題色彩"
msgstr "主題色彩"
-#: ./lib/app/settings/theme/color/page.dart:43
+#: ./lib/app/settings/theme/color/page.dart:51
msgid "使用系統配色"
msgstr "使用系統配色"
-#: ./lib/app/settings/theme/color/page.dart:62
+#: ./lib/app/settings/theme/color/page.dart:70
msgid "自訂"
msgstr "自訂"
-#: ./lib/app/settings/theme/color/page.dart:72
+#: ./lib/app/settings/theme/color/page.dart:79
msgid "自訂色彩"
msgstr "自訂色彩"
-#: ./lib/app/home/_widgets/thunderstorm_card.dart:84
+#: ./lib/app/map/_lib/managers/radar.dart:614
+msgid "雷達回波"
+msgstr "雷達回波"
+
+#: ./lib/app/home/_widgets/weather_parameters.dart:52
+msgid "相對溼度"
+msgstr "相對溼度"
+
+#: ./lib/app/home/_widgets/weather_parameters.dart:57
+msgid "空氣品質"
+msgstr "空氣品質"
+
+#: ./lib/app/map/_lib/managers/wind.dart:343
+msgid "風向/風速"
+msgstr "風向/風速"
+
+#: ./lib/app/home/_widgets/weather_parameters.dart:68
+msgid "降水量"
+msgstr "降水量"
+
+#: ./lib/app/home/_widgets/location_chip.dart:84
+msgid "清除暫時位置"
+msgstr "清除暫時位置"
+
+#: ./lib/app/home/_widgets/location_chip.dart:159
+msgid "目前選擇地區"
+msgstr "目前選擇地區"
+
+#: ./lib/app/home_old/_widgets/location_button.dart:170
+msgid "快速切換"
+msgstr "快速切換"
+
+#: ./lib/app/home/layout.dart:88
+msgid "首頁"
+msgstr "首頁"
+
+#: ./lib/app/home/layout.dart:98
+msgid "小工具"
+msgstr "小工具"
+
+#: ./lib/app/changelog/page.dart:86
+msgid "發生錯誤"
+msgstr "發生錯誤"
+
+#: ./lib/route/image_viewer/image_viewer.dart:85
+msgid "再試一次"
+msgstr "再試一次"
+
+#: ./lib/app/changelog/page.dart:217
+msgid "目前版本"
+msgstr "目前版本"
+
+#: ./lib/app/welcome/4-permissions/page.dart:383
+msgid "下一步"
+msgstr "下一步"
+
+#: ./lib/app/welcome/1-about/page.dart:73
+msgid "防災資訊平台"
+msgstr "防災資訊平台"
+
+#: ./lib/app/welcome/2-exptech/page.dart:98
+msgid "我們是誰?"
+msgstr "我們是誰?"
+
+#: ./lib/app/welcome/2-exptech/page.dart:105
+msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
+msgstr "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
+
+#: ./lib/app/welcome/2-exptech/page.dart:111
+msgid "我們的初衷"
+msgstr "我們的初衷"
+
+#: ./lib/app/welcome/2-exptech/page.dart:118
+msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
+msgstr "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
+
+#: ./lib/app/welcome/3-notice/page.dart:50
+msgid "注意事項"
+msgstr "注意事項"
+
+#: ./lib/app/welcome/3-notice/page.dart:70
+msgid "任何資訊應以中央氣象署發布之內容為準。"
+msgstr "任何資訊應以中央氣象署發布之內容為準。"
+
+#: ./lib/app/welcome/3-notice/page.dart:87
+msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
+msgstr "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
+
+#: ./lib/app/welcome/3-notice/page.dart:101
+msgid "強烈搖晃有機率比通知早抵達使用者所在地。"
+msgstr "強烈搖晃有機率比通知早抵達使用者所在地。"
+
+#: ./lib/app/welcome/3-notice/page.dart:115
+msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
+msgstr "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
+
+#: ./lib/app/welcome/3-notice/page.dart:129
+msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
+msgstr "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
+
+#: ./lib/app/welcome/1-about/page.dart:51
+msgid "歡迎使用 DPIP"
+msgstr "歡迎使用 DPIP"
+
+#: ./lib/app/welcome/1-about/page.dart:96
+msgid ""
+"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
+"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
+msgstr ""
+"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
+"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
+
+#: ./lib/app/welcome/4-permissions/page.dart:112
+msgid "在重大災害發生時以通知來傳遞即時防災資訊"
+msgstr "在重大災害發生時以通知來傳遞即時防災資訊"
+
+#: ./lib/app/welcome/4-permissions/page.dart:120
+msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
+msgstr "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
+
+#: ./lib/app/welcome/4-permissions/page.dart:126
+msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
+msgstr "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
+
+#: ./lib/route/image_viewer/image_viewer.dart:254
+msgid "儲存"
+msgstr "儲存"
+
+#: ./lib/app/welcome/4-permissions/page.dart:133
+msgid "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
+msgstr "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
+
+#: ./lib/app/welcome/4-permissions/page.dart:293
+msgid "權限請求"
+msgstr "權限請求"
+
+#: ./lib/app/welcome/4-permissions/page.dart:294
+msgid "需要使用者手動到設定開啟相關權限。"
+msgstr "需要使用者手動到設定開啟相關權限。"
+
+#: ./lib/route/image_viewer/image_viewer.dart:145
+msgid "確定"
+msgstr "確定"
+
+#: ./lib/app/welcome/4-permissions/page.dart:317
+msgid "需要背景位置權限"
+msgstr "需要背景位置權限"
+
+#: ./lib/app/welcome/4-permissions/page.dart:319
+msgid ""
+"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
+"\n"
+"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
+msgstr ""
+"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
+"\n"
+"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
+
+#: ./lib/app/welcome/4-permissions/page.dart:325
+msgid "稍後"
+msgstr "稍後"
+
+#: ./lib/app/welcome/4-permissions/page.dart:329
+msgid "前往設定"
+msgstr "前往設定"
+
+#: ./lib/app/welcome/4-permissions/page.dart:406
+msgid "權限"
+msgstr "權限"
+
+#: ./lib/app/welcome/4-permissions/page.dart:419
+msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
+msgstr "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
+
+#: ./lib/app/home_old/_widgets/thunderstorm_card.dart:93
msgid "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。"
msgstr "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。"
-#: ./lib/app/home/_widgets/forecast_card.dart:59
+#: ./lib/app/home_old/_widgets/forecast_card.dart:68
msgid "天氣預報(24h)"
msgstr "天氣預報(24h)"
-#: ./lib/app/home/_widgets/location_out_of_service.dart:28
+#: ./lib/app/home_old/_widgets/location_out_of_service.dart:34
msgid "服務區域外,僅在臺灣各地可用"
msgstr "服務區域外,僅在臺灣各地可用"
-#: ./lib/app/map/_lib/managers/radar.dart:587
-msgid "雷達回波"
-msgstr "雷達回波"
-
-#: ./lib/app/map/_lib/managers/monitor.dart:497
+#: ./lib/app/map/_lib/managers/monitor.dart:518
msgid "無資料"
msgstr "無資料"
-#: ./lib/app/home/_widgets/wind_card.dart:372
+#: ./lib/app/home_old/_widgets/wind_card.dart:329
msgid "{wind}級 {Desc}"
msgstr "{wind}級 {Desc}"
-#: ./lib/app/home/_widgets/wind_card.dart:389
+#: ./lib/app/home_old/_widgets/wind_card.dart:346
msgid "陣風 {speed} m/s"
msgstr "陣風 {speed} m/s"
-#: ./lib/app/home/_widgets/wind_card.dart:471
+#: ./lib/app/home_old/_widgets/wind_card.dart:408
msgid "無法測量"
msgstr "無法測量"
-#: ./lib/app/home/_widgets/wind_card.dart:492
+#: ./lib/app/home_old/_widgets/wind_card.dart:429
msgid "指北針不可靠"
msgstr "指北針不可靠"
-#: ./lib/app/home/_widgets/wind_card.dart:494
+#: ./lib/app/home_old/_widgets/wind_card.dart:431
msgid "指北針準確度下降"
msgstr "指北針準確度下降"
-#: ./lib/app/home/_widgets/wind_card.dart:495
+#: ./lib/app/home_old/_widgets/wind_card.dart:432
msgid "指北針正常"
msgstr "指北針正常"
-#: ./lib/app/home/_widgets/wind_card.dart:502
+#: ./lib/app/home_old/_widgets/wind_card.dart:439
msgid "方向精確度"
msgstr "方向精確度"
-#: ./lib/app/home/_widgets/wind_card.dart:521
+#: ./lib/app/home_old/_widgets/wind_card.dart:458
msgid "正常範圍:±0-15°"
msgstr "正常範圍:±0-15°"
-#: ./lib/app/home/_widgets/wind_card.dart:538
+#: ./lib/app/home_old/_widgets/wind_card.dart:475
msgid "附近有強磁場干擾,指北針方向可能完全不準確。請遠離磁鐵、電子裝置或金屬物品。"
msgstr "附近有強磁場干擾,指北針方向可能完全不準確。請遠離磁鐵、電子裝置或金屬物品。"
-#: ./lib/app/home/_widgets/wind_card.dart:539
+#: ./lib/app/home_old/_widgets/wind_card.dart:476
msgid "附近可能有磁場干擾,指北針方向可能有偏差。"
msgstr "附近可能有磁場干擾,指北針方向可能有偏差。"
-#: ./lib/route/image_viewer/image_viewer.dart:145
-msgid "確定"
-msgstr "確定"
-
-#: ./lib/app/home/_widgets/location_button.dart:29
+#: ./lib/app/home_old/_widgets/location_button.dart:38
msgid "尚未設定"
msgstr "尚未設定"
-#: ./lib/app/home/_widgets/location_button.dart:138
-msgid "切換區域"
-msgstr "切換區域"
-
-#: ./lib/app/home/_widgets/location_button.dart:144
-msgid "位置設定"
-msgstr "位置設定"
-
-#: ./lib/app/home/_widgets/location_button.dart:195
-msgid "快速切換"
-msgstr "快速切換"
-
-#: ./lib/app/home/_widgets/location_button.dart:240
+#: ./lib/app/home_old/_widgets/location_button.dart:211
msgid "選擇縣市"
msgstr "選擇縣市"
-#: ./lib/app/home/_widgets/location_button.dart:250
+#: ./lib/app/home_old/_widgets/location_button.dart:221
msgid "目前選擇"
msgstr "目前選擇"
-#: ./lib/app/home/page.dart:888
+#: ./lib/app/home_old/_widgets/location_button.dart:279
+msgid "切換區域"
+msgstr "切換區域"
+
+#: ./lib/app/home_old/_widgets/location_button.dart:285
+msgid "位置設定"
+msgstr "位置設定"
+
+#: ./lib/app/home_old/page.dart:630
msgid "濕度"
msgstr "濕度"
-#: ./lib/app/home/page.dart:916
+#: ./lib/app/home_old/page.dart:658
msgid "風速"
msgstr "風速"
-#: ./lib/app/home/_widgets/weather_header.dart:181
+#: ./lib/app/home_old/_widgets/weather_header.dart:199
msgid "風向"
msgstr "風向"
-#: ./lib/app/home/_widgets/weather_header.dart:190
+#: ./lib/app/home_old/_widgets/weather_header.dart:206
msgid "風級"
msgstr "風級"
-#: ./lib/app/home/page.dart:895
+#: ./lib/app/home_old/page.dart:637
msgid "氣壓"
msgstr "氣壓"
-#: ./lib/app/home/page.dart:902
+#: ./lib/app/home_old/page.dart:644
msgid "降雨"
msgstr "降雨"
-#: ./lib/app/home/page.dart:909
+#: ./lib/app/home_old/page.dart:651
msgid "能見度"
msgstr "能見度"
-#: ./lib/app/home/page.dart:923
+#: ./lib/app/home_old/page.dart:665
msgid "陣風"
msgstr "陣風"
-#: ./lib/app/home/_widgets/weather_header.dart:233
+#: ./lib/app/home_old/_widgets/weather_header.dart:243
msgid "陣風級"
msgstr "陣風級"
-#: ./lib/app/home/_widgets/weather_header.dart:241
+#: ./lib/app/home_old/_widgets/weather_header.dart:251
msgid "日照"
msgstr "日照"
-#: ./lib/app/home/_widgets/hero_weather.dart:142
+#: ./lib/app/home_old/_widgets/hero_weather.dart:151
msgid "體感 {feelsLike}°"
msgstr "體感 {feelsLike}°"
-#: ./lib/app/home/_widgets/hero_weather.dart:185
+#: ./lib/app/home_old/_widgets/hero_weather.dart:194
msgid "無天氣資料"
msgstr "無天氣資料"
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:14
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:32
msgid "全國 · 生效中"
msgstr "全國 · 生效中"
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:16
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:34
msgid "全國 · 歷史"
msgstr "全國 · 歷史"
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:18
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:36
msgid "所在地 · 生效中"
msgstr "所在地 · 生效中"
-#: ./lib/app/home/_widgets/mode_toggle_button.dart:20
+#: ./lib/app/home_old/_widgets/mode_toggle_button.dart:38
msgid "所在地 · 歷史"
msgstr "所在地 · 歷史"
-#: ./lib/app/map/_lib/managers/monitor.dart:1258
+#: ./lib/app/map/_lib/managers/monitor.dart:1274
msgid "EEW"
msgstr "EEW"
-#: ./lib/app/map/_lib/managers/monitor.dart:1397
+#: ./lib/app/map/_lib/managers/monitor.dart:1407
msgid "第 {serial} 報"
msgstr "第 {serial} 報"
-#: ./lib/app/map/_lib/managers/monitor.dart:1415
+#: ./lib/app/map/_lib/managers/monitor.dart:1425
msgid ""
"{time} 左右,{location}附近發生有感地震,預估規模 "
"M{magnitude}、所在地最大震度{intensity}。"
@@ -971,7 +1133,7 @@ msgstr ""
"{time} 左右,{location}附近發生有感地震,預估規模 "
"M{magnitude}、所在地最大震度{intensity}。"
-#: ./lib/app/map/_lib/managers/monitor.dart:1423
+#: ./lib/app/map/_lib/managers/monitor.dart:1433
msgid ""
"{time} 左右,{location}附近發生有感地震,預估規模 "
"M{magnitude}、深度{depth}公里。"
@@ -979,453 +1141,319 @@ msgstr ""
"{time} 左右,{location}附近發生有感地震,預估規模 "
"M{magnitude}、深度{depth}公里。"
-#: ./lib/app/map/_lib/managers/monitor.dart:1469
+#: ./lib/app/map/_lib/managers/monitor.dart:1479
msgid "所在地預估"
msgstr "所在地預估"
-#: ./lib/app/map/_lib/managers/monitor.dart:1505
+#: ./lib/app/map/_lib/managers/monitor.dart:1515
msgid "震波"
msgstr "震波"
-#: ./lib/app/map/_lib/managers/monitor.dart:1527
+#: ./lib/app/map/_lib/managers/monitor.dart:1535
msgid " 秒"
msgstr " 秒"
-#: ./lib/app/map/_lib/managers/monitor.dart:1544
+#: ./lib/app/map/_lib/managers/monitor.dart:1551
msgid "抵達"
msgstr "抵達"
-#: ./lib/app/home/page.dart:195
+#: ./lib/app/home_old/page.dart:158
msgid "已更新至 {version}"
msgstr "已更新至 {version}"
-#: ./lib/utils/weather_icon.dart:284
+#: ./lib/utils/weather_icon.dart:282
msgid "取得天氣異常"
msgstr "取得天氣異常"
-#: ./lib/app/home/page.dart:366
+#: ./lib/app/home_old/page.dart:331
msgid "取得歷史資訊異常"
msgstr "取得歷史資訊異常"
-#: ./lib/app/home/page.dart:777
+#: ./lib/app/home_old/page.dart:571
msgid "上午"
msgstr "上午"
-#: ./lib/app/home/page.dart:777
+#: ./lib/app/home_old/page.dart:571
msgid "下午"
msgstr "下午"
-#: ./lib/app/changelog/page.dart:76
-msgid "發生錯誤"
-msgstr "發生錯誤"
-
-#: ./lib/route/image_viewer/image_viewer.dart:85
-msgid "再試一次"
-msgstr "再試一次"
-
-#: ./lib/app/changelog/page.dart:203
-msgid "目前版本"
-msgstr "目前版本"
-
-#: ./lib/app/welcome/4-permissions/page.dart:403
-msgid "下一步"
-msgstr "下一步"
-
-#: ./lib/app/welcome/1-about/page.dart:68
-msgid "防災資訊平台"
-msgstr "防災資訊平台"
-
-#: ./lib/app/welcome/2-exptech/page.dart:93
-msgid "我們是誰?"
-msgstr "我們是誰?"
-
-#: ./lib/app/welcome/2-exptech/page.dart:100
-msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
-msgstr "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。"
-
-#: ./lib/app/welcome/2-exptech/page.dart:106
-msgid "我們的初衷"
-msgstr "我們的初衷"
-
-#: ./lib/app/welcome/2-exptech/page.dart:113
-msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
-msgstr "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。"
-
-#: ./lib/app/welcome/3-notice/page.dart:45
-msgid "注意事項"
-msgstr "注意事項"
-
-#: ./lib/app/welcome/3-notice/page.dart:65
-msgid "任何資訊應以中央氣象署發布之內容為準。"
-msgstr "任何資訊應以中央氣象署發布之內容為準。"
-
-#: ./lib/app/welcome/3-notice/page.dart:82
-msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
-msgstr "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。"
-
-#: ./lib/app/welcome/3-notice/page.dart:97
-msgid "強烈搖晃有機率比通知早抵達使用者所在地。"
-msgstr "強烈搖晃有機率比通知早抵達使用者所在地。"
-
-#: ./lib/app/welcome/3-notice/page.dart:111
-msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
-msgstr "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。"
-
-#: ./lib/app/welcome/3-notice/page.dart:125
-msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
-msgstr "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。"
-
-#: ./lib/app/welcome/1-about/page.dart:46
-msgid "歡迎使用 DPIP"
-msgstr "歡迎使用 DPIP"
-
-#: ./lib/app/welcome/1-about/page.dart:91
-msgid ""
-"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
-"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
-msgstr ""
-"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) "
-"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。"
-
-#: ./lib/app/welcome/4-permissions/page.dart:167
-msgid "在重大災害發生時以通知來傳遞即時防災資訊"
-msgstr "在重大災害發生時以通知來傳遞即時防災資訊"
-
-#: ./lib/app/welcome/4-permissions/page.dart:175
-msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
-msgstr "使用定位來自動更新所在地設定,提供當地的即時防災資訊"
-
-#: ./lib/app/welcome/4-permissions/page.dart:181
-msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
-msgstr "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。"
-
-#: ./lib/route/image_viewer/image_viewer.dart:255
-msgid "儲存"
-msgstr "儲存"
-
-#: ./lib/app/welcome/4-permissions/page.dart:188
-msgid "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
-msgstr "用於儲存中央氣象署或 ExpTech 提供之資料視覺化圖片"
-
-#: ./lib/app/welcome/4-permissions/page.dart:352
-msgid "權限請求"
-msgstr "權限請求"
-
-#: ./lib/app/welcome/4-permissions/page.dart:353
-msgid "需要使用者手動到設定開啟相關權限。"
-msgstr "需要使用者手動到設定開啟相關權限。"
-
-#: ./lib/app/welcome/4-permissions/page.dart:376
-msgid "需要背景位置權限"
-msgstr "需要背景位置權限"
-
-#: ./lib/app/welcome/4-permissions/page.dart:378
-msgid ""
-"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
-"\n"
-"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
-msgstr ""
-"為了在背景持續提供即時防災資訊,DPIP 需要「永遠允許」位置權限。\n"
-"\n"
-"接下來系統會引導您到設定頁面,請選擇「永遠允許」選項。"
-
-#: ./lib/app/welcome/4-permissions/page.dart:384
-msgid "稍後"
-msgstr "稍後"
-
-#: ./lib/app/welcome/4-permissions/page.dart:388
-msgid "前往設定"
-msgstr "前往設定"
-
-#: ./lib/app/welcome/4-permissions/page.dart:426
-msgid "權限"
-msgstr "權限"
-
-#: ./lib/app/welcome/4-permissions/page.dart:439
-msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
-msgstr "我們一直和使用者站在一起,為使用者的隱私而不斷努力。"
-
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:84
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:96
msgid "地圖圖層"
msgstr "地圖圖層"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:85
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:97
msgid "選擇要顯示的地圖圖層"
msgstr "選擇要顯示的地圖圖層"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:91
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:103
msgid "底圖"
msgstr "底圖"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:97
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:109
msgid "簡單"
msgstr "簡單"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:119
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131
msgid "監視器"
msgstr "監視器"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:124
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:136
msgid "報告"
msgstr "報告"
-#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:135
+#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:147
msgid "氣象"
msgstr "氣象"
-#: ./lib/app/map/_lib/managers/temperature.dart:453
+#: ./lib/app/map/_lib/managers/temperature.dart:480
msgid "氣溫"
msgstr "氣溫"
-#: ./lib/app/map/_lib/managers/precipitation.dart:577
+#: ./lib/app/map/_lib/managers/precipitation.dart:587
msgid "降水"
msgstr "降水"
-#: ./lib/app/map/_lib/managers/wind.dart:320
-msgid "風向/風速"
-msgstr "風向/風速"
-
-#: ./lib/app/map/_lib/managers/lightning.dart:294
+#: ./lib/app/map/_lib/managers/lightning.dart:302
msgid "閃電"
msgstr "閃電"
-#: ./lib/app/map/_widgets/map_legend.dart:202
+#: ./lib/app/map/_widgets/map_legend.dart:250
msgid "單位:{unit}"
msgstr "單位:{unit}"
-#: ./lib/app/map/_lib/managers/tsunami.dart:485
+#: ./lib/app/map/_lib/managers/tsunami.dart:494
msgid "近期無海嘯資訊"
msgstr "近期無海嘯資訊"
-#: ./lib/app/map/_lib/managers/tsunami.dart:486
+#: ./lib/app/map/_lib/managers/tsunami.dart:494
msgid "海嘯警報"
msgstr "海嘯警報"
-#: ./lib/app/map/_lib/managers/tsunami.dart:496
+#: ./lib/app/map/_lib/managers/tsunami.dart:504
msgid "{id}號 第{serial}報"
msgstr "{id}號 第{serial}報"
-#: ./lib/app/map/_lib/managers/tsunami.dart:551
+#: ./lib/app/map/_lib/managers/tsunami.dart:558
msgid "發布"
msgstr "發布"
-#: ./lib/app/map/_lib/managers/tsunami.dart:553
+#: ./lib/app/map/_lib/managers/tsunami.dart:560
msgid "更新"
msgstr "更新"
-#: ./lib/app/map/_lib/managers/tsunami.dart:554
+#: ./lib/app/map/_lib/managers/tsunami.dart:561
msgid "解除"
msgstr "解除"
-#: ./lib/app/map/_lib/managers/tsunami.dart:607
+#: ./lib/app/map/_lib/managers/tsunami.dart:612
msgid "預估海嘯到達時間及波高"
msgstr "預估海嘯到達時間及波高"
-#: ./lib/app/map/_lib/managers/tsunami.dart:626
+#: ./lib/app/map/_lib/managers/tsunami.dart:630
msgid "各地觀測到的海嘯"
msgstr "各地觀測到的海嘯"
-#: ./lib/app/map/_lib/managers/tsunami.dart:641
+#: ./lib/app/map/_lib/managers/tsunami.dart:645
msgid "地震資訊"
msgstr "地震資訊"
-#: ./lib/app/map/_lib/managers/tsunami.dart:654
+#: ./lib/app/map/_lib/managers/tsunami.dart:657
msgid "發生時間"
msgstr "發生時間"
-#: ./lib/app/map/_lib/managers/report.dart:1072
+#: ./lib/app/map/_lib/managers/report.dart:1069
msgid "位於"
msgstr "位於"
-#: ./lib/app/map/_lib/managers/tsunami.dart:736
+#: ./lib/app/map/_lib/managers/tsunami.dart:730
msgid "規模"
msgstr "規模"
-#: ./lib/app/map/_lib/managers/tsunami.dart:765
+#: ./lib/app/map/_lib/managers/tsunami.dart:753
msgid "深度"
msgstr "深度"
-#: ./lib/app/map/_lib/managers/radar.dart:744
+#: ./lib/app/map/_lib/managers/radar.dart:750
msgid "長按設定播放起點"
msgstr "長按設定播放起點"
-#: ./lib/app/map/_lib/managers/radar.dart:760
+#: ./lib/app/map/_lib/managers/radar.dart:766
msgid "目前時間"
msgstr "目前時間"
-#: ./lib/app/map/_lib/managers/radar.dart:765
+#: ./lib/app/map/_lib/managers/radar.dart:771
msgid "播放起點"
msgstr "播放起點"
-#: ./lib/app/map/_lib/managers/radar.dart:1099
+#: ./lib/app/map/_lib/managers/radar.dart:1100
msgid "播放進度"
msgstr "播放進度"
-#: ./lib/app/map/_lib/managers/lightning.dart:393
+#: ./lib/app/map/_lib/managers/lightning.dart:399
msgid "5 分鐘內對地閃電"
msgstr "5 分鐘內對地閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:401
+#: ./lib/app/map/_lib/managers/lightning.dart:407
msgid "10 分鐘內對地閃電"
msgstr "10 分鐘內對地閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:409
+#: ./lib/app/map/_lib/managers/lightning.dart:415
msgid "30 分鐘內對地閃電"
msgstr "30 分鐘內對地閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:417
+#: ./lib/app/map/_lib/managers/lightning.dart:423
msgid "60 分鐘內對地閃電"
msgstr "60 分鐘內對地閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:425
+#: ./lib/app/map/_lib/managers/lightning.dart:431
msgid "5 分鐘內雲間閃電"
msgstr "5 分鐘內雲間閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:433
+#: ./lib/app/map/_lib/managers/lightning.dart:439
msgid "10 分鐘內雲間閃電"
msgstr "10 分鐘內雲間閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:441
+#: ./lib/app/map/_lib/managers/lightning.dart:447
msgid "30 分鐘內雲間閃電"
msgstr "30 分鐘內雲間閃電"
-#: ./lib/app/map/_lib/managers/lightning.dart:449
+#: ./lib/app/map/_lib/managers/lightning.dart:455
msgid "60 分鐘內雲間閃電"
msgstr "60 分鐘內雲間閃電"
-#: ./lib/app/map/_lib/managers/precipitation.dart:396
+#: ./lib/app/map/_lib/managers/precipitation.dart:420
msgid "今日"
msgstr "今日"
-#: ./lib/app/map/_lib/managers/precipitation.dart:397
+#: ./lib/app/map/_lib/managers/precipitation.dart:421
msgid "10 分鐘"
msgstr "10 分鐘"
-#: ./lib/app/map/_lib/managers/precipitation.dart:398
+#: ./lib/app/map/_lib/managers/precipitation.dart:422
msgid "1 小時"
msgstr "1 小時"
-#: ./lib/app/map/_lib/managers/precipitation.dart:399
+#: ./lib/app/map/_lib/managers/precipitation.dart:423
msgid "3 小時"
msgstr "3 小時"
-#: ./lib/app/map/_lib/managers/precipitation.dart:400
+#: ./lib/app/map/_lib/managers/precipitation.dart:424
msgid "6 小時"
msgstr "6 小時"
-#: ./lib/app/map/_lib/managers/precipitation.dart:401
+#: ./lib/app/map/_lib/managers/precipitation.dart:425
msgid "12 小時"
msgstr "12 小時"
-#: ./lib/app/map/_lib/managers/precipitation.dart:402
+#: ./lib/app/map/_lib/managers/precipitation.dart:426
msgid "24 小時"
msgstr "24 小時"
-#: ./lib/app/map/_lib/managers/precipitation.dart:403
+#: ./lib/app/map/_lib/managers/precipitation.dart:427
msgid "2 天"
msgstr "2 天"
-#: ./lib/app/map/_lib/managers/precipitation.dart:404
+#: ./lib/app/map/_lib/managers/precipitation.dart:428
msgid "3 天"
msgstr "3 天"
-#: ./lib/app/map/_lib/managers/monitor.dart:474
+#: ./lib/app/map/_lib/managers/monitor.dart:495
msgid "海外測站"
msgstr "海外測站"
-#: ./lib/app/map/_lib/managers/monitor.dart:494
+#: ./lib/app/map/_lib/managers/monitor.dart:515
msgid "即時震度:"
msgstr "即時震度:"
-#: ./lib/app/map/_lib/managers/monitor.dart:517
+#: ./lib/app/map/_lib/managers/monitor.dart:538
msgid "地動加速度:"
msgstr "地動加速度:"
-#: ./lib/app/map/_lib/managers/monitor.dart:541
+#: ./lib/app/map/_lib/managers/monitor.dart:562
msgid "地動速度:"
msgstr "地動速度:"
-#: ./lib/app/map/_lib/managers/monitor.dart:1331
+#: ./lib/app/map/_lib/managers/monitor.dart:1346
msgid "規模 M{magnitude},所在地預估{intensity}"
msgstr "規模 M{magnitude},所在地預估{intensity}"
-#: ./lib/app/map/_lib/managers/monitor.dart:1349
+#: ./lib/app/map/_lib/managers/monitor.dart:1362
msgid "{countdown}秒後抵達"
msgstr "{countdown}秒後抵達"
-#: ./lib/app/map/_lib/managers/monitor.dart:1352
+#: ./lib/app/map/_lib/managers/monitor.dart:1365
msgid "已抵達"
msgstr "已抵達"
-#: ./lib/app/map/_lib/managers/monitor.dart:1364
+#: ./lib/app/map/_lib/managers/monitor.dart:1376
msgid "規模 M{magnitude},深度{depth}公里"
msgstr "規模 M{magnitude},深度{depth}公里"
-#: ./lib/app/map/_lib/managers/monitor.dart:1591
+#: ./lib/app/map/_lib/managers/monitor.dart:1594
msgid "目前沒有生效中的地震速報"
msgstr "目前沒有生效中的地震速報"
-#: ./lib/app/map/_lib/managers/report.dart:516
+#: ./lib/app/map/_lib/managers/report.dart:541
msgid "CWA 正在製圖中"
msgstr "CWA 正在製圖中"
-#: ./lib/app/map/_lib/managers/report.dart:639
+#: ./lib/app/map/_lib/managers/report.dart:660
msgid "近期的地震報告"
msgstr "近期的地震報告"
-#: ./lib/app/map/_lib/managers/report.dart:647
+#: ./lib/app/map/_lib/managers/report.dart:667
msgid "更多"
msgstr "更多"
-#: ./lib/app/map/_lib/managers/report.dart:995
+#: ./lib/app/map/_lib/managers/report.dart:994
msgid "編號 {number} 顯著有感地震"
msgstr "編號 {number} 顯著有感地震"
-#: ./lib/app/map/_lib/managers/report.dart:998
+#: ./lib/app/map/_lib/managers/report.dart:997
msgid "小區域有感地震"
msgstr "小區域有感地震"
-#: ./lib/app/map/_lib/managers/report.dart:1083
+#: ./lib/app/map/_lib/managers/report.dart:1080
msgid "地震規模"
msgstr "地震規模"
-#: ./lib/app/map/_lib/managers/report.dart:1110
+#: ./lib/app/map/_lib/managers/report.dart:1107
msgid "震源深度"
msgstr "震源深度"
-#: ./lib/app/map/_lib/managers/report.dart:886
+#: ./lib/app/map/_lib/managers/report.dart:893
msgid "沒有更多資料"
msgstr "沒有更多資料"
-#: ./lib/app/map/_lib/managers/report.dart:1030
+#: ./lib/app/map/_lib/managers/report.dart:1029
msgid "報告頁面"
msgstr "報告頁面"
-#: ./lib/route/report/report_sheet_content.dart:90
+#: ./lib/route/report/report_sheet_content.dart:88
msgid "重播"
msgstr "重播"
-#: ./lib/app/map/_lib/managers/report.dart:1064
+#: ./lib/app/map/_lib/managers/report.dart:1061
msgid "發震時間"
msgstr "發震時間"
-#: ./lib/app/map/_lib/managers/report.dart:1132
+#: ./lib/app/map/_lib/managers/report.dart:1129
msgid "各地震度"
msgstr "各地震度"
-#: ./lib/app/map/_lib/managers/report.dart:1212
+#: ./lib/app/map/_lib/managers/report.dart:1205
msgid "地震報告圖"
msgstr "地震報告圖"
-#: ./lib/app/map/_lib/managers/report.dart:1228
+#: ./lib/app/map/_lib/managers/report.dart:1220
msgid "震度圖"
msgstr "震度圖"
-#: ./lib/app/map/_lib/managers/report.dart:1248
+#: ./lib/app/map/_lib/managers/report.dart:1240
msgid "最大地動加速度圖"
msgstr "最大地動加速度圖"
-#: ./lib/app/map/_lib/managers/report.dart:1268
+#: ./lib/app/map/_lib/managers/report.dart:1260
msgid "最大地動速度圖"
msgstr "最大地動速度圖"
@@ -1477,11 +1505,11 @@ msgstr "氣象相關"
msgid "未知"
msgstr "未知"
-#: ./lib/route/announcement/announcement.dart:105
+#: ./lib/route/announcement/announcement.dart:104
msgid "目前沒有公告"
msgstr "目前沒有公告"
-#: ./lib/route/announcement/announcement.dart:246
+#: ./lib/route/announcement/announcement.dart:245
msgid "公告詳情"
msgstr "公告詳情"
@@ -1497,302 +1525,302 @@ msgstr "已儲存圖片"
msgid "儲存圖片時發生錯誤"
msgstr "儲存圖片時發生錯誤"
-#: ./lib/utils/extensions/number.dart:26
+#: ./lib/utils/extensions/number.dart:25
msgid "0級"
msgstr "0級"
-#: ./lib/utils/extensions/number.dart:27
+#: ./lib/utils/extensions/number.dart:26
msgid "1級"
msgstr "1級"
-#: ./lib/utils/extensions/number.dart:28
+#: ./lib/utils/extensions/number.dart:27
msgid "2級"
msgstr "2級"
-#: ./lib/utils/extensions/number.dart:29
+#: ./lib/utils/extensions/number.dart:28
msgid "3級"
msgstr "3級"
-#: ./lib/utils/extensions/number.dart:30
+#: ./lib/utils/extensions/number.dart:29
msgid "4級"
msgstr "4級"
-#: ./lib/utils/extensions/number.dart:31
+#: ./lib/utils/extensions/number.dart:30
msgid "5弱"
msgstr "5弱"
-#: ./lib/utils/extensions/number.dart:32
+#: ./lib/utils/extensions/number.dart:31
msgid "5強"
msgstr "5強"
-#: ./lib/utils/extensions/number.dart:33
+#: ./lib/utils/extensions/number.dart:32
msgid "6弱"
msgstr "6弱"
-#: ./lib/utils/extensions/number.dart:34
+#: ./lib/utils/extensions/number.dart:33
msgid "6強"
msgstr "6強"
-#: ./lib/utils/extensions/number.dart:35
+#: ./lib/utils/extensions/number.dart:34
msgid "7級"
msgstr "7級"
-#: ./lib/utils/weather_icon.dart:285
+#: ./lib/utils/weather_icon.dart:283
msgid "晴"
msgstr "晴"
-#: ./lib/utils/weather_icon.dart:286
+#: ./lib/utils/weather_icon.dart:284
msgid "晴有霾"
msgstr "晴有霾"
-#: ./lib/utils/weather_icon.dart:287
+#: ./lib/utils/weather_icon.dart:285
msgid "晴有靄"
msgstr "晴有靄"
-#: ./lib/utils/weather_icon.dart:288
+#: ./lib/utils/weather_icon.dart:286
msgid "晴有閃電"
msgstr "晴有閃電"
-#: ./lib/utils/weather_icon.dart:304
+#: ./lib/utils/weather_icon.dart:302
msgid "晴天伴有雷"
msgstr "晴天伴有雷"
-#: ./lib/utils/weather_icon.dart:290
+#: ./lib/utils/weather_icon.dart:288
msgid "晴有霧"
msgstr "晴有霧"
-#: ./lib/utils/weather_icon.dart:291
+#: ./lib/utils/weather_icon.dart:289
msgid "晴有雨"
msgstr "晴有雨"
-#: ./lib/utils/weather_icon.dart:292
+#: ./lib/utils/weather_icon.dart:290
msgid "晴有雨雪"
msgstr "晴有雨雪"
-#: ./lib/utils/weather_icon.dart:293
+#: ./lib/utils/weather_icon.dart:291
msgid "晴有大雪"
msgstr "晴有大雪"
-#: ./lib/utils/weather_icon.dart:294
+#: ./lib/utils/weather_icon.dart:292
msgid "晴有雪珠"
msgstr "晴有雪珠"
-#: ./lib/utils/weather_icon.dart:295
+#: ./lib/utils/weather_icon.dart:293
msgid "晴有冰珠"
msgstr "晴有冰珠"
-#: ./lib/utils/weather_icon.dart:296
+#: ./lib/utils/weather_icon.dart:294
msgid "晴有陣雪"
msgstr "晴有陣雪"
-#: ./lib/utils/weather_icon.dart:297
+#: ./lib/utils/weather_icon.dart:295
msgid "晴陣雨雪"
msgstr "晴陣雨雪"
-#: ./lib/utils/weather_icon.dart:298
+#: ./lib/utils/weather_icon.dart:296
msgid "晴有雹"
msgstr "晴有雹"
-#: ./lib/utils/weather_icon.dart:299
+#: ./lib/utils/weather_icon.dart:297
msgid "晴有雷雨"
msgstr "晴有雷雨"
-#: ./lib/utils/weather_icon.dart:300
+#: ./lib/utils/weather_icon.dart:298
msgid "晴有雷雪"
msgstr "晴有雷雪"
-#: ./lib/utils/weather_icon.dart:301
+#: ./lib/utils/weather_icon.dart:299
msgid "晴有雷雹"
msgstr "晴有雷雹"
-#: ./lib/utils/weather_icon.dart:302
+#: ./lib/utils/weather_icon.dart:300
msgid "晴大雷雨"
msgstr "晴大雷雨"
-#: ./lib/utils/weather_icon.dart:303
+#: ./lib/utils/weather_icon.dart:301
msgid "晴大雷雹"
msgstr "晴大雷雹"
-#: ./lib/utils/weather_icon.dart:305
+#: ./lib/utils/weather_icon.dart:303
msgid "多雲"
msgstr "多雲"
-#: ./lib/utils/weather_icon.dart:306
+#: ./lib/utils/weather_icon.dart:304
msgid "多雲有霾"
msgstr "多雲有霾"
-#: ./lib/utils/weather_icon.dart:307
+#: ./lib/utils/weather_icon.dart:305
msgid "多雲有靄"
msgstr "多雲有靄"
-#: ./lib/utils/weather_icon.dart:308
+#: ./lib/utils/weather_icon.dart:306
msgid "多雲有閃電"
msgstr "多雲有閃電"
-#: ./lib/utils/weather_icon.dart:324
+#: ./lib/utils/weather_icon.dart:322
msgid "多雲伴有雷"
msgstr "多雲伴有雷"
-#: ./lib/utils/weather_icon.dart:310
+#: ./lib/utils/weather_icon.dart:308
msgid "多雲有霧"
msgstr "多雲有霧"
-#: ./lib/utils/weather_icon.dart:311
+#: ./lib/utils/weather_icon.dart:309
msgid "多雲有雨"
msgstr "多雲有雨"
-#: ./lib/utils/weather_icon.dart:312
+#: ./lib/utils/weather_icon.dart:310
msgid "多雲有雨雪"
msgstr "多雲有雨雪"
-#: ./lib/utils/weather_icon.dart:313
+#: ./lib/utils/weather_icon.dart:311
msgid "多雲有大雪"
msgstr "多雲有大雪"
-#: ./lib/utils/weather_icon.dart:314
+#: ./lib/utils/weather_icon.dart:312
msgid "多雲有雪珠"
msgstr "多雲有雪珠"
-#: ./lib/utils/weather_icon.dart:315
+#: ./lib/utils/weather_icon.dart:313
msgid "多雲有冰珠"
msgstr "多雲有冰珠"
-#: ./lib/utils/weather_icon.dart:316
+#: ./lib/utils/weather_icon.dart:314
msgid "多雲有陣雪"
msgstr "多雲有陣雪"
-#: ./lib/utils/weather_icon.dart:317
+#: ./lib/utils/weather_icon.dart:315
msgid "多雲陣雨雪"
msgstr "多雲陣雨雪"
-#: ./lib/utils/weather_icon.dart:318
+#: ./lib/utils/weather_icon.dart:316
msgid "多雲有雹"
msgstr "多雲有雹"
-#: ./lib/utils/weather_icon.dart:319
+#: ./lib/utils/weather_icon.dart:317
msgid "多雲有雷雨"
msgstr "多雲有雷雨"
-#: ./lib/utils/weather_icon.dart:320
+#: ./lib/utils/weather_icon.dart:318
msgid "多雲有雷雪"
msgstr "多雲有雷雪"
-#: ./lib/utils/weather_icon.dart:321
+#: ./lib/utils/weather_icon.dart:319
msgid "多雲有雷雹"
msgstr "多雲有雷雹"
-#: ./lib/utils/weather_icon.dart:322
+#: ./lib/utils/weather_icon.dart:320
msgid "多雲大雷雨"
msgstr "多雲大雷雨"
-#: ./lib/utils/weather_icon.dart:323
+#: ./lib/utils/weather_icon.dart:321
msgid "多雲大雷雹"
msgstr "多雲大雷雹"
-#: ./lib/utils/weather_icon.dart:325
+#: ./lib/utils/weather_icon.dart:323
msgid "陰"
msgstr "陰"
-#: ./lib/utils/weather_icon.dart:326
+#: ./lib/utils/weather_icon.dart:324
msgid "陰有霾"
msgstr "陰有霾"
-#: ./lib/utils/weather_icon.dart:327
+#: ./lib/utils/weather_icon.dart:325
msgid "陰有靄"
msgstr "陰有靄"
-#: ./lib/utils/weather_icon.dart:328
+#: ./lib/utils/weather_icon.dart:326
msgid "陰有閃電"
msgstr "陰有閃電"
-#: ./lib/utils/weather_icon.dart:344
+#: ./lib/utils/weather_icon.dart:342
msgid "陰天伴有雷"
msgstr "陰天伴有雷"
-#: ./lib/utils/weather_icon.dart:330
+#: ./lib/utils/weather_icon.dart:328
msgid "陰有霧"
msgstr "陰有霧"
-#: ./lib/utils/weather_icon.dart:331
+#: ./lib/utils/weather_icon.dart:329
msgid "陰有雨"
msgstr "陰有雨"
-#: ./lib/utils/weather_icon.dart:332
+#: ./lib/utils/weather_icon.dart:330
msgid "陰有雨雪"
msgstr "陰有雨雪"
-#: ./lib/utils/weather_icon.dart:333
+#: ./lib/utils/weather_icon.dart:331
msgid "陰有大雪"
msgstr "陰有大雪"
-#: ./lib/utils/weather_icon.dart:334
+#: ./lib/utils/weather_icon.dart:332
msgid "陰有雪珠"
msgstr "陰有雪珠"
-#: ./lib/utils/weather_icon.dart:335
+#: ./lib/utils/weather_icon.dart:333
msgid "陰有冰珠"
msgstr "陰有冰珠"
-#: ./lib/utils/weather_icon.dart:336
+#: ./lib/utils/weather_icon.dart:334
msgid "陰有陣雪"
msgstr "陰有陣雪"
-#: ./lib/utils/weather_icon.dart:337
+#: ./lib/utils/weather_icon.dart:335
msgid "陰陣雨雪"
msgstr "陰陣雨雪"
-#: ./lib/utils/weather_icon.dart:338
+#: ./lib/utils/weather_icon.dart:336
msgid "陰有雹"
msgstr "陰有雹"
-#: ./lib/utils/weather_icon.dart:339
+#: ./lib/utils/weather_icon.dart:337
msgid "陰有雷雨"
msgstr "陰有雷雨"
-#: ./lib/utils/weather_icon.dart:340
+#: ./lib/utils/weather_icon.dart:338
msgid "陰有雷雪"
msgstr "陰有雷雪"
-#: ./lib/utils/weather_icon.dart:341
+#: ./lib/utils/weather_icon.dart:339
msgid "陰有雷雹"
msgstr "陰有雷雹"
-#: ./lib/utils/weather_icon.dart:342
+#: ./lib/utils/weather_icon.dart:340
msgid "陰大雷雨"
msgstr "陰大雷雨"
-#: ./lib/utils/weather_icon.dart:343
+#: ./lib/utils/weather_icon.dart:341
msgid "陰大雷雹"
msgstr "陰大雷雹"
-#: ./lib/api/model/location/location.dart:85
+#: ./lib/api/model/location/location.dart:84
msgid "{city}{cityLevel} {town}{townLevel}"
msgstr "{city}{cityLevel} {town}{townLevel}"
-#: ./lib/api/model/location/location.dart:98
+#: ./lib/api/model/location/location.dart:97
msgid "{city} {town}"
msgstr "{city} {town}"
-#: ./lib/api/model/location/location.dart:113
+#: ./lib/api/model/location/location.dart:112
msgid "{city}{cityLevel}"
msgstr "{city}{cityLevel}"
-#: ./lib/api/model/location/location.dart:130
+#: ./lib/api/model/location/location.dart:129
msgid "{town}{townLevel}"
msgstr "{town}{townLevel}"
-#: ./lib/widgets/ui/color_picker.dart:363
+#: ./lib/widgets/ui/color_picker.dart:361
msgid "色相"
msgstr "色相"
-#: ./lib/widgets/ui/color_picker.dart:379
+#: ./lib/widgets/ui/color_picker.dart:377
msgid "彩度"
msgstr "彩度"
-#: ./lib/widgets/ui/color_picker.dart:395
+#: ./lib/widgets/ui/color_picker.dart:393
msgid "明度"
msgstr "明度"
-#: ./lib/widgets/ui/color_picker.dart:415
+#: ./lib/widgets/ui/color_picker.dart:413
msgid "十六進位值"
msgstr "十六進位值"
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 407d35693..bcd67660b 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -9,8 +9,6 @@ PODS:
- Flutter
- IosAwnCore (~> 0.10.0)
- IosAwnFcmCore (~> 0.10.1)
- - clipboard (3.0.9):
- - Flutter
- device_info_plus (0.0.1):
- Flutter
- Firebase/CoreOnly (11.15.0):
@@ -168,7 +166,6 @@ PODS:
DEPENDENCIES:
- awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`)
- awesome_notifications_fcm (from `.symlinks/plugins/awesome_notifications_fcm/ios`)
- - clipboard (from `.symlinks/plugins/clipboard/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
@@ -213,8 +210,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/awesome_notifications/ios"
awesome_notifications_fcm:
:path: ".symlinks/plugins/awesome_notifications_fcm/ios"
- clipboard:
- :path: ".symlinks/plugins/clipboard/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
firebase_core:
@@ -255,7 +250,6 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888
awesome_notifications_fcm: ad14f584c81e2488ae4310ab96331327dcbb5368
- clipboard: 85f02e190f24debf05943aff98c26644b2a90245
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
firebase_core: 995454a784ff288be5689b796deb9e9fa3601818
@@ -290,7 +284,7 @@ SPEC CHECKSUMS:
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
- zstandard_ios: b20c54862b56c31c7a47074b79fcf181780268b0
+ zstandard_ios: 09cab18e0ee494020cc24d82a95c5bf4252d240c
PODFILE CHECKSUM: 3d88bce62bfe048ac33ca00d3fb1bc02caeda4d3
diff --git a/lib/api/endpoints/device.dart b/lib/api/endpoints/device.dart
index 3c0245c76..2dac44a95 100644
--- a/lib/api/endpoints/device.dart
+++ b/lib/api/endpoints/device.dart
@@ -50,9 +50,7 @@ mixin DeviceEndpoints {
final res = await _dio.get(
'https://api-1.exptech.dev/api/v2/notify/$token',
);
- return NotifySettings.fromJson(
- (res.data as List).map((e) => e as int).toList(),
- );
+ return NotifySettings.fromJson((res.data as List).cast());
}
/// 設定通知
@@ -78,9 +76,7 @@ mixin DeviceEndpoints {
final res = await _dio.get(
'https://api-1.exptech.dev/api/v2/notify/$token/${channel.index}/${status.index}',
);
- return NotifySettings.fromJson(
- (res.data as List).map((e) => e as int).toList(),
- );
+ return NotifySettings.fromJson((res.data as List).cast());
}
/// Reports network diagnostics to the server.
diff --git a/lib/api/endpoints/earthquake.dart b/lib/api/endpoints/earthquake.dart
index b88f605d7..aba3ecf9d 100644
--- a/lib/api/endpoints/earthquake.dart
+++ b/lib/api/endpoints/earthquake.dart
@@ -63,10 +63,12 @@ mixin EarthquakeEndpoints {
? 'https://api.core.exptech.dev/api/v2/eq/eew/${time ~/ 1000}'
: '${lb}/v2/eq/eew';
final res = await _dio.get(url);
- final eewList = (res.data as List).map(
+ Iterable eewList = (res.data as List).map(
(e) => Eew.fromMap(e as Map),
);
- if (Preference.experimentalEewAllSource == true) return eewList.toList();
- return eewList.where((e) => e.agency == 'cwa').toList();
+ if (Preference.experimental__eewAllSource != true) {
+ eewList = eewList.where((e) => e.agency == 'cwa');
+ }
+ return eewList.toList();
}
}
diff --git a/lib/app.dart b/lib/app.dart
index f265dd5ac..4b013fcec 100644
--- a/lib/app.dart
+++ b/lib/app.dart
@@ -28,6 +28,7 @@ import 'main.dart';
class DpipApp extends StatefulWidget {
/// Creates a new [DpipApp] instance.
final String? initialShortcut;
+
const DpipApp({super.key, this.initialShortcut});
@override
@@ -37,61 +38,49 @@ class DpipApp extends StatefulWidget {
class _DpipAppState extends State with WidgetsBindingObserver {
bool _hasHandledInitialShortcut = false;
- Future _checkUpdate() async {
- if (kDebugMode) return;
-
- try {
- if (Platform.isAndroid) {
- final info = await InAppUpdate.checkForUpdate();
+ Future _checkNotificationPermission() async {
+ if (Platform.isAndroid) return;
+ await fcmReadyCompleter.future;
+ final status = (await FirebaseMessaging.instance.getNotificationSettings()).authorizationStatus;
+ final allowed = status == .authorized || status == .provisional;
- if (info.updateAvailability != UpdateAvailability.updateAvailable) return;
+ if (Preference.isFirstLaunch || allowed) return;
- if (info.immediateUpdateAllowed) {
- InAppUpdate.performImmediateUpdate();
- } else if (info.flexibleUpdateAllowed) {
- final updateResult = await InAppUpdate.startFlexibleUpdate();
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (mounted && router.routerDelegate.navigatorKey.currentContext != null) {
+ const WelcomePermissionsRoute().go(context);
+ }
+ });
+ }
- if (updateResult != AppUpdateResult.success) return;
+ Future _checkUpdate() async {
+ if (kDebugMode || !Platform.isAndroid) return;
- InAppUpdate.completeFlexibleUpdate();
- }
+ try {
+ final info = await InAppUpdate.checkForUpdate();
+ if (info.updateAvailability != UpdateAvailability.updateAvailable) return;
+
+ if (info.immediateUpdateAllowed) {
+ InAppUpdate.performImmediateUpdate();
+ } else if (info.flexibleUpdateAllowed) {
+ final updateResult = await InAppUpdate.startFlexibleUpdate();
+ if (updateResult != AppUpdateResult.success) return;
+ InAppUpdate.completeFlexibleUpdate();
}
} catch (e, s) {
TalkerManager.instance.error('_DpipState._checkUpdate', e, s);
}
}
- Future _checkNotificationPermission() async {
- if (Platform.isAndroid) return;
- await fcmReadyCompleter.future;
- bool notificationAllowed = false;
- final settings = await FirebaseMessaging.instance.getNotificationSettings();
- notificationAllowed =
- settings.authorizationStatus == .authorized || settings.authorizationStatus == .provisional;
-
- if (!Preference.isFirstLaunch && !notificationAllowed) {
- WidgetsBinding.instance.addPostFrameCallback((_) {
- final ctx = router.routerDelegate.navigatorKey.currentContext;
- if (ctx != null && mounted) {
- WelcomePermissionsRoute().go(context);
- }
- });
- }
- }
-
void _tryHandleInitialShortcut() {
if (_hasHandledInitialShortcut) return;
if (widget.initialShortcut == null) return;
-
- final ctx = router.routerDelegate.navigatorKey.currentContext;
- if (ctx == null) return;
+ if (router.routerDelegate.navigatorKey.currentContext == null) return;
_hasHandledInitialShortcut = true;
- switch (widget.initialShortcut) {
- case 'monitor':
- MapRoute(layers: MapLayer.monitor.name).push(context);
- break;
+ if (widget.initialShortcut == 'monitor') {
+ MapRoute(layers: MapLayer.monitor.name).push(context);
}
}
@@ -110,9 +99,10 @@ class _DpipAppState extends State with WidgetsBindingObserver {
_checkNotificationPermission();
WidgetsBinding.instance.addPostFrameCallback((_) {
- Future.delayed(const Duration(milliseconds: 500), () {
- handlePendingNotificationNavigation(context);
- });
+ Future.delayed(
+ const Duration(milliseconds: 500),
+ () => handlePendingNotificationNavigation(context),
+ );
_tryHandleInitialShortcut();
});
}
@@ -130,62 +120,71 @@ class _DpipAppState extends State with WidgetsBindingObserver {
),
);
- ThemeData lightTheme = .new(
- colorSchemeSeed: model.themeColor ?? lightDynamic?.primary,
- brightness: .light,
- snackBarTheme: const .new(behavior: .floating),
- pageTransitionsTheme: kZoomPageTransitionsTheme,
- switchTheme: switchTheme,
- // TODO(kamiya4047): Opt-in to new Material 3 update, remove this after it becomes the default option
- sliderTheme: const .new(year2023: false),
- progressIndicatorTheme: const .new(year2023: false),
- );
- ThemeData darkTheme = .new(
- colorSchemeSeed: model.themeColor ?? darkDynamic?.primary,
- brightness: .dark,
- snackBarTheme: const .new(behavior: .floating),
- pageTransitionsTheme: kZoomPageTransitionsTheme,
- switchTheme: switchTheme,
- // TODO(kamiya4047): Opt-in to new Material 3 update, remove this after it becomes the default option
- sliderTheme: const .new(year2023: false),
- progressIndicatorTheme: const .new(year2023: false),
+ final cardTheme = CardThemeData(
+ shape: RoundedRectangleBorder(borderRadius: .circular(16)),
);
- final fontTextTheme = switch (I18n.locale.toLanguageTag()) {
- 'zh-Hans' => GoogleFonts.notoSansScTextTheme,
- 'ja' => GoogleFonts.notoSansJpTextTheme,
- 'ko' => GoogleFonts.notoSansKrTextTheme,
- 'vi' => GoogleFonts.notoSansTextTheme,
- 'ru' => GoogleFonts.notoSansTextTheme,
- _ => GoogleFonts.notoSansTcTextTheme,
+ final notoFallback = switch (I18n.locale.toLanguageTag()) {
+ 'zh-Hans' => GoogleFonts.notoSansSc().fontFamily!,
+ 'ja' => GoogleFonts.notoSansJp().fontFamily!,
+ 'ko' => GoogleFonts.notoSansKr().fontFamily!,
+ 'vi' || 'ru' => GoogleFonts.notoSans().fontFamily!,
+ _ => GoogleFonts.notoSansTc().fontFamily!,
};
- lightTheme = lightTheme.copyWith(
- textTheme: GoogleFonts.latoTextTheme(
- fontTextTheme(lightTheme.textTheme),
- ),
+ TextStyle applyFlex(TextStyle? base) => (base ?? const TextStyle()).copyWith(
+ fontFamily: 'Google Sans Flex',
+ fontFamilyFallback: [...?base?.fontFamilyFallback, notoFallback],
);
- darkTheme = darkTheme.copyWith(
- textTheme: GoogleFonts.latoTextTheme(
- fontTextTheme(darkTheme.textTheme),
- ),
+
+ TextTheme buildTextTheme(TextTheme base) => base.copyWith(
+ displayLarge: applyFlex(base.displayLarge),
+ displayMedium: applyFlex(base.displayMedium),
+ displaySmall: applyFlex(base.displaySmall),
+ headlineLarge: applyFlex(base.headlineLarge),
+ headlineMedium: applyFlex(base.headlineMedium),
+ headlineSmall: applyFlex(base.headlineSmall),
+ titleLarge: applyFlex(base.titleLarge),
+ titleMedium: applyFlex(base.titleMedium),
+ titleSmall: applyFlex(base.titleSmall),
+ bodyLarge: applyFlex(base.bodyLarge),
+ bodyMedium: applyFlex(base.bodyMedium),
+ bodySmall: applyFlex(base.bodySmall),
+ labelLarge: applyFlex(base.labelLarge),
+ labelMedium: applyFlex(base.labelMedium),
+ labelSmall: applyFlex(base.labelSmall),
);
+ ThemeData buildTheme(Brightness brightness, Color? seed) {
+ final ThemeData base = .new(
+ colorSchemeSeed: seed,
+ brightness: brightness,
+ snackBarTheme: const .new(behavior: .floating),
+ pageTransitionsTheme: kZoomPageTransitionsTheme,
+ cardTheme: cardTheme,
+ switchTheme: switchTheme,
+ // TODO(kamiya4047): Opt-in to new Material 3 update, remove this after it becomes the default option
+ sliderTheme: const .new(year2023: false),
+ progressIndicatorTheme: const .new(year2023: false),
+ );
+ return base.copyWith(textTheme: buildTextTheme(base.textTheme));
+ }
+
+ final seed = model.themeColor;
+
return MaterialApp.router(
builder: (context, child) {
- final mediaQueryData = MediaQuery.of(context);
- final scale = mediaQueryData.textScaler.clamp(
- minScaleFactor: 0.5,
- maxScaleFactor: 1.2,
- );
+ final mq = MediaQuery.of(context);
return MediaQuery(
- data: mediaQueryData.copyWith(textScaler: scale),
+ data: mq.copyWith(
+ textScaler: mq.textScaler.clamp(minScaleFactor: 0.5, maxScaleFactor: 1.2),
+ ),
child: child!,
);
},
title: 'DPIP',
- theme: lightTheme,
- darkTheme: darkTheme,
+ theme: buildTheme(.light, seed ?? lightDynamic?.primary),
+ darkTheme: buildTheme(.dark, seed ?? darkDynamic?.primary),
themeMode: model.themeMode,
localizationsDelegates: I18n.localizationsDelegates,
supportedLocales: I18n.supportedLocales,
diff --git a/lib/app/changelog/_widgets/update_card.dart b/lib/app/changelog/_widgets/update_card.dart
index 772c8977a..ca035b8ca 100644
--- a/lib/app/changelog/_widgets/update_card.dart
+++ b/lib/app/changelog/_widgets/update_card.dart
@@ -30,6 +30,8 @@ class UpdateCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final primary = context.theme.primaryColor;
+ final bodyMedium = context.texts.bodyMedium;
return Card(
elevation: 8,
shape: RoundedRectangleBorder(
@@ -41,10 +43,7 @@ class UpdateCard extends StatelessWidget {
gradient: LinearGradient(
begin: .topLeft,
end: .bottomRight,
- colors: [
- context.theme.primaryColor.withValues(alpha: 0.1),
- context.theme.primaryColor.withValues(alpha: 0.3),
- ],
+ colors: [primary.withValues(alpha: 0.1), primary.withValues(alpha: 0.3)],
),
),
child: Padding(
@@ -58,17 +57,13 @@ class UpdateCard extends StatelessWidget {
children: [
Row(
children: [
- Icon(
- Icons.new_releases,
- size: 28,
- color: context.theme.primaryColor,
- ),
+ Icon(Icons.new_releases, size: 28, color: primary),
const SizedBox(width: 10),
Text(
title,
style: context.texts.titleLarge?.copyWith(
fontWeight: .bold,
- color: context.theme.primaryColor,
+ color: primary,
),
),
],
@@ -76,8 +71,8 @@ class UpdateCard extends StatelessWidget {
const SizedBox(height: 12),
Text(
description,
- style: context.texts.bodyMedium?.copyWith(
- color: context.texts.bodyMedium?.color?.withValues(alpha: 0.8),
+ style: bodyMedium?.copyWith(
+ color: bodyMedium.color?.withValues(alpha: 0.8),
),
),
],
diff --git a/lib/app/changelog/page.dart b/lib/app/changelog/page.dart
index f6c583588..c529953ff 100644
--- a/lib/app/changelog/page.dart
+++ b/lib/app/changelog/page.dart
@@ -36,10 +36,7 @@ class _ChangelogPageState extends State {
Result, String>? releases;
Future _refresh() async {
- if (_refreshIndicatorKey.currentState case final state?) {
- state.show();
- }
-
+ _refreshIndicatorKey.currentState?.show();
final result = await ExpTech().getReleases();
setState(() => releases = result);
}
@@ -181,14 +178,8 @@ class _ReleaseHeaderDelegate extends SliverPersistentHeaderDelegate {
spacing: 16,
children: [
ContainedIcon(
- switch (release.prerelease) {
- true => Symbols.experiment_rounded,
- false => Symbols.package_2_rounded,
- },
- color: switch (release.prerelease) {
- true => Colors.orangeAccent,
- false => Colors.greenAccent,
- },
+ release.prerelease ? Symbols.experiment_rounded : Symbols.package_2_rounded,
+ color: release.prerelease ? Colors.orangeAccent : Colors.greenAccent,
size: 28,
),
Expanded(
diff --git a/lib/app/home/_widgets/date_timeline_item.dart b/lib/app/home/_widgets/date_timeline_item.dart
index 4ed3e2c98..c67cfd09e 100644
--- a/lib/app/home/_widgets/date_timeline_item.dart
+++ b/lib/app/home/_widgets/date_timeline_item.dart
@@ -73,6 +73,7 @@ class DateTimelineItem extends StatelessWidget {
shape: RoundedRectangleBorder(borderRadius: .circular(16)),
elevation: 8,
items: availableModes.map((m) {
+ final isSelected = mode == m;
return PopupMenuItem(
value: m,
child: Row(
@@ -81,13 +82,13 @@ class DateTimelineItem extends StatelessWidget {
Icon(
m.icon,
size: 20,
- color: mode == m ? context.colors.primary : context.colors.onSurfaceVariant,
+ color: isSelected ? context.colors.primary : context.colors.onSurfaceVariant,
),
Text(
m.label,
style: context.texts.bodyMedium?.copyWith(
- color: mode == m ? context.colors.primary : context.colors.onSurface,
- fontWeight: mode == m ? .bold : .normal,
+ color: isSelected ? context.colors.primary : context.colors.onSurface,
+ fontWeight: isSelected ? .bold : .normal,
),
),
],
diff --git a/lib/app/home/_widgets/eew_card.dart b/lib/app/home/_widgets/eew_card.dart
index 46f459b63..2a7b92027 100644
--- a/lib/app/home/_widgets/eew_card.dart
+++ b/lib/app/home/_widgets/eew_card.dart
@@ -45,6 +45,22 @@ class _EewCardState extends State {
Timer? _timer;
+ String _buildAlertText() {
+ final info = widget.data.info;
+ final commonArgs = {
+ 'time': info.time.toSimpleDateTimeString(),
+ 'location': info.location,
+ 'magnitude': info.magnitude.toStringAsFixed(1),
+ };
+ return localIntensity != null
+ ? '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。'
+ .i18n
+ .args({...commonArgs, 'intensity': localIntensity!.asIntensityLabel})
+ : '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。'
+ .i18n
+ .args({...commonArgs, 'depth': info.depth.toStringAsFixed(1)});
+ }
+
void _updateCountdown() {
if (localArrivalTime == null) return;
@@ -152,23 +168,7 @@ class _EewCardState extends State {
Padding(
padding: const .only(top: 8),
child: StyledText(
- text: localIntensity != null
- ? '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。'
- .i18n
- .args({
- 'time': widget.data.info.time.toSimpleDateTimeString(),
- 'location': widget.data.info.location,
- 'magnitude': widget.data.info.magnitude.toStringAsFixed(1),
- 'intensity': localIntensity!.asIntensityLabel,
- })
- : '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。'
- .i18n
- .args({
- 'time': widget.data.info.time.toSimpleDateTimeString(),
- 'location': widget.data.info.location,
- 'magnitude': widget.data.info.magnitude.toStringAsFixed(1),
- 'depth': widget.data.info.depth.toStringAsFixed(1),
- }),
+ text: _buildAlertText(),
style: context.texts.bodyLarge!.copyWith(
color: context.colors.onErrorContainer,
),
diff --git a/lib/app/home/_widgets/hero_weather.dart b/lib/app/home/_widgets/hero_weather.dart
index c2dddd6e3..cfd6a5357 100644
--- a/lib/app/home/_widgets/hero_weather.dart
+++ b/lib/app/home/_widgets/hero_weather.dart
@@ -120,7 +120,7 @@ class HeroWeather extends StatelessWidget {
Icon(
_getWeatherIcon(data.weatherCode),
size: 24,
- color: Colors.white.withValues(alpha: 1),
+ color: Colors.white,
shadows: [
Shadow(
color: Colors.black.withValues(alpha: 0.3),
@@ -133,7 +133,7 @@ class HeroWeather extends StatelessWidget {
Text(
data.weather,
style: context.texts.titleMedium?.copyWith(
- color: Colors.white.withValues(alpha: 1),
+ color: Colors.white,
fontWeight: .w400,
shadows: [
Shadow(
@@ -152,7 +152,7 @@ class HeroWeather extends StatelessWidget {
'feelsLike': feelsLike.round(),
}),
style: context.texts.bodyMedium?.copyWith(
- color: Colors.white.withValues(alpha: 1),
+ color: Colors.white,
shadows: [
Shadow(
color: Colors.black.withValues(alpha: 0.3),
@@ -203,16 +203,15 @@ class HeroWeather extends StatelessWidget {
}
/// Returns the appropriate [IconData] for the given CWA weather [code].
- IconData _getWeatherIcon(int code) {
- if (code >= 1 && code <= 3) return Symbols.clear_day_rounded;
- if (code >= 4 && code <= 7) return Symbols.partly_cloudy_day_rounded;
- if (code >= 8 && code <= 14) return Symbols.cloud_rounded;
- if (code >= 15 && code <= 22) return Symbols.rainy_rounded;
- if (code >= 23 && code <= 28) return Symbols.rainy_heavy_rounded;
- if (code >= 29 && code <= 35) return Symbols.thunderstorm_rounded;
- if (code >= 36 && code <= 41) return Symbols.weather_snowy_rounded;
- if (code >= 42) return Symbols.foggy_rounded;
-
- return Symbols.cloud_rounded;
- }
+ IconData _getWeatherIcon(int code) => switch (code) {
+ >= 1 && <= 3 => Symbols.clear_day_rounded,
+ >= 4 && <= 7 => Symbols.partly_cloudy_day_rounded,
+ >= 8 && <= 14 => Symbols.cloud_rounded,
+ >= 15 && <= 22 => Symbols.rainy_rounded,
+ >= 23 && <= 28 => Symbols.rainy_heavy_rounded,
+ >= 29 && <= 35 => Symbols.thunderstorm_rounded,
+ >= 36 && <= 41 => Symbols.weather_snowy_rounded,
+ >= 42 => Symbols.foggy_rounded,
+ _ => Symbols.cloud_rounded,
+ };
}
diff --git a/lib/app/home/_widgets/history_timeline_item.dart b/lib/app/home/_widgets/history_timeline_item.dart
index 1857fd61b..f718b45a6 100644
--- a/lib/app/home/_widgets/history_timeline_item.dart
+++ b/lib/app/home/_widgets/history_timeline_item.dart
@@ -39,6 +39,7 @@ class HistoryTimelineItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
final hasDetail = shouldShowArrow(history);
+ final alpha = expired ? 0.6 : 1.0;
return Container(
margin: const .fromLTRB(16, 4, 16, 4),
@@ -98,7 +99,7 @@ class HistoryTimelineItem extends StatelessWidget {
),
style: context.texts.labelSmall?.copyWith(
color: context.colors.onSurfaceVariant.withValues(
- alpha: expired ? 0.6 : 1,
+ alpha: alpha,
),
),
),
@@ -107,7 +108,7 @@ class HistoryTimelineItem extends StatelessWidget {
history.text.content['all']!.subtitle,
style: context.texts.titleSmall?.copyWith(
color: context.colors.onSurface.withValues(
- alpha: expired ? 0.6 : 1,
+ alpha: alpha,
),
fontWeight: .w600,
),
@@ -119,7 +120,7 @@ class HistoryTimelineItem extends StatelessWidget {
history.text.description['all']!,
style: context.texts.bodySmall?.copyWith(
color: context.colors.onSurfaceVariant.withValues(
- alpha: expired ? 0.6 : 1,
+ alpha: alpha,
),
),
maxLines: 2,
diff --git a/lib/app/home/_widgets/location_button.dart b/lib/app/home/_widgets/location_button.dart
index 3ca2caa8a..51ae0d801 100644
--- a/lib/app/home/_widgets/location_button.dart
+++ b/lib/app/home/_widgets/location_button.dart
@@ -31,14 +31,7 @@ class LocationButton extends StatelessWidget {
final favorited = settingsLocation.favorited;
final temporaryCode = homeLocation.temporaryCode;
final displayCode = temporaryCode ?? savedCode;
- final location = Global.location[displayCode];
-
- late String content;
- if (location == null) {
- content = '尚未設定'.i18n;
- } else {
- content = location.dynamicName;
- }
+ final content = Global.location[displayCode]?.dynamicName ?? '尚未設定'.i18n;
return BlurredTextButton(
onPressed: () => _showLocationMenu(
@@ -74,11 +67,7 @@ class LocationButton extends StatelessWidget {
currentCode: currentCode,
onLocationSelected: (code) {
sheetContext.navigator.pop();
- if (code == savedCode) {
- model.setTemporaryCode(null);
- } else {
- model.setTemporaryCode(code);
- }
+ model.setTemporaryCode(code == savedCode ? null : code);
},
onAddLocationPressed: () {
sheetContext.navigator.pop();
diff --git a/lib/app/home/_widgets/mode_toggle_button.dart b/lib/app/home/_widgets/mode_toggle_button.dart
index ee03b906c..dbaae9de9 100644
--- a/lib/app/home/_widgets/mode_toggle_button.dart
+++ b/lib/app/home/_widgets/mode_toggle_button.dart
@@ -104,6 +104,7 @@ class ModeToggleButton extends StatelessWidget {
shape: RoundedRectangleBorder(borderRadius: .circular(16)),
elevation: 8,
items: HomeMode.values.map((mode) {
+ final isSelected = currentMode == mode;
return PopupMenuItem(
value: mode,
child: Row(
@@ -112,15 +113,13 @@ class ModeToggleButton extends StatelessWidget {
Icon(
mode.icon,
size: 20,
- color: currentMode == mode
- ? context.colors.primary
- : context.colors.onSurfaceVariant,
+ color: isSelected ? context.colors.primary : context.colors.onSurfaceVariant,
),
Text(
mode.label,
style: context.texts.bodyMedium?.copyWith(
- color: currentMode == mode ? context.colors.primary : context.colors.onSurface,
- fontWeight: currentMode == mode ? .bold : .normal,
+ color: isSelected ? context.colors.primary : context.colors.onSurface,
+ fontWeight: isSelected ? .bold : .normal,
),
),
],
diff --git a/lib/app/home/_widgets/thunderstorm_card.dart b/lib/app/home/_widgets/thunderstorm_card.dart
index dbc839913..a7caba34c 100644
--- a/lib/app/home/_widgets/thunderstorm_card.dart
+++ b/lib/app/home/_widgets/thunderstorm_card.dart
@@ -26,6 +26,7 @@ class ThunderstormCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final extended = context.theme.extendedColors;
return ResponsiveContainer(
maxWidth: 720,
child: Stack(
@@ -33,11 +34,8 @@ class ThunderstormCard extends StatelessWidget {
IgnorePointer(
child: Container(
decoration: BoxDecoration(
- color: context.theme.extendedColors.blueContainer,
- border: Border.all(
- color: context.theme.extendedColors.blue,
- width: 2,
- ),
+ color: extended.blueContainer,
+ border: Border.all(color: extended.blue, width: 2),
borderRadius: .circular(16),
),
padding: const .all(12),
@@ -54,7 +52,7 @@ class ThunderstormCard extends StatelessWidget {
children: [
Container(
decoration: BoxDecoration(
- color: context.theme.extendedColors.blue,
+ color: extended.blue,
borderRadius: .circular(8),
),
padding: const .fromLTRB(8, 6, 12, 6),
@@ -64,14 +62,14 @@ class ThunderstormCard extends StatelessWidget {
children: [
Icon(
Symbols.thunderstorm_rounded,
- color: context.theme.extendedColors.onBlue,
+ color: extended.onBlue,
weight: 700,
size: 22,
),
Text(
'雷雨即時訊息'.i18n,
style: context.texts.labelLarge!.copyWith(
- color: context.theme.extendedColors.onBlue,
+ color: extended.onBlue,
fontWeight: .bold,
),
),
@@ -94,13 +92,11 @@ class ThunderstormCard extends StatelessWidget {
'time': history.time.expiresAt.toSimpleDateTimeString(),
}),
style: context.texts.bodyLarge!.copyWith(
- color: context.theme.extendedColors.onBlueContainer,
+ color: extended.onBlueContainer,
),
tags: {
'bold': StyledTextTag(
- style: const TextStyle(
- fontWeight: .bold,
- ),
+ style: const TextStyle(fontWeight: .bold),
),
},
),
@@ -118,9 +114,7 @@ class ThunderstormCard extends StatelessWidget {
builder: (context) => ThunderstormPage(item: history),
),
),
- splashColor: context.theme.extendedColors.blue.withValues(
- alpha: 0.2,
- ),
+ splashColor: extended.blue.withValues(alpha: 0.2),
borderRadius: .circular(16),
),
),
diff --git a/lib/app/home/_widgets/wind_card.dart b/lib/app/home/_widgets/wind_card.dart
index ec2e118fb..1252ae142 100644
--- a/lib/app/home/_widgets/wind_card.dart
+++ b/lib/app/home/_widgets/wind_card.dart
@@ -404,6 +404,7 @@ class _WindCardState extends State with WidgetsBindingObserver, RouteA
void _showMagneticFieldInfo(BuildContext context) {
final hasDanger = _compassHasDanger;
final hasWarning = _compassHasWarning;
+ final statusColor = _compassStatusColor;
final valueText = _compassAccuracy < 0
? '無法測量'.i18n
: '±${_compassAccuracy.toStringAsFixed(1)}°';
@@ -417,11 +418,7 @@ class _WindCardState extends State with WidgetsBindingObserver, RouteA
: hasWarning
? Symbols.warning_rounded
: Symbols.check_circle_rounded,
- color: hasDanger
- ? Colors.red
- : hasWarning
- ? Colors.orange
- : Colors.green,
+ color: statusColor,
size: 48,
),
title: Text(
@@ -446,11 +443,7 @@ class _WindCardState extends State with WidgetsBindingObserver, RouteA
valueText,
style: context.texts.headlineSmall?.copyWith(
fontWeight: .bold,
- color: hasDanger
- ? Colors.red
- : hasWarning
- ? Colors.orange
- : Colors.green,
+ color: statusColor,
),
),
const SizedBox(height: 12),
@@ -465,9 +458,7 @@ class _WindCardState extends State with WidgetsBindingObserver, RouteA
Container(
padding: const .all(12),
decoration: BoxDecoration(
- color: (hasDanger ? Colors.red : Colors.orange).withValues(
- alpha: 0.1,
- ),
+ color: statusColor.withValues(alpha: 0.1),
borderRadius: .circular(8),
),
child: Text(
diff --git a/lib/app/home/page.dart b/lib/app/home/page.dart
index df5fd690d..58f1eb58f 100644
--- a/lib/app/home/page.dart
+++ b/lib/app/home/page.dart
@@ -96,36 +96,35 @@ class _HomePageState extends State with WidgetsBindingObserver {
void _measureFirstCard() {
WidgetsBinding.instance.addPostFrameCallback((_) {
final cardContext = _firstCardKey.currentContext;
- if (cardContext != null) {
- final box = cardContext.findRenderObject() as RenderBox?;
- if (box != null && box.hasSize) {
- final height = box.size.height + 28;
- final isFirstMeasure = _measuredFirstCardHeight == null;
- if (isFirstMeasure || ((_measuredFirstCardHeight! - height).abs() > 1)) {
- _sheetController.removeListener(_onSheetChanged);
- _sheetController.dispose();
-
- setState(() {
- _measuredFirstCardHeight = height;
- _sheetKey = UniqueKey();
- _sheetController = DraggableScrollableController();
- });
-
- _sheetController.addListener(_onSheetChanged);
-
- if (isFirstMeasure && mounted) {
- WidgetsBinding.instance.addPostFrameCallback((_) {
- final screenHeight = context.dimension.height;
- final targetSize = (height / screenHeight).clamp(0.25, 0.6);
- _sheetController.animateTo(
- targetSize,
- duration: const Duration(milliseconds: 350),
- curve: Curves.easeOutCubic,
- );
- });
- }
- }
- }
+ if (cardContext == null) return;
+ final box = cardContext.findRenderObject() as RenderBox?;
+ if (box == null || !box.hasSize) return;
+
+ final height = box.size.height + 28;
+ final isFirstMeasure = _measuredFirstCardHeight == null;
+ if (!isFirstMeasure && (_measuredFirstCardHeight! - height).abs() <= 1) return;
+
+ _sheetController.removeListener(_onSheetChanged);
+ _sheetController.dispose();
+
+ setState(() {
+ _measuredFirstCardHeight = height;
+ _sheetKey = UniqueKey();
+ _sheetController = DraggableScrollableController();
+ });
+
+ _sheetController.addListener(_onSheetChanged);
+
+ if (isFirstMeasure && mounted) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ final screenHeight = context.dimension.height;
+ final targetSize = (height / screenHeight).clamp(0.25, 0.6);
+ _sheetController.animateTo(
+ targetSize,
+ duration: const Duration(milliseconds: 350),
+ curve: Curves.easeOutCubic,
+ );
+ });
}
});
}
@@ -841,25 +840,15 @@ class _HomePageState extends State with WidgetsBindingObserver {
final currentSize = _sheetController.size;
final velocity = details.primaryVelocity ?? 0;
- double targetSnap;
+ final double targetSnap;
if (velocity.abs() > 500) {
- if (velocity > 0) {
- targetSnap =
- snapSizes.where((s) => s < currentSize).lastOrNull ?? snapSizes.first;
- } else {
- targetSnap =
- snapSizes.where((s) => s > currentSize).firstOrNull ?? snapSizes.last;
- }
+ targetSnap = velocity > 0
+ ? (snapSizes.where((s) => s < currentSize).lastOrNull ?? snapSizes.first)
+ : (snapSizes.where((s) => s > currentSize).firstOrNull ?? snapSizes.last);
} else {
- targetSnap = snapSizes.first;
- double minDist = (currentSize - targetSnap).abs();
- for (final snap in snapSizes) {
- final dist = (currentSize - snap).abs();
- if (dist < minDist) {
- minDist = dist;
- targetSnap = snap;
- }
- }
+ targetSnap = snapSizes.reduce(
+ (a, b) => (currentSize - a).abs() < (currentSize - b).abs() ? a : b,
+ );
}
_sheetController.animateTo(
@@ -892,7 +881,8 @@ class _HomePageState extends State with WidgetsBindingObserver {
return BlurredIconButton(
icon: const Icon(Symbols.map_rounded),
tooltip: '地圖',
- onPressed: () => MapRoute(layers: layers.map((l) => l.name).join(',')).push(context),
+ onPressed: () =>
+ MapRoute(layers: layers.map((l) => l.name).join(',')).push(context),
elevation: 2,
);
},
@@ -1006,6 +996,11 @@ class _StationChip extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final isDark = context.theme.brightness == .dark;
+ final borderColor = (isDark ? Colors.white : Colors.black).withValues(alpha: 0.25);
+ final labelColor = isDark ? Colors.white : const Color.fromARGB(255, 90, 90, 90);
+ final valueColor = isDark ? Colors.white : const Color.fromARGB(255, 60, 60, 60);
+
return ClipRRect(
borderRadius: .circular(8),
child: BackdropFilter(
@@ -1015,12 +1010,7 @@ class _StationChip extends StatelessWidget {
decoration: BoxDecoration(
color: color.withValues(alpha: 0.15),
borderRadius: .circular(8),
- border: Border.all(
- color: context.theme.brightness == .dark
- ? Colors.white.withValues(alpha: 0.25)
- : const Color.fromARGB(255, 0, 0, 0).withValues(alpha: 0.25),
- width: 0.5,
- ),
+ border: Border.all(color: borderColor, width: 0.5),
),
child: Column(
mainAxisSize: .min,
@@ -1028,9 +1018,7 @@ class _StationChip extends StatelessWidget {
Text(
label,
style: context.texts.labelSmall?.copyWith(
- color: context.theme.brightness == .dark
- ? Colors.white
- : const Color.fromARGB(255, 90, 90, 90),
+ color: labelColor,
fontWeight: .w700,
fontSize: 9,
),
@@ -1038,9 +1026,7 @@ class _StationChip extends StatelessWidget {
Text(
value,
style: context.texts.bodySmall?.copyWith(
- color: context.theme.brightness == .dark
- ? Colors.white
- : const Color.fromARGB(255, 60, 60, 60),
+ color: valueColor,
fontWeight: .w600,
fontSize: 12,
),
diff --git a/lib/app/map/_lib/managers/lightning.dart b/lib/app/map/_lib/managers/lightning.dart
index 70aeadcb0..1d4fe249f 100644
--- a/lib/app/map/_lib/managers/lightning.dart
+++ b/lib/app/map/_lib/managers/lightning.dart
@@ -114,10 +114,9 @@ class LightningMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.lightning(time);
final layerId = MapLayerIds.lightning(time);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (!isSourceExists) {
late final List lightningData;
diff --git a/lib/app/map/_lib/managers/monitor.dart b/lib/app/map/_lib/managers/monitor.dart
index 208903738..721b30cc3 100644
--- a/lib/app/map/_lib/managers/monitor.dart
+++ b/lib/app/map/_lib/managers/monitor.dart
@@ -59,7 +59,8 @@ class MonitorMapLayerManager extends MapLayerManager {
static const double kLabelLineHeight = 1.2;
/// Whether data has been received within the last 12 seconds.
- bool get dataStatus => _dataStatus();
+ bool get dataStatus =>
+ (GlobalProviders.data.currentTime - (_lastDataReceivedTime ?? 0)) < 12000;
/// The most recently measured round-trip latency in milliseconds.
double get ping => _ping;
@@ -81,6 +82,11 @@ class MonitorMapLayerManager extends MapLayerManager {
String? _lastEewId;
int? _lastEewSerial;
+ // Cached visibility states - avoid redundant setLayerVisibility platform calls.
+ bool? _lastRtsLayersVisible;
+ bool? _lastIntensityLayersVisible;
+ bool? _lastBoxLayerVisible;
+
late final String _rtsSourceId = MapSourceIds.rts();
late final String _rtsLayerId = MapLayerIds.rts();
late final String _intensitySourceId = MapSourceIds.intensity();
@@ -108,10 +114,6 @@ class MonitorMapLayerManager extends MapLayerManager {
_setupBlinkTimer();
}
- bool _dataStatus() {
- return (GlobalProviders.data.currentTime - (_lastDataReceivedTime ?? 0)) < 12000;
- }
-
/// The timestamp of the most recently processed RTS data packet.
final currentRtsTime = ValueNotifier(GlobalProviders.data.syncTime);
@@ -177,26 +179,18 @@ class MonitorMapLayerManager extends MapLayerManager {
final hasEew = GlobalProviders.data.activeEew.isNotEmpty;
final shouldBlinkEpicenter = hasEew;
- // Boxes blinking - only toggle if conditions allow, otherwise hide
- if (shouldBlinkBoxes) {
- _isBoxVisible = !_isBoxVisible;
- await controller.setLayerVisibility(_boxLayerId, _isBoxVisible);
- } else {
- _isBoxVisible = false;
- await controller.setLayerVisibility(_boxLayerId, false);
- }
-
- // Epicenter blinking - independent of boxes
- if (shouldBlinkEpicenter) {
- _isEpicenterVisible = !_isEpicenterVisible;
- await controller.setLayerVisibility(
- _epicenterLayerId,
- _isEpicenterVisible,
- );
- } else {
- _isEpicenterVisible = false;
- await controller.setLayerVisibility(_epicenterLayerId, false);
- }
+ // Boxes blinking - toggle when conditions allow, otherwise hide.
+ // Skip the platform call when state didn't change.
+ final nextBoxVisible = shouldBlinkBoxes && !_isBoxVisible;
+ final nextEpicenterVisible = shouldBlinkEpicenter && !_isEpicenterVisible;
+ await Future.wait([
+ if (nextBoxVisible != _isBoxVisible)
+ controller.setLayerVisibility(_boxLayerId, nextBoxVisible),
+ if (nextEpicenterVisible != _isEpicenterVisible)
+ controller.setLayerVisibility(_epicenterLayerId, nextEpicenterVisible),
+ ]);
+ _isBoxVisible = nextBoxVisible;
+ _isEpicenterVisible = nextEpicenterVisible;
} catch (e, s) {
TalkerManager.instance.error(
'MonitorMapLayerManager._blinkTimer',
@@ -893,53 +887,40 @@ class MonitorMapLayerManager extends MapLayerManager {
final hasIntensityData = (_cachedIntensityGeoJson?['features'] as List?)?.isNotEmpty ?? false;
final hasBoxData = (_cachedBoxGeoJson?['features'] as List?)?.isNotEmpty ?? false;
+ final rtsVisible = hasRtsData && !hasBox;
+ final intensityVisible = hasIntensityData && hasBox;
+ final boxVisible = hasBoxData && hasBox;
+
await Future.wait([
if (hasRtsData && existingSources.contains(_rtsSourceId))
controller.setGeoJsonSource(_rtsSourceId, _cachedRtsGeoJson!),
if (hasIntensityData && existingSources.contains(_intensitySourceId))
- controller.setGeoJsonSource(
- _intensitySourceId,
- _cachedIntensityGeoJson!,
- ),
+ controller.setGeoJsonSource(_intensitySourceId, _cachedIntensityGeoJson!),
if (hasIntensityData && existingSources.contains(_intensity0SourceId))
- controller.setGeoJsonSource(
- _intensity0SourceId,
- _cachedIntensityGeoJson!,
- ),
+ controller.setGeoJsonSource(_intensity0SourceId, _cachedIntensityGeoJson!),
if (hasBoxData && existingSources.contains(_boxSourceId))
controller.setGeoJsonSource(_boxSourceId, _cachedBoxGeoJson!),
- controller.setLayerVisibility(_rtsLayerId, hasRtsData && !hasBox),
- controller.setLayerVisibility(
- '$_rtsLayerId-label-id',
- hasRtsData && !hasBox,
- ),
- controller.setLayerVisibility(
- '$_rtsLayerId-label-loc',
- hasRtsData && !hasBox,
- ),
- controller.setLayerVisibility(
- '$_rtsLayerId-label-detail-i',
- hasRtsData && !hasBox,
- ),
- controller.setLayerVisibility(
- '$_rtsLayerId-label-detail-pga',
- hasRtsData && !hasBox,
- ),
- controller.setLayerVisibility(
- '$_rtsLayerId-label-detail-pgv',
- hasRtsData && !hasBox,
- ),
- controller.setLayerVisibility(
- _intensityLayerId,
- hasIntensityData && hasBox,
- ),
- controller.setLayerVisibility(
- _intensity0LayerId,
- hasIntensityData && hasBox,
- ),
- controller.setLayerVisibility(_boxLayerId, hasBoxData && hasBox),
+ // RTS layers share visibility - skip the 6 platform calls if unchanged.
+ if (rtsVisible != _lastRtsLayersVisible) ...[
+ controller.setLayerVisibility(_rtsLayerId, rtsVisible),
+ controller.setLayerVisibility('$_rtsLayerId-label-id', rtsVisible),
+ controller.setLayerVisibility('$_rtsLayerId-label-loc', rtsVisible),
+ controller.setLayerVisibility('$_rtsLayerId-label-detail-i', rtsVisible),
+ controller.setLayerVisibility('$_rtsLayerId-label-detail-pga', rtsVisible),
+ controller.setLayerVisibility('$_rtsLayerId-label-detail-pgv', rtsVisible),
+ ],
+ if (intensityVisible != _lastIntensityLayersVisible) ...[
+ controller.setLayerVisibility(_intensityLayerId, intensityVisible),
+ controller.setLayerVisibility(_intensity0LayerId, intensityVisible),
+ ],
+ if (boxVisible != _lastBoxLayerVisible)
+ controller.setLayerVisibility(_boxLayerId, boxVisible),
]);
+
+ _lastRtsLayersVisible = rtsVisible;
+ _lastIntensityLayersVisible = intensityVisible;
+ _lastBoxLayerVisible = boxVisible;
} catch (e, s) {
TalkerManager.instance.error(
'MonitorMapLayerManager._updateRtsFromCache',
@@ -1190,6 +1171,12 @@ class MonitorMapLayerManager extends MapLayerManager {
}
didSetup = false;
+ // Reset cached visibility so the next setup re-applies it.
+ _lastRtsLayersVisible = null;
+ _lastIntensityLayersVisible = null;
+ _lastBoxLayerVisible = null;
+ _isBoxVisible = true;
+ _isEpicenterVisible = true;
}
@override
diff --git a/lib/app/map/_lib/managers/precipitation.dart b/lib/app/map/_lib/managers/precipitation.dart
index bf14fdd0d..0132c98c2 100644
--- a/lib/app/map/_lib/managers/precipitation.dart
+++ b/lib/app/map/_lib/managers/precipitation.dart
@@ -137,13 +137,14 @@ class PrecipitationMapLayerManager extends MapLayerManager {
final showLayerId = '$layerId-$interval';
final hideLayerId = '$layerId-${currentPrecipitationInterval.value}';
- await controller.setLayerVisibility(showLayerId, true);
- await controller.setLayerVisibility('$showLayerId-label-name', true);
- await controller.setLayerVisibility('$showLayerId-label-value', true);
-
- await controller.setLayerVisibility(hideLayerId, false);
- await controller.setLayerVisibility('$hideLayerId-label-name', false);
- await controller.setLayerVisibility('$hideLayerId-label-value', false);
+ await Future.wait([
+ controller.setLayerVisibility(showLayerId, true),
+ controller.setLayerVisibility('$showLayerId-label-name', true),
+ controller.setLayerVisibility('$showLayerId-label-value', true),
+ controller.setLayerVisibility(hideLayerId, false),
+ controller.setLayerVisibility('$hideLayerId-label-name', false),
+ controller.setLayerVisibility('$hideLayerId-label-value', false),
+ ]);
currentPrecipitationInterval.value = interval;
} catch (e, s) {
@@ -208,10 +209,9 @@ class PrecipitationMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.precipitation(time);
final layerId = MapLayerIds.precipitation(time);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (!isSourceExists) {
late final List rainData;
@@ -235,6 +235,9 @@ class PrecipitationMapLayerManager extends MapLayerManager {
}
if (!isLayerExists) {
+ final activeInterval = currentPrecipitationInterval.value;
+ final outlineHex = colors.outlineVariant.toHexStringRGB();
+ final onSurfaceVariantHex = colors.onSurfaceVariant.toHexStringRGB();
final Map properties = {
for (final interval in precipitationIntervals)
...({
@@ -266,23 +269,23 @@ class PrecipitationMapLayerManager extends MapLayerManager {
],
circleRadius: kCircleIconSize,
circleOpacity: 0.75,
- circleStrokeColor: colors.outlineVariant.toHexStringRGB(),
+ circleStrokeColor: outlineHex,
circleStrokeWidth: 0.5,
circleStrokeOpacity: 0.75,
- visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none',
+ visibility: interval == activeInterval ? 'visible' : 'none',
),
'$interval-label-name': SymbolLayerProperties(
textField: [Expressions.get, 'name'],
textSize: 10,
- textColor: colors.onSurfaceVariant.toHexStringRGB(),
- textHaloColor: colors.outlineVariant.toHexStringRGB(),
+ textColor: onSurfaceVariantHex,
+ textHaloColor: outlineHex,
textHaloWidth: 1,
textFont: ['Noto Sans TC Bold'],
textOffset: [0, kLabelBaseOffset],
textAnchor: 'top',
textAllowOverlap: true,
textIgnorePlacement: true,
- visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none',
+ visibility: interval == activeInterval ? 'visible' : 'none',
),
'$interval-label-value': SymbolLayerProperties(
textField: [
@@ -291,15 +294,15 @@ class PrecipitationMapLayerManager extends MapLayerManager {
'mm',
],
textSize: 10,
- textColor: colors.onSurfaceVariant.toHexStringRGB(),
- textHaloColor: colors.outlineVariant.toHexStringRGB(),
+ textColor: onSurfaceVariantHex,
+ textHaloColor: outlineHex,
textHaloWidth: 1,
textFont: ['Noto Sans TC Bold'],
- textOffset: [0, kLabelBaseOffset + kLabelLineHeight * 1],
+ textOffset: [0, kLabelBaseOffset + kLabelLineHeight],
textAnchor: 'top',
textAllowOverlap: true,
textIgnorePlacement: true,
- visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none',
+ visibility: interval == activeInterval ? 'visible' : 'none',
),
}),
};
@@ -339,14 +342,14 @@ class PrecipitationMapLayerManager extends MapLayerManager {
if (!visible) return;
final layerId = MapLayerIds.precipitation(currentPrecipitationTime.value);
- final hideLayerId = '$layerId-${currentPrecipitationInterval.value}';
- final hideNameLayerId = '$layerId-${currentPrecipitationInterval.value}-label-name';
- final hideValueLayerId = '$layerId-${currentPrecipitationInterval.value}-label-value';
+ final base = '$layerId-${currentPrecipitationInterval.value}';
try {
- await controller.setLayerVisibility(hideLayerId, false);
- await controller.setLayerVisibility(hideNameLayerId, false);
- await controller.setLayerVisibility(hideValueLayerId, false);
+ await Future.wait([
+ controller.setLayerVisibility(base, false),
+ controller.setLayerVisibility('$base-label-name', false),
+ controller.setLayerVisibility('$base-label-value', false),
+ ]);
visible = false;
} catch (e, s) {
@@ -359,14 +362,14 @@ class PrecipitationMapLayerManager extends MapLayerManager {
if (visible) return;
final layerId = MapLayerIds.precipitation(currentPrecipitationTime.value);
- final showLayerId = '$layerId-${currentPrecipitationInterval.value}';
- final showNameLayerId = '$layerId-${currentPrecipitationInterval.value}-label-name';
- final showValueLayerId = '$layerId-${currentPrecipitationInterval.value}-label-value';
+ final base = '$layerId-${currentPrecipitationInterval.value}';
try {
- await controller.setLayerVisibility(showLayerId, true);
- await controller.setLayerVisibility(showNameLayerId, true);
- await controller.setLayerVisibility(showValueLayerId, true);
+ await Future.wait([
+ controller.setLayerVisibility(base, true),
+ controller.setLayerVisibility('$base-label-name', true),
+ controller.setLayerVisibility('$base-label-value', true),
+ ]);
await _focus();
diff --git a/lib/app/map/_lib/managers/radar.dart b/lib/app/map/_lib/managers/radar.dart
index 755fd462e..986c21345 100644
--- a/lib/app/map/_lib/managers/radar.dart
+++ b/lib/app/map/_lib/managers/radar.dart
@@ -210,8 +210,9 @@ class RadarMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.radar(time);
final layerId = MapLayerIds.radar(time);
- final isSourceExists = (await controller.getSourceIds()).contains(sourceId);
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (!isSourceExists) {
final properties = RasterSourceProperties(
@@ -260,28 +261,22 @@ class RadarMapLayerManager extends MapLayerManager {
final layersToPreload = [];
for (int i = 1; i <= 3; i++) {
- if (currentIndex - i >= 0) {
- layersToPreload.add(radarList[currentIndex - i]);
- }
- if (currentIndex + i < radarList.length) {
- layersToPreload.add(radarList[currentIndex + i]);
- }
+ final prev = currentIndex - i;
+ final next = currentIndex + i;
+ if (prev >= 0) layersToPreload.add(radarList[prev]);
+ if (next < radarList.length) layersToPreload.add(radarList[next]);
}
- for (final time in layersToPreload) {
- if (!_preloadedLayers.contains(time)) {
+ await Future.wait(
+ layersToPreload.where((t) => !_preloadedLayers.contains(t)).map((time) async {
try {
await _setupAndShowLayer(time);
await _hideLayer(time);
} catch (e, s) {
- TalkerManager.instance.error(
- 'Failed to preload radar layer: $time',
- e,
- s,
- );
+ TalkerManager.instance.error('Failed to preload radar layer: $time', e, s);
}
- }
- }
+ }),
+ );
}
/// Starts auto-play if stopped, or stops it if currently running.
@@ -1082,11 +1077,9 @@ class _RadarProgressBar extends StatelessWidget {
return const SizedBox.shrink();
}
- double progress = 0.0;
- if (startIndex != endIndex) {
- progress = (startIndex - currentIndex) / (startIndex - endIndex);
- progress = progress.clamp(0.0, 1.0);
- }
+ final progress = startIndex == endIndex
+ ? 0.0
+ : ((startIndex - currentIndex) / (startIndex - endIndex)).clamp(0.0, 1.0);
return Row(
spacing: 8,
diff --git a/lib/app/map/_lib/managers/report.dart b/lib/app/map/_lib/managers/report.dart
index d39677bf7..d4bb4aacd 100644
--- a/lib/app/map/_lib/managers/report.dart
+++ b/lib/app/map/_lib/managers/report.dart
@@ -224,10 +224,9 @@ class ReportMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.report();
final layerId = MapLayerIds.report();
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (isSourceExists && isLayerExists) return;
@@ -382,10 +381,9 @@ class ReportMapLayerManager extends MapLayerManager {
report.time.millisecondsSinceEpoch.toString(),
);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (isSourceExists && isLayerExists) return;
@@ -437,10 +435,9 @@ class ReportMapLayerManager extends MapLayerManager {
report.time.millisecondsSinceEpoch.toString(),
);
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (isLayerExists) {
await controller.removeLayer(layerId);
diff --git a/lib/app/map/_lib/managers/temperature.dart b/lib/app/map/_lib/managers/temperature.dart
index 8c66d0476..2b30fe8b0 100644
--- a/lib/app/map/_lib/managers/temperature.dart
+++ b/lib/app/map/_lib/managers/temperature.dart
@@ -163,10 +163,9 @@ class TemperatureMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.temperature(time);
final layerId = MapLayerIds.temperature(time);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (!isSourceExists) {
late final List weatherData;
@@ -263,7 +262,7 @@ class TemperatureMapLayerManager extends MapLayerManager {
textHaloColor: colors.outlineVariant.toHexStringRGB(),
textHaloWidth: 1,
textFont: ['Noto Sans TC Bold'],
- textOffset: [0, kLabelBaseOffset + kLabelLineHeight * 1],
+ textOffset: [0, kLabelBaseOffset + kLabelLineHeight],
textAnchor: 'top',
textAllowOverlap: true,
textIgnorePlacement: true,
@@ -307,9 +306,11 @@ class TemperatureMapLayerManager extends MapLayerManager {
final layerId = MapLayerIds.temperature(currentTemperatureTime.value);
try {
- await controller.setLayerVisibility(layerId, false);
- await controller.setLayerVisibility('$layerId-label-name', false);
- await controller.setLayerVisibility('$layerId-label-value', false);
+ await Future.wait([
+ controller.setLayerVisibility(layerId, false),
+ controller.setLayerVisibility('$layerId-label-name', false),
+ controller.setLayerVisibility('$layerId-label-value', false),
+ ]);
visible = false;
} catch (e, s) {
@@ -324,9 +325,11 @@ class TemperatureMapLayerManager extends MapLayerManager {
final layerId = MapLayerIds.temperature(currentTemperatureTime.value);
try {
- await controller.setLayerVisibility(layerId, true);
- await controller.setLayerVisibility('$layerId-label-name', true);
- await controller.setLayerVisibility('$layerId-label-value', true);
+ await Future.wait([
+ controller.setLayerVisibility(layerId, true),
+ controller.setLayerVisibility('$layerId-label-name', true),
+ controller.setLayerVisibility('$layerId-label-value', true),
+ ]);
await _focus();
diff --git a/lib/app/map/_lib/managers/tsunami.dart b/lib/app/map/_lib/managers/tsunami.dart
index 4e257fb94..55f0ef305 100644
--- a/lib/app/map/_lib/managers/tsunami.dart
+++ b/lib/app/map/_lib/managers/tsunami.dart
@@ -20,7 +20,6 @@ import 'package:dpip/utils/extensions/latlng.dart';
import 'package:dpip/utils/extensions/number.dart';
import 'package:dpip/utils/log.dart';
import 'package:dpip/widgets/map/map.dart';
-import 'package:flex_color_picker/flex_color_picker.dart';
import 'package:flutter/material.dart';
import 'package:i18n_extension/i18n_extension.dart';
import 'package:intl/intl.dart';
@@ -45,10 +44,9 @@ class TsunamiMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.tsunami(currentTsunami.value);
final layerId = MapLayerIds.tsunami(currentTsunami.value);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (isSourceExists && isLayerExists) return;
@@ -173,23 +171,12 @@ class _TsunamiMapLayerSheetState extends State {
setState(() {});
}
- String heightToColor(int height) {
- Color color;
- if (height == 3) {
- color = const Color(0xFFE543FF);
- } else if (height == 2) {
- color = const Color(0xFFC90000);
- } else if (height == 1) {
- color = const Color(0xFFFFC900);
- } else {
- color = const Color(0xFF00AAFF);
- }
- return '#${color.hex}';
- }
-
- DateTime _convertTimestamp(int timestamp) {
- return DateTime.fromMillisecondsSinceEpoch(timestamp);
- }
+ String heightToColor(int height) => switch (height) {
+ 3 => '#E543FF',
+ 2 => '#C90000',
+ 1 => '#FFC900',
+ _ => '#00AAFF',
+ };
Future addTsunamiObservationPoints(Tsunami tsunami) async {
await _mapController.removeLayer('tsunami-actual-circles');
@@ -238,7 +225,7 @@ class _TsunamiMapLayerSheetState extends State {
'waveHeight': actualStation.waveHeight,
'arrivalTime': DateFormat(
'MM/dd HH:mm',
- ).format(_convertTimestamp(actualStation.arrivalTime)),
+ ).format(DateTime.fromMillisecondsSinceEpoch(actualStation.arrivalTime)),
},
'geometry': {
'type': 'Point',
@@ -377,11 +364,11 @@ class _TsunamiMapLayerSheetState extends State {
_tsunami_id = id.split('-')[0];
_tsunami_serial = int.parse(id.split('-')[1]);
tsunami = await ExpTech().getTsunami(id);
- (tsunami?.status == 0)
- ? tsunamiStatus = '發布'
- : (tsunami?.status == 1)
- ? tsunamiStatus = '更新'
- : tsunamiStatus = '解除';
+ tsunamiStatus = switch (tsunami?.status) {
+ 0 => '發布',
+ 1 => '更新',
+ _ => '解除',
+ };
final List options = generateTsunamiOptions();
if (options.isNotEmpty && _selectedOption == null) {
diff --git a/lib/app/map/_lib/managers/wind.dart b/lib/app/map/_lib/managers/wind.dart
index f5ccb5b12..21d2d4a3d 100644
--- a/lib/app/map/_lib/managers/wind.dart
+++ b/lib/app/map/_lib/managers/wind.dart
@@ -120,10 +120,9 @@ class WindMapLayerManager extends MapLayerManager {
final sourceId = MapSourceIds.wind(time);
final layerId = MapLayerIds.wind(time);
- final isSourceExists = (await controller.getSourceIds()).contains(
- sourceId,
- );
- final isLayerExists = (await controller.getLayerIds()).contains(layerId);
+ final ids = await Future.wait([controller.getSourceIds(), controller.getLayerIds()]);
+ final isSourceExists = ids[0].contains(sourceId);
+ final isLayerExists = ids[1].contains(layerId);
if (!isSourceExists) {
late final List weatherData;
@@ -196,7 +195,7 @@ class WindMapLayerManager extends MapLayerManager {
textHaloColor: colors.outlineVariant.toHexStringRGB(),
textHaloWidth: 1,
textFont: ['Noto Sans TC Bold'],
- textOffset: [0, kLabelBaseOffset + kLabelLineHeight * 1],
+ textOffset: [0, kLabelBaseOffset + kLabelLineHeight],
textAnchor: 'top',
textAllowOverlap: true,
textIgnorePlacement: true,
@@ -239,13 +238,12 @@ class WindMapLayerManager extends MapLayerManager {
final layerId = MapLayerIds.wind(currentWindTime.value);
- final nameLayerId = '$layerId-label-name';
- final valueLayerId = '$layerId-label-value';
-
try {
- await controller.setLayerVisibility(layerId, false);
- await controller.setLayerVisibility(nameLayerId, false);
- await controller.setLayerVisibility(valueLayerId, false);
+ await Future.wait([
+ controller.setLayerVisibility(layerId, false),
+ controller.setLayerVisibility('$layerId-label-name', false),
+ controller.setLayerVisibility('$layerId-label-value', false),
+ ]);
visible = false;
} catch (e, s) {
@@ -259,13 +257,12 @@ class WindMapLayerManager extends MapLayerManager {
final layerId = MapLayerIds.wind(currentWindTime.value);
- final nameLayerId = '$layerId-label-name';
- final valueLayerId = '$layerId-label-value';
-
try {
- await controller.setLayerVisibility(layerId, true);
- await controller.setLayerVisibility(nameLayerId, true);
- await controller.setLayerVisibility(valueLayerId, true);
+ await Future.wait([
+ controller.setLayerVisibility(layerId, true),
+ controller.setLayerVisibility('$layerId-label-name', true),
+ controller.setLayerVisibility('$layerId-label-value', true),
+ ]);
visible = true;
diff --git a/lib/app/map/_lib/utils.dart b/lib/app/map/_lib/utils.dart
index 7d7128c7a..3a48af86f 100644
--- a/lib/app/map/_lib/utils.dart
+++ b/lib/app/map/_lib/utils.dart
@@ -98,6 +98,8 @@ bool isValidLayerCombination(Set layers) {
return false;
}
+String _scopedId(String base, String? suffix) => suffix == null ? base : '$base-$suffix';
+
/// Provides stable MapLibre GeoJSON source ID strings for each data type.
///
/// Pass an optional time or code suffix to obtain a time-specific ID,
@@ -106,35 +108,34 @@ class MapSourceIds {
const MapSourceIds._();
/// Returns the source ID for radar data, optionally scoped to [time].
- static String radar([String? time]) => time == null ? 'radar' : 'radar-$time';
+ static String radar([String? time]) => _scopedId('radar', time);
/// Returns the source ID for earthquake report data, optionally scoped to
/// [time].
- static String report([String? time]) => time == null ? 'report' : 'report-$time';
+ static String report([String? time]) => _scopedId('report', time);
/// Returns the source ID for tsunami data, optionally scoped to [code].
- static String tsunami([String? code]) => code == null ? 'tsunami' : 'tsunami-$code';
+ static String tsunami([String? code]) => _scopedId('tsunami', code);
/// Returns the source ID for real-time seismograph (RTS) data, optionally
/// scoped to [time].
- static String rts([String? time]) => time == null ? 'rts' : 'rts-$time';
+ static String rts([String? time]) => _scopedId('rts', time);
/// Returns the source ID for EEW data, optionally scoped to [code].
- static String eew([String? code]) => code == null ? 'eew' : 'eew-$code';
+ static String eew([String? code]) => _scopedId('eew', code);
/// Returns the source ID for temperature data, optionally scoped to [time].
- static String temperature([String? time]) => time == null ? 'temperature' : 'temperature-$time';
+ static String temperature([String? time]) => _scopedId('temperature', time);
/// Returns the source ID for precipitation data, optionally scoped to
/// [time].
- static String precipitation([String? time]) =>
- time == null ? 'precipitation' : 'precipitation-$time';
+ static String precipitation([String? time]) => _scopedId('precipitation', time);
/// Returns the source ID for wind data, optionally scoped to [time].
- static String wind([String? time]) => time == null ? 'wind' : 'wind-$time';
+ static String wind([String? time]) => _scopedId('wind', time);
/// Returns the source ID for lightning data, optionally scoped to [time].
- static String lightning([String? time]) => time == null ? 'lightning' : 'lightning-$time';
+ static String lightning([String? time]) => _scopedId('lightning', time);
/// Returns the source ID for seismic intensity polygon data.
static String intensity() => 'intensity';
@@ -154,34 +155,33 @@ class MapLayerIds {
const MapLayerIds._();
/// Returns the layer ID for radar data, optionally scoped to [time].
- static String radar([String? time]) => time == null ? 'radar' : 'radar-$time';
+ static String radar([String? time]) => _scopedId('radar', time);
/// Returns the layer ID for earthquake report data, optionally scoped to
/// [time].
- static String report([String? time]) => time == null ? 'report' : 'report-$time';
+ static String report([String? time]) => _scopedId('report', time);
/// Returns the layer ID for tsunami data, optionally scoped to [code].
- static String tsunami([String? code]) => code == null ? 'tsunami' : 'tsunami-$code';
+ static String tsunami([String? code]) => _scopedId('tsunami', code);
/// Returns the layer ID for real-time seismograph (RTS) data, optionally
/// scoped to [time].
- static String rts([String? time]) => time == null ? 'rts' : 'rts-$time';
+ static String rts([String? time]) => _scopedId('rts', time);
/// Returns the layer ID for EEW data, optionally scoped to [code].
- static String eew([String? code]) => code == null ? 'eew' : 'eew-$code';
+ static String eew([String? code]) => _scopedId('eew', code);
/// Returns the layer ID for temperature data, optionally scoped to [time].
- static String temperature([String? time]) => time == null ? 'temperature' : 'temperature-$time';
+ static String temperature([String? time]) => _scopedId('temperature', time);
/// Returns the layer ID for precipitation data, optionally scoped to [time].
- static String precipitation([String? time]) =>
- time == null ? 'precipitation' : 'precipitation-$time';
+ static String precipitation([String? time]) => _scopedId('precipitation', time);
/// Returns the layer ID for wind data, optionally scoped to [time].
- static String wind([String? time]) => time == null ? 'wind' : 'wind-$time';
+ static String wind([String? time]) => _scopedId('wind', time);
/// Returns the layer ID for lightning data, optionally scoped to [time].
- static String lightning([String? time]) => time == null ? 'lightning' : 'lightning-$time';
+ static String lightning([String? time]) => _scopedId('lightning', time);
/// Returns the layer ID for seismic intensity polygon data.
static String intensity() => 'intensity';
@@ -197,15 +197,12 @@ class MapLayerIds {
///
/// Preserves layers listed in [BaseMapLayerIds.values] and the `map` source.
Future cleanupMap(MapLibreMapController controller) async {
- final layerIds = (await controller.getLayerIds()).cast()
- ..removeWhere((v) => BaseMapLayerIds.values().contains(v));
- final sourceIds = (await controller.getSourceIds())..removeWhere((v) => v == 'map');
-
- for (final layerId in layerIds) {
- await controller.removeLayer(layerId);
- }
-
- for (final sourceId in sourceIds) {
- await controller.removeSource(sourceId);
- }
+ final ids = await Future.wait([controller.getLayerIds(), controller.getSourceIds()]);
+ final baseLayers = BaseMapLayerIds.values().toSet();
+ final layerIds = ids[0].cast().where((v) => !baseLayers.contains(v));
+ final sourceIds = ids[1].cast().where((v) => v != 'map');
+
+ // Layers must be removed before their sources.
+ await Future.wait(layerIds.map(controller.removeLayer));
+ await Future.wait(sourceIds.map(controller.removeSource));
}
diff --git a/lib/app/map/_widgets/map_legend.dart b/lib/app/map/_widgets/map_legend.dart
index e0658fa9a..94ea5b5bd 100644
--- a/lib/app/map/_widgets/map_legend.dart
+++ b/lib/app/map/_widgets/map_legend.dart
@@ -92,12 +92,13 @@ class ColorLegend extends StatelessWidget {
@override
Widget build(BuildContext context) {
final items = reverse ? this.items.reversed.toList() : this.items;
- final visibleItems = items.where((item) => !item.hidden).toList();
+ final visibleCount = items.where((item) => !item.hidden).length;
+ int visibleCounter = 0;
final children = items.mapIndexed((index, item) {
if (item.hidden) return const SizedBox.shrink();
- final visibleIndex = visibleItems.indexOf(item);
+ final visibleIndex = visibleCounter++;
final previous = index == 0 ? null : items.elementAtOrNull(index - 1);
final next = items.elementAtOrNull(index + 1);
@@ -134,7 +135,7 @@ class ColorLegend extends StatelessWidget {
),
borderRadius: visibleIndex == 0
? const .vertical(top: Radius.circular(8))
- : (visibleIndex + 1) == visibleItems.length
+ : (visibleIndex + 1) == visibleCount
? const .vertical(bottom: Radius.circular(8))
: null,
),
diff --git a/lib/app/map/page.dart b/lib/app/map/page.dart
index 83ce0e586..4946772a7 100644
--- a/lib/app/map/page.dart
+++ b/lib/app/map/page.dart
@@ -62,8 +62,14 @@ class MapPage extends StatefulWidget {
/// Optional configuration controlling the initial layer and report state.
final MapPageOptions? options;
+ /// Whether to display the floating back button on the top-left.
+ ///
+ /// Set to `false` when embedding the map as a shell tab where the bottom
+ /// nav already provides navigation.
+ final bool showBackButton;
+
/// Creates a [MapPage] with optional [options].
- const MapPage({super.key, this.options});
+ const MapPage({super.key, this.options, this.showBackButton = true});
/// Returns the route path for this page, including any query parameters
/// derived from [options].
@@ -148,31 +154,12 @@ class _MapPageState extends State with TickerProviderStateMixin {
}
void _setupWeatherLayerTimeSync() {
- final temperatureManager = getLayerManager(
- MapLayer.temperature,
- );
- temperatureManager?.onTimeChanged = (time) {
- syncTimeToRadar(time);
- };
-
- final precipitationManager = getLayerManager(
- MapLayer.precipitation,
- );
- precipitationManager?.onTimeChanged = (time) {
- syncTimeToRadar(time);
- };
-
- final windManager = getLayerManager(MapLayer.wind);
- windManager?.onTimeChanged = (time) {
- syncTimeToRadar(time);
- };
-
- final lightningManager = getLayerManager(
- MapLayer.lightning,
- );
- lightningManager?.onTimeChanged = (time) {
- syncTimeToRadar(time);
- };
+ getLayerManager(MapLayer.temperature)?.onTimeChanged =
+ syncTimeToRadar;
+ getLayerManager(MapLayer.precipitation)?.onTimeChanged =
+ syncTimeToRadar;
+ getLayerManager(MapLayer.wind)?.onTimeChanged = syncTimeToRadar;
+ getLayerManager(MapLayer.lightning)?.onTimeChanged = syncTimeToRadar;
}
Future _syncRadarTimeOnCombination(MapLayer newLayer) async {
@@ -284,13 +271,14 @@ class _MapPageState extends State with TickerProviderStateMixin {
Future setLayers(Set layers) async {
if (!mounted) return;
- for (final layer in layers) {
- final manager = _managers[layer];
- if (manager != null) {
+ await Future.wait(
+ layers.map((layer) async {
+ final manager = _managers[layer];
+ if (manager == null) return;
if (!manager.didSetup) await manager.setup();
await manager.show();
- }
- }
+ }),
+ );
setState(() => _activeLayers = layers);
}
@@ -385,7 +373,7 @@ class _MapPageState extends State with TickerProviderStateMixin {
onLayerChanged: toggleLayer,
onBaseMapChanged: setBaseMapType,
),
- PositionedBackButton(onPressed: _handleBack),
+ if (widget.showBackButton) PositionedBackButton(onPressed: _handleBack),
..._activeLayers.map((layer) {
final manager = _managers[layer];
if (manager != null) {
diff --git a/lib/app/new_home/_models/home_model.dart b/lib/app/new_home/_models/home_model.dart
new file mode 100644
index 000000000..abd9de420
--- /dev/null
+++ b/lib/app/new_home/_models/home_model.dart
@@ -0,0 +1,136 @@
+/// Provider model for the home page weather data and temporary location override.
+library;
+
+import 'dart:async';
+
+import 'package:collection/collection.dart';
+import 'package:dpip/api/model/history/history.dart';
+import 'package:dpip/api/model/weather_schema.dart';
+import 'package:dpip/global.dart';
+import 'package:dpip/models/settings/location.dart';
+import 'package:dpip/utils/log.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+/// Manages weather data and a temporary location override for the home page.
+///
+/// Pass the app-level [SettingsLocationModel] at construction; the model
+/// subscribes to it internally and re-fetches whenever the persisted location
+/// changes (unless a temporary override is active).
+///
+/// Call [setTemporaryCode] to temporarily show weather for a different location.
+/// Call [startAutoRefresh] once on page init to begin a 30-minute refresh cycle.
+class HomeModel extends ChangeNotifier {
+ static const _autoRefreshInterval = Duration(minutes: 30);
+
+ final SettingsLocationModel _settingsLocation;
+ String? _temporaryCode;
+ RealtimeWeather? _weather;
+ List _alerts = const [];
+ Map? _forecast;
+ Timer? _autoRefreshTimer;
+
+ /// Creates a [HomeModel] backed by [settingsLocation].
+ ///
+ /// Attaches a listener so the model re-fetches automatically when the
+ /// persisted location changes.
+ HomeModel(this._settingsLocation) {
+ _settingsLocation.addListener(_onSettingsLocationChanged);
+ }
+
+ void _onSettingsLocationChanged() {
+ if (_temporaryCode == null) _doRefresh();
+ }
+
+ /// Runs [task] and logs failures under [tag]; returns `null` on error.
+ static Future _safe(String tag, Future Function() task) async {
+ try {
+ return await task();
+ } catch (e) {
+ TalkerManager.instance.error('HomeModel $tag', e);
+ return null;
+ }
+ }
+
+ Future _doRefresh() async {
+ final code = _temporaryCode ?? _settingsLocation.code;
+ final loc = code != null ? Global.location[code] : null;
+ final lat = loc?.lat ?? _settingsLocation.coordinates?.latitude;
+ final lon = loc?.lng ?? _settingsLocation.coordinates?.longitude;
+ if (lat == null || lon == null) return;
+
+ // Fetch weather + alerts + forecast in parallel.
+ final results = await Future.wait