Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions .github/workflows/release-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ jobs:

# ─── JOB 2: PRODUCTION BUILD (requires manual approval) ─────────────
build-production:
name: Build and Deploy Production APK
name: Build and Deploy Production AAB
environment: production
runs-on: ubuntu-latest
needs: build-staging
Expand Down Expand Up @@ -221,15 +221,18 @@ jobs:
sudo rm -rf /usr/share/dotnet /usr/local/share/powershell /usr/share/swift /opt/ghc /opt/hostedtoolcache/CodeQL
df -h

- name: Build production APK
- name: Build production AAB
env:
KEYSTORE_PATH: ${{ runner.temp }}/mapswipe-prod.keystore
STORE_PASSWORD: ${{ secrets.ANDROID_PRODUCTION_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.ANDROID_PRODUCTION_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.ANDROID_PRODUCTION_KEY_PASSWORD }}
# bundleRelease produces an Android App Bundle for the Play Store. No
# -PreactNativeArchitectures override, so all ABIs are included and Play
# splits per device. The prod keystore signs it as the upload key; Play
# App Signing re-signs the delivered APKs.
run: |
cd android && ./gradlew assembleRelease --stacktrace \
-PreactNativeArchitectures=armeabi-v7a,arm64-v8a \
cd android && ./gradlew bundleRelease --stacktrace \
-Pandroid.injected.signing.store.file=$KEYSTORE_PATH \
-Pandroid.injected.signing.store.password=$STORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
Expand All @@ -244,11 +247,11 @@ jobs:
echo "tag=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
fi

- name: Rename APK
- name: Rename AAB
run: |
mkdir -p generated
cp android/app/build/outputs/apk/release/app-release.apk \
generated/mapswipe-${{ steps.tag.outputs.tag }}.apk
cp android/app/build/outputs/bundle/release/app-release.aab \
generated/mapswipe-${{ steps.tag.outputs.tag }}.aab

- name: Publish production release
env:
Expand All @@ -258,14 +261,15 @@ jobs:
--title "MapSwipe Mobile ${{ steps.tag.outputs.tag }}" \
--notes "## MapSwipe Mobile ${{ steps.tag.outputs.tag }}

### 📱 Install
1. Download the APK below
2. Enable 'Install from unknown sources' in Android settings
3. Install
### 🚀 Play Store release
1. Download the AAB below
2. Upload it to the Play Console production track (Google re-signs it via Play App Signing)
3. Review and roll out the release

### 🔧 Build info
- Commit: \`${{ github.sha }}\`
- Build: #${{ github.run_number }}
- Date: $(date +'%Y-%m-%d %H:%M:%S UTC')
- Package: \`org.missingmaps.mapswipe\`" \
generated/mapswipe-${{ steps.tag.outputs.tag }}.apk
- Package: \`org.missingmaps.mapswipe\`
- Artifact: Android App Bundle (.aab), signed with the upload key" \
generated/mapswipe-${{ steps.tag.outputs.tag }}.aab
15 changes: 7 additions & 8 deletions components/CompareMappingSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,16 @@ function CompareMappingSession(props: Props) {

const flatListRef = useRef<FlatList<FbMappingTaskCompareCreateOnlyInput>>(null);

// "Go Back" on the outro scrolls back to the last task so the user can
// revise their answer (the outro is the page after the final task).
// "Go Back" on the outro returns to the first task so the user reviews the
// group from the start. The jump is instant (not animated): animating all
// the way back from the completion page would render every intermediate
// page and is what made repeated go-backs unstable.
const handleOutroGoBack = useCallback(() => {
if (compressedTasks.length === 0) {
return;
}
flatListRef.current?.scrollToOffset({
offset: (compressedTasks.length - 1) * pageWidth,
animated: true,
offset: 0,
animated: false,
});
}, [compressedTasks.length, pageWidth]);
}, []);

// FIXME: Discuss with Ankit on how to better define this
const tileWidth = Math.min(pageWidth - 20, pageHeight / 2 - 120);
Expand Down
15 changes: 7 additions & 8 deletions components/LocateFeaturesMappingSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -372,17 +372,16 @@ function LocateFeaturesMappingSession(props: Props) {
}
}, [pageWidth, tasks.length, onReachedEnd]);

// "Go Back" on the outro scrolls back to the last task so the user can
// revise their answer (the outro is the page after the final task).
// "Go Back" on the outro returns to the first task so the user reviews the
// group from the start. The jump is instant (not animated): animating all
// the way back from the completion page would render every intermediate
// page and is what made repeated go-backs unstable.
const handleOutroGoBack = useCallback(() => {
if (tasks.length === 0) {
return;
}
flatListRef.current?.scrollToOffset({
offset: (tasks.length - 1) * pageWidth,
animated: true,
offset: 0,
animated: false,
});
}, [tasks.length, pageWidth]);
}, []);

const tileWidth = Math.min(pageWidth - 20, pageHeight / 2);
// The tile is vertically centered in the viewport, so its bottom edge sits
Expand Down
15 changes: 7 additions & 8 deletions components/TileGridMappingSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,16 @@ function TileGridMappingSession(props: Props) {
}
}, [pageWidth, groupedTasks.length, contentPages, onReachedEnd]);

// "Go Back" on the outro scrolls back to the last task page so the user can
// revise their answers (the outro is the page after the final tasks).
// "Go Back" on the outro returns to the first task so the user reviews the
// group from the start. The jump is instant (not animated): animating all
// the way back from the completion page would render every intermediate
// page and is what made repeated go-backs unstable.
const handleOutroGoBack = useCallback(() => {
if (contentPages === 0) {
return;
}
flatListRef.current?.scrollToOffset({
offset: (contentPages - 1) * pageWidth,
animated: true,
offset: 0,
animated: false,
});
}, [contentPages, pageWidth]);
}, []);

const handleTilePress = useCallback((taskId: string) => {
onResultsChange((prevResults) => {
Expand Down
Loading