Skip to content

fix(app): 乘客端叫車的定位出口——定位服務關著時整條是靜默的(第二十二輪) - #93

Merged
thothawei merged 1 commit into
mainfrom
claude/next-task-ff48fd
Jul 30, 2026
Merged

thothawei merged 1 commit into
mainfrom
claude/next-task-ff48fd

Conversation

@thothawei

Copy link
Copy Markdown
Owner

根因

第二十一輪換族到「定位健康度」,這一輪把同族的乘客端清完。三個病都在 placeOrder 這一條路上:

  1. 靜默_acquirePosition 只攔 TimeoutException,而系統定位服務被關掉時 getCurrentPosition 丟的是 LocationServiceDisabledExceptionplaceOrdercatch 只收 ApiException,例外整個穿出去變成未處理的非同步錯誤——_error 沒被設、busyfinally 清掉,乘客按下叫車只看到按鈕轉一下就回到原狀
  2. 文案沒有出路deniedForever 之後 requestPermission 不會再彈任何視窗,訊息卻只說「需要定位權限才能叫車」,乘客在 App 裡按到死都按不出結果。
  3. 不必要的阻擋:多停靠點行程的 pickup/dropoff 由 stops 推導(後端 prepareStops 會覆蓋座標欄位,根本不看 App 送的那組),placeOrder 卻照樣先要權限再等 GPS fix。程式碼裡「N3:多乘客模式下…故不需要定位」那句註解本來就是對的,是實作與它矛盾

順手第四個:司機端 goOffline() 清了 _locationStreamFailed 卻沒清那句紅字,離線後畫面仍寫「請開啟才能接單」。只清這一類,後端明確拒絕的業務錯誤不動。

修法

  • 新增 lib/core/location/customer_locator.dart:geolocator 的四個呼叫抽成介面。接縫刻意開在最外層呼叫,不是「餵一個錯誤給錯誤處理函式」——後者測不到「哪一種例外從哪一支呼叫冒出來」,把 on ... 分支拔掉照樣會綠。
  • _resolvePickupPosition():三種失敗分開講(定位服務關閉/權限被永久拒絕含「去系統設定」/拿不到 fix)。
  • 多停靠點跳過定位,pickupLat/Lng 用第一個上車點(送 (0,0) 會被後端 validatePickupCoords 判成無效座標)。

驗收

  • flutter analyze 無 issue、flutter test 377 passed(367 +乘客 8 +司機 2)。
  • 反向驗證三半各一次:拿掉例外分支 → 2 案 FAIL;拿掉 deniedForever 分岔 → 2 案 FAIL;讓多停靠點回去走定位路徑 → 2 案 FAIL。
  • 模擬器實跑m6_pixel +本機後端,settings put secure location_mode 0):
情境 結果
正向對照(定位開著) ride #35 建單成功
定位關閉+單點叫車 SnackBar「裝置定位服務已關閉,請開啟後再叫車」
同上另一次 走到「目前無法取得定位…」——geolocator 在同一情境有時丟 TimeoutException,兩條出口都有話講
定位關閉+多停靠點 建單成功 ride #36pickup_point =第一個上車點,ride_stops 兩筆,全程沒碰 GPS
  • 同場補完第二十一輪留的實跑尾巴:hero 真的會降級成「位置回報失敗,暫時收不到派單」,恢復也成立;但這台模擬器造不出「串流永久靜止」location_mode=0 後 geolocator 有時仍持續吐位置,後端照樣每 8 秒收到 200,此時回綠是正確的),所以「定期重評」那一半只驗到局部——TODO 已寫明,不宣稱兩半都實跑過

學到的兩條(已寫進 TODO)

  1. 同一個 API 在同一情境不保證丟同一種例外——出口要按「使用者的下一步」分類,不要賭例外型別。
  2. 短命 UI 的負向斷言要用連拍:我一開始在裝置上「看不到 SnackBar」差點誤判成沒顯示,widget tree dump 顯示它就在 Scaffold 的 snackBar slot(offset y=842.3、高 72),是截圖落在它出現之前。

🤖 Generated with Claude Code

第二十一輪換族到「定位健康度」,這一輪把同族的乘客端清完。三個病都在 placeOrder:

1. 靜默:_acquirePosition 只攔 TimeoutException,系統定位服務被關時
   getCurrentPosition 丟的是 LocationServiceDisabledException,而 placeOrder 的
   catch 只收 ApiException——例外整個穿出去變成未處理的非同步錯誤,_error 沒設、
   busy 被 finally 清掉,乘客按下叫車只看到按鈕轉一下就回到原狀。
2. deniedForever 之後 requestPermission 不會再彈窗,文案卻只說「需要定位權限」,
   乘客在 App 裡按到死都按不出結果——現在會說要去系統設定。
3. 多停靠點行程的 pickup/dropoff 由 stops 推導(後端 prepareStops 覆蓋座標欄位,
   根本不看 App 送的那組),卻照樣先要權限再等 GPS fix。程式碼裡的註解本來就寫著
   「不需要定位」,是實作與它矛盾。現在改用第一個上車點的座標,不再碰 GPS。

順手第四個:司機端 goOffline() 清了 _locationStreamFailed 卻沒清那句紅字,
離線後畫面仍寫「請開啟才能接單」。只清這一類,業務錯誤不動。

測試接縫 CustomerLocator 刻意開在最外層的 geolocator 呼叫,不是餵錯誤給
錯誤處理函式——後者測不到「哪一種例外從哪一支呼叫冒出來」,把 on 分支拔掉照樣綠。

驗收:flutter analyze 無 issue、flutter test 377 passed(367+乘客 8+司機 2)。
反向驗證三半各跑一次,各 2 案 FAIL。模擬器實跑(m6_pixel,location_mode=0):
單點叫車出現「裝置定位服務已關閉,請開啟後再叫車」;多停靠點在定位關著時建單成功
(ride #36,pickup_point = 第一個上車點,ride_stops 兩筆)。
同場補完第二十一輪留的實跑尾巴:hero 真的會降級、恢復也成立,但這台模擬器
造不出「串流永久靜止」,定期重評那一半只驗到局部——文件已寫明,不宣稱兩半都驗過。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@thothawei
thothawei merged commit 867f6e2 into main Jul 30, 2026
2 checks passed
@thothawei
thothawei deleted the claude/next-task-ff48fd branch August 1, 2026 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant