Add iOS & Android build + frontend fixes for desktop
Build & Push Docker Images / test-backend (push) Successful in 53s
Build & Push Docker Images / test-frontend (push) Successful in 58s
Build & Push Docker Images / build-backend (push) Successful in 1m4s
Build & Push Docker Images / build-frontend (push) Failing after 56s
Build & Push Docker Images / test-backend (push) Successful in 53s
Build & Push Docker Images / test-frontend (push) Successful in 58s
Build & Push Docker Images / build-backend (push) Successful in 1m4s
Build & Push Docker Images / build-frontend (push) Failing after 56s
This commit is contained in:
@@ -20,7 +20,24 @@
|
||||
"WebFetch(domain:dev.to)",
|
||||
"Bash(command -v npx node java)",
|
||||
"Bash(npx --version)",
|
||||
"Bash(npx cap *)"
|
||||
"Bash(npx cap *)",
|
||||
"Bash(pacman -Si jdk17-openjdk)",
|
||||
"Bash(yay -Si android-sdk-cmdline-tools-latest)",
|
||||
"Bash(sudo pacman -S --needed --noconfirm jdk17-openjdk)",
|
||||
"Bash(sudo -n pacman -S --needed --noconfirm jdk17-openjdk)",
|
||||
"Bash(java -version)",
|
||||
"Read(//opt/android-sdk/**)",
|
||||
"Read(//usr/lib/jvm/**)",
|
||||
"Bash(getent group *)",
|
||||
"Bash(cat)",
|
||||
"Bash(grep -q '^android/local.properties$' /home/anunez/Projects/FarmaFinder/.gitignore)",
|
||||
"Bash(JAVA_HOME=/usr/lib/jvm/java-17-openjdk ANDROID_HOME=/opt/android-sdk ANDROID_SDK_ROOT=/opt/android-sdk PATH=/usr/lib/jvm/java-17-openjdk/bin:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:__TRACKED_VAR__ ./gradlew --no-daemon assembleDebug)",
|
||||
"Bash(shred -u /tmp/.farmafinder-keystore-pass)",
|
||||
"Read(//tmp/**)",
|
||||
"Bash(JAVA_HOME=/usr/lib/jvm/java-17-openjdk /usr/lib/jvm/java-17-openjdk/bin/jarsigner -verify -verbose:summary /home/anunez/Projects/FarmaFinder/android/app/build/outputs/bundle/release/app-release.aab)",
|
||||
"Bash(openssl pkcs7 *)",
|
||||
"Bash(openssl x509 *)",
|
||||
"Bash(/opt/android-sdk/build-tools/34.0.0/apksigner verify *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,11 @@ build/
|
||||
.DS_Store
|
||||
*.log
|
||||
|
||||
# Local Android SDK path — machine-specific
|
||||
android/local.properties
|
||||
ios/App/Pods/
|
||||
|
||||
# Android release signing — NEVER commit
|
||||
android/keystore.properties
|
||||
android/app/*.jks
|
||||
android/app/*.keystore
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
# Native Mobile App Build Guide
|
||||
|
||||
FarmaFinder ships as a PWA and is wrapped for the App Store / Play Store via [Capacitor 6](https://capacitorjs.com). The web frontend in `frontend/` is bundled into each native shell — there's no separate codebase for Android or iOS.
|
||||
|
||||
```
|
||||
FarmaFinder/
|
||||
├── frontend/ # React + Vite PWA (the actual UI)
|
||||
├── backend/ # Node API
|
||||
├── android/ # Capacitor-generated Android Studio project
|
||||
├── ios/ # Capacitor-generated Xcode project
|
||||
└── capacitor.config.json
|
||||
```
|
||||
|
||||
The `android/` and `ios/` folders are real native projects — open them in their IDEs, change Swift / Kotlin / Gradle / xib as needed.
|
||||
|
||||
---
|
||||
|
||||
## One-time setup
|
||||
|
||||
### Common (any OS)
|
||||
```bash
|
||||
npm run install:all # root + frontend + backend deps
|
||||
```
|
||||
|
||||
### Android prerequisites
|
||||
- **JDK 21** (or 17). Install via your package manager or [Adoptium](https://adoptium.net/).
|
||||
- **Android Studio** (Hedgehog or later) with the Android SDK Platform 34 installed.
|
||||
- Set `ANDROID_HOME` and add `platform-tools` to `PATH`, e.g.:
|
||||
```bash
|
||||
export ANDROID_HOME="$HOME/Android/Sdk"
|
||||
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
|
||||
```
|
||||
- Open `android/` once in Android Studio so Gradle resolves the dependencies.
|
||||
|
||||
### iOS prerequisites (macOS only)
|
||||
- **Xcode 15+** from the App Store. Run it once and accept the licence.
|
||||
- **Command Line Tools**: `xcode-select --install`
|
||||
- **CocoaPods**: `sudo gem install cocoapods` (or `brew install cocoapods`)
|
||||
- After cloning, run pod install inside `ios/App`:
|
||||
```bash
|
||||
cd ios/App && pod install && cd -
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Day-to-day workflow
|
||||
|
||||
1. **Build the web bundle**
|
||||
```bash
|
||||
npm run build:web
|
||||
```
|
||||
Produces `frontend/dist/`, which Capacitor copies into the native projects.
|
||||
|
||||
2. **Sync into the native shells**
|
||||
```bash
|
||||
npm run cap:sync
|
||||
```
|
||||
- Copies `frontend/dist/` → `android/app/src/main/assets/public/` and `ios/App/App/public/`
|
||||
- Re-runs `pod install` if new plugins were added
|
||||
- Updates `capacitor.config.json` inside each platform
|
||||
|
||||
3. **Open the native project in its IDE**
|
||||
```bash
|
||||
npm run cap:open:android # Android Studio
|
||||
npm run cap:open:ios # Xcode (macOS only)
|
||||
```
|
||||
|
||||
4. **Run on a device or emulator**
|
||||
```bash
|
||||
npm run cap:run:android
|
||||
npm run cap:run:ios
|
||||
```
|
||||
These build the web bundle, sync, and launch on the first connected device/emulator.
|
||||
|
||||
After editing anything under `frontend/`, repeat steps 1 + 2 (or use `cap:sync`). Editing native files (Gradle, Swift, Kotlin, plist) is done directly inside `android/` and `ios/` — those edits survive `cap sync`.
|
||||
|
||||
---
|
||||
|
||||
## Pointing the app at the backend
|
||||
|
||||
The native bundle loads `index.html` from inside the app (`capacitor://localhost/` on iOS, `https://localhost/` on Android by default), so **relative `/api/...` paths do not reach the backend**. Pick one of:
|
||||
|
||||
### Option A — wrap the deployed PWA (simplest)
|
||||
Add a `server.url` to `capacitor.config.json` so the WebView loads the production site:
|
||||
```json
|
||||
{
|
||||
"server": {
|
||||
"url": "https://farmacias.hacecalor.net",
|
||||
"cleartext": false,
|
||||
"androidScheme": "https"
|
||||
}
|
||||
}
|
||||
```
|
||||
Run `npm run cap:sync` after the change. The native app is now a thin shell around the live PWA — fastest to ship, but useless without a network.
|
||||
|
||||
### Option B — bundled web + absolute API URLs (recommended)
|
||||
Keep the web assets bundled (no `server.url`) and rewrite frontend `fetch()` calls to use an absolute backend URL. The path of least resistance:
|
||||
|
||||
1. Add a Vite env var to `frontend/.env.production`:
|
||||
```
|
||||
VITE_API_BASE=https://farmacias.hacecalor.net
|
||||
```
|
||||
2. Centralise `fetch` calls through a helper (e.g. `frontend/src/utils/api.js`):
|
||||
```js
|
||||
const BASE = import.meta.env.VITE_API_BASE || '';
|
||||
export const apiUrl = (path) => `${BASE}${path.startsWith('/') ? path : '/' + path}`;
|
||||
```
|
||||
3. Replace `fetch('/api/...')` with `fetch(apiUrl('/api/...'))` across the components.
|
||||
4. On the backend, set `CORS_ORIGIN=https://farmacias.hacecalor.net,capacitor://localhost,https://localhost` so the native WebView origin is allowed.
|
||||
|
||||
This lets the app work offline for cached UI and only hits the network for live data.
|
||||
|
||||
---
|
||||
|
||||
## Permissions already declared
|
||||
|
||||
The two manifests are pre-wired for the features the PWA already uses:
|
||||
|
||||
**`android/app/src/main/AndroidManifest.xml`**
|
||||
- `INTERNET` — network calls
|
||||
- `ACCESS_FINE_LOCATION` / `ACCESS_COARSE_LOCATION` — "Sort by distance"
|
||||
- `POST_NOTIFICATIONS` — Android 13+ push opt-in
|
||||
|
||||
**`ios/App/App/Info.plist`**
|
||||
- `NSLocationWhenInUseUsageDescription` — shown by the OS when geolocation is requested
|
||||
- `NSLocationAlwaysAndWhenInUseUsageDescription` — same for background-style requests
|
||||
- `UIBackgroundModes: remote-notification` — required for APNs push delivery
|
||||
|
||||
If you add features that need new permissions (camera, contacts, etc.), edit those files directly.
|
||||
|
||||
---
|
||||
|
||||
## App icons & splash screens
|
||||
|
||||
Capacitor generated placeholder assets:
|
||||
- Android: `android/app/src/main/res/mipmap-*/ic_launcher*.png`
|
||||
- iOS: `ios/App/App/Assets.xcassets/AppIcon.appiconset/`
|
||||
- Splash: `ios/App/App/Assets.xcassets/Splash.imageset/` and the Android theme
|
||||
|
||||
Replace these with real artwork before shipping. The easiest way is the official asset generator — drop a single 1024×1024 PNG (and a foreground/background for adaptive icons) into a `resources/` folder at the project root and run:
|
||||
```bash
|
||||
npx @capacitor/assets generate --iconBackgroundColor '#0f766e' --splashBackgroundColor '#0f766e'
|
||||
```
|
||||
(install once: `npm install --save-dev @capacitor/assets`)
|
||||
|
||||
Splash colour and behaviour are configured in `capacitor.config.json` (`plugins.SplashScreen`). The runtime hook in `frontend/src/utils/native.js` hides the splash after React mounts.
|
||||
|
||||
---
|
||||
|
||||
## Push notifications on native
|
||||
|
||||
The web PWA uses VAPID + the browser PushManager. **Native iOS and Android cannot use Web Push.** To deliver push from the existing backend to native shells:
|
||||
|
||||
- **Android** — set up Firebase Cloud Messaging, add `android/app/google-services.json`, install `@capacitor/push-notifications`. The backend then sends to FCM tokens instead of (or in addition to) the existing Web Push subscriptions.
|
||||
- **iOS** — create an APNs key in the Apple Developer portal, enable the Push capability in Xcode, configure the `aps-environment` entitlement, install `@capacitor/push-notifications`.
|
||||
|
||||
Until those are wired up, the bell button in the native app is a no-op — `pushSupported()` in `frontend/src/utils/notifications.js` returns false because there's no service worker in the native WebView.
|
||||
|
||||
---
|
||||
|
||||
## Releasing
|
||||
|
||||
### Android
|
||||
1. In Android Studio: **Build → Generate Signed Bundle / APK → Android App Bundle**.
|
||||
2. Create or reuse a keystore; the password unlocks the release signing config.
|
||||
3. Bump `versionCode` and `versionName` in `android/app/build.gradle` for each release.
|
||||
4. Upload the produced `.aab` to Google Play Console.
|
||||
|
||||
### iOS
|
||||
1. In Xcode: select an **Any iOS Device (arm64)** destination → **Product → Archive**.
|
||||
2. From the Organizer, **Distribute App → App Store Connect**.
|
||||
3. Bump `CURRENT_PROJECT_VERSION` (build) and `MARKETING_VERSION` (display) under the App target's *General* tab.
|
||||
4. Submit via App Store Connect.
|
||||
|
||||
Both stores require: privacy policy URL, screenshots (multiple device sizes), an app description, and an age rating questionnaire. The pharmacy domain typically triggers an extra medical-content review on iOS — keep marketing copy factual.
|
||||
|
||||
---
|
||||
|
||||
## Updating Capacitor / plugins
|
||||
|
||||
```bash
|
||||
npm install @capacitor/core@latest @capacitor/cli@latest \
|
||||
@capacitor/android@latest @capacitor/ios@latest \
|
||||
@capacitor/app@latest @capacitor/splash-screen@latest @capacitor/status-bar@latest
|
||||
npm run cap:sync
|
||||
```
|
||||
After major upgrades follow the migration guide at https://capacitorjs.com/docs/updating.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **`cap sync` says `Could not find platform 'android'`** — you removed the folder. Re-create with `npx cap add android`.
|
||||
- **iOS build fails with `Sandbox: rsync ... deny`** — clean build folder (`Cmd-Shift-K`), then `pod install` inside `ios/App`.
|
||||
- **WebView shows a white screen on Android 14** — verify `android:usesCleartextTraffic` isn't blocking your dev backend (HTTPS only by default in `capacitor.config.json`).
|
||||
- **Geolocation never returns** — Android 14 requires both `ACCESS_FINE_LOCATION` *and* a runtime grant via the system dialog; iOS requires the `Info.plist` keys above plus enabling Location on the simulator (`Features → Location`).
|
||||
@@ -1,5 +1,11 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
def keystorePropertiesFile = rootProject.file('keystore.properties')
|
||||
def keystoreProperties = new Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "net.hacecalor.farmafinder"
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
@@ -16,10 +22,24 @@ android {
|
||||
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
storeFile file(keystoreProperties['storeFile'])
|
||||
storePassword keystoreProperties['storePassword']
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ android {
|
||||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-splash-screen')
|
||||
implementation project(':capacitor-status-bar')
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vendored
+24
@@ -19,3 +19,27 @@
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
# --- Capacitor 6 ---
|
||||
# Plugins are discovered + invoked by reflection from the JS bridge.
|
||||
-keep class com.getcapacitor.** { *; }
|
||||
-keep @com.getcapacitor.annotation.CapacitorPlugin class * { *; }
|
||||
-keepclassmembers class * extends com.getcapacitor.Plugin {
|
||||
@com.getcapacitor.PluginMethod public *;
|
||||
}
|
||||
-keepclassmembers @com.getcapacitor.annotation.CapacitorPlugin class * {
|
||||
@com.getcapacitor.PluginMethod public *;
|
||||
}
|
||||
|
||||
# --- Cordova compatibility layer (capacitor-cordova-android-plugins) ---
|
||||
-keep class org.apache.cordova.** { *; }
|
||||
-keep public class * extends org.apache.cordova.CordovaPlugin
|
||||
|
||||
# --- WebView JS interface ---
|
||||
-keepclassmembers class * {
|
||||
@android.webkit.JavascriptInterface <methods>;
|
||||
}
|
||||
|
||||
# Helpful stack traces from release builds.
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-renamesourcefileattribute SourceFile
|
||||
|
||||
@@ -38,4 +38,7 @@
|
||||
<!-- Permissions -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
</manifest>
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
|
||||
|
||||
include ':capacitor-splash-screen'
|
||||
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')
|
||||
|
||||
include ':capacitor-status-bar'
|
||||
project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.25rem;
|
||||
margin-top: 1rem;
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
padding: 0.5rem 0.5rem 0.5rem 0;
|
||||
animation: fadeInUp 0.8s ease-out 0.4s backwards;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
import { initNativeShell } from './utils/native';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
@@ -9,3 +10,5 @@ ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
initNativeShell();
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Capacitor bootstrap — no-ops on the web, configures native shell on mobile.
|
||||
// Plugins are dynamic-imported so the web bundle isn't penalized.
|
||||
|
||||
let initStarted = false;
|
||||
|
||||
export function isNativeApp() {
|
||||
return typeof window !== 'undefined' && Boolean(window.Capacitor?.isNativePlatform?.());
|
||||
}
|
||||
|
||||
export async function initNativeShell() {
|
||||
if (initStarted || !isNativeApp()) return;
|
||||
initStarted = true;
|
||||
|
||||
try {
|
||||
const { StatusBar, Style } = await import('@capacitor/status-bar');
|
||||
await StatusBar.setBackgroundColor({ color: '#0f766e' }).catch(() => {});
|
||||
await StatusBar.setStyle({ style: Style.Light }).catch(() => {});
|
||||
} catch {
|
||||
/* plugin not present — fine on web */
|
||||
}
|
||||
|
||||
try {
|
||||
const { SplashScreen } = await import('@capacitor/splash-screen');
|
||||
await SplashScreen.hide({ fadeOutDuration: 250 }).catch(() => {});
|
||||
} catch {
|
||||
/* plugin not present — fine on web */
|
||||
}
|
||||
|
||||
try {
|
||||
const { App } = await import('@capacitor/app');
|
||||
App.addListener('backButton', ({ canGoBack }) => {
|
||||
if (canGoBack) window.history.back();
|
||||
else App.exitApp();
|
||||
});
|
||||
} catch {
|
||||
/* plugin not present — fine on web */
|
||||
}
|
||||
}
|
||||
@@ -45,5 +45,13 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>FarmaFinder uses your location to sort nearby pharmacies by distance.</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>FarmaFinder uses your location to sort nearby pharmacies by distance.</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
+3
-1
@@ -11,7 +11,9 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
|
||||
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
||||
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
|
||||
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
|
||||
end
|
||||
|
||||
target 'App' do
|
||||
|
||||
Generated
+31
-1
@@ -9,8 +9,11 @@
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^6.2.1",
|
||||
"@capacitor/app": "^6.0.3",
|
||||
"@capacitor/core": "^6.2.1",
|
||||
"@capacitor/ios": "^6.2.1"
|
||||
"@capacitor/ios": "^6.2.1",
|
||||
"@capacitor/splash-screen": "^6.0.4",
|
||||
"@capacitor/status-bar": "^6.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/cli": "^6.2.1",
|
||||
@@ -26,6 +29,15 @@
|
||||
"@capacitor/core": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/app": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/app/-/app-6.0.3.tgz",
|
||||
"integrity": "sha512-4gFUCbcVz0N/YYN32OBFerocWXslIv3Nc90gDiRsBkJc0plwK6kIUT6PKa5WtW2kfhteUeCVXQbvArH2fH+0Ug==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/cli": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-6.2.1.tgz",
|
||||
@@ -90,6 +102,24 @@
|
||||
"@capacitor/core": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/splash-screen": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-6.0.4.tgz",
|
||||
"integrity": "sha512-uJXR+28cdaie7zIIUBvgkWgHim6Gr1itJym9voIMTmrjXkOaPtejwxYJsdQWPJz9zgGnSbXuC1mNNibLgv3OpQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/status-bar": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-6.0.3.tgz",
|
||||
"integrity": "sha512-nFlgSmtx6Zwaw0tEvZgQsWHBeOfWWB/AvEoCApopLT4mHkBVoSrwkLvy2PjZs5wxCbsmqvQczr3XCyTwaDZVQg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/cli-framework-output": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz",
|
||||
|
||||
+12
-2
@@ -10,7 +10,14 @@
|
||||
"start": "npm-run-all --parallel start:backend start:frontend",
|
||||
"start:backend": "npm start --prefix backend",
|
||||
"start:frontend": "npm run preview --prefix frontend",
|
||||
"install:all": "npm install && npm install --prefix backend && npm install --prefix frontend"
|
||||
"install:all": "npm install && npm install --prefix backend && npm install --prefix frontend",
|
||||
"build:web": "npm run build --prefix frontend",
|
||||
"cap:sync": "npm run build:web && cap sync",
|
||||
"cap:copy": "npm run build:web && cap copy",
|
||||
"cap:open:android": "cap open android",
|
||||
"cap:open:ios": "cap open ios",
|
||||
"cap:run:android": "npm run build:web && cap run android",
|
||||
"cap:run:ios": "npm run build:web && cap run ios"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/cli": "^6.2.1",
|
||||
@@ -18,7 +25,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^6.2.1",
|
||||
"@capacitor/app": "^6.0.3",
|
||||
"@capacitor/core": "^6.2.1",
|
||||
"@capacitor/ios": "^6.2.1"
|
||||
"@capacitor/ios": "^6.2.1",
|
||||
"@capacitor/splash-screen": "^6.0.4",
|
||||
"@capacitor/status-bar": "^6.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user