318 Commits
Author SHA1 Message Date
harukin-expo-dev-env ff8313ee42 feat: 音声案内テキストの全角スペースを適切な読点に置換し、発車時刻表の表示を改善 2026-07-30 08:12:22 +00:00
harukin-expo-dev-env 22ce82a799 feat: りっかちゃん音声案内基盤を拡張 2026-07-29 05:31:35 +00:00
harukin-expo-dev-env 37c3a80483 Merge commit '5df00c8b1766969c3c71154733dc4fa098fd8468' into experimental/station-announce-tools 2026-07-15 08:04:41 +00:00
harukin-expo-dev-env a89c896012 fix: 列車情報の時間フィルタリングロジックを改善し、再生中の基準時刻を追加 2026-07-14 10:49:31 +00:00
harukin-expo-dev-env dfec6d1c89 fix: 列車情報の表示ロジックを改善し、条件付きHTML生成を追加 2026-07-14 09:11:23 +00:00
harukin-expo-dev-env b97531d5b4 feat: 列車タイプのラッピング処理を追加し、表示ロジックを改善 2026-07-14 05:57:05 +00:00
harukin-expo-dev-env bb6873eb10 feat: JR-WEST-PLUSフォントの調整と表示領域の正規化を実施 2026-07-14 04:26:38 +00:00
harukin-expo-dev-env 2e6586260c feat: JR-WEST-PLUSフォントを追加し、フォント設定を最適化 2026-07-14 02:51:41 +00:00
harukin-expo-dev-env 12b01edb3e fix: 修正された列車データの取得と表示ロジックを改善し、未登録列車の処理を追加 2026-07-14 00:46:35 +00:00
harukin-expo-dev-env ca045ca3a3 feat: Implement X投稿向け運行情報画像セット generation in ndView.tsx
- Added functionality to generate a set of images for posting to X (formerly Twitter) with multiple images.
- Introduced a new button for creating X投稿向け画像, which generates up to 4 PNG images.
- The first image serves as a cover with a route map and summary, while subsequent images contain detailed operation information.
- Ensured images maintain a fixed size of 1080 x 1440 px and follow specific naming conventions.
- Implemented error handling for image generation failures and ensured compatibility with existing sharing features.
- Updated UI elements and styles for the new functionality, including button states and layout adjustments.
- Added necessary TypeScript type checks and validation for the new features.
2026-07-12 19:01:51 +00:00
harukin-expo-dev-env 092590bc3d 型定義を改善し、originalStationListの使用を最適化 2026-07-12 15:35:00 +00:00
harukin-expo-dev-env 9fe6f3ebf3 履歴管理機能を追加し、ビューポートメタタグの管理を強化 2026-07-10 11:28:15 +00:00
harukin-expo-dev-env 3f6b9da6c5 Adjust train type badge rendering 2026-07-09 10:15:49 +00:00
harukin-expo-dev-env 3ead0cbe10 各種機能の改善と最適化、ナビゲーションの明示的なターゲット設定を追加 2026-07-08 14:39:15 +00:00
harukin-expo-dev-env d4db82cc65 各種データの取得フラグ機能を実装、動作の最適化 2026-07-08 01:39:29 +00:00
harukin-expo-dev-env 873acde54b Tune data fetch observability after first run 2026-07-07 04:10:24 +00:00
harukin-expo-dev-env a6fa5dfadb Add data fetch observability 2026-07-07 02:47:13 +00:00
harukin-expo-dev-env 658c3f01a5 Guard iOS webview remount on tab blur 2026-07-04 15:57:04 +00:00
harukin-expo-dev-env 93806a274a Adjust WebView remount behavior for background tabs 2026-07-03 10:24:41 +00:00
harukin-expo-dev-env 34542c35c3 Merge commit 'dd0b4bf312f8f5d255f7cb5a0bc27d8bda43b5e9' into experimental/station-announce-tools 2026-07-01 12:11:25 +00:00
harukin-expo-dev-env b783157553 Add recording JSON import and export 2026-06-29 14:39:30 +00:00
harukin-expo-dev-env fed1044089 Voicepeak APIの案内音声再生タイミングを変更 2026-06-29 04:51:21 +00:00
harukin-expo-dev-env 3c5b403fb5 Merge commit '65f248f658482f2aa64fb0246a33ea7d19c72bad' into experimental/station-announce-tools 2026-06-25 17:47:42 +00:00
harukin-expo-dev-env 497265c5f9 団体臨時から臨時を削除 2026-06-25 16:01:31 +00:00
harukin-expo-dev-env 28950019c6 アイコンステータスの表示改善 2026-06-23 17:11:28 +00:00
harukin-expo-dev-env c44bad5f86 unyohubアイコン対応 2026-06-23 16:40:44 +00:00
harukinMBP d27b75cbd3 feat: Voicepeak発車案内機能の強化とネイティブオーディオサポートの追加 2026-06-06 17:47:29 +09:00
harukinMBP 08147b7f26 feat: Voicepeak発車案内機能の追加と設定管理の実装 2026-06-06 17:47:29 +09:00
harukin-expo-dev-env 3b3d5d0ed6 feat: えれサイトの列車情報をグループ化し、表示を改善 2026-06-05 12:31:54 +00:00
harukin-expo-dev-envandCopilot ce4172d327 fix: マリンライナー編成順序の修正(elesite連携)
マリンライナー(3xxxM)の岡山〜高松間の駅シーケンスを
elesiteTrainOrder.ts と webViewInjectjavascript.ts に追加。
originData には JR 西日本区間の駅がないため、
MARINE_STATION_SEQUENCE としてインラインで定義した。

