Skip to content

feat: v2 iOS native redesign - #61

Merged
darui3018823 merged 153 commits into
mainfrom
dev/v2-ios-native
Sep 17, 2026
Merged

darui3018823 merged 153 commits into
mainfrom
dev/v2-ios-native

Conversation

@darui3018823

@darui3018823 darui3018823 commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Description

iOS-native redesign for v2 (2.0.0-beta32): platform-split screens (*-screen.ios.tsx) for Login/Register, Settings and its child screens (About, Acknowledgements, Billing, Gmail, Language, Password, Privacy, Profile, Support, Time Zone, ToS), Edit Subscription, icon/image picker overhaul, new theme constants per screen, i18n additions, license generation script, and CI/version-check updates to treat beta tags as prereleases.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Dependencies update

Related Issues

N/A

Testing

  • I have tested this change locally
  • New and existing unit tests pass locally with my changes (43 suites / 187 tests)
  • I have run the linter and fixed any issues (0 errors)
  • Real-device verification (Android/iOS) — not yet recorded, recommended before tagging a stable release

Checklist

  • My changes generate no new warnings
  • Any dependent changes have been merged and published — this branch has merge conflicts with main in package.json, pnpm-lock.yaml, and pnpm-workspace.yaml because main independently landed overlapping dependency-security fixes (nanoid, Expo SDK alignment, jest-preset) after this branch diverged. These need to be resolved during review before merging.

Additional Notes

Local security/quality gates (as of this PR):

  • TypeScript: pass
  • ESLint: 0 errors
  • Jest: 43 suites / 187 tests pass, coverage above configured thresholds
  • pnpm audit --prod: 0 known vulnerabilities
  • Server-side (subscription-server, unaffected by this PR): cargo test 13/13, cargo clippy clean
  • Security-focused diff review found no high-confidence vulnerabilities (UI-only redesign; no changes to auth/token/network/filesystem logic beyond code movement)

Known gap: merge conflicts with main (see checklist above) must be resolved before this can land.

The file browser accepted any image/* (BMP, TIFF, ...) which the upload
endpoint rejects with a generic error, and `allowsEditing` only applies to
the photo picker, so file picks reached the server uncropped.

- Offer only PNG/JPEG/GIF/WebP in the document picker.
- When a square icon is requested, centre-crop the file pick, cap it at
  512px, and re-encode it (JPEG for opaque sources, PNG otherwise) via
  expo-image-manipulator, mirroring the in-app crop screen's output.
- Share the opaque-source check with image-crop.tsx.
… tone

Replace the custom Cancel / Crop / Use header View with the native Stack
header: SF Symbol xmark / checkmark items on iOS (matching the add and edit
sheets) and text buttons on Android. The screen and header now use #0A0A0A
instead of pure black, and Use is guarded against a second tap while the
crop renders.
Split app/login.tsx and app/register.tsx into the existing platform-split
convention (components/auth/*-screen.tsx for Android, *-screen.ios.tsx for
iOS), matching the rest of the app's iOS treatment: full-black surface,
a single borderless grouped card for the fields, native iOS accent colors,
and a native back control on Register instead of the custom transparent
button. Android behavior and styling are unchanged.
app/_layout.tsx sets headerShown: false for the register route by default;
the iOS screen forgot to override it back to true, so the native header
(and its back chevron) never rendered.
Centering within the space below the header shifted the content down by
half the header's height compared to Login's full-screen centering. Offset
the ScrollView content by -headerHeight/2 (via expo-router/react-navigation's
useHeaderHeight) so it lines up the same as Login.
…oid, decode-uri-component

Add pnpm overrides for transitive dependencies pulled in by Expo CLI
tooling (jest-preset, xcpretty, metro-config, @expo/plist) and
expo-router's query-string dependency.
- generate-licenses.js: declare __dirname as a global (CJS script,
  not covered by the app's node globals)
- notifications.ts: scope the require-imports disable to the
  intentional lazy/conditional require of expo-notifications
- i18n/index.ts: scope the no-named-as-default-member disable to
  the intentional i18n.use() plugin call
The pnpm-workspace.yaml audit override pins decode-uri-component to
0.5.0, which ships ESM-only. query-string (used transitively by
expo-router) requires it, so Jest needs to transform it instead of
treating it as CommonJS.
@github-actions

Copy link
Copy Markdown

@codex review

@github-actions

Copy link
Copy Markdown

@claude review

@github-actions

Copy link
Copy Markdown

@gemini-code-assist review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@darui3018823

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

# Conflicts:
#	package.json
#	pnpm-lock.yaml
#	pnpm-workspace.yaml

Co-authored-by: darui3018823 <151906210+darui3018823@users.noreply.github.com>

Copilot AI commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved by merging origin/main into this branch and fixing the conflicts in package.json, pnpm-lock.yaml, and pnpm-workspace.yaml in commit 0603288.

expo install --check was failing CI (build-android, build-ios) because
expo, expo-image-manipulator, expo-image-picker, and expo-notifications
had drifted a patch version behind the SDK 57 recommended set.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Release validation, accessibility, localization, payment-flow, theme-convention issues, and declared merge conflicts remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Introduces the v2 iOS-native redesign while preserving Android implementations and extending release tooling for beta versions.

Changes:

  • Adds platform-specific iOS screens, native tabs, themes, search, and icon/payment flows.
  • Adds localization, license acknowledgements, and regression tests.
  • Updates Expo dependencies, security overrides, versioning, and prerelease workflows.
File summaries
File Description
update-version.js Accepts beta release versions.
scripts/verify-release-tag.js Validates beta tags as prereleases.
scripts/update-version.test.ts Tests beta promotion.
scripts/generate-licenses.js Generates dependency license data.
pnpm-workspace.yaml Adds security overrides.
package.json Bumps v2 beta and Expo dependencies.
lib/versionCheck.test.ts Tests prerelease update behavior.
lib/subscriptionSearch.ts Adds subscription filtering.
lib/subscriptionSearch.test.ts Tests search filtering.
lib/paymentMethodPresets.ts Centralizes payment presets.
lib/paymentMethodErrors.ts Maps duplicate-payment errors.
lib/paymentMethodErrors.test.ts Tests error mapping.
lib/notifications.ts Documents conditional loading.
lib/iconPicker.ts Adds photo/file icon selection.
lib/iconPicker.test.ts Tests image selection and processing.
jest.config.js Transforms overridden ESM dependency.
i18n/locales/ja.json Adds Japanese UI strings.
i18n/locales/en.json Adds English UI strings.
i18n/index.ts Documents i18next plugin usage.
docs/ios-icon-picker-draft.md Records postponed native picker design.
constants/settings-theme.ts Defines default Settings background.
constants/settings-theme.test.ts Tests iOS Settings theme.
constants/settings-theme.ios.ts Defines iOS Settings theme.
constants/licenses.ts Exposes generated license metadata.
constants/licenses.test.ts Validates license metadata.
constants/home-theme.ts Defines default Home background.
constants/home-theme.test.ts Tests iOS Home theme.
constants/home-theme.ios.ts Defines iOS Home background.
constants/detail-theme.ts Defines default Detail background.
constants/detail-theme.test.ts Tests iOS Detail theme.
constants/detail-theme.ios.ts Defines iOS Detail background.
constants/calendar-theme.ts Defines default Calendar background.
constants/calendar-theme.test.ts Tests iOS Calendar theme.
constants/calendar-theme.ios.ts Defines iOS Calendar background.
constants/auth-theme.ts Defines default auth background.
constants/auth-theme.ios.ts Defines iOS auth background.
constants/add-theme.ts Defines default add-sheet palette.
constants/add-theme.test.ts Tests iOS add-sheet palette.
constants/add-theme.ios.ts Defines iOS add-sheet palette.
components/ui/tab-bar-types.ts Extracts tab-bar prop types.
components/ui/icon-symbol.tsx Adds tab icon mappings.
components/ui/custom-tab-bar.tsx Extracts Android custom tab bar.
components/tab-scroll.test.tsx Tests tab reselection scrolling.
components/SubscriptionIconPickerSheet.types.ts Defines picker props.
components/SubscriptionIconPickerSheet.tsx Adds default icon picker.
components/SubscriptionIconPickerSheet.ios.tsx Adds iOS picker variant.
components/subscription/edit-screen.ios.test.tsx Tests iOS edit sheet.
components/settings/tos-screen.tsx Moves default ToS screen.
components/settings/tos-screen.ios.tsx Adds native iOS ToS design.
components/settings/tos-screen.ios.test.tsx Tests iOS ToS styling.
components/settings/time-zone-screen.tsx Moves default time-zone screen.
components/settings/time-zone-screen.ios.tsx Adds native iOS time-zone search.
components/settings/time-zone-screen.ios.test.tsx Tests iOS time-zone UI.
components/settings/support-screen.tsx Moves default support screen.
components/settings/support-screen.ios.tsx Adds native iOS support design.
components/settings/settings-screen.ios.test.tsx Tests iOS Settings navigation.
components/settings/profile-screen.tsx Moves default profile screen.
components/settings/privacy-screen.tsx Moves default privacy screen.
components/settings/privacy-screen.ios.tsx Adds native iOS privacy design.
components/settings/privacy-screen.ios.test.tsx Tests iOS privacy styling.
components/settings/password-screen.tsx Moves default password screen.
components/settings/password-screen.ios.tsx Adds native iOS password design.
components/settings/password-screen.ios.test.tsx Tests iOS password styling.
components/settings/language-support-screens.ios.test.tsx Tests language/support designs.
components/settings/language-screen.tsx Moves default language screen.
components/settings/language-screen.ios.tsx Adds native iOS language design.
components/settings/gmail-screen.ios.test.tsx Tests iOS Gmail styling.
components/settings/billing-screen.tsx Moves default billing screen.
components/settings/billing-screen.ios.test.tsx Tests iOS billing behavior.
components/settings/acknowledgements-screen.tsx Adds license acknowledgements.
components/settings/acknowledgements-screen.ios.test.tsx Tests iOS acknowledgements.
components/settings/about-screen.ios.test.tsx Tests iOS About design.
components/IconSourceSheet.types.ts Defines icon-source options.
components/IconSourceSheet.tsx Adds default source sheet.
components/IconSourceSheet.ios.tsx Uses native iOS action sheet.
components/auth/register-screen.ios.test.tsx Tests iOS registration.
components/auth/login-screen.tsx Moves default login screen.
components/auth/login-screen.ios.tsx Adds native iOS login design.
components/auth/login-screen.ios.test.tsx Tests iOS login behavior.
components/AddPaymentMethodSheet.test.tsx Tests duplicate-submit prevention.
CLAUDE.md Documents platform and design conventions.
app/settings/tos.tsx Re-exports platform ToS screen.
app/settings/time-zone.tsx Re-exports platform time-zone screen.
app/settings/support.tsx Re-exports platform support screen.
app/settings/profile.tsx Re-exports platform profile screen.
app/settings/privacy.tsx Re-exports platform privacy screen.
app/settings/payment-method.tsx Applies platform-specific picker styling.
app/settings/payment-method-detail.tsx Uses shared Settings theme.
app/settings/password.tsx Re-exports platform password screen.
app/settings/language.tsx Re-exports platform language screen.
app/settings/currency-picker.tsx Applies add-sheet palette.
app/settings/billing.tsx Re-exports platform billing screen.
app/settings/billing-cycle.tsx Applies add-sheet palette.
app/settings/acknowledgements.tsx Adds acknowledgements route.
app/login.tsx Re-exports platform login screen.
app/detail.tsx Applies platform detail styling.
app/add-payment-method/[brandId].tsx Adds preset confirmation screen.
app/add-payment-method/_layout.tsx Adds nested modal navigation.
app/(tabs)/search/_layout.tsx Adds Search stack.
app/(tabs)/calendar.tsx Adds theme and tab scrolling.
app/(tabs)/_layout.tsx Refactors default tab layout.
app/(tabs)/_layout.ios.tsx Adds native iOS tabs.
app/_layout.tsx Registers modal flows and gesture root.
app.json Bumps native and release versions.
.github/workflows/build-ios.yml Marks hyphenated tags prereleases.
.github/workflows/build-android.yml Marks hyphenated tags prereleases.
Review details

Suppressed comments (2)

lib/paymentMethodPresets.ts:20

  • その他 is rendered as a card-brand option regardless of the selected language, leaving an untranslated Japanese control in the English UI. Use a stable option id and translate its display label through both locale files.
    components/settings/password-screen.ios.tsx:53
  • The success alert and failure title are hard-coded in English, leaving the Japanese password flow partially untranslated. Move these strings into the password namespace in both locale files and use the existing localized common error title.
  • Files reviewed: 135/137 changed files
  • Comments generated: 11
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/add-payment-method/[brandId].tsx Outdated
Comment thread app/add-payment-method/[brandId].tsx Outdated
Comment thread components/auth/login-screen.ios.tsx
Comment thread components/settings/password-screen.ios.tsx Outdated
Comment thread components/ui/custom-tab-bar.tsx
Comment thread constants/detail-theme.ios.ts
Comment thread constants/home-theme.ios.ts
Comment thread lib/paymentMethodPresets.ts Outdated
Comment thread scripts/verify-release-tag.js Outdated
Comment thread update-version.js Outdated
darui3018823 and others added 7 commits September 17, 2026 16:24
…os-native

# Conflicts:
#	package.json
#	pnpm-lock.yaml
The RC pattern already rejected rc.0 via [1-9]\d*, but the beta
pattern used \d*, so bare "-beta" and "-beta0" tags passed release
verification even though the versioning scheme only uses numbered
betas (beta1, beta2, ...).
…nt-method screen

An unmatched brandId rendered a blank modal with no way back. The
confirm handler also dismissed the modal before addMethod resolved,
so a failed create silently discarded the memo with no way to retry.
Await the store call and only dismiss on success.
The iOS login heading and the password-change alerts were hard-coded
in English, leaving Japanese users with a partially untranslated
screen. The custom tab bar's icon-only tabs also had no accessible
name for screen readers; wire up the existing tabs.* keys.
"App Store決済", "Google Play決済", and "その他" mixed Japanese into
the preset list regardless of the user's selected language, and these
values are persisted as the payment method's label.
The full-black surface was documented as Settings-only (with an
undocumented addendum for auth), but Home, Calendar, and Detail were
each deliberately moved to #000000 in earlier commits without the
docs being updated to match. Clarify that these are the dedicated
iOS-native full-screen surfaces, while modal sheets and Android stay
on the standard dark-surface rules.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@darui3018823
darui3018823 merged commit 466a83a into main Sep 17, 2026
7 checks passed
@darui3018823
darui3018823 deleted the dev/v2-ios-native branch September 17, 2026 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants