Skip to content

feat(redesign): ✨ Rebuild Loyus on Expo SDK 58 with store brands - #35

Merged
Zaphkiel-Ivanovna merged 13 commits into
mainfrom
feat/redesign
Sep 30, 2026
Merged

Zaphkiel-Ivanovna merged 13 commits into
mainfrom
feat/redesign

Conversation

@Zaphkiel-Ivanovna

Copy link
Copy Markdown
Contributor

Summary

  • Upgrades to Expo SDK 58 preview (React Native 0.88 RC, React 19.3) and Yarn 4, and removes code comments.
  • Rebuilds the app from docs/DESIGN_RESEARCH.md: native tabs, a neutral UI where color comes from the cards, checkout barcodes sized to the GS1 specs, pinning, sorting and manual order, photos, notes, iOS widgets and quick actions.
  • Adds 434 store brands (SVG logos, colors, aliases) to pick when creating a card, and a new README with light and dark screenshots.

Test plan

  • yarn check, yarn typecheck and yarn test (422 tests) pass locally
  • Tried on an iOS 26.5 simulator and on an iPhone 14 Pro Max running iOS 27 (Release build)
  • Maestro flows (rewritten, not run yet)
  • Android build

Notes for reviewers

  • Five commits, one per concern. "Rebase and merge" keeps them.
  • 237 logos come from Brands of the World, whose terms allow non-commercial use only, with the trademark holder's permission (see docs/BRANDS.md). This needs a decision before a store release; yarn brands:build --exclude-source=brandsoftheworld builds a catalog without them.
  • On iOS 27 the search tab sits inside the tab bar, because react-native-screens doesn't use UISearchTab yet (feat(iOS, Tabs): Use UISearchTab with automaticallyActivatesSearch prop software-mansion/react-native-screens#4679).
  • Development builds close on a full JavaScript reload (Expo SDK 58 preview, ExpoFabricView.injectInitializer). Relaunching fixes it.

Move the app to Expo SDK 58 (preview.7), React Native 0.88.0-rc.1 and
React 19.3, and switch the package manager from pnpm to Yarn 4.18.1.
SDK 58 builds with Xcode 27 without local Podfile patches.

Package manager
- Yarn 4 via Corepack with `nodeLinker: node-modules` (RN has no PnP)
- Husky hook wired through `postinstall` (Yarn Berry skips `prepare`)
- CI moved to Corepack + Node 24, `corepack: true` in EAS profiles

Dependencies
- Bump Nitro 0.37, MMKV 4.3.2, Unistyles 3.3, i18next 26.4, zustand 5.0.15
- Bump TypeScript 6.0, Biome 2.5, lint-staged 17; keep Jest 29
- Add @react-native/jest-preset (no longer shipped by react-native)
- Drop @react-navigation/native, react-native-edge-to-edge,
  expo-modules-core, @shopify/flash-list, @expo-google-fonts/manrope

VisionCamera 5
- Scanning split per platform: native object output on iOS, ML Kit on
  Android (excluded from iOS autolinking, no simulator slices)
- Camera permission moved to app config (v5 ships no config plugin)

Breaking API changes
- useFocusEffect now imported from expo-router
- InteractionManager replaced by requestIdleCallback
- Strict RN types: TextInputInstance refs, ColorValue tab icons
- Splash config moved to the expo-splash-screen plugin
- File.write() awaited; compileSdk/targetSdk pins removed
Remove section markers, JSDoc that restates names, test narration,
planning IDs and stale notes across app, src, mocks, configs and CI.
The comments left are one-liners covering platform quirks, workarounds
and constraints; empty catch blocks keep theirs for Biome.

Comment-only change: code is identical to the previous commit.
498 retailers with names, aliases, markets, loyalty programs, popularity
and colors in assets/brands/brands.json, and 442 SVG logos. Sources and
licences are listed in docs/BRANDS.md.
- Native tabs (Cards, Settings, Search) with titles aligned to their
  actions, Liquid Glass buttons on iOS 26+, routes moved to src/app
- Neutral UI on the system font; color comes from the card tiles, with
  six accent colors and a faint top gradient