これにより heading_to:"unknown" のマリン系統でも
正しく進行方向を推論できるようになり、
連結順序が逆順になる問題を解消した。

Co-authored-by: Copilot <[email protected]>
2026-05-20 13:48:47 +00:00
harukin-expo-dev-env 48a078f831 feat: add experimental diagram URL support and update related components 2026-05-19 03:06:45 +00:00
harukin-expo-dev-env 17565da7ab Refactor Elesite sorting logic and introduce new utility functions
- Moved the Elesite sorting logic to a new module `elesiteTrainOrder.ts`.
- Created utility functions to infer heading direction and sort Elesite entries by train number.
- Updated `injectJavascriptData` to utilize the new sorting logic and handle station sequences.
- Refactored `useElesite` to use the new sorting utility for improved readability and maintainability.
2026-05-15 17:21:18 +00:00
harukin-expo-dev-env eb0ca2ead4 Merge commit 'a112f3947b6cd5e81802a16db454861a734cd8b7' into develop 2026-05-05 08:09:57 +00:00
harukin-expo-dev-env 86092b33de Add script to compile web inject JavaScript with minification and obfuscation options
- Introduced `compile-web-script.ts` for generating JavaScript files for userscripts.
- Supports options for minification and obfuscation.
- Generates base JS, minified JS, and obfuscated userscript.
- Configurable via command line arguments and environment variables.
2026-05-05 08:04:47 +00:00
harukin-expo-dev-envandCopilot 1c5fbca65d fix: use /train-positions/current endpoint for mock polling
Co-authored-by: Copilot <[email protected]>
2026-05-03 18:25:47 +00:00
harukin-expo-dev-envandCopilot a59faa9341 feat: poll mock API server for live train positions
- positionMasters: add fetchMockTrainPositions() targeting
  /train-positions/latest on the mock API server
- useTrainMenu: when mockApiFeatureEnabled and not recording/playing,
  poll /train-positions/latest every 15s and update mockTrainPositions
  (same interval as live mode); on mode switch updates immediately
- useCurrentTrain:
  - playing: use local recording data (no network call)
  - mock ON idle: fetch from mock API server (15s poll driven by useTrainMenu)
  - mock OFF: fetch from real backend as before
- Recording still forces mock OFF so real API data is captured

