Refactor SAR marker handling and add template management

- Updated CompassSarList and DetailedCompassDialog to use marker.displayName instead of marker.type.displayName.
- Enhanced DrawingLayer and DrawingMarkersLayer to support simple mode for drawing visibility and interaction.
- Added toggle switches in DrawingToolbar for showing/hiding received drawings and SAR markers.
- Modified MapMarkers to utilize custom emojis and display names for markers.
- Introduced RecipientSelectorSheet for selecting message recipients with search functionality.
- Refactored SarUpdateSheet to use SAR templates instead of marker types, allowing for emoji and name customization.
- Created SarTemplateEditDialog for adding and editing SAR templates with color selection and preview.
This commit is contained in:
Janez T
2025-10-21 23:44:49 +02:00
parent e9d516b749
commit 021ce21cbe
60 changed files with 8736 additions and 1413 deletions

100
.github/workflows/README.md vendored Normal file
View File

@@ -0,0 +1,100 @@
# CI/CD Workflows
## Build Multi-Platform Workflow
Automatically builds the MeshCore SAR app for Android, iOS, macOS, and Windows.
### Triggers
- **Push to main/develop**: Builds with version `1.0.0+1` (from pubspec.yaml)
- **Pull requests to main**: Test builds only
- **Version tags** (e.g., `v1.2.3`): Release builds with versioned artifacts
- **Manual**: Via GitHub Actions UI
### Creating a Release
1. **Ensure your local version is 1.0.0**:
```bash
# pubspec.yaml should show:
version: 1.0.0+1
```
2. **Commit all changes**:
```bash
git add .
git commit -m "Prepare for release"
git push origin main
```
3. **Create and push a version tag**:
```bash
git tag v1.2.3
git push origin v1.2.3
```
4. **GitHub Actions will**:
- Temporarily patch version to `1.2.3+<timestamp>` in builds only
- Build Android APK & App Bundle
- Build iOS app (unsigned - configure secrets for signed IPA)
- Build macOS DMG
- Build Windows executable (ZIP)
- Create a draft GitHub release with all artifacts
5. **Publish the release**:
- Go to GitHub Releases
- Edit the draft release
- Add release notes
- Publish
### Build Artifacts
| Platform | Artifact | Location |
|----------|----------|----------|
| Android APK | `app-release.apk` | `artifacts/android-apk/` |
| Android Bundle | `app-release.aab` | `artifacts/android-appbundle/` |
| macOS | `MeshCore-SAR.dmg` | `artifacts/macos-dmg/` |
| iOS | `Runner.app` | `artifacts/ios-build/` (unsigned) |
| Windows | `MeshCore-SAR-Windows.zip` | `artifacts/windows-executable/` |
### iOS Code Signing (Optional)
To build signed IPA files, add these repository secrets:
1. **IOS_P12_BASE64**: Base64-encoded .p12 certificate
```bash
base64 -i Certificate.p12 | pbcopy
```
2. **IOS_P12_PASSWORD**: Password for the .p12 certificate
3. **IOS_PROVISION_PROFILE_BASE64**: Base64-encoded provisioning profile
```bash
base64 -i Profile.mobileprovision | pbcopy
```
Then uncomment the signing steps in the workflow.
### Version Numbering
- **Local**: Always keep `pubspec.yaml` at `version: 1.0.0+1`
- **CI builds**: Uses `1.0.0+1` for regular commits
- **Release builds**: Uses `<tag>+<timestamp>` (e.g., `1.2.3+1729512345`)
- **No commits**: Version changes are temporary and never committed back
### Troubleshooting
**Build fails on macOS DMG creation**:
- The workflow tries `create-dmg` first, then falls back to `hdiutil`
- Check if app icon path exists at `macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png`
**Windows build fails**:
- Ensure Windows desktop is properly configured in project
- Run locally: `flutter config --enable-windows-desktop && flutter build windows`
**iOS build fails**:
- Check CocoaPods version and dependencies
- Review code signing configuration (currently set to `--no-codesign`)
**Android build fails**:
- Verify Java 17 is compatible with your Gradle version
- Check `android/build.gradle` for minimum SDK requirements

View File

