Skip to content

Commit d14455f

Browse files
committed
Prototype of hybrid mobile apps structure
1 parent 72de7cb commit d14455f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3545
-17
lines changed

.github/workflows/android.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: Android Build
2+
3+
on:
4+
push:
5+
branches: [main, mobile-app]
6+
paths:
7+
- 'android/**'
8+
- '.github/workflows/android.yml'
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- 'android/**'
13+
- '.github/workflows/android.yml'
14+
workflow_dispatch:
15+
16+
jobs:
17+
build:
18+
runs-on: ubuntu-latest
19+
defaults:
20+
run:
21+
working-directory: android
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Set up JDK 17
28+
uses: actions/setup-java@v4
29+
with:
30+
java-version: '17'
31+
distribution: 'temurin'
32+
33+
- name: Setup Gradle
34+
uses: gradle/actions/setup-gradle@v3
35+
with:
36+
gradle-version: 8.5
37+
38+
- name: Cache Gradle packages
39+
uses: actions/cache@v4
40+
with:
41+
path: |
42+
~/.gradle/caches
43+
~/.gradle/wrapper
44+
key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') }}
45+
restore-keys: |
46+
${{ runner.os }}-gradle-
47+
48+
- name: Make gradlew executable
49+
run: chmod +x ./gradlew
50+
51+
- name: Build debug APK
52+
run: ./gradlew assembleDebug --no-daemon
53+
54+
- name: Run unit tests
55+
run: ./gradlew testDebugUnitTest --no-daemon
56+
continue-on-error: true
57+
58+
- name: Upload debug APK
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: app-debug
62+
path: android/app/build/outputs/apk/debug/app-debug.apk
63+
retention-days: 7
64+
65+
release:
66+
runs-on: ubuntu-latest
67+
needs: build
68+
if: github.ref == 'refs/heads/main'
69+
defaults:
70+
run:
71+
working-directory: android
72+
73+
steps:
74+
- name: Checkout repository
75+
uses: actions/checkout@v4
76+
77+
- name: Set up JDK 17
78+
uses: actions/setup-java@v4
79+
with:
80+
java-version: '17'
81+
distribution: 'temurin'
82+
83+
- name: Setup Gradle
84+
uses: gradle/actions/setup-gradle@v3
85+
with:
86+
gradle-version: 8.5
87+
88+
- name: Cache Gradle packages
89+
uses: actions/cache@v4
90+
with:
91+
path: |
92+
~/.gradle/caches
93+
~/.gradle/wrapper
94+
key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') }}
95+
restore-keys: |
96+
${{ runner.os }}-gradle-
97+
98+
- name: Make gradlew executable
99+
run: chmod +x ./gradlew
100+
101+
- name: Build release APK (unsigned)
102+
run: ./gradlew assembleRelease --no-daemon
103+
104+
- name: Upload release APK
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: app-release-unsigned
108+
path: android/app/build/outputs/apk/release/app-release-unsigned.apk
109+
retention-days: 30
110+
111+
# Note: For actual Play Store deployment, you would need to:
112+
# 1. Set up signing keystore from secrets
113+
# 2. Sign the APK or build AAB
114+
# 3. Upload to Play Store using fastlane or Google Play Developer API
115+
116+
- name: Release step placeholder
117+
run: |
118+
echo "Release step placeholder"
119+
echo "In production, this would:"
120+
echo "1. Decode signing keystore from secrets"
121+
echo "2. Sign the release APK or build signed AAB"
122+
echo "3. Upload to Google Play Console"

.github/workflows/ios.yml

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: iOS Build
2+
3+
on:
4+
push:
5+
branches: [main, mobile-app]
6+
paths:
7+
- 'ios/**'
8+
- '.github/workflows/ios.yml'
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- 'ios/**'
13+
- '.github/workflows/ios.yml'
14+
workflow_dispatch:
15+
16+
jobs:
17+
build:
18+
runs-on: macos-14
19+
defaults:
20+
run:
21+
working-directory: ios
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Select Xcode version
28+
run: sudo xcode-select -s /Applications/Xcode_15.2.app
29+
30+
- name: Show Xcode version
31+
run: xcodebuild -version
32+
33+
- name: Cache Swift Package Manager
34+
uses: actions/cache@v4
35+
with:
36+
path: |
37+
ios/.build
38+
~/Library/Caches/org.swift.swiftpm
39+
key: ${{ runner.os }}-spm-${{ hashFiles('ios/Package.swift') }}
40+
restore-keys: |
41+
${{ runner.os }}-spm-
42+
43+
- name: Resolve Swift packages
44+
run: swift package resolve
45+
46+
- name: Build for iOS Simulator
47+
run: |
48+
xcodebuild build \
49+
-scheme MySpeedPuzzling \
50+
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.2' \
51+
-configuration Debug \
52+
CODE_SIGNING_ALLOWED=NO \
53+
| xcpretty
54+
55+
- name: Run tests
56+
run: |
57+
xcodebuild test \
58+
-scheme MySpeedPuzzling \
59+
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.2' \
60+
-configuration Debug \
61+
CODE_SIGNING_ALLOWED=NO \
62+
| xcpretty
63+
continue-on-error: true
64+
65+
archive:
66+
runs-on: macos-14
67+
needs: build
68+
if: github.ref == 'refs/heads/main'
69+
defaults:
70+
run:
71+
working-directory: ios
72+
73+
steps:
74+
- name: Checkout repository
75+
uses: actions/checkout@v4
76+
77+
- name: Select Xcode version
78+
run: sudo xcode-select -s /Applications/Xcode_15.2.app
79+
80+
- name: Cache Swift Package Manager
81+
uses: actions/cache@v4
82+
with:
83+
path: |
84+
ios/.build
85+
~/Library/Caches/org.swift.swiftpm
86+
key: ${{ runner.os }}-spm-${{ hashFiles('ios/Package.swift') }}
87+
restore-keys: |
88+
${{ runner.os }}-spm-
89+
90+
- name: Resolve Swift packages
91+
run: swift package resolve
92+
93+
# Note: For actual App Store deployment, you would need to:
94+
# 1. Set up code signing certificates and provisioning profiles
95+
# 2. Use fastlane or manual xcodebuild archive commands
96+
# 3. Upload to App Store Connect using xcrun altool or fastlane deliver
97+
98+
- name: Archive for distribution (dry run)
99+
run: |
100+
echo "Archive step placeholder"
101+
echo "In production, this would:"
102+
echo "1. Import signing certificates from secrets"
103+
echo "2. Build and archive the app"
104+
echo "3. Export IPA for App Store"
105+
echo "4. Upload to App Store Connect"