Co-authored-by: Copilot <[email protected]>
2026-05-03 18:01:12 +00:00
harukin-expo-dev-envandCopilot a4416de1bc feat: integrate position-masters API into mock system
- Add lib/mockApi/positionMasters.ts
  - fetchPositionMasters() from jr-shikoku-backend-mock-api-v1.haruk.in
  - buildPosLookup() / lookupPos() helpers
  - serializePosLookupForJs() for baking into injected scripts
- webviewXhrInterceptor: accept positionMasters in MockApiConfig,
  bake _POS_LOOKUP into injected JS, enrich Pos from PosNum on serve
- useTrainMenu: fetch position masters on mock-enable (and at startup
  if already enabled); expose positionMasters + lookupPosText()
- useCurrentTrain: fill Pos via lookupPosText when mapping mock data
- mockApi/index.ts: re-export positionMasters types and helpers

Co-authored-by: Copilot <[email protected]>
2026-05-03 17:46:13 +00:00
harukin-expo-dev-env bd1b1f15c0 fix: update header colors in injected JavaScript for better visibility 2026-05-02 02:52:22 +00:00
harukin-expo-dev-envandCopilot 922add003a fix: sync WebView train display when playback frame changes
The XHR interceptor baked _MOCK_TRAIN at page load time, so seeking or
advancing a playback frame only changed React state but had no effect
on the already-loaded WebView page.

- webviewXhrInterceptor.ts:
  - Expose window.__jrsMockUpdateTrain(newData) from inside the IIFE so
    the _MOCK_TRAIN variable can be updated after page load
  - Add generateMockUpdateScript(trainPositions) helper: calls
    __jrsMockUpdateTrain with fresh data + GetDateTime, then calls
    window.setReload() to trigger the page's own redraw cycle

- WebView.tsx:
  - Import generateMockUpdateScript
  - Add useEffect watching mockTrainPositions (skips first mount since
    beforeContentLoaded already has correct data)
  - When mockApiFeatureEnabled && mockTrainPositions changes, inject the
    update script via webview.current.injectJavaScript()

Result: seeking, prev/next frame, and auto-advance during playback now
immediately update the train position display in the WebView.

Co-authored-by: Copilot <[email protected]>
2026-05-02 01:06:34 +00:00
harukin-expo-dev-envandCopilot 77f15345e5 fix: crash on playback start + support multiple recordings
Crash fix (React Hooks violation):
- PlaybackTimeline.tsx: move ALL hooks (useRef for PanResponder, useCallback)
  to before the early return; use seekRef/totalRef to share values into
  PanResponder handlers without stale closure issues

Multiple recordings support:
- trainRecorder.ts: redesign to id-based multi-recording system
  - RecordingMeta type for lightweight list (no snapshots)
  - TrainRecording now includes id field
  - saveRecording/loadRecordingById/deleteRecordingById/loadRecordingList
  - migrateOldRecording() migrates old single MOCK_RECORDING key on first launch
- constants/storage.ts: add MOCK_RECORDINGS_INDEX + MOCK_RECORDING_DATA_PREFIX keys
- useTrainMenu: savedRecording → recordingList (RecordingMeta[]) + activeRecording (TrainRecording|null)
  - startPlayback(id) loads full recording on demand
  - deleteRecording(id) deletes by id and refreshes list
  - stopPlayback clears activeRecording
- DataSourceSettings: recording list UI
  - shows all recordings with date/time, snapshot count, duration
  - ▶ play and 削除 buttons per row
  - recording/playing status indicator

Co-authored-by: Copilot <[email protected]>
2026-05-02 00:52:30 +00:00
harukin-expo-dev-envandCopilot 597151e875 feat: add train position record & playback feature
Implements snapshot-based recording and playback of live train
position data for mock API debugging (admin-only).

Recording:
- startRecording() disables mock mode and begins capturing live
  train snapshots every ~15s (via getCurrentTrain polling)
- Each snapshot stores { t: elapsed_ms, trains: TrainEntry[] }
- stopRecording() saves completed recording to AsyncStorage

Playback:
- startPlayback() enables mock mode and loops through snapshots
  at their original recorded timing using useEffect+setTimeout
