forked from jsnbuchanan/crowd-funder-for-time-pwa
- Implement app.requestSingleInstanceLock() to prevent multiple instances - Add user-friendly dialog when second instance is attempted - Focus and restore existing window instead of creating new instance - Prevent database corruption and resource conflicts - Update documentation with single-instance behavior details
929 lines
24 KiB
Markdown
929 lines
24 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 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
|
|
rm -rf dist
|
|
npm run build:web
|
|
```
|
|
|
|
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`.
|
|
|
|
* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build`
|
|
|
|
* 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 in the step later).
|
|
|
|
* Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 1.0.2 && git push origin 1.0.2`.
|
|
|
|
* 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_DEFAULT_PUSH_SERVER=https://test.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build:web
|
|
```
|
|
|
|
... 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.test 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 1.0.2 && npm install && npm run build:web && cd -`
|
|
|
|
(The plain `npm run build:web` uses the .env.production file.)
|
|
|
|
* Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-2 && 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`, commit, and push. Also record what version is on production.
|
|
|
|
## Docker Deployment
|
|
|
|
The application can be containerized using Docker for consistent deployment across environments.
|
|
|
|
### Prerequisites
|
|
|
|
- Docker installed on your system
|
|
- Docker Compose (optional, for multi-container setups)
|
|
|
|
### Building the Docker Image
|
|
|
|
1. Build the Docker image:
|
|
|
|
```bash
|
|
docker build -t timesafari:latest .
|
|
```
|
|
|
|
2. For development builds with specific environment variables:
|
|
|
|
```bash
|
|
docker build --build-arg NODE_ENV=development -t timesafari:dev .
|
|
```
|
|
|
|
### Running the Container
|
|
|
|
1. Run the container:
|
|
|
|
```bash
|
|
docker run -d -p 80:80 timesafari:latest
|
|
```
|
|
|
|
2. For development with hot-reloading:
|
|
|
|
```bash
|
|
docker run -d -p 80:80 -v $(pwd):/app timesafari:dev
|
|
```
|
|
|
|
### Using Docker Compose
|
|
|
|
Create a `docker-compose.yml` file:
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
services:
|
|
timesafari:
|
|
build: .
|
|
ports:
|
|
- "80:80"
|
|
environment:
|
|
- NODE_ENV=production
|
|
restart: unless-stopped
|
|
```
|
|
|
|
Run with Docker Compose:
|
|
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Production Deployment
|
|
|
|
For production deployment, consider the following:
|
|
|
|
1. Use specific version tags instead of 'latest'
|
|
2. Implement health checks
|
|
3. Configure proper logging
|
|
4. Set up reverse proxy with SSL termination
|
|
5. Use Docker secrets for sensitive data
|
|
|
|
Example production deployment:
|
|
|
|
```bash
|
|
# Build with specific version
|
|
docker build -t timesafari:1.0.0 .
|
|
|
|
# Run with production settings
|
|
docker run -d \
|
|
--name timesafari \
|
|
-p 80:80 \
|
|
--restart unless-stopped \
|
|
-e NODE_ENV=production \
|
|
timesafari:1.0.0
|
|
```
|
|
|
|
### Troubleshooting Docker
|
|
|
|
1. **Container fails to start**
|
|
- Check logs: `docker logs <container_id>`
|
|
- Verify port availability
|
|
- Check environment variables
|
|
|
|
2. **Build fails**
|
|
- Ensure all dependencies are in package.json
|
|
- Check Dockerfile syntax
|
|
- Verify build context
|
|
|
|
3. **Performance issues**
|
|
- Monitor container resources: `docker stats`
|
|
- Check nginx configuration
|
|
- Verify caching settings
|
|
|
|
## Desktop Build (Electron)
|
|
|
|
TimeSafari's Electron build system provides comprehensive desktop application
|
|
packaging and distribution capabilities across Windows, macOS, and Linux
|
|
platforms. The system supports multiple build modes, environment
|
|
configurations, and package formats.
|
|
|
|
### Quick Start
|
|
|
|
#### Development Build
|
|
|
|
```bash
|
|
# Start development build (runs app)
|
|
npm run build:electron:dev
|
|
|
|
# Development build only
|
|
npm run build:electron --dev
|
|
```
|
|
|
|
#### Production Build
|
|
|
|
```bash
|
|
# Production build for all platforms
|
|
npm run build:electron:prod
|
|
|
|
# Platform-specific production builds
|
|
npm run build:electron:windows:prod
|
|
npm run build:electron:mac:prod
|
|
npm run build:electron:linux:prod
|
|
```
|
|
|
|
#### Package-Specific Builds
|
|
|
|
```bash
|
|
# AppImage for Linux
|
|
npm run build:electron:appimage:prod
|
|
|
|
# DEB package for Debian/Ubuntu
|
|
npm run build:electron:deb:prod
|
|
|
|
# DMG for macOS
|
|
npm run build:electron:dmg:prod
|
|
```
|
|
|
|
### Single Instance Enforcement
|
|
|
|
The Electron app enforces single-instance operation to prevent:
|
|
- Database corruption from multiple instances
|
|
- Resource conflicts and performance issues
|
|
- User confusion from multiple windows
|
|
|
|
**Behavior:**
|
|
- Only one instance can run at a time
|
|
- Attempting to launch a second instance shows a user-friendly dialog
|
|
- The existing window is focused and restored if minimized
|
|
- Second instance exits gracefully
|
|
|
|
**Implementation:**
|
|
- Uses Electron's `requestSingleInstanceLock()` API
|
|
- Handles `second-instance` events to focus existing window
|
|
- Shows informative dialog explaining why only one instance is allowed
|
|
|
|
#### Direct Script Usage
|
|
|
|
```bash
|
|
# Direct script usage (no npm chaining)
|
|
./scripts/build-electron.sh --dev # Development build
|
|
./scripts/build-electron.sh --test # Test build
|
|
./scripts/build-electron.sh --prod # Production build
|
|
./scripts/build-electron.sh --prod --windows # Windows production
|
|
./scripts/build-electron.sh --test --appimage # Linux AppImage test
|
|
./scripts/build-electron.sh --dev --mac # macOS development
|
|
./scripts/build-electron.sh --prod --dmg # macOS DMG production
|
|
```
|
|
|
|
### Build Architecture
|
|
|
|
The Electron build process follows a multi-stage approach:
|
|
|
|
```
|
|
1. Web Build (Vite) → 2. Capacitor Sync → 3. TypeScript Compile → 4. Package
|
|
```
|
|
|
|
**Stage 1: Web Build**
|
|
- Vite builds web assets with Electron-specific configuration
|
|
- Environment variables loaded based on build mode
|
|
- Assets optimized for desktop application
|
|
|
|
**Stage 2: Capacitor Sync**
|
|
- Copies web assets to Electron app directory
|
|
- Syncs Capacitor configuration and plugins
|
|
- Prepares native module bindings
|
|
|
|
**Stage 3: TypeScript Compile**
|
|
- Compiles Electron main process TypeScript
|
|
- Rebuilds native modules for target platform
|
|
- Generates production-ready JavaScript
|
|
|
|
**Stage 4: Package Creation**
|
|
- Creates platform-specific installers
|
|
- Generates distribution packages
|
|
- Signs applications (when configured)
|
|
|
|
### Build Modes
|
|
|
|
#### Development Mode
|
|
|
|
**Purpose**: Local development and testing
|
|
**Command**: `npm run build:electron:dev`
|
|
**Features**:
|
|
- Hot reload enabled
|
|
- Debug tools available
|
|
- Development logging
|
|
- Unoptimized assets
|
|
|
|
#### Testing Mode
|
|
|
|
**Purpose**: Staging and testing environments
|
|
**Command**: `npm run build:electron -- --mode test`
|
|
**Features**:
|
|
- Test API endpoints
|
|
- Staging configurations
|
|
- Optimized for testing
|
|
- Debug information available
|
|
|
|
#### Production Mode
|
|
|
|
**Purpose**: Production deployment
|
|
**Command**: `npm run build:electron -- --mode production`
|
|
**Features**:
|
|
- Production optimizations
|
|
- Code minification
|
|
- Security hardening
|
|
- Performance optimizations
|
|
|
|
### Platform-Specific Builds
|
|
|
|
#### Windows Builds
|
|
|
|
**Target Platforms**: Windows 10/11 (x64)
|
|
**Package Formats**: NSIS installer, portable executable
|
|
|
|
```bash
|
|
# Windows development build
|
|
npm run build:electron:windows:dev
|
|
|
|
# Windows test build
|
|
npm run build:electron:windows:test
|
|
|
|
# Windows production build
|
|
npm run build:electron:windows:prod
|
|
```
|
|
|
|
**Configuration**:
|
|
- NSIS installer with custom options
|
|
- Desktop and Start Menu shortcuts
|
|
- Elevation permissions for installation
|
|
- Custom installation directory support
|
|
|
|
#### macOS Builds
|
|
|
|
**Target Platforms**: macOS 10.15+ (x64, arm64)
|
|
**Package Formats**: DMG installer, app bundle
|
|
|
|
```bash
|
|
# macOS development build
|
|
npm run build:electron:mac:dev
|
|
|
|
# macOS test build
|
|
npm run build:electron:mac:test
|
|
|
|
# macOS production build
|
|
npm run build:electron:mac:prod
|
|
```
|
|
|
|
**Configuration**:
|
|
- Universal binary (x64 + arm64)
|
|
- DMG installer with custom branding
|
|
- App Store compliance (when configured)
|
|
- Code signing support
|
|
|
|
#### Linux Builds
|
|
|
|
**Target Platforms**: Ubuntu 18.04+, Debian 10+, Arch Linux
|
|
**Package Formats**: AppImage, DEB, RPM
|
|
|
|
```bash
|
|
# Linux development build
|
|
npm run build:electron:linux:dev
|
|
|
|
# Linux test build
|
|
npm run build:electron:linux:test
|
|
|
|
# Linux production build
|
|
npm run build:electron:linux:prod
|
|
```
|
|
|
|
**Configuration**:
|
|
- AppImage for universal distribution
|
|
- DEB package for Debian-based systems
|
|
- RPM package for Red Hat-based systems
|
|
- Desktop integration
|
|
|
|
### Package-Specific Builds
|
|
|
|
#### AppImage Package
|
|
|
|
**Format**: Self-contained Linux executable
|
|
**Distribution**: Universal Linux distribution
|
|
|
|
```bash
|
|
# AppImage development build
|
|
npm run build:electron:appimage:dev
|
|
|
|
# AppImage test build
|
|
npm run build:electron:appimage:test
|
|
|
|
# AppImage production build
|
|
npm run build:electron:appimage:prod
|
|
```
|
|
|
|
**Features**:
|
|
- Single file distribution
|
|
- No installation required
|
|
- Portable across Linux distributions
|
|
- Automatic updates support
|
|
|
|
#### DEB Package
|
|
|
|
**Format**: Debian package installer
|
|
**Distribution**: Debian-based Linux systems
|
|
|
|
```bash
|
|
# DEB development build
|
|
npm run build:electron:deb:dev
|
|
|
|
# DEB test build
|
|
npm run build:electron:deb:test
|
|
|
|
# DEB production build
|
|
npm run build:electron:deb:prod
|
|
```
|
|
|
|
**Features**:
|
|
- Native package management
|
|
- Dependency resolution
|
|
- System integration
|
|
- Easy installation/uninstallation
|
|
|
|
#### DMG Package
|
|
|
|
**Format**: macOS disk image
|
|
**Distribution**: macOS systems
|
|
|
|
```bash
|
|
# DMG development build
|
|
npm run build:electron:dmg:dev
|
|
|
|
# DMG test build
|
|
npm run build:electron:dmg:test
|
|
|
|
# DMG production build
|
|
npm run build:electron:dmg:prod
|
|
```
|
|
|
|
**Features**:
|
|
- Native macOS installer
|
|
- Custom branding and layout
|
|
- Drag-and-drop installation
|
|
- Code signing support
|
|
|
|
### Build Scripts Reference
|
|
|
|
#### Main Build Scripts
|
|
|
|
```bash
|
|
# Development builds
|
|
npm run build:electron:dev # Development build and run
|
|
npm run build:electron --dev # Development build only
|
|
|
|
# Testing builds
|
|
npm run build:electron:test # Test environment build
|
|
|
|
# Production builds
|
|
npm run build:electron:prod # Production environment build
|
|
```
|
|
|
|
#### Platform-Specific Scripts
|
|
|
|
```bash
|
|
# Windows builds
|
|
npm run build:electron:windows # Windows production build
|
|
npm run build:electron:windows:dev # Windows development build
|
|
npm run build:electron:windows:test # Windows test build
|
|
npm run build:electron:windows:prod # Windows production build
|
|
|
|
# macOS builds
|
|
npm run build:electron:mac # macOS production build
|
|
npm run build:electron:mac:dev # macOS development build
|
|
npm run build:electron:mac:test # macOS test build
|
|
npm run build:electron:mac:prod # macOS production build
|
|
|
|
# Linux builds
|
|
npm run build:electron:linux # Linux production build
|
|
npm run build:electron:linux:dev # Linux development build
|
|
npm run build:electron:linux:test # Linux test build
|
|
npm run build:electron:linux:prod # Linux production build
|
|
```
|
|
|
|
#### Package-Specific Scripts
|
|
|
|
```bash
|
|
# AppImage builds
|
|
npm run build:electron:appimage # Linux AppImage production build
|
|
npm run build:electron:appimage:dev # AppImage development build
|
|
npm run build:electron:appimage:test # AppImage test build
|
|
npm run build:electron:appimage:prod # AppImage production build
|
|
|
|
# DEB builds
|
|
npm run build:electron:deb # Debian package production build
|
|
npm run build:electron:deb:dev # DEB development build
|
|
npm run build:electron:deb:test # DEB test build
|
|
npm run build:electron:deb:prod # DEB production build
|
|
|
|
# DMG builds
|
|
npm run build:electron:dmg # macOS DMG production build
|
|
npm run build:electron:dmg:dev # DMG development build
|
|
npm run build:electron:dmg:test # DMG test build
|
|
npm run build:electron:dmg:prod # DMG production build
|
|
```
|
|
|
|
#### Direct Script Usage
|
|
|
|
All npm scripts use the underlying `./scripts/build-electron.sh` script:
|
|
|
|
```bash
|
|
# Direct script usage examples
|
|
./scripts/build-electron.sh --dev # Development build
|
|
./scripts/build-electron.sh --test # Test build
|
|
./scripts/build-electron.sh --prod # Production build
|
|
./scripts/build-electron.sh --prod --windows # Windows production
|
|
./scripts/build-electron.sh --test --appimage # Linux AppImage test
|
|
./scripts/build-electron.sh --dev --mac # macOS development
|
|
./scripts/build-electron.sh --prod --dmg # macOS DMG production
|
|
```
|
|
|
|
#### Utility Scripts
|
|
|
|
```bash
|
|
# Cleanup scripts
|
|
npm run clean:electron # Clean Electron build artifacts
|
|
|
|
# Development scripts
|
|
npm run electron:dev # Start development server
|
|
npm run electron:dev-full # Full development workflow
|
|
npm run electron:setup # Setup Electron environment
|
|
```
|
|
|
|
### Build Output Structure
|
|
|
|
#### Development Build
|
|
|
|
```
|
|
electron/
|
|
├── app/ # Web assets
|
|
├── build/ # Compiled TypeScript
|
|
├── dist/ # Build artifacts (empty in dev)
|
|
└── node_modules/ # Dependencies
|
|
```
|
|
|
|
#### Production Build
|
|
|
|
```
|
|
electron/
|
|
├── app/ # Web assets
|
|
├── build/ # Compiled TypeScript
|
|
├── dist/ # Distribution packages
|
|
│ ├── TimeSafari.exe # Windows executable
|
|
│ ├── TimeSafari.dmg # macOS installer
|
|
│ ├── TimeSafari.AppImage # Linux AppImage
|
|
│ └── TimeSafari.deb # Debian package
|
|
└── node_modules/ # Dependencies
|
|
```
|
|
|
|
### Code Signing and Notarization
|
|
|
|
#### macOS Code Signing
|
|
|
|
For public distribution on macOS, you need to code sign and notarize your app:
|
|
|
|
1. Set up environment variables:
|
|
```bash
|
|
export CSC_LINK=/path/to/your/certificate.p12
|
|
export CSC_KEY_PASSWORD=your_certificate_password
|
|
export APPLE_ID=your_apple_id
|
|
export APPLE_ID_PASSWORD=your_app_specific_password
|
|
```
|
|
|
|
2. Build with signing:
|
|
```bash
|
|
npm run build:electron:mac:prod
|
|
```
|
|
|
|
#### Windows Code Signing
|
|
|
|
For Windows distribution, configure Authenticode signing:
|
|
|
|
1. Set up environment variables:
|
|
```bash
|
|
export CSC_LINK=/path/to/your/certificate.p12
|
|
export CSC_KEY_PASSWORD=your_certificate_password
|
|
```
|
|
|
|
2. Build with signing:
|
|
```bash
|
|
npm run build:electron:windows:prod
|
|
```
|
|
|
|
### Running the Packaged App
|
|
|
|
#### Linux
|
|
|
|
- **AppImage**: Make executable and run
|
|
```bash
|
|
chmod +x electron/dist/TimeSafari-*.AppImage
|
|
./electron/dist/TimeSafari-*.AppImage
|
|
```
|
|
|
|
- **DEB**: Install and run
|
|
```bash
|
|
sudo dpkg -i electron/dist/timesafari_*_amd64.deb
|
|
timesafari
|
|
```
|
|
|
|
#### macOS
|
|
|
|
- **`.app` bundle**: Double-click `TimeSafari.app` in Finder
|
|
- **`.dmg` installer**:
|
|
1. Double-click the `.dmg` file
|
|
2. Drag the app to your Applications folder
|
|
3. Launch from Applications
|
|
|
|
Note: If you get a security warning when running the app:
|
|
1. Right-click the app
|
|
2. Select "Open"
|
|
3. Click "Open" in the security dialog
|
|
|
|
#### Windows
|
|
|
|
- **NSIS installer**: Run the `.exe` installer and follow the setup wizard
|
|
- **Portable**: Extract and run the portable executable
|
|
|
|
### Troubleshooting
|
|
|
|
#### Common Build Issues
|
|
|
|
**TypeScript Compilation Errors**:
|
|
```bash
|
|
# Clean and rebuild
|
|
npm run clean:electron
|
|
cd electron && npm run build
|
|
```
|
|
|
|
**Native Module Issues**:
|
|
```bash
|
|
# Rebuild native modules
|
|
cd electron && npm run build
|
|
```
|
|
|
|
**Asset Copy Issues**:
|
|
```bash
|
|
# Verify Capacitor sync
|
|
npx cap sync electron
|
|
```
|
|
|
|
#### Platform-Specific Issues
|
|
|
|
**Windows**:
|
|
- Ensure Windows Build Tools installed
|
|
- Check NSIS installation
|
|
- Verify code signing certificates
|
|
|
|
**macOS**:
|
|
- Install Xcode Command Line Tools
|
|
- Configure code signing certificates
|
|
- Check app notarization requirements
|
|
|
|
**Linux**:
|
|
- Install required packages (rpm-tools, etc.)
|
|
- Check AppImage dependencies
|
|
- Verify desktop integration
|
|
|
|
### Performance Optimization
|
|
|
|
#### Build Performance
|
|
|
|
- Use concurrent TypeScript compilation
|
|
- Optimize asset copying
|
|
- Minimize file system operations
|
|
- Cache node_modules between builds
|
|
|
|
#### Runtime Performance
|
|
|
|
- Optimize main process initialization
|
|
- Minimize startup dependencies
|
|
- Use lazy loading for features
|
|
- Monitor memory usage and implement proper cleanup
|
|
|
|
### Security Considerations
|
|
|
|
#### Production Builds
|
|
|
|
- Disable developer tools
|
|
- Remove debug information
|
|
- Enable security policies
|
|
- Implement sandboxing
|
|
|
|
#### Update Security
|
|
|
|
- Secure update channels
|
|
- Package integrity verification
|
|
- Rollback capabilities
|
|
|
|
For detailed documentation, see [docs/electron-build-patterns.md](docs/electron-build-patterns.md).
|
|
|
|
## Mobile Builds (Capacitor)
|
|
|
|
### iOS Build
|
|
|
|
Prerequisites: macOS with Xcode installed
|
|
|
|
#### Automated Build Script
|
|
|
|
The recommended way to build for iOS is using the automated build script:
|
|
|
|
```bash
|
|
# Standard build and open Xcode
|
|
./scripts/build-ios.sh
|
|
|
|
# Build with specific version numbers
|
|
./scripts/build-ios.sh --version 1.0.3 --build-number 35
|
|
|
|
# Build without opening Xcode (for CI/CD)
|
|
./scripts/build-ios.sh --no-xcode
|
|
|
|
# Show all available options
|
|
./scripts/build-ios.sh --help
|
|
```
|
|
|
|
The script handles all the necessary steps including:
|
|
- Environment setup and validation
|
|
- Web asset building
|
|
- Capacitor synchronization
|
|
- iOS asset generation
|
|
- Version number updates
|
|
- Xcode project opening
|
|
|
|
#### Manual Build Process
|
|
|
|
If you need to build manually or want to understand the individual steps:
|
|
|
|
#### First-time iOS Configuration
|
|
|
|
- Generate certificates inside XCode.
|
|
|
|
- Right-click on App and under Signing & Capabilities set the Team.
|
|
|
|
#### Each Release
|
|
|
|
0. First time (or if dependencies change):
|
|
|
|
- `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
|
|
```
|
|
|
|
1. Build the web assets & update ios:
|
|
|
|
```bash
|
|
rm -rf dist
|
|
npm run build:web
|
|
npm run build:capacitor
|
|
npx cap sync ios
|
|
```
|
|
|
|
- If that fails with "Could not find..." then look at the "gem_path" instructions above.
|
|
|
|
3. Copy the assets:
|
|
|
|
```bash
|
|
# It makes no sense why capacitor-assets will not run without these but it actually changes the contents.
|
|
mkdir -p ios/App/App/Assets.xcassets/AppIcon.appiconset
|
|
echo '{"images":[]}' > ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json
|
|
mkdir -p ios/App/App/Assets.xcassets/Splash.imageset
|
|
echo '{"images":[]}' > ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
|
|
npx capacitor-assets generate --ios
|
|
```
|
|
|
|
4. Bump the version to match Android & package.json:
|
|
|
|
```
|
|
cd ios/App && xcrun agvtool new-version 35 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.2;/g" App.xcodeproj/project.pbxproj && cd -
|
|
# Unfortunately this edits Info.plist directly.
|
|
#xcrun agvtool new-marketing-version 0.4.5
|
|
```
|
|
|
|
5. Open the project in Xcode:
|
|
|
|
```bash
|
|
npx cap open ios
|
|
```
|
|
|
|
6. Use Xcode to build and run on simulator or device.
|
|
|
|
* Select Product -> Destination with some Simulator version. Then click the run arrow.
|
|
|
|
7. Release
|
|
|
|
* Someday: Under "General" we want to rename a bunch of things to "Time Safari"
|
|
* Choose Product -> Destination -> Any iOS Device
|
|
* Choose Product -> Archive
|
|
* This will trigger a build and take time, needing user's "login" keychain password (user's login password), repeatedly.
|
|
* If it fails with `building for 'iOS', but linking in dylib (.../.pkgx/zlib.net/v1.3.0/lib/libz.1.3.dylib) built for 'macOS'` then run XCode outside that terminal (ie. not with `npx cap open ios`).
|
|
* Click Distribute -> App Store Connect
|
|
* In AppStoreConnect, add the build to the distribution: remove the current build with the "-" when you hover over it, then "Add Build" with the new build.
|
|
* May have to go to App Review, click Submission, then hover over the build and click "-".
|
|
* It can take 15 minutes for the build to show up in the list of builds.
|
|
* You'll probably have to "Manage" something about encryption, disallowed in France.
|
|
* Then "Save" and "Add to Review" and "Resubmit to App Review".
|
|
|
|
### Android Build
|
|
|
|
Prerequisites: Android Studio with Java SDK installed
|
|
|
|
1. Build the web assets:
|
|
|
|
```bash
|
|
rm -rf dist
|
|
npm run build:web
|
|
npm run build:capacitor
|
|
```
|
|
|
|
2. Update Android project with latest build:
|
|
|
|
```bash
|
|
npx cap sync android
|
|
```
|
|
|
|
3. Copy the assets
|
|
|
|
```bash
|
|
npx capacitor-assets generate --android
|
|
```
|
|
|
|
4. Bump version to match iOS & package.json: android/app/build.gradle
|
|
|
|
5. Open the project in Android Studio:
|
|
|
|
```bash
|
|
npx cap open android
|
|
```
|
|
|
|
6. 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 -
|
|
```
|
|
|
|
... or, to create the `aab` file, `bundle` instead of `build`:
|
|
|
|
```bash
|
|
./gradlew bundleDebug -Dlint.baselines.continue=true
|
|
```
|
|
|
|
... or, to create a signed release:
|
|
|
|
* Setup by adding the app/gradle.properties.secrets file (see properties at top of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file
|
|
* In app/build.gradle, bump the versionCode and maybe the versionName
|
|
* Then `bundleRelease`:
|
|
|
|
```bash
|
|
cd android
|
|
./gradlew bundleRelease -Dlint.baselines.continue=true
|
|
cd -
|
|
```
|
|
|
|
... and find your `aab` file at app/build/outputs/bundle/release
|
|
|
|
At play.google.com/console:
|
|
|
|
- Go to the Testing Track (eg. Closed).
|
|
- Click "Create new release".
|
|
- Upload the `aab` file.
|
|
- Hit "Next".
|
|
- Save, go to "Publishing Overview" as prompted, and click "Send changes for review".
|
|
|
|
- Note that if you add testers, you have to go to "Publishing Overview" and send those changes or your (closed) testers won't see it.
|
|
|
|
|
|
## 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>
|
|
```
|
|
|
|
... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError]
|