Release v1.4.0 (native — runtimeVersion 1.2.0 → 1.3.0) - #109
Merged
Conversation
Served its purpose diagnosing the v1.3.0 build; not a permanent workflow.
Expo SDK dictates the versions of expo/expo-*/react-native/react and async-storage; a minor or major bump belongs to a deliberate SDK upgrade, not a weekly Dependabot PR. Ignoring minor+major for that set stops a repeat of the v1.3.0 bundling break while still letting patch security fixes through.
The production build errored in the JS bundling phase: Dependabot had merged SDK-incompatible bumps (react-native 0.87.1, async-storage 3.x, react 19.2.8, drifted expo-* patches). 'expo install --fix' pins every SDK-managed package back to what Expo SDK 57 expects (async-storage 2.2.0, react-native 0.86.3, react 19.2.3, expo-* aligned). npm ci and tsc both pass. (cherry picked from commit 9f691fc)
Bumps [@react-navigation/bottom-tabs](https://github.com/react-navigation/react-navigation/tree/HEAD/packages/bottom-tabs) from 7.18.17 to 7.18.18. - [Release notes](https://github.com/react-navigation/react-navigation/releases) - [Changelog](https://github.com/react-navigation/react-navigation/blob/@react-navigation/bottom-tabs@7.18.18/packages/bottom-tabs/CHANGELOG.md) - [Commits](https://github.com/react-navigation/react-navigation/commits/@react-navigation/bottom-tabs@7.18.18/packages/bottom-tabs) --- updated-dependencies: - dependency-name: "@react-navigation/bottom-tabs" dependency-version: 7.18.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) from 19.2.3 to 19.2.8. - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.2.8/packages/react-dom) --- updated-dependencies: - dependency-name: react-dom dependency-version: 19.2.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Main > Develop
The first entry is the current version and the source of truth the card compares against; bump it in lockstep with expo.version each release.
Device-global (not per-account) since the card is about the app version. Reads and writes are best-effort so a storage failure never crashes the app.
Shows the card whenever the last dismissed version isn't the current one, and persists the current version on dismiss so it never reappears for that version.
A one-time card with a light fade + slide-up (built-in Animated, no new deps), dismissible via the button, the close icon, tapping outside, or Android back.
Mount the card as an overlay in the signed-in app; it appears once per version and never again once dismissed.
Read the current version from expo-constants (app.config.js expo.version) rather than duplicating it in whatsNew.ts, so the two can never drift and a version-bump that forgets the highlights just shows no card instead of silently no-opping. Look the entry up by version with find(), which is safe if WHATS_NEW is empty — no more WHATS_NEW[0] crashing at import.
The Modal's animationType="fade" already animates opacity; animating it again on the card double-drove it. Keep only the slide-up.
Add a one-time "What's New" card on version change
…le/react-dom-19.2.8 Bump react-dom from 19.2.3 to 19.2.8 in /mobile
…le/react-navigation/bottom-tabs-7.18.18 Bump @react-navigation/bottom-tabs from 7.18.17 to 7.18.18 in /mobile
The saved list only had bare slugs, so the app could not name a saved concept
without the bundled demo catalog. Add a 'saved' field carrying {slug,title,topic}
alongside the existing 'bookmarks' slugs (kept for membership/count and for
already-installed apps that don't read the new field).
Signed-in bookmarks were resolved against the bundled 20-concept catalog, so server-catalog saves never showed. Render from savedConcepts when present, fall back to the bundled catalog for the signed-out demo. Broaden CategoryChip to accept any label string (topic names match the Category values).
toggleBookmark reloads /me/state to refresh the saved list, but a failed reload threw after the save had already persisted, so ProgressContext rolled the UI back to un-saved. Catch the reload failure and patch in place instead, so a succeeded toggle is never reverted; the saved list catches up on the next load.
Fix saved concepts not appearing on Profile (#90)
markLearned patched the cache with a client-side guess (the caller's concept id, no title/topic) and only a full reload — an app restart — brought the true server history. Reload /me/state after /daily/complete so the History tab reflects the completed concept immediately. If the reload fails the completion has already persisted, so patch in place rather than rolling it back.
markLearned recorded ProgressContext's locally-selected concept, so a signed-in user completing the server's concept stored the wrong one — visible on the reload failure fallback and as a brief wrong-title flash before the reload. Thread the concept the screen actually showed (the server's, when signed in) into markLearned, carrying its title and topic into the optimistic/fallback record.
Installing expo-splash-screen surfaced a latent conflict: react-dom had drifted to 19.2.8 while react is pinned to SDK 57's 19.2.3, so a fresh resolve failed (react-dom 19.2.8 needs react ^19.2.8). Pin react-dom back to 19.2.3 to match, then add expo-splash-screen (SDK 57's ~57.0.8).
App() rendered null until the font loaded with no splash management, so every launch flashed a blank screen. Keep the native splash up via preventAutoHideAsync and hide it onLayout of the root view once the font is ready — the splash hands straight over to real UI with no blank frame. Register the config plugin.
Three fixes to the splash wiring: (1) useFonts' error was ignored, so a font failure left fontsLoaded false forever and the held native splash never hid — the app was stuck on the splash. Treat fontsLoaded || fontError as ready so it falls back to the system font instead of hanging. (2) Drop the dead if(fontsLoaded) guard in onLayout (the view only mounts when ready). (3) Guard hideAsync with a ref so repeated layout passes don't re-call it.
Hold the splash until first paint; no launch blank-flash (#93)
The 'Alerts — Daily reminders arrive in Phase 3' card was a non-interactive placeholder; reminders are live and controlled by the Daily reminders toggle on the Profile screen. Remove the card, its now-unused styles, and the now-unused radius import.
Remove the redundant "Alerts" card from Personalization (#94)
apply() ran the optimistic update inside the serialised chain, so a tap's icon only flipped after any prior mutation's network finished — Like felt laggy right after Save/Mark-learned (now two round trips each). Apply the optimistic update immediately, keep the network runs serialised, apply the whole-state server snapshot only when nothing else is pending (no flicker), and undo just the failed change functionally (a flip is its own inverse; mark-learned removes its record). Restores instant feedback without reintroducing the #39 clobber.
Counting likes per concept needs an index keyed by concept_id (the existing one is keyed by user_id). Partial on liked_at is not null so it only covers likes.
Return the count of likes by OTHER users on the day's concept; the client adds the viewer's own like on top, so a like/unlike is an instant +/-1.
The like number is shown wherever a card appears (Today, History, Saved), so the learned and saved rows now include the same others'-likes count.
Parse the server's others'-likes count into Concept.likeCount and into the learned/saved records, so every surface can render it.
Add a small flame+number badge, and show it in the concept action bar next to the like button: others' likes plus the viewer's own (optimistic), hidden at zero. Tapping like ticks it +/-1 instantly.
The count appears wherever a card is shown, per the issue: each row adds the viewer's own like to the server's others'-count and hides it at zero.
Match the codebase's memoisation pattern (cf. learnedIds in ProgressContext) so the liked-set isn't rebuilt on every render.
Instant optimistic feedback for Like/Save/etc. (#95 part A)
Public like counts on every card (#95 part B)
Codify the content policy: the card shows only new user-facing features, never bug fixes, leaks, perf/UI tweaks, or removals — those belong in the release notes. Re-curate the entry accordingly: the one genuine new feature this cycle is public like counts, so 1.4.0 leads with that (the old 1.3.0 entry mixed in fixes and never actually displayed — the card shipped after 1.3.0's build). The card's mechanics (heading, version, once-per-version, dismiss, animation) already meet the issue from the original build.
…only What's New card: new features only (#97)
production-apk extends production (channel production, environment production) but builds a sideloadable APK instead of the Play Store .aab. A phone on this build only updates on a release to main (production channel) — never from develop.
On release, rebuild the sideload APK only when the release is native (runtimeVersion changed) and publish it to a fixed 'apk-latest' release asset; JS-only releases reuse the existing APK and update over the air. The asset lives at a stable URL, so the README link never needs editing and nothing has to push to the protected main/develop branches.
Link to the apk-latest release asset (stable URL) and document that an installed app changes only on a release to main.
…iew) actions/checkout had no ref, so a manual run would build from the default branch (develop) and could ship unreleased code as the production APK. Pin the ref to the release tag on a release event, or main on a manual run.
…review) The workflow triggers on release:published and itself publishes the apk-latest release. GitHub's GITHUB_TOKEN non-recursion rule already prevents a loop, but add a job-level guard (skip when the release is apk-latest) as insurance against a future switch to a PAT.
Production APK on release only; stable install link
Native release: expo-splash-screen and expo-constants were added since the last build (runtime 1.2.0), so installed apps need a new APK. Advance the native-ABI runtime to 1.3.0 (decoupled from the marketing version, per app.config.js).
chore: bump to v1.4.0 (version 1.3.0→1.4.0, runtimeVersion 1.2.0→1.3.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v1.4.0 — promotes
developtomain.runtimeVersion1.2.0 → 1.3.0 (new native modules:expo-splash-screen,expo-constants). Installed apps need a new APK — it's built and published automatically on merge (see below).version1.3.0 → 1.4.0.New features
Fixes & improvements
openapiclosed in prod, generation moved off the request path (low-watermark prefetch).Infra
What happens on merge
release.yml→ publishes production + preview OTA (runtime 1.3.0) and cuts thev1.4.0tag + GitHub Release.release-apk.yml(native, runtimeVersion changed) → builds the production APK and publishes it to the stableapk-latestlink (~15–20 min).After merge — do
…/releases/download/apk-latest/one-concept.apk). That production build then updates only on future releases.