- stopPlayback() returns to idle

Storage:
- Single slot in AsyncStorage (MOCK_RECORDING key)
- Loaded on app start in useTrainMenu
- deleteRecording() removes it

New files:
- lib/mockApi/trainRecorder.ts — TrainRecording/TrainSnapshot types
  + save/load/delete AsyncStorage helpers

Modified files:
- constants/storage.ts — add MOCK_RECORDING key
- stateBox/useTrainMenu.tsx — recorder state + all controls
- stateBox/useCurrentTrain.tsx — call addTrainSnapshot after live fetch
- components/Settings/DataSourceSettings.tsx — record/play UI with
  status dot, snapshot count, and action buttons

Co-authored-by: Copilot <[email protected]>
2026-05-02 00:31:55 +00:00
harukin-expo-dev-env 224ce83abf fix: update useWebViewRemount to include backgroundThresholdMs option for better app state handling 2026-05-01 23:25:50 +00:00
harukin-expo-dev-envandCopilot 1176234c08 refactor: remove map-screen MOCK switch; settings toggle controls mock directly
The separate runtime MOCK switch on the map screen is removed.
Now the admin-only settings toggle (MOCK_API_FEATURE_ENABLED) is the
single control point — turning it on activates mock mode immediately,
turning it off deactivates it.

- useTrainMenu: remove mockApiEnabled/setMockApiEnabled state;
  mockApiConfig now derives from mockApiFeatureEnabled alone
- WebView: use mockApiFeatureEnabled for key prop (triggers reload)
- Apps.tsx: remove MockApiToggle import and JSX usage

Co-authored-by: Copilot <[email protected]>
2026-05-01 12:35:36 +00:00
harukin-expo-dev-envandCopilot 85b0eb5b58 fix: eliminate UX flash by calling setStrings() immediately in observer
The 100ms pure-debounce approach caused a visible layout flash on every
render (normal mode too) because Tokyo UX was not applied for 100ms.

Fix: call setStrings() immediately in the MutationObserver callback to
prevent any flash, AND keep a 250ms delayed follow-up call to catch
async train re-renders from mock XHR setTimeout(0) responses.

Co-authored-by: Copilot <[email protected]>
2026-05-01 11:59:52 +00:00
harukin-expo-dev-envandCopilot 8885a70792 fix: re-apply Tokyo UX after async train re-renders
Root cause: setStrings() was called synchronously in setReload(),
but the mock XHR interceptor responds via setTimeout(0), so the
site re-rendered train elements AFTER setStrings() ran, stripping
Tokyo UX styling.

Two-pronged fix:
1. setReload() now calls setStrings() again after 200ms to
   re-apply Tokyo UX once the async re-render completes.
2. textInsert MutationObserver now watches with subtree:true
   (childList only, not attributes - no infinite loop risk)
   with 100ms debouncing, so ANY train element re-render
   (including those triggered by mock XHR data) will trigger
   a re-application of Tokyo UX.
   - currentLines postMessage now only fires when direct
     children of #disp change (line selection changes only)

Co-authored-by: Copilot <[email protected]>
2026-05-01 11:51:13 +00:00
harukin-expo-dev-envandCopilot c6aecd151c fix: Tokyo UX stripped when mock is active
Two bugs caused the Tokyo UX to be stripped/broken when mock mode was ON:

1. **Double callback firing**: the interceptor's `setTimeout` called both
   `onreadystatechange.call(self)` AND `dispatchEvent(new Event('readystatechange'))`.
   Since `dispatchEvent` already fires `onXxx` property handlers via the DOM event
   model, the page's callback fired twice, causing a second DOM re-render that could
   overwrite Tokyo UX modifications. Fixed by relying on `dispatchEvent` only (with
   `ProgressEvent` for load events), with a direct-call fallback only for environments
   that lack `dispatchEvent`.

