No description
  • TypeScript 57.9%
  • Swift 35.5%
  • Shell 3.4%
  • JavaScript 2.2%
  • Nix 0.5%
  • Other 0.5%
Find a file
2026-08-19 22:36:13 +07:00
.eas/workflows chore: disable eas workflow 2026-04-04 10:52:05 +02:00
.maestro FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
.pi Add maestro mcp server 2026-06-26 16:04:50 +02:00
.plans FOC-35: add deterministic Maestro simulator runners 2026-08-01 21:48:31 +07:00
assets FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
modules/focus-only-timer-core FOC-63: enable Live Activities from App Intents 2026-08-17 21:35:40 +07:00
scripts FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
src FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
targets FOC-63: enable Live Activities from App Intents 2026-08-17 21:35:40 +07:00
.dir-locals.el nix flake init 2025-12-28 19:40:43 +01:00
.envrc nix flake init 2025-12-28 19:40:43 +01:00
.gitignore FOC-48: add shared native timer command service 2026-08-11 13:20:31 +07:00
.prettierignore Ignore the locals dir for formatting 2026-02-12 15:22:51 +01:00
.prettierrc.json chore: new prettier rules 2026-01-30 13:34:58 +01:00
AGENTS.md FOC-000: document iOS-only platform 2026-07-31 14:30:38 +07:00
app.config.ts FOC-000: bump version 2026-08-19 22:36:13 +07:00
babel.config.js Setup lingui and apply it for the strings 2026-02-12 14:21:24 +01:00
bun.lock FOC-53: upgrade apple targets to version 5 2026-08-09 12:14:51 +07:00
eas.json Add simulator EAS build profile 2026-06-24 15:20:59 +02:00
eslint.config.js chore(eslint): install plugin for import ordering 2026-03-03 11:29:59 +01:00
flake.lock nix flake init 2025-12-28 19:40:43 +01:00
flake.nix FOC-000: configure macOS SDK in development shell 2026-07-29 16:17:50 +07:00
index.ts feat: Set up unistyles and status bar 2026-01-30 13:29:24 +01:00
lingui.config.js Setup lingui and apply it for the strings 2026-02-12 14:21:24 +01:00
metro.config.js Setup Sentry 2026-02-04 14:17:00 +01:00
package.json FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
README.md FOC-68: automate localized App Store screenshots 2026-08-19 22:35:37 +07:00
skills-lock.json FOC-000: update agent skills 2026-08-04 19:23:29 +07:00
tsconfig.json Upgrade Expo SDK dependencies 2026-06-19 18:09:29 +02:00

Focus Only

Agent skills

Agent skill files are kept out of Git. Restore the skills listed in skills-lock.json after cloning the repository or when the lock file changes:

npx skills experimental_install

Create a TestFlight build

TestFlight builds use the production EAS profile and the production bundle identifier. Update version in app.config.ts to the release version, such as 1.12.0. Commit the version change and create its matching Git tag before building.

Build the iOS app and submit it to App Store Connect:

bunx eas-cli@latest build \
  --platform ios \
  --profile production \
  --auto-submit

The production profile sets APP_VARIANT=production and automatically increments the remote build number. During the first submission, EAS may prompt you for Apple credentials and App Store Connect access.

After Apple processes the upload, open App Store Connect → Focus Only → TestFlight and assign the build to an internal testing group. Don't use the preview or development profiles for TestFlight because they use internal distribution rather than App Store distribution.

App Store screenshots

Generate the English and German App Store screenshots with:

bun run screenshots:app-store

The script builds the test app once, then captures dark-mode portrait screenshots on an iPhone 17 Pro Max and a 13-inch iPad Pro. It writes three screenshots for each locale and device:

assets/screenshots/
  iPhone/
    en-US/
    de-DE/
  iPad/
    en-US/
    de-DE/

Each set contains the running timer at 24:42, statistics populated from the last-ten-days fixture, and the default settings screen. The script fixes the status bar at 9:41, removes PNG alpha channels, and checks the output dimensions against App Store Connect's accepted 6.9-inch iPhone and 13-inch iPad sizes.

Reuse the existing screenshot build while editing the Maestro flow:

./scripts/capture-app-store-screenshots.sh --skip-build

Override SCREENSHOTS_IOS_RUNTIME, SCREENSHOTS_IPHONE_NAME, or SCREENSHOTS_IPAD_NAME when the local simulator names or runtime differ from the defaults.

Fixture links remain available in development and test builds. For example, seed the ten-day statistics fixture in the currently booted development simulator with:

xcrun simctl openurl \
  booted \
  "focusonly-dev://e2e-setup?sessionHistoryFixture=last-ten-days"

Maestro end-to-end tests

Run a device suite

Run the complete build and test sequence for either device with:

bun run maestro:test:iphone
bun run maestro:test:ipad

The script boots the selected simulator, creates a clean native project for the test variant, builds and installs the Release configuration, and runs the flows configured in .maestro/config.yaml against de.totap.focustimer.test on that exact simulator.

The defaults are iPhone 17 Pro with iOS 26.0 and a dedicated Focus Only iPad Pro 13 with iOS 26.4. The script creates either simulator when it does not exist. The iPhone suite runs 43 flows; the iPad suite excludes the swipe-to-dismiss flow because that gesture is intentionally disabled on iPad.

To reuse an already installed test build while iterating on the Maestro flows, run:

./scripts/run-maestro-ios.sh iphone --skip-build
./scripts/run-maestro-ios.sh ipad --skip-build

Override MAESTRO_IPHONE_NAME, MAESTRO_IPAD_NAME, or MAESTRO_IOS_RUNTIME when the local simulator uses a different name or runtime.

The lower-level bun run ios:test command remains available for manual builds. bun run maestro:test is the low-level iPhone-filtered suite; use the device-specific commands above to apply the correct flow tags and simulator UDID automatically.