Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fb3d26e
テレメトリにインタラクションイベント送信を実装しアプリ起動時にapp_launchを送信 (#6391)
TinyKitten Jul 11, 2026
665ccde
Bump version for canary release (#6393)
github-actions[bot] Jul 11, 2026
2c3140c
origin/dev をマージし versionName の競合を 10.9.0 で解決
TinyKitten Jul 11, 2026
549c5c7
Merge pull request #6396 from TrainLCD/chore/dev-from-master
TinyKitten Jul 11, 2026
88923fb
省電力測位の精度・更新間隔を既定値へ昇格し、省電力モードをBalanced精度と停車中の自動休止に変更 (#6395)
TinyKitten Jul 11, 2026
3245ae5
Bump version for canary release (#6398)
github-actions[bot] Jul 11, 2026
ed46a72
ライセンス画面に京王バスと東急バスのODPTライセンスを追記 (#6399)
TinyKitten Jul 12, 2026
ce43d15
Bump version for canary release (#6401)
github-actions[bot] Jul 12, 2026
a3d8302
origin/dev をマージし版数競合を解決(semver=10.9.1、ビルド番号=531/2744)
TinyKitten Jul 12, 2026
b91a4b8
Merge pull request #6404 from TrainLCD/chore/dev-from-master
TinyKitten Jul 12, 2026
54d3de7
TTS 送信前に英語駅名のマクロンを除去して誤読を防ぐ (#6407)
TinyKitten Jul 12, 2026
151d7f4
オートモードで終点到着後は1分停車してから方面を逆転して折り返すよう変更 (#6403)
TinyKitten Jul 12, 2026
9b26e1d
省電力モードを試験的機能から外し設定に「バッテリー」画面を新設して移動 (#6409)
TinyKitten Jul 12, 2026
9c5fe10
オートモードの折り返し時にTTSの初回放送を再発火するよう変更 (#6408)
TinyKitten Jul 12, 2026
8db439d
TZ=UTC のテストスクリプトを cross-env 経由にしてWindowsで動くようにする (#6406)
TinyKitten Jul 12, 2026
fca5fba
cherry-pickリリース後の同期PRの版数コンフリクト解決手順をスキルに追記 (#6405)
TinyKitten Jul 12, 2026
2f544ac
Bump version for canary release (#6411)
github-actions[bot] Jul 12, 2026
6bfde55
初期画面のPull to Refreshの対象をプリセットカードより下の路線リストのみに限定 (#6412)
TinyKitten Jul 13, 2026
392ba14
Bump version for canary release (#6415)
github-actions[bot] Jul 13, 2026
86f1490
初期画面のPull to Refresh対象を路線リストに限定した変更をリバートして元のスクロール挙動に戻す (#6416)
TinyKitten Jul 13, 2026
3bf50be
試験的機能からETAアシストの手動トグルを廃止しリモート設定のみで自動有効化するよう変更 (#6413)
TinyKitten Jul 13, 2026
f9cec41
Bump version for canary release (#6418)
github-actions[bot] Jul 13, 2026
84b8203
Apollo Client から TanStack Query への移行経緯とパフォーマンス改善理由をドキュメント化 (#6419)
TinyKitten Jul 15, 2026
db5df14
未使用スタイルの削除とListFooterやToast設定の再レンダリング対策 (#6421)
TinyKitten Jul 15, 2026
04ff08e
高頻度atom購読の隔離で位置更新ごとの全画面再レンダーを解消 (#6422)
TinyKitten Jul 16, 2026
5d01a40
JSスレッド駆動アニメーションのネイティブ化と検索結果の仮想化などパフォーマンス改善のフォローアップ (#6423)
TinyKitten Jul 16, 2026
8251d6d
Bump version for canary release (#6425)
github-actions[bot] Jul 16, 2026
2907656
ETA実装LineBoardの最後尾ドット右隣に残り分数の単位(分/min./분)を表示 (#6428)
TinyKitten Jul 16, 2026
ad7aec7
TTS機能のリモートキルスイッチ(tts_enabled)を追加し、無効時は設定画面のトグルを無効化してサービスステータスへのリンクを表示…
TinyKitten Jul 16, 2026
c432a7e
Bump version for canary release (#6430)
github-actions[bot] Jul 16, 2026
726aec8
v10.10.0 をリリース
claude Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/skills/finalize-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ sync 側の走行は **必須**。master→dev 差分が 0 件の場合のみ自

sync が **スキップ**(差分 0 件)された場合はこの手順を飛ばす。新規作成・流用いずれかで dev<-master PR が存在する場合のみ実行する。**緩和→マージ→復元は 1 つの bash 呼び出しにまとめ、`set +e` でマージ失敗を握って復元を無条件実行する**(途中で関数が分かれて復元が飛ぶ事故を防ぐ)。

**マージ前にコンフリクトを確認する。** `gh pr view <n> --json mergeable,mergeStateStatus` が `CONFLICTING` を返す場合、`master` から特定コミットだけを cherry-pick したリリース(`create-release-pr` の「この変更だけ」指定など)の後に起きる **版数ファイルのねじれ** が典型。このときは Ruleset 緩和より先に `sync-dev-from-master` の「版数ファイルのコンフリクト解決」に従って版数を解決し(本番版数の判断はユーザー承認を取る)、PR を `MERGEABLE` にしてから 6-3 以降へ進む。`mergeable` はプッシュ直後に非同期で古い値を返すことがあるため、`git merge-base --is-ancestor origin/dev origin/chore/dev-from-master` で構造的な包含も確認するとよい。

1. マージ対象 PR 番号を確定(手順 5 で新規作成 or 流用した PR)。ローカルが `chore/dev-from-master` に居るとブランチ削除で支障が出るため `git switch dev`(または安全な枝)へ退避する。
2. `OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)` を解決。プレフライトの「マージ方式制約」記録を使う:
- dev が `merge` を許可済み → **緩和不要**。そのまま手順 6-5 のマージへ。
Expand Down
51 changes: 51 additions & 0 deletions .claude/skills/sync-dev-from-master/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ description: Open a dev<-master merge PR that syncs master back into dev after a

- 何もコミットは積まない(master 先端そのまま)。biome 等のフォーマッタは走らせない(新規コミット無し)。
- push 前に、対象 SHA(`git rev-parse origin/master`)・取り込まれるコミット件数・本文に入れる version をユーザーに提示して承認を取る。
- **例外**: この PR が版数ファイルで衝突する場合(`master` から特定 PR だけ cherry-pick したリリースの後に起きる。後述の「版数ファイルのコンフリクト解決」を参照)は、この枝に `origin/dev` をマージして解決コミットを 1 つだけ積む。それ以外は master 先端そのまま。

5. **PR 本文を組み立て(テンプレ厳守・全節を実内容で埋める)**

Expand Down Expand Up @@ -160,6 +161,56 @@ description: Open a dev<-master merge PR that syncs master back into dev after a
- テスト欄のチェック状態(全 OFF + 説明文あり)
- 使用した `release_version`(どこから取ったか)

## 版数ファイルのコンフリクト解決(cherry-pick / hotfix リリース後)

通常の「dev から丸ごと」リリースでは `master` が `dev` の完全な祖先になるため、この同期 PR は衝突しない(手順 4 のとおり master 先端そのままで済む)。しかし **リリースブランチを `master` から切って特定 PR だけ cherry-pick したリリース**(`create-release-pr` に「この変更だけ」と指定したホットフィックス型など)では、`dev` を `master` に取り込んでいないため、`master` のリリース版数と `dev` の canary bump 版数が **ねじれたまま** 残り、この同期 PR が版数ファイルで衝突する。

衝突するのは版数ファイルのみで、アプリコードは衝突しない:

- `android/app/build.gradle`(`versionCode` / `versionName`)
- `app.config.ts`(`version` / `buildNumber` / `versionCode`)
- `ios/TrainLCD.xcodeproj/project.pbxproj`(`MARKETING_VERSION` / `CURRENT_PROJECT_VERSION`)

### 解決方針: semver はリリース版、ビルド番号は最大値

| 種別 | 採用する側 | 理由 |
| ---- | ---- | ---- |
| semver(`version` / `versionName` / `MARKETING_VERSION`) | `master`(リリース版数) | `dev` をリリース済みバージョンへ前進させる。過去 PR #6396 も semver 競合をリリース版で解決している |
| ビルド番号(`versionCode` / `CURRENT_PROJECT_VERSION` / `buildNumber`) | `max(dev, master)`(通常は `dev` 側が大きい) | ストアはビルド番号の単調増加を要求する。canary で既発行の番号より下げると次回 bump で衝突する |

### 解決手順

1. `chore/dev-from-master`(= master 先端)に居る状態で `origin/dev` をマージする(手順 4 の「コミットを積まない」原則の唯一の例外):

```bash
git switch chore/dev-from-master
git merge --no-ff --no-commit origin/dev
```

2. 衝突した版数 3 ファイルを master 側(`--ours`)で確定してから、ビルド番号だけ `dev` 側の最大値へ引き上げる(下は master=530/2743・dev=531/2744 の例):

```bash
git checkout --ours android/app/build.gradle app.config.ts ios/TrainLCD.xcodeproj/project.pbxproj
sed -i 's/versionCode 100000530/versionCode 100000531/g' android/app/build.gradle
sed -i "s/buildNumber: '2743'/buildNumber: '2744'/g; s/versionCode: 100000530/versionCode: 100000531/g" app.config.ts
sed -i 's/CURRENT_PROJECT_VERSION = 2743;/CURRENT_PROJECT_VERSION = 2744;/g' ios/TrainLCD.xcodeproj/project.pbxproj
```

これらの版数ファイルは master↔dev で数値以外の差分が無い(`git diff origin/dev origin/master -- <path>` で確認できる)ため、`--ours` で master を採ってもコンテンツは失われない。

3. **`dev` への正味の変化が semver だけ**(ビルド番号は据え置き)であることを確認してからマージコミットを作成し push する:

```bash
git add android/app/build.gradle app.config.ts ios/TrainLCD.xcodeproj/project.pbxproj
git diff origin/dev HEAD # semver(例 10.9.0 -> 10.9.1)のみが出るのが正
git commit -m "origin/dev をマージし版数競合を解決(semver=<release>、ビルド番号=<max>)"
git push origin chore/dev-from-master
```

4. 以降は通常どおり merge commit でマージする(`finalize-release` が Ruleset 一時緩和つきで実行する)。マージ後は dev HEAD が 2 親の merge commit になり、`git rev-list --count origin/dev..origin/master` が `0`(dev が master を完全包含)になることを検証する。

**semver をリリース版数へ更新する判断とビルド番号の採用値は本番の版数に関わるため、自動で確定せずユーザーに確認する。**

## 注意事項

- **Squash merge 禁止**。これがこのスキルの存在理由の半分。実行時と完了報告で二重に明示する。
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ This handbook defines how automation agents collaborate safely and effectively o
- Biome is authoritative; avoid `// biome-ignore` unless a rule is truly incompatible and document the rationale inline.
- Components → PascalCase (`StationBanner.tsx`); hooks → `use*` (`useStationFeed.ts`); Jotai atoms → `store/atoms/*.ts`; GraphQL operations → `FeatureVerbQuery`.
- Jotai state is held in field-level primitive atoms (named exports such as `arrivedAtom`, `headerStateAtom`). Always subscribe to those for reads; the default-exported `stationState` / `navigationState` / `lineState` are write-compatible facades and subscribing to them re-renders on every field change. See `docs/state-management.md`.
- Void side-effect hooks that subscribe to high-frequency atoms (`locationAtom` updates every second while riding) must not be called in a screen component's body. Host them in a renderless effects component instead (`MainScreenEffects` in `src/screens/Main.tsx`, `PermittedLayoutEffects` in `src/components/Permitted.tsx`; one hook per `Fx*` component so per-hook render cost stays measurable). Gate platform- or setting-specific hooks by conditionally mounting their host (`FxTTS`, `FxUpdateLiveActivities`). For objects with high-frequency fields such as `pictureInPictureAtom.activityState`, subscribe the narrow derived atoms (`pictureInPictureEnabledAtom` / `pictureInPictureActiveAtom`) instead of the whole atom. Details in `docs/state-management.md`.
- Co-locate style modules or constants near their consumers; share cross-cutting utilities through `src/utils/`.
- Keep comments purposeful: explain intent or non-obvious constraints, not obvious mechanics.

Expand Down
8 changes: 4 additions & 4 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ android {
dimension "environment"
applicationId "me.tinykitten.trainlcd.dev"
versionNameSuffix "-dev"
versionCode 100000530
versionName "10.9.1"
versionCode 100000537
versionName "10.10.0"
}
prod {
dimension "environment"
versionCode 100000530
versionName "10.9.1"
versionCode 100000537
versionName "10.10.0"
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const IS_DEV = process.env.APP_VARIANT === 'dev';
export default {
name: 'TrainLCD',
slug: 'trainlcd',
version: '10.9.1',
version: '10.10.0',
plugins: [
'expo-image',
'expo-font',
Expand Down Expand Up @@ -52,15 +52,15 @@ export default {
},
},
ios: {
buildNumber: '2743',
buildNumber: '2750',
scheme: IS_DEV ? 'CanaryTrainLCD' : 'ProdTrainLCD',
bundleIdentifier: IS_DEV ? 'me.tinykitten.trainlcd.dev' : 'me.tinykitten.trainlcd',
supportsTablet: true,
},
android: {
package: IS_DEV ? 'me.tinykitten.trainlcd.dev' : 'me.tinykitten.trainlcd',
permissions: [],
versionCode: 100000530,
versionCode: 100000537,
},
owner: 'trainlcd',
experiments: {
Expand Down
8 changes: 5 additions & 3 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
"ttsAlertText": "The automatic announcement feature does not work in silent mode or when the Internet is not connected. Please be careful.",
"bgTtsAlertText": "When the background audio feature is enabled, sound will play even when silent mode is on. Please be especially mindful when on a train.",
"bgTtsAppClipAlertText": "To use the background audio feature, please download the full version.",
"ttsFeatureDisabledText": "The automatic announcement feature is temporarily unavailable. Please check the Service Status page below for the latest availability.",
"serviceStatus": "Service Status",
"failedToOpenLink": "Failed to open the link. Please try again later.",
"weekdayNotice": "Weekday transit stations are included. The corresponding station will be displayed as a passage. Please be careful.",
"holidayNotice": "Includes holiday transit stations. The corresponding station will be displayed as a passage. Please Be careful.",
"shareNotice": "Press and hold the screen for easy sharing😊.",
Expand Down Expand Up @@ -329,9 +332,8 @@
"portraitModeTitle": "Portrait Mode",
"portraitModeDescription": "When enabled, the running screen switches to a layout optimized for portrait orientation while you hold your device upright.",
"telemetryDescription": "Your device's geographic coordinates are sent to our analytics server. The information is used only for analytics.",
"etaAssistTitle": "Improve arrival detection",
"etaAssistDescription": "When enabled, in sections where GPS accuracy drops such as subways, the app uses the server's estimated arrival times (ETA) to assist arrival detection. GPS remains the source of truth for arrival and current location; ETA is only an aid.",
"batterySettings": "Battery",
"powerSavingLocationTitle": "Power-saving location mode",
"powerSavingLocationDescription": "When enabled, the app requests location updates less often and allows tracking to pause while stopped while retaining the high accuracy needed for station detection, reducing battery drain and heat on long rides. On Android, removing the app from the Recents screen stops the foreground location service and its persistent notification, but does not guarantee that the location task itself is unregistered. This works on both Android and iOS and turns on automatically while your device is in low-power mode. If arrival notices become delayed, also turn off the device's low-power mode.",
"powerSavingLocationDescription": "When enabled, location accuracy is lowered to a battery-friendly level and iOS pauses tracking automatically while you are stopped, further reducing battery drain and heat on long rides. The lower accuracy may delay or shift station detection and arrival announcements. The relaxed update frequency is already part of the default settings. It also turns on automatically while your device is in low-power mode.",
"passStationLabel": "Pass"
}
8 changes: 5 additions & 3 deletions assets/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@
"ttsAlertText": "自動アナウンス機能はマナーモードもしくはインターネット未接続状態では動作いたしません。ご注意ください。",
"bgTtsAlertText": "バックグラウンド音声機能を有効にすると、マナーモード設定中でも音声が流れます。特に電車内ではご注意ください。",
"bgTtsAppClipAlertText": "バックグラウンド音声機能をご利用になるには完全版をダウンロードしてください。",
"ttsFeatureDisabledText": "自動アナウンス機能は現在一時的にご利用いただけません。最新の稼働状況は下記のサービスステータスをご確認ください。",
"serviceStatus": "サービスステータス",
"failedToOpenLink": "リンクを開けませんでした。しばらく経ってからもう一度お試しください。",
"weekdayNotice": "平日通過の駅が含まれています。該当の駅は通過表示となります。ご注意ください。",
"holidayNotice": "休日通過の駅が含まれています。該当の駅は通過表示となります。ご注意ください。",
"shareNotice": "画面を長押しすると簡単にシェアができます😊",
Expand Down Expand Up @@ -330,9 +333,8 @@
"portraitModeTitle": "ポートレートモード",
"portraitModeDescription": "有効にすると、走行画面で端末を縦向きにした際に、縦画面に最適化されたデザインで表示します。",
"telemetryDescription": "お使いの端末の地理的座標を解析用サーバに送信します。送信された情報は解析以外に使用されません。",
"etaAssistTitle": "到着判定の改善",
"etaAssistDescription": "有効にすると、地下鉄などGPSの精度が落ちる区間で、サーバーの到着予測(ETA)を使って到着判定を補助します。到着や現在地はGPSが基準で、ETAはあくまで補助です。",
"batterySettings": "バッテリー",
"powerSavingLocationTitle": "省電力測位モード",
"powerSavingLocationDescription": "有効にすると、駅判定に必要な高精度測位を維持しながら位置情報の更新頻度を抑え、停車中は測位を自動休止して、長時間の乗車での電池消費と発熱を減らします。Androidでは履歴画面からアプリを削除した際に、位置情報のフォアグラウンドサービスと常駐通知を停止しますが、測位タスク自体の登録解除を保証するものではありません。AndroidとiOSの両方で動作し、端末の省電力モード中は自動的に有効になります。到着案内が遅れる場合は端末の省電力モードも解除してください。",
"powerSavingLocationDescription": "有効にすると、測位精度を電池優先まで下げ、停車中はiOSが測位を自動休止して、長時間の乗車での電池消費と発熱をさらに減らします。精度の低下により駅の判定や到着案内が遅れたりずれたりする場合があります。位置情報の更新頻度の緩和は標準設定に組み込まれています。端末の省電力モード中は自動的に有効になります。",
"passStationLabel": "通過"
}
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
## ドキュメント一覧

- [状態管理ガイドライン (Jotai)](./state-management.md)
- [Apollo Client → TanStack Query 移行メモ](./apollo-to-react-query-migration.md)
- [canary リリース PR でのバージョン更新](./bump-version-on-canary-pr.md)
- [本番リリース PR でのバージョン更新](./bump-version-on-release-pr.md)
Loading
Loading