2. **No double-injection guard**: if `injectedJavaScriptBeforeContentLoaded` caused
   the interceptor to run more than once (e.g., `onPageStarted` fires multiple times
   on Android), `_origOpen` would capture the already-patched version, leading to
   unexpected behaviour. Fixed by adding `if (window.__jrsMockActive) return;` at the
   top of the interceptor IIFE.

3. **Belt-and-suspenders injection**: the interceptor is now also prepended to
   `injectedJavaScript` (Tokyo UX script) via the restored `mockApiConfig` parameter
   on `injectJavascriptData`. The `__jrsMockActive` guard ensures it's a no-op when
   `injectedJavaScriptBeforeContentLoaded` already ran it, but guarantees the
   interceptor is active on platforms where IJBCL is unreliable — before
   `MoveDisplayStation` triggers the first train-data poll via `onLoadEnd`.

Co-authored-by: Copilot <[email protected]>
2026-05-01 11:40:11 +00:00
harukin-expo-dev-envandCopilot 8ee546277c chore: update train.json with live disrupted data (2026-05-01 19:42)
94列車、62列車遅延の運行乱れデータをキャプチャ。
モックAPIのテストデータとして有用な状態。

Co-authored-by: Copilot <[email protected]>
2026-05-01 10:43:19 +00:00
harukin-expo-dev-envandCopilot 547b5074db fix: call _origOpen even when intercepting to allow setRequestHeader
インターセプト対象のXHRでも_origOpen()を呼ぶよう修正。
これによりXHRがOPENED状態に入り、ページ側のsetRequestHeader()呼び出しが
エラーなく実行される。実際のリクエストはsend()でブロックすることで
モックデータのみ返す動作は維持される。

Playwright実機テスト結果:
- arg1=train&arg2=train: 2回インターセプト成功、実ネットワーク0件
- setRequestHeaderエラー: 解消
- 路線選択後のstation dataロード: 正常動作

Co-authored-by: Copilot <[email protected]>
2026-04-30 22:49:22 +00:00
harukin-expo-dev-envandCopilot 75fce29d74 fix: move XHR interceptor to injectedJavaScriptBeforeContentLoaded
インターセプターをページスクリプトより前に実行されるよう修正。
injectedJavaScript(ページ読込後)からinjectedJavaScriptBeforeContentLoaded
(ページスクリプト実行前)へ移動することで、モックON時のページフリーズを解消。

- lib/webViewInjectjavascript.ts: injectJavascriptDataからインターセプターを分離、
  generateBeforeContentLoadedScript()を新規エクスポート
- stateBox/useTrainMenu.tsx: injectJavascriptBeforeContentLoadedを別途計算しコンテキストに追加
- components/Apps/WebView.tsx: injectedJavaScriptBeforeContentLoadedプロップを追加

Co-authored-by: Copilot <[email protected]>
2026-04-30 16:50:55 +00:00
harukin-expo-dev-envandCopilot c31d35c099 fix: rewrite XHR interceptor using prototype patching
Replaces the MockXHR wrapper class with direct prototype patching.

Root cause of broken page:
1. CRITICAL: callbacks called without .call(self) → 'this' inside
   onload/onreadystatechange was the global object, so this.responseText
   returned undefined and the page's JSON.parse crashed silently
2. responseType='json' not handled → page received string instead of
   parsed object when using xhr.response
3. instanceof XMLHttpRequest returned false, potentially breaking page
   validation logic

New approach (prototype-patch):
- Save original XMLHttpRequest.prototype.open and .send
- Patch open() to detect mock URL and store mock body on the instance
- Patch send() to define instance-level property getters (status,
  responseText, response, readyState) and fire callbacks with correct
  'this' context via .call(self)
- responseType='json' handled: response getter returns parsed object
- instanceof XMLHttpRequest always true (prototype chain untouched)
- dispatchEvent fires load/readystatechange for addEventListener users
- Non-mock requests delegate to original open/send unchanged

All 6 test cases pass: onload, onreadystatechange, addEventListener,
responseType=json, instanceof, and non-mock pass-through

Co-authored-by: Copilot <[email protected]>
2026-04-30 16:05:41 +00:00