- Checkout: barcodes sized to the GS1 specs and snapped to device pixels,
  full brightness, rotation, note, and the store logo in the header
- Cards: pinning, sorting (most used, recent, A to Z, manual reorder),
  owner, note, photos, duplicate check, reading a barcode from a photo
- Store brands: 434 brands with their SVG logos and colors, a store row
  and a searchable sheet in the card form, typeahead suggestions
- iOS widgets, quick actions, backup restore, iOS 27 search field fixes
- No code comments; Biome and TypeScript clean, 422 Jest tests
Features, compatibility, setup, how the barcode sizing works,
troubleshooting and roadmap, with ten screens in light and dark mode
under docs/screenshots.
Nothing imported src/infra/network/netinfo.ts, so drop it together with
the @react-native-community/netinfo dependency, its Jest mock, the
EXPO_PUBLIC_E2E_OFFLINE flag and the notes that still described it.
- Backups: validate the type of every card field on restore (bad name,
  code, format or dates reject the file, malformed optional fields are
  dropped) and always delete the temporary export/import file, even
  when sharing fails or the file is invalid
- Formats: add generic ITF (any even number of digits) instead of forcing
  ITF-14, accept Code 39 Full ASCII values and draw them with their
  shift pairs, accept GS1 DataBar Expanded payloads
- Scanning: confirm a code once it stays in view for 500 ms, whatever
  its position in the frame, and forget codes lost for over a second
- Form: the preview and the auto color follow the store linked from the
  typed name, saving waits for a photo still being copied and runs once
- Photos: the card store deletes the photos of a removed card and the
  ones an edit drops
- Settings: ignore unknown values read back from storage
- Haptics: remove the doubled selection feedback on store picks and on
  the Android action sheet
- Share one copy of the card subtitle, the section titles, saving a new
  card, the image picker, the no-op catch handler, the card ratio and
  the thumbnail radius (new radius.thumb token)
- Keep the language list in src/domain/language.ts, so settingsStore no
  longer imports infra/i18n and the three lists cannot drift
- Fold accents in one place (foldText) for card and store search, and
  cache the normalized store names instead of redoing it per keystroke
- Keep the search query in the search screen instead of uiStore, and
  wrap the tab gradients with withUnistyles instead of useUnistyles
- Read Reduce Motion through one shared subscription
- Remove dead code: parseBarcodeFormat, selectCardCount, IconKey, two
  unused test IDs and five unused strings
- Check in architecture.test.ts that infra never imports state or the
  UI, and that state only uses infra/persistence
The Expo SDK 58 preview headers (expo-modules-jsi RuntimeScheduler.h)
no longer compile with Xcode 26.2, which failed the e2e-ios job before
Maestro ran. Use the xcode-27 image and its iPhone 17 simulator, and
update the prerequisite in the README.
expo run:ios starts Metro by default, even for a Release build, then
keeps streaming the app logs, so the step never ended and the job hit
its 90-minute timeout before Maestro ran. The Release build embeds its
bundle, so pass --no-bundler and let the command exit after launch.
Arthurmtro
Arthurmtro previously approved these changes Sep 30, 2026

@Arthurmtro Arthurmtro left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

banger de zinzin en vrai!

With --device, expo run:ios also lists physical devices through
devicectl, whose 5-second timeout expired on the runner and failed the
step. The job already boots the simulator, and without --device the CLI
picks the booted one through simctl only.
Maestro text selectors are regexes matched against the full element
text, so "No card matches", "Brightness at maximum" and "This code looks
temporary" never matched the longer strings the app shows.
actions/cache only saves in its post step when the job succeeds, so
every failing run started from a cold 45-minute build. Restore and save
the CocoaPods and DerivedData caches explicitly, saving right after the
build step even on failure. Stop caching ios/Pods: ios/ is generated by
prebuild, and a restored ios/Pods folder alone could make run:ios skip
it.
@Zaphkiel-Ivanovna
Zaphkiel-Ivanovna merged commit 95df136 into main Sep 30, 2026
4 checks passed
@Zaphkiel-Ivanovna
Zaphkiel-Ivanovna deleted the feat/redesign branch September 30, 2026 16:41
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.

2 participants