Skip to content
Merged

canary #6417

Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,12 @@ android {
dimension "environment"
applicationId "me.tinykitten.trainlcd.dev"
versionNameSuffix "-dev"
versionCode 100000533
versionCode 100000534
versionName "10.9.1"
}
prod {
dimension "environment"
versionCode 100000533
versionCode 100000534
versionName "10.9.1"
}
}
Expand Down
4 changes: 2 additions & 2 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ export default {
},
},
ios: {
buildNumber: '2746',
buildNumber: '2747',
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: 100000533,
versionCode: 100000534,
},
owner: 'trainlcd',
experiments: {
Expand Down
2 changes: 0 additions & 2 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,6 @@
"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, 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.",
Expand Down
2 changes: 0 additions & 2 deletions assets/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,6 @@
"portraitModeTitle": "ポートレートモード",
"portraitModeDescription": "有効にすると、走行画面で端末を縦向きにした際に、縦画面に最適化されたデザインで表示します。",
"telemetryDescription": "お使いの端末の地理的座標を解析用サーバに送信します。送信された情報は解析以外に使用されません。",
"etaAssistTitle": "到着判定の改善",
"etaAssistDescription": "有効にすると、地下鉄などGPSの精度が落ちる区間で、サーバーの到着予測(ETA)を使って到着判定を補助します。到着や現在地はGPSが基準で、ETAはあくまで補助です。",
"batterySettings": "バッテリー",
"powerSavingLocationTitle": "省電力測位モード",
"powerSavingLocationDescription": "有効にすると、測位精度を電池優先まで下げ、停車中はiOSが測位を自動休止して、長時間の乗車での電池消費と発熱をさらに減らします。精度の低下により駅の判定や到着案内が遅れたりずれたりする場合があります。位置情報の更新頻度の緩和は標準設定に組み込まれています。端末の省電力モード中は自動的に有効になります。",
Expand Down
36 changes: 18 additions & 18 deletions ios/TrainLCD.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2407,7 +2407,7 @@
CODE_SIGN_ENTITLEMENTS = ProdTrainLCD.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = E6R2G33Z36;
INFOPLIST_FILE = TrainLCD/Schemes/Prod/Info.plist;
Expand Down Expand Up @@ -2446,7 +2446,7 @@
CODE_SIGN_ENTITLEMENTS = ProdTrainLCD.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEVELOPMENT_TEAM = E6R2G33Z36;
INFOPLIST_FILE = TrainLCD/Schemes/Prod/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = TrainLCD;
Expand Down Expand Up @@ -2505,7 +2505,7 @@
CODE_SIGN_ENTITLEMENTS = TrainLCD/trainlcd.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
CXX = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -2611,7 +2611,7 @@
CODE_SIGN_ENTITLEMENTS = TrainLCD/trainlcd.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
CXX = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down Expand Up @@ -2690,7 +2690,7 @@
CODE_SIGN_ENTITLEMENTS = CanaryTrainLCD.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = E6R2G33Z36;
INFOPLIST_FILE = TrainLCD/Schemes/Dev/Info.plist;
Expand Down Expand Up @@ -2729,7 +2729,7 @@
CODE_SIGN_ENTITLEMENTS = CanaryTrainLCD.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
INFOPLIST_FILE = TrainLCD/Schemes/Dev/Info.plist;
Expand Down Expand Up @@ -2940,7 +2940,7 @@
CODE_SIGN_ENTITLEMENTS = RideSessionActivity/CanaryRideSessionActivity.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
GCC_C_LANGUAGE_STANDARD = gnu11;
Expand Down Expand Up @@ -2991,7 +2991,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
GCC_C_LANGUAGE_STANDARD = gnu11;
Expand Down Expand Up @@ -3042,7 +3042,7 @@
CODE_SIGN_ENTITLEMENTS = WatchWidget/ProdWatchWidget.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -3100,7 +3100,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -3151,7 +3151,7 @@
CODE_SIGN_ENTITLEMENTS = WatchWidget/CanaryWatchWidget.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -3208,7 +3208,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -3256,7 +3256,7 @@
CODE_SIGN_ENTITLEMENTS = RideSessionActivity/ProdRideSessionActivity.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
GCC_C_LANGUAGE_STANDARD = gnu11;
Expand Down Expand Up @@ -3307,7 +3307,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
GCC_C_LANGUAGE_STANDARD = gnu11;
Expand Down Expand Up @@ -3526,7 +3526,7 @@
CODE_SIGN_ENTITLEMENTS = ProdAppClip/ProdAppClip.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
Expand Down Expand Up @@ -3582,7 +3582,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
Expand Down Expand Up @@ -3632,7 +3632,7 @@
CODE_SIGN_ENTITLEMENTS = CanaryAppClip/CanaryAppClip.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
Expand Down Expand Up @@ -3690,7 +3690,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2746;
CURRENT_PROJECT_VERSION = 2747;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = E6R2G33Z36;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
Expand Down
13 changes: 1 addition & 12 deletions src/components/Permitted.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ import {
import { useTrainTypeModal } from '../hooks/useTrainTypeModal';
import { storage } from '../lib/storage';
import { THEME_PREFERENCE, type ThemePreference } from '../models/Theme';
import {
etaAssistManualEnabledAtom,
portraitModeEnabledAtom,
} from '../store/atoms/experimental';
import { portraitModeEnabledAtom } from '../store/atoms/experimental';
import navigationState, {
autoModeEnabledAtom,
isAppLatestAtom,
Expand Down Expand Up @@ -78,7 +75,6 @@ const PermittedLayout: React.FC<Props> = ({ children }: Props) => {
const setNotify = useSetAtom(notifyState);
const setPictureInPicture = useSetAtom(pictureInPictureAtom);
const setPortraitModeEnabled = useSetAtom(portraitModeEnabledAtom);
const setEtaAssistManualEnabled = useSetAtom(etaAssistManualEnabledAtom);
const { enabled: pictureInPictureEnabled, active: pictureInPictureActive } =
useAtomValue(pictureInPictureAtom);
const isAppActive = useIsAppActive();
Expand Down Expand Up @@ -440,9 +436,6 @@ const PermittedLayout: React.FC<Props> = ({ children }: Props) => {
const portraitModeEnabledStr = storage.getString(
STORAGE_KEYS.PORTRAIT_MODE_ENABLED
);
const etaAssistManualEnabledStr = storage.getString(
STORAGE_KEYS.ETA_ASSIST_MANUAL_ENABLED
);
// NOTE: powerSavingLocationEnabledAtom はここでは復元しない。effect復元だと
// 継続測位がデフォルト精度で一度起動してから再起動されるため、
// atom定義側(store/atoms/battery.ts)でMMKVから同期的に初期値を確定している。
Expand Down Expand Up @@ -555,9 +548,6 @@ const PermittedLayout: React.FC<Props> = ({ children }: Props) => {
if (portraitModeEnabledStr) {
setPortraitModeEnabled(portraitModeEnabledStr === 'true');
}
if (etaAssistManualEnabledStr) {
setEtaAssistManualEnabled(etaAssistManualEnabledStr === 'true');
}
};

loadSettings();
Expand All @@ -569,7 +559,6 @@ const PermittedLayout: React.FC<Props> = ({ children }: Props) => {
setNotify,
setPictureInPicture,
setPortraitModeEnabled,
setEtaAssistManualEnabled,
]);

useEffect(() => {
Expand Down
1 change: 0 additions & 1 deletion src/constants/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const STORAGE_KEYS = {
WRONG_DIRECTION_NOTIFY_ENABLED: '@TrainLCD:wrongDirectionNotifyEnabled',
PICTURE_IN_PICTURE_ENABLED: '@TrainLCD:pictureInPictureEnabled',
PORTRAIT_MODE_ENABLED: '@TrainLCD:portraitModeEnabled',
ETA_ASSIST_MANUAL_ENABLED: '@TrainLCD:etaAssistManualEnabled',
POWER_SAVING_LOCATION_ENABLED: '@TrainLCD:powerSavingLocationEnabled',
} as const;

Expand Down
39 changes: 8 additions & 31 deletions src/lib/remoteConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { MAX_PERMIT_ACCURACY } from '~/constants/location';
import { store } from '~/store';
import { etaAssistManualEnabledAtom } from '~/store/atoms/experimental';
import {
getEtaFallbackArrivalConfirmMarginSec,
getEtaFallbackMaxDurationMin,
getMaxPermitAccuracy,
isEtaAssistEnabled,
isEtaAssistRemoteEnabled,
isForceNotArrivedOnLowAccuracyEnabled,
resetRemoteConfigCache,
setupRemoteConfig,
Expand All @@ -31,8 +28,6 @@ const mockRemoteConfig = (body: unknown, ok = true) => {
afterEach(() => {
jest.clearAllMocks();
resetRemoteConfigCache();
// 手動トグルは共有ストアに残るため、テスト間の汚染を防ぐべく毎回戻す。
store.set(etaAssistManualEnabledAtom, false);
});

afterAll(() => {
Expand Down Expand Up @@ -84,48 +79,30 @@ describe('isForceNotArrivedOnLowAccuracyEnabled', () => {
});
});

describe('isEtaAssistRemoteEnabled(マスタースイッチ)', () => {
describe('isEtaAssistEnabled(Remoteマスタースイッチのみで判定)', () => {
it('falls back to false before setup', () => {
expect(isEtaAssistRemoteEnabled()).toBe(false);
expect(isEtaAssistEnabled()).toBe(false);
});

it('returns the remote boolean after setup', async () => {
it('RemoteがONなら自動的に有効(手動トグルなし)', async () => {
mockRemoteConfig({
max_permit_accuracy: 1500,
force_not_arrived_on_low_accuracy: true,
eta_assist_enabled: true,
});
await setupRemoteConfig();
expect(isEtaAssistRemoteEnabled()).toBe(true);
});

it('falls back to false when the boolean is missing', async () => {
mockRemoteConfig({ max_permit_accuracy: 1500 });
await setupRemoteConfig();
expect(isEtaAssistRemoteEnabled()).toBe(false);
});
});

describe('isEtaAssistEnabled(Remote AND 手動トグル)', () => {
it('Remoteと手動トグルの両方がONのときだけ有効', async () => {
mockRemoteConfig({ eta_assist_enabled: true });
await setupRemoteConfig();
// Remoteがtrueでも手動トグルOFFなら無効
expect(isEtaAssistEnabled()).toBe(false);
// 手動トグルONで有効
store.set(etaAssistManualEnabledAtom, true);
expect(isEtaAssistEnabled()).toBe(true);
});

it('Remoteがfalseなら手動トグルONでも無効(マスターOFF)', async () => {
store.set(etaAssistManualEnabledAtom, true);
mockRemoteConfig({ eta_assist_enabled: false });
it('RemoteがOFFなら無効(サーバー側キルスイッチ)', async () => {
mockRemoteConfig({ max_permit_accuracy: 1500, eta_assist_enabled: false });
await setupRemoteConfig();
expect(isEtaAssistEnabled()).toBe(false);
});

it('セットアップ前(Remote未取得=false)は手動トグルONでも無効', () => {
store.set(etaAssistManualEnabledAtom, true);
it('falls back to false when the boolean is missing', async () => {
mockRemoteConfig({ max_permit_accuracy: 1500 });
await setupRemoteConfig();
expect(isEtaAssistEnabled()).toBe(false);
});
});
Expand Down
19 changes: 6 additions & 13 deletions src/lib/remoteConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { MAX_PERMIT_ACCURACY } from '~/constants/location';
import { store } from '~/store';
import { etaAssistManualEnabledAtom } from '~/store/atoms/experimental';
import { workerUrl } from './workerApi';

// Cloudflare Worker(/config/remote) 配信の設定キー。Worker 側のレスポンスキーと一致させる。
Expand Down Expand Up @@ -121,23 +119,18 @@ export const isForceNotArrivedOnLowAccuracyEnabled = (): boolean => {
return FORCE_NOT_ARRIVED_ON_LOW_ACCURACY_FALLBACK;
};

// Remote Config が配信する ETA補助の許可(マスタースイッチ)を同期的に取得する。
// setupRemoteConfig 完了後は取得済みのリモート値を、未設定・取得失敗時はフォールバック
// (false=既定無効)を返す。これが false のときは機能を提供せず、設定画面の手動トグルも
// 操作不可にする(ExperimentalSettings 側で disabled)。
export const isEtaAssistRemoteEnabled = (): boolean => {
// ETA補助機能の実効的な有効/無効を同期的に取得する。以前は設定画面の手動トグルとの AND で
// 判定していたが、手動トグルを廃止し自動有効化に変更したため、Remote Config が配信する
// マスタースイッチ(eta_assist_enabled)のみで判定する。setupRemoteConfig 完了後は取得済みの
// リモート値を、未設定・取得失敗時はフォールバック(false=既定無効)を返す。これが false の
// ときは機能を提供しない(サーバー側キルスイッチ)。
export const isEtaAssistEnabled = (): boolean => {
if (cachedEtaAssistEnabled != null) {
return cachedEtaAssistEnabled;
}
return ETA_ASSIST_ENABLED_FALLBACK;
};

// ETA補助機能の実効的な有効/無効を同期的に取得する。Remote Config が許可(マスターON)し、
// かつ設定画面の手動トグルもONのときだけ有効。Remote が false のときは手動トグルの値に
// 関わらず無効。
export const isEtaAssistEnabled = (): boolean =>
isEtaAssistRemoteEnabled() && store.get(etaAssistManualEnabledAtom);

// ETAフォールバックの到着確定マージン(秒)を同期的に取得する。setupRemoteConfig 完了後は
// 取得済みのリモート値を、未完了・未設定・取得失敗時はフォールバックを返す。
// 0 や負値・非数といった不正値もフォールバックへ倒す。
Expand Down
Loading
Loading