android/.gitignore

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Gradle
2+
.gradle/
3+
build/
4+
!gradle/wrapper/gradle-wrapper.jar
5+
6+
# Android Studio
7+
*.iml
8+
.idea/
9+
*.hprof
10+
11+
# Local configuration
12+
local.properties
13+
secrets.properties
14+
15+
# Keystore files
16+
*.jks
17+
*.keystore
18+
19+
# Google Services
20+
google-services.json
21+
22+
# Proguard
23+
proguard/
24+
25+
# Log Files
26+
*.log
27+
28+
# OS generated files
29+
.DS_Store
30+
.DS_Store?
31+
._*
32+
.Spotlight-V100
33+
.Trashes
34+
ehthumbs.db
35+
Thumbs.db
36+
37+
# Kotlin
38+
.kotlin/
39+
40+
# Caches
41+
.cxx/
42+
43+
# Environment files
44+
.env
45+
.env.*
46+
!.env.example
47+
48+
# Generated files
49+
*.apk
50+
*.aab
51+
*.ap_
52+
*.dex
53+
54+
# Native
55+
obj/

android/app/build.gradle.kts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
plugins {
2+
id("com.android.application")
3+
id("org.jetbrains.kotlin.android")
4+
}
5+
6+
android {
7+
namespace = "com.myspeedpuzzling.app"
8+
compileSdk = 34
9+
10+
defaultConfig {
11+
applicationId = "com.myspeedpuzzling.app"
12+
minSdk = 26
13+
targetSdk = 34
14+
versionCode = 1
15+
versionName = "1.0.0"
16+
17+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18+
}
19+
20+
buildTypes {
21+
release {
22+
isMinifyEnabled = true
23+
proguardFiles(
24+
getDefaultProguardFile("proguard-android-optimize.txt"),
25+
"proguard-rules.pro"
26+
)
27+
}
28+
debug {
29+
isDebuggable = true
30+
}
31+
}
32+
33+
compileOptions {
34+
sourceCompatibility = JavaVersion.VERSION_17
35+
targetCompatibility = JavaVersion.VERSION_17
36+
}
37+
38+
kotlinOptions {
39+
jvmTarget = "17"
40+
}
41+
42+
buildFeatures {
43+
viewBinding = true
44+
}
45+
}
46+
47+
dependencies {
48+
// Hotwire Native Android
49+
implementation("dev.hotwire:turbo:7.1.3")
50+
51+
// AndroidX
52+
implementation("androidx.core:core-ktx:1.12.0")
53+
implementation("androidx.appcompat:appcompat:1.6.1")
54+
implementation("androidx.activity:activity-ktx:1.8.2")
55+
implementation("androidx.fragment:fragment-ktx:1.6.2")
56+
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
57+
implementation("androidx.webkit:webkit:1.9.0")
58+
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
59+
60+
// Material Design
61+
implementation("com.google.android.material:material:1.11.0")
62+
63+
// CameraX for barcode scanning
64+
implementation("androidx.camera:camera-core:1.3.1")
65+
implementation("androidx.camera:camera-camera2:1.3.1")
66+
implementation("androidx.camera:camera-lifecycle:1.3.1")
67+
implementation("androidx.camera:camera-view:1.3.1")
68+
69+
// ML Kit Barcode Scanning
70+
implementation("com.google.mlkit:barcode-scanning:17.2.0")
71+
72+
// Google Play Billing
73+
implementation("com.android.billingclient:billing-ktx:6.1.0")
74+
75+
// Coroutines
76+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
77+
78+
// OkHttp for API calls
79+
implementation("com.squareup.okhttp3:okhttp:4.12.0")
80+
implementation("org.json:json:20231013")
81+
82+
// Testing
83+
testImplementation("junit:junit:4.13.2")
84+
androidTestImplementation("androidx.test.ext:junit:1.1.5")
85+
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
86+
}

android/app/proguard-rules.pro

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.kts.
4+
5+
# Keep JavaScript interface methods
6+
-keepclassmembers class com.myspeedpuzzling.features.BarcodeScannerBridge {
7+
@android.webkit.JavascriptInterface <methods>;
8+
}
9+
10+
-keepclassmembers class com.myspeedpuzzling.billing.BillingBridge {
11+
@android.webkit.JavascriptInterface <methods>;
12+
}
13+
14+
# Keep Hotwire Turbo classes
15+
-keep class dev.hotwire.turbo.** { *; }
16+
17+
# Keep Google Play Billing classes
18+
-keep class com.android.vending.billing.** { *; }
19+
20+
# OkHttp
21+
-dontwarn okhttp3.**
22+
-dontwarn okio.**
23+
-keep class okhttp3.** { *; }
24+
-keep interface okhttp3.** { *; }
25+
26+
# ML Kit
27+
-keep class com.google.mlkit.** { *; }

0 commit comments

Comments
 (0)