@@ -0,0 +1,349 @@
name: Build Multi-Platform
on:
push:
branches: [main, develop]
tags:
- 'v*'
pull_request:
branches: [main]
workflow_dispatch:
env:
FLUTTER_VERSION: '3.24.0'
jobs:
# Update version from tag
update-version:
name: Update Version from Tag
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
outputs:
version: ${{ steps.get_version.outputs.version }}
build_number: ${{ steps.get_version.outputs.build_number }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get version from tag
id: get_version
run: |
# Extract version from tag (e.g., v1.2.3 -> 1.2.3)
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
# Generate build number from timestamp
BUILD_NUMBER=$(date +%s)
echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
echo "Build Number: $BUILD_NUMBER"
- name: Update pubspec.yaml
run: |
VERSION="${{ steps.get_version.outputs.version }}"
BUILD_NUMBER="${{ steps.get_version.outputs.build_number }}"
# Update version in pubspec.yaml
sed -i.bak "s/^version: .*/version: $VERSION+$BUILD_NUMBER/" pubspec.yaml
echo "Updated pubspec.yaml:"
grep "^version:" pubspec.yaml
- name: Upload updated pubspec
uses: actions/upload-artifact@v4
with:
name: versioned-pubspec
path: pubspec.yaml
retention-days: 1
# Android APK Build
build-android:
name: Build Android APK
runs-on: ubuntu-latest
needs: [update-version]
if: always() && (needs.update-version.result == 'success' || needs.update-version.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download versioned pubspec
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/download-artifact@v4
with:
name: versioned-pubspec
path: .
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
cache: 'gradle'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: 'stable'
cache: true
- name: Install dependencies
run: flutter pub get
- name: Generate localizations
run: flutter gen-l10n
- name: Run analyzer
run: flutter analyze
- name: Run tests
run: flutter test
- name: Build APK
run: flutter build apk --release
- name: Build App Bundle
run: flutter build appbundle --release
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: android-apk
path: build/app/outputs/flutter-apk/app-release.apk
retention-days: 30
- name: Upload App Bundle
uses: actions/upload-artifact@v4
with:
name: android-appbundle
path: build/app/outputs/bundle/release/app-release.aab
retention-days: 30
# iOS IPA Build
build-ios:
name: Build iOS IPA
runs-on: macos-latest
needs: [update-version]
if: always() && (needs.update-version.result == 'success' || needs.update-version.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download versioned pubspec
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/download-artifact@v4
with:
name: versioned-pubspec
path: .
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: 'stable'
cache: true
- name: Install dependencies
run: flutter pub get
- name: Generate localizations
run: flutter gen-l10n
- name: Install CocoaPods dependencies
run: |
cd ios
pod install
cd ..
- name: Build iOS (No Codesign)
run: flutter build ios --release --no-codesign
# For signed builds, uncomment and configure secrets:
# - name: Import Code Signing Certificates
# uses: apple-actions/import-codesign-certs@v2
# with:
# p12-file-base64: ${{ secrets.IOS_P12_BASE64 }}
# p12-password: ${{ secrets.IOS_P12_PASSWORD }}
# - name: Import Provisioning Profile
# run: |
# mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# echo "${{ secrets.IOS_PROVISION_PROFILE_BASE64 }}" | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision
# - name: Build IPA (Signed)
# run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
- name: Upload iOS Build
uses: actions/upload-artifact@v4
with:
name: ios-build
path: build/ios/iphoneos/Runner.app
retention-days: 30
# Uncomment when signing is configured:
# - name: Upload IPA
# uses: actions/upload-artifact@v4
# with:
# name: ios-ipa
# path: build/ios/ipa/*.ipa
# retention-days: 30
# macOS DMG Build
build-macos:
name: Build macOS DMG
runs-on: macos-latest
needs: [update-version]
if: always() && (needs.update-version.result == 'success' || needs.update-version.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download versioned pubspec
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/download-artifact@v4
with:
name: versioned-pubspec
path: .
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: 'stable'
cache: true
- name: Enable macOS desktop
run: flutter config --enable-macos-desktop
- name: Install dependencies
run: flutter pub get
- name: Generate localizations
run: flutter gen-l10n
- name: Build macOS app
run: flutter build macos --release
- name: Create DMG
run: |
# Install create-dmg if not available
brew install create-dmg || true
# Create DMG from the built app
create-dmg \
--volname "MeshCore SAR" \
--volicon "macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png" \
--window-pos 200 120 \
--window-size 800 400 \
--icon-size 100 \
--icon "MeshCore SAR.app" 200 190 \
--hide-extension "MeshCore SAR.app" \
--app-drop-link 600 185 \
"MeshCore-SAR.dmg" \
"build/macos/Build/Products/Release/meshcore_sar_app.app" || \
# Fallback: simple DMG creation
hdiutil create -volname "MeshCore SAR" \
-srcfolder build/macos/Build/Products/Release/meshcore_sar_app.app \
-ov -format UDZO MeshCore-SAR.dmg
- name: Upload macOS DMG
uses: actions/upload-artifact@v4
with:
name: macos-dmg
path: MeshCore-SAR.dmg
retention-days: 30
- name: Upload macOS App
uses: actions/upload-artifact@v4
with:
name: macos-app
path: build/macos/Build/Products/Release/meshcore_sar_app.app
retention-days: 30
# Windows Executable Build
build-windows:
name: Build Windows Executable
runs-on: windows-latest
needs: [update-version]
if: always() && (needs.update-version.result == 'success' || needs.update-version.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download versioned pubspec
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/download-artifact@v4
with:
name: versioned-pubspec
path: .
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: 'stable'
cache: true
- name: Enable Windows desktop
run: flutter config --enable-windows-desktop
- name: Install dependencies
run: flutter pub get
- name: Generate localizations
run: flutter gen-l10n
- name: Build Windows app
run: flutter build windows --release
- name: Create installer (Optional - using Inno Setup)
shell: pwsh
run: |
# Download and install Inno Setup if needed
# This is optional - you can skip installer creation
Write-Host "Windows executable built successfully"
Write-Host "To create installer, configure Inno Setup script"
- name: Archive Windows Build
shell: pwsh
run: |
Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath MeshCore-SAR-Windows.zip
- name: Upload Windows Executable
uses: actions/upload-artifact@v4
with:
name: windows-executable
path: MeshCore-SAR-Windows.zip
retention-days: 30
# Create Release on Tag
create-release:
name: Create Release
needs: [build-android, build-ios, build-macos, build-windows]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: |
artifacts/android-apk/*.apk
artifacts/android-appbundle/*.aab
artifacts/macos-dmg/*.dmg
artifacts/windows-executable/*.zip
draft: true
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}