forked from jsnbuchanan/crowd-funder-for-time-pwa
- Refactor writeFile method to properly handle Android Storage Access Framework (SAF) URIs - Update path construction for Android to use Download directory with correct permissions - Enhance error handling and logging throughout file operations - Add detailed logging for debugging file system operations - Fix permission checking logic to handle "File does not exist" case correctly - Improve error messages and stack traces in logs - Add timestamp to all log entries for better debugging - Use proper directory types (ExternalStorage for Android, Documents for iOS) - Add UTF-8 encoding specification for file writes This is a work in progress as we're still seeing permission issues with Android file writing.
527 lines
12 KiB
Markdown
527 lines
12 KiB
Markdown
# Building TimeSafari
|
|
|
|
This guide explains how to build TimeSafari for different platforms.
|
|
|
|
## Prerequisites
|
|
|
|
For a quick dev environment setup, use [pkgx](https://pkgx.dev).
|
|
|
|
- Node.js (LTS version recommended)
|
|
- npm (comes with Node.js)
|
|
- Git
|
|
- For Android builds: Android Studio with SDK installed
|
|
- For iOS builds: macOS with Xcode and ruby gems & bundle
|
|
- pkgx +rubygems.org sh
|
|
|
|
- ... and you may have to fix these, especially with pkgx
|
|
|
|
```bash
|
|
gem_path=$(which gem)
|
|
shortened_path="${gem_path:h:h}"
|
|
export GEM_HOME=$shortened_path
|
|
export GEM_PATH=$shortened_path
|
|
```
|
|
|
|
- For desktop builds: Additional build tools based on your OS
|
|
|
|
## Forks
|
|
|
|
If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup.
|
|
|
|
```bash
|
|
npx cap add android
|
|
npx cap add ios
|
|
```
|
|
|
|
You'll also want to edit the deep link configuration (see below).
|
|
|
|
## Initial Setup
|
|
|
|
Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
## Web Dev Locally
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
## Web Build for Server
|
|
|
|
1. Run the production build:
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
The built files will be in the `dist` directory.
|
|
|
|
2. To test the production build locally:
|
|
|
|
You'll likely want to use test locations for the Endorser & image & partner servers; see "DEFAULT_ENDORSER_API_SERVER" & "DEFAULT_IMAGE_API_SERVER" & "DEFAULT_PARTNER_API_SERVER" below.
|
|
|
|
```bash
|
|
npm run serve
|
|
```
|
|
|
|
### Compile and minify for test & production
|
|
|
|
* If there are DB changes: before updating the test server, open browser(s) with current version to test DB migrations.
|
|
|
|
* `npx prettier --write ./sw_scripts/`
|
|
|
|
* Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`.
|
|
|
|
* Commit everything (since the commit hash is used the app).
|
|
|
|
* Put the commit hash in the changelog (which will help you remember to bump the version later).
|
|
|
|
* Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 0.3.55 && git push origin 0.3.55`.
|
|
|
|
* For test, build the app (because test server is not yet set up to build):
|
|
|
|
```bash
|
|
TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_PASSKEYS_ENABLED=true npm run build
|
|
```
|
|
|
|
... and transfer to the test server:
|
|
|
|
```bash
|
|
rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari
|
|
```
|
|
|
|
(Let's replace that with a .env.development or .env.staging file.)
|
|
|
|
(Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.)
|
|
|
|
* For prod, get on the server and run the correct build:
|
|
|
|
... and log onto the server:
|
|
|
|
* `pkgx +npm sh`
|
|
|
|
* `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 0.3.55 && npm install && npm run build && cd -`
|
|
|
|
(The plain `npm run build` uses the .env.production file.)
|
|
|
|
* Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev.0 && mv crowd-funder-for-time-pwa/dist time-safari/`
|
|
|
|
* Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, and commit. Also record what version is on production.
|
|
|
|
|
|
|
|
|
|
## Desktop Build (Electron)
|
|
|
|
### Linux Build
|
|
|
|
1. Build the electron app in production mode:
|
|
|
|
```bash
|
|
npm run build:electron-prod
|
|
```
|
|
|
|
2. Package the Electron app for Linux:
|
|
|
|
```bash
|
|
# For AppImage (recommended)
|
|
npm run electron:build-linux
|
|
|
|
# For .deb package
|
|
npm run electron:build-linux-deb
|
|
```
|
|
|
|
3. The packaged applications will be in `dist-electron-packages/`:
|
|
- AppImage: `dist-electron-packages/TimeSafari-x.x.x.AppImage`
|
|
- DEB: `dist-electron-packages/timesafari_x.x.x_amd64.deb`
|
|
|
|
### Running the Packaged App
|
|
|
|
- AppImage: Make executable and run
|
|
|
|
```bash
|
|
chmod +x dist-electron-packages/TimeSafari-*.AppImage
|
|
./dist-electron-packages/TimeSafari-*.AppImage
|
|
```
|
|
|
|
- DEB: Install and run
|
|
|
|
```bash
|
|
sudo dpkg -i dist-electron-packages/timesafari_*_amd64.deb
|
|
timesafari
|
|
```
|
|
|
|
### Development Testing
|
|
|
|
For testing the Electron build before packaging:
|
|
|
|
```bash
|
|
# Build and run in development mode (includes DevTools)
|
|
npm run electron:dev
|
|
|
|
# Build in production mode and test
|
|
npm run build:electron-prod && npm run electron:start
|
|
```
|
|
|
|
## Mobile Builds (Capacitor)
|
|
|
|
### iOS Build
|
|
|
|
Prerequisites: macOS with Xcode installed
|
|
|
|
1. Build the web assets:
|
|
|
|
```bash
|
|
npm run build:capacitor
|
|
```
|
|
|
|
2. Update iOS project with latest build:
|
|
|
|
```bash
|
|
npx cap sync ios
|
|
```
|
|
|
|
3. Copy the assets:
|
|
|
|
```bash
|
|
mkdir -p ios/App/App/Assets.xcassets/AppIcon.appiconset
|
|
npx capacitor-assets generate --ios
|
|
```
|
|
|
|
3. Open the project in Xcode:
|
|
|
|
```bash
|
|
npx cap open ios
|
|
```
|
|
|
|
4. Use Xcode to build and run on simulator or device.
|
|
|
|
#### First-time iOS Configuration
|
|
|
|
- Generate certificates inside XCode.
|
|
|
|
- Right-click on App and under Signing & Capabilities set the Team.
|
|
|
|
### Android Build
|
|
|
|
Prerequisites: Android Studio with SDK installed
|
|
|
|
1. Build the web assets:
|
|
|
|
```bash
|
|
rm -rf dist
|
|
npm run build:web
|
|
npm run build:capacitor
|
|
cd android
|
|
./gradlew clean
|
|
./gradlew assembleDebug
|
|
```
|
|
|
|
2. Update Android project with latest build:
|
|
|
|
```bash
|
|
npx cap sync android
|
|
```
|
|
|
|
3. Copy the assets
|
|
|
|
```bash
|
|
npx capacitor-assets generate --android
|
|
```
|
|
|
|
4. Open the project in Android Studio:
|
|
|
|
```bash
|
|
npx cap open android
|
|
```
|
|
|
|
5. Use Android Studio to build and run on emulator or device.
|
|
|
|
## Android Build from the console
|
|
|
|
```bash
|
|
cd android
|
|
./gradlew clean
|
|
./gradlew build -Dlint.baselines.continue=true
|
|
cd ..
|
|
npx cap run android
|
|
```
|
|
|
|
... or, to create the `aab` file, `bundle` instead of `build`:
|
|
|
|
```bash
|
|
./gradlew bundleDebug -Dlint.baselines.continue=true
|
|
```
|
|
|
|
... or, to create a signed release, add the app/gradle.properties.secrets file (see properties at top of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file, then `bundleRelease`:
|
|
|
|
```bash
|
|
./gradlew bundleRelease -Dlint.baselines.continue=true
|
|
```
|
|
|
|
|
|
|
|
## First-time Android Configuration for deep links
|
|
|
|
You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file:
|
|
|
|
```xml
|
|
<intent-filter android:autoVerify="true">
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="timesafari" />
|
|
</intent-filter>
|
|
```
|
|
|
|
You must also add the following to the `android/app/build.gradle` file:
|
|
|
|
```gradle
|
|
android {
|
|
// ... existing config ...
|
|
|
|
lintOptions {
|
|
disable 'UnsanitizedFilenameFromContentProvider'
|
|
abortOnError false
|
|
baseline file("lint-baseline.xml")
|
|
|
|
// Ignore Capacitor module issues
|
|
ignore 'DefaultLocale'
|
|
ignore 'UnsanitizedFilenameFromContentProvider'
|
|
ignore 'LintBaseline'
|
|
ignore 'LintBaselineFixed'
|
|
}
|
|
}
|
|
```
|
|
|
|
Modify `/android/build.gradle` to use a stable version of AGP and make sure Kotlin version is compatible.
|
|
|
|
```gradle
|
|
buildscript {
|
|
repositories {
|
|
google()
|
|
mavenCentral()
|
|
}
|
|
dependencies {
|
|
// Use a stable version of AGP
|
|
classpath 'com.android.tools.build:gradle:8.1.0'
|
|
|
|
// Make sure Kotlin version is compatible
|
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"
|
|
}
|
|
}
|
|
|
|
allprojects {
|
|
repositories {
|
|
google()
|
|
mavenCentral()
|
|
}
|
|
}
|
|
|
|
// Add this to handle version conflicts
|
|
configurations.all {
|
|
resolutionStrategy {
|
|
force 'org.jetbrains.kotlin:kotlin-stdlib:1.8.0'
|
|
force 'org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0'
|
|
}
|
|
}
|
|
```
|
|
|
|
## PyWebView Desktop Build
|
|
|
|
### Prerequisites for PyWebView
|
|
|
|
- Python 3.8 or higher
|
|
- pip (Python package manager)
|
|
- virtualenv (recommended)
|
|
- System dependencies:
|
|
|
|
```bash
|
|
# For Ubuntu/Debian
|
|
sudo apt-get install python3-webview
|
|
# or
|
|
sudo apt-get install python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-webkit2-4.0
|
|
|
|
# For Arch Linux
|
|
sudo pacman -S webkit2gtk python-gobject python-cairo
|
|
|
|
# For Fedora
|
|
sudo dnf install python3-webview
|
|
# or
|
|
sudo dnf install python3-gobject python3-cairo webkit2gtk3
|
|
```
|
|
|
|
### Setup
|
|
|
|
1. Create and activate a virtual environment (recommended):
|
|
|
|
```bash
|
|
python -m venv .venv
|
|
source .venv/bin/activate # On Linux/macOS
|
|
# or
|
|
.venv\Scripts\activate # On Windows
|
|
```
|
|
|
|
2. Install Python dependencies:
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
If encountering PyInstaller version errors:
|
|
|
|
```bash
|
|
# Try installing the latest stable version
|
|
pip install --upgrade pyinstaller
|
|
```
|
|
|
|
### Development of PyWebView
|
|
|
|
1. Start the PyWebView development build:
|
|
|
|
```bash
|
|
npm run pywebview:dev
|
|
```
|
|
|
|
### Building for Distribution
|
|
|
|
#### Linux
|
|
|
|
```bash
|
|
npm run pywebview:package-linux
|
|
```
|
|
|
|
The packaged application will be in `dist/TimeSafari`
|
|
|
|
#### Windows
|
|
|
|
```bash
|
|
npm run pywebview:package-win
|
|
```
|
|
|
|
The packaged application will be in `dist/TimeSafari`
|
|
|
|
#### macOS
|
|
|
|
```bash
|
|
npm run pywebview:package-mac
|
|
```
|
|
|
|
The packaged application will be in `dist/TimeSafari`
|
|
|
|
## Testing
|
|
|
|
Run all tests (requires XCode and Android Studio/device):
|
|
|
|
```bash
|
|
npm run test:all
|
|
```
|
|
|
|
See [TESTING.md](test-playwright/TESTING.md) for more details.
|
|
|
|
## Linting
|
|
|
|
Check code style:
|
|
|
|
```bash
|
|
npm run lint
|
|
```
|
|
|
|
Fix code style issues:
|
|
|
|
```bash
|
|
npm run lint-fix
|
|
```
|
|
|
|
## Environment Configuration
|
|
|
|
See `.env.*` files for configuration.
|
|
|
|
## Notes
|
|
|
|
- The application uses PWA (Progressive Web App) features for web builds
|
|
- Electron builds disable PWA features automatically
|
|
- Build output directories:
|
|
- Web: `dist/`
|
|
- Electron: `dist-electron/`
|
|
- Capacitor: `dist-capacitor/`
|
|
|
|
## Deployment
|
|
|
|
### Version Management
|
|
|
|
1. Update CHANGELOG.md with new changes
|
|
2. Update version in package.json
|
|
3. Commit changes and tag release:
|
|
|
|
```bash
|
|
git tag <VERSION_TAG>
|
|
git push origin <VERSION_TAG>
|
|
```
|
|
|
|
4. After deployment, update package.json with next version + "-beta"
|
|
|
|
### Test Server
|
|
|
|
```bash
|
|
# Build using staging environment
|
|
npm run build -- --mode staging
|
|
|
|
# Deploy to test server
|
|
rsync -azvu -e "ssh -i ~/.ssh/<YOUR_KEY>" dist ubuntutest@test.timesafari.app:time-safari/
|
|
```
|
|
|
|
### Production Server
|
|
|
|
```bash
|
|
# On the production server:
|
|
pkgx +npm sh
|
|
cd crowd-funder-for-time-pwa
|
|
git checkout master && git pull
|
|
git checkout <VERSION_TAG>
|
|
npm install
|
|
npm run build
|
|
cd -
|
|
|
|
# Backup and deploy
|
|
mv time-safari/dist time-safari-dist-prev.0 && mv crowd-funder-for-time-pwa/dist time-safari/
|
|
```
|
|
|
|
## Troubleshooting Builds
|
|
|
|
### Common Build Issues
|
|
|
|
1. **Missing Environment Variables**
|
|
- Check that all required variables are set in your .env file
|
|
- For development, ensure local services are running on correct ports
|
|
|
|
2. **Electron Build Failures**
|
|
- Verify Node.js version compatibility
|
|
- Check that all required dependencies are installed
|
|
- Ensure proper paths in electron/main.js
|
|
|
|
3. **Mobile Build Issues**
|
|
- For iOS: Xcode command line tools must be installed
|
|
- For Android: Correct SDK version must be installed
|
|
- Check Capacitor configuration in capacitor.config.ts
|
|
|
|
|
|
# List all installed packages
|
|
adb shell pm list packages | grep timesafari
|
|
|
|
# Force stop the app (if it's running)
|
|
adb shell am force-stop app.timesafari
|
|
|
|
# Clear app data (if you don't want to fully uninstall)
|
|
adb shell pm clear app.timesafari
|
|
|
|
# Uninstall for all users
|
|
adb shell pm uninstall -k --user 0 app.timesafari
|
|
|
|
# Check if app is installed
|
|
adb shell pm path app.timesafari |