Update README.md #37
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
| name: Build APK (Node 22 + Icons + Storage Fix) | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node 22 | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Create .env file | |
| run: | | |
| echo "VITE_GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}" > .env | |
| # 🔧 localStorage patch (no code edit) | |
| - name: Create localStorage patch | |
| run: | | |
| mkdir -p public | |
| cat << 'EOF' > public/localstorage-fix.js | |
| (function () { | |
| if (window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Preferences) { | |
| const pref = window.Capacitor.Plugins.Preferences; | |
| const originalSet = localStorage.setItem; | |
| const originalGet = localStorage.getItem; | |
| localStorage.setItem = function (key, value) { | |
| try { | |
| pref.set({ key: key, value: value }); | |
| } catch (e) { | |
| originalSet.call(localStorage, key, value); | |
| } | |
| }; | |
| localStorage.getItem = function (key) { | |
| try { | |
| let value = null; | |
| pref.get({ key: key }).then(function (res) { | |
| value = res.value; | |
| }); | |
| return value; | |
| } catch (e) { | |
| return originalGet.call(localStorage, key); | |
| } | |
| }; | |
| } | |
| })(); | |
| EOF | |
| - name: Inject script into index.html | |
| run: | | |
| sed -i 's|</head>|<script src="/localstorage-fix.js"></script></head>|' index.html | |
| - name: Build React app | |
| run: npm run build -- --mode production | |
| - name: Add Android platform | |
| run: npx cap add android | |
| - name: Update Android version | |
| run: | | |
| sed -i "s/versionCode [0-9]\+/versionCode 2/" android/app/build.gradle | |
| sed -i "s/versionName \".*\"/versionName \"2.0\"/" android/app/build.gradle | |
| - name: Generate adaptive launcher icons | |
| run: | | |
| if [ -f "resources/icon.png" ] || [ -f "resources/icon-foreground.png" ]; then | |
| npm install @capacitor/assets --no-save | |
| npx capacitor-assets generate --android | |
| else | |
| echo "::warning::No icon files found in resources/ — using default Capacitor icon." | |
| fi | |
| - name: Sync Capacitor | |
| run: npx cap sync android | |
| - name: Setup Java (JDK 21) | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| # 🔐 Decode keystore | |
| - name: Decode Keystore | |
| run: | | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > android/app/release.keystore | |
| # 🔐 Create keystore.properties (SAFE METHOD) | |
| - name: Create keystore.properties | |
| run: | | |
| echo "storeFile=release.keystore" > android/keystore.properties | |
| echo "storePassword=${{ secrets.SIGNING_KEY_PASSWORD }}" >> android/keystore.properties | |
| echo "keyAlias=${{ secrets.SIGNING_KEY_ALIAS }}" >> android/keystore.properties | |
| echo "keyPassword=${{ secrets.SIGNING_KEY_PASSWORD }}" >> android/keystore.properties | |
| # 🔥 Inject signing config safely | |
| - name: Inject signing config | |
| run: | | |
| FILE=android/app/build.gradle | |
| echo "" >> $FILE | |
| echo "def keystoreProperties = new Properties()" >> $FILE | |
| echo "def keystorePropertiesFile = rootProject.file(\"keystore.properties\")" >> $FILE | |
| echo "if (keystorePropertiesFile.exists()) {" >> $FILE | |
| echo " keystoreProperties.load(new FileInputStream(keystorePropertiesFile))" >> $FILE | |
| echo "}" >> $FILE | |
| echo "" >> $FILE | |
| echo "android {" >> $FILE | |
| echo " signingConfigs {" >> $FILE | |
| echo " release {" >> $FILE | |
| echo " storeFile file(keystoreProperties['storeFile'])" >> $FILE | |
| echo " storePassword keystoreProperties['storePassword']" >> $FILE | |
| echo " keyAlias keystoreProperties['keyAlias']" >> $FILE | |
| echo " keyPassword keystoreProperties['keyPassword']" >> $FILE | |
| echo " }" >> $FILE | |
| echo " }" >> $FILE | |
| echo " buildTypes {" >> $FILE | |
| echo " release {" >> $FILE | |
| echo " signingConfig signingConfigs.release" >> $FILE | |
| echo " minifyEnabled false" >> $FILE | |
| echo " }" >> $FILE | |
| echo " }" >> $FILE | |
| echo "}" >> $FILE | |
| - name: Build Release APK | |
| run: | | |
| cd android | |
| chmod +x gradlew | |
| ./gradlew assembleRelease | |
| - name: Upload APK | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: app-release-apk | |
| path: android/app/build/outputs/apk/release/app-release.apk |