Repository navigation
feat: v2 iOS native redesign - #61
Conversation
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.
|
@codex review |
|
@claude review |
|
@gemini-code-assist review |
|
To use Codex here, create a Codex account and connect to github. |
|
@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>
Resolved by merging |
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.
There was a problem hiding this comment.
🟡 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
passwordnamespace 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.
…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>
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
Related Issues
N/A
Testing
Checklist
maininpackage.json,pnpm-lock.yaml, andpnpm-workspace.yamlbecausemainindependently 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):
pnpm audit --prod: 0 known vulnerabilitiessubscription-server, unaffected by this PR):cargo test13/13,cargo clippycleanKnown gap: merge conflicts with
main(see checklist above) must be resolved before this can land.