From dc3d250466011256dee166b4367d40d90cf23dfd Mon Sep 17 00:00:00 2001 From: harukin-expo-dev-env Date: Tue, 24 Mar 2026 01:39:31 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=AC=A1=E9=A7=85=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=82=92Direction=E9=9D=9E=E4=BE=9D=E5=AD=98=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=EF=BC=88JS/Kotlin=E4=B8=A1=E6=96=B9=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JS側: currentPosition[0]ではなくstopStationIDList上のmax(idx0,idx1)で進行方向の駅を判定 - Kotlin側: pollRunnable復活、allStationsのダイヤ順でmaxOf(idx0,idx1)で向かう駅を判定 - Kotlin at-station: 停車中は現在駅を表示(JS側と統一) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Apps/FixedPositionBox/FixedTrainBox.tsx | 13 ++- .../LiveActivityForegroundService.kt | 101 ++++++++++++------ 2 files changed, 80 insertions(+), 34 deletions(-) diff --git a/components/Apps/FixedPositionBox/FixedTrainBox.tsx b/components/Apps/FixedPositionBox/FixedTrainBox.tsx index d32b727..8e9486a 100644 --- a/components/Apps/FixedPositionBox/FixedTrainBox.tsx +++ b/components/Apps/FixedPositionBox/FixedTrainBox.tsx @@ -217,12 +217,17 @@ export const FixedTrain: FC = ({ trainID }) => { const delayTime = train?.delay == "入線" ? 0 : train?.delay; let additionalSkipCount = 0; - // 2駅間走行中の場合: currentPosition[0]が向かう駅IDなので - // trainDataWidhThroughでその駅以降の最初の停車駅を探す + // 2駅間走行中の場合: ダイヤ順で後ろのインデックスが進行方向の駅 + // Direction に関係なく、travel-order で大きい方が「向かう駅」 let searchStart: number; if (currentPosition.length === 2) { - const toIdx = stopStationIDList.findIndex(d => d.includes(currentPosition[0])); - searchStart = toIdx >= 0 ? toIdx : searchCountLast; + const idx0 = stopStationIDList.findIndex(d => d.includes(currentPosition[0])); + const idx1 = stopStationIDList.findIndex(d => d.includes(currentPosition[1])); + const aheadIdx = Math.max( + idx0 >= 0 ? idx0 : -1, + idx1 >= 0 ? idx1 : -1 + ); + searchStart = aheadIdx >= 0 ? aheadIdx : searchCountLast; } else { searchStart = searchCountFirst; } diff --git a/modules/expo-live-activity/android/src/main/java/expo/modules/liveactivity/LiveActivityForegroundService.kt b/modules/expo-live-activity/android/src/main/java/expo/modules/liveactivity/LiveActivityForegroundService.kt index 5275326..a76f254 100644 --- a/modules/expo-live-activity/android/src/main/java/expo/modules/liveactivity/LiveActivityForegroundService.kt +++ b/modules/expo-live-activity/android/src/main/java/expo/modules/liveactivity/LiveActivityForegroundService.kt @@ -62,9 +62,12 @@ class LiveActivityForegroundService : Service() { private val handler = Handler(Looper.getMainLooper()) private val pollRunnable = object : Runnable { override fun run() { - // ポーリングは無効化。JS側が10秒ごとに更新を送信する。 - // ネイティブ側のポーリングはDirectionを考慮できず - // JS側の更新と競合して不正な表示になるため。 + if (!isRunning) return + when (currentMode) { + "train" -> executor.execute { pollTrainPosition() } + "station" -> executor.execute { pollStationTrains() } + } + handler.postDelayed(this, POLL_INTERVAL_MS) } } @@ -233,37 +236,75 @@ class LiveActivityForegroundService : Service() { val delay = parseDelay(train) val stationStops = parseLinesJson(stationStopsJson) - val posStations = pos.split("~") - val currentStation = posStations.firstOrNull() - ?.replace("(下り)", "")?.replace("(上り)", "") - ?.replace("(下り)", "")?.replace("(上り)", "") - ?.trim() ?: "" - val nextStation = if (posStations.size > 1) { - posStations[1] - .replace("(下り)", "").replace("(上り)", "") - .replace("(下り)", "").replace("(上り)", "") - .trim() - } else "" - - // allStationsから現在地インデックスを計算 val allStations = parseAllStationsJson(allStationsJson) - val currentIndex = if (allStations.isNotEmpty()) { - allStations.indexOfFirst { it.first == currentStation }.let { if (it < 0) 0 else it } - } else { - if (stationStops.isNotEmpty() && currentStation.isNotEmpty()) { - stationStops.indexOf(currentStation).let { if (it < 0) 0 else it } - } else 0 - } - val progressTotal = if (allStations.isNotEmpty()) allStations.size else stationStops.size - val delayText = if (delay > 0) "${delay}分遅れ" else "定刻" + // Posの方向表記を除去 + val cleanedPos = pos + .replace("(下り)", "").replace("(上り)", "") + .replace("(下り)", "").replace("(上り)", "") + .replace("(徳島線)", "").replace("(高徳線)", "") + .replace("(坂出方)", "").replace("(児島方)", "") + .trim() + val posStations = cleanedPos.split("~").map { it.trim() } val isAtStation = posStations.size <= 1 + + // allStationsのダイヤ順で現在地と次の停車駅を決定 + var nextStopName = "" + var currentIndex = 0 + + if (allStations.isNotEmpty()) { + if (isAtStation) { + // 駅に停車中: 現在駅を表示(JS側と同じ "ただいま [駅名]") + val stationName = posStations.firstOrNull() ?: "" + val idx = allStations.indexOfFirst { it.first == stationName } + currentIndex = if (idx >= 0) idx else 0 + nextStopName = stationName + } else { + // 2駅間走行中: 両方の駅をallStationsで見つけ、ダイヤ上で後ろにある方が向かう駅 + val idx0 = allStations.indexOfFirst { it.first == posStations[0] } + val idx1 = allStations.indexOfFirst { it.first == posStations.getOrElse(1) { "" } } + val towardIdx: Int + if (idx0 >= 0 && idx1 >= 0) { + // ダイヤ順で後ろの方が「向かっている駅」 + towardIdx = maxOf(idx0, idx1) + currentIndex = minOf(idx0, idx1) + } else if (idx0 >= 0) { + towardIdx = idx0 + currentIndex = idx0 + } else if (idx1 >= 0) { + towardIdx = idx1 + currentIndex = idx1 + } else { + towardIdx = 0 + currentIndex = 0 + } + // 向かう駅以降で最初の停車駅を探す + for (i in towardIdx until allStations.size) { + if (allStations[i].second) { // isStop == true + nextStopName = allStations[i].first + break + } + } + if (nextStopName.isEmpty() && posStations.size > 1) { + nextStopName = posStations[1] + } + } + } else { + // allStationsが空の場合のフォールバック + val stationName = posStations.firstOrNull() ?: "" + currentIndex = if (stationStops.isNotEmpty()) { + stationStops.indexOf(stationName).let { if (it < 0) 0 else it } + } else 0 + nextStopName = if (posStations.size > 1) posStations[1] else stationName + } + + val progressTotal = if (allStations.isNotEmpty()) allStations.size else stationStops.size + val delayText = if (delay > 0) "${delay}分遅れ" else "定刻" val positionLabel = if (isAtStation) "ただいま" else "次は" - val displayStation = if (isAtStation) currentStation else nextStation val bodyLines = mutableListOf() - bodyLines.add("$positionLabel $displayStation") - if (!isAtStation && currentStation.isNotEmpty() && nextStation.isNotEmpty()) { - bodyLines.add("${currentStation}~${nextStation}間走行中") + bodyLines.add("$positionLabel $nextStopName") + if (!isAtStation) { + bodyLines.add("${cleanedPos}間走行中") } bodyLines.add(delayText) val body = bodyLines.joinToString("\n") @@ -279,7 +320,7 @@ class LiveActivityForegroundService : Service() { val nm = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(NOTIFICATION_ID, notification) } - Log.d(TAG, "Poll updated: pos=$pos delay=$delay") + Log.d(TAG, "Poll updated: pos=$pos nextStop=$nextStopName delay=$delay") } catch (e: Exception) { Log.e(TAG, "Poll error", e) }