Skip to content

Repository files navigation

SnakeAid.Mobile

CodeMagic CI/CD

This repository includes a minimal codemagic.yaml for MVP builds.

Current CI direction:

  • Android: build a debug APK that can be downloaded from CodeMagic artifacts and installed directly on an Android device
  • iOS: build an unsigned IPA with --no-codesign for sideloading or TrollStore-style workflows

Required CodeMagic Variables

Only these environment variables are currently generated into .env during CI:

  • BASE_URL
  • API_TIMEOUT (optional, defaults to 30000)

Android Firebase Requirement

The Android workflow also requires Firebase configuration because the project applies the Google Services Gradle plugin.

CodeMagic must provide:

  • GOOGLE_SERVICES_JSON_BASE64

This secret should contain the Base64-encoded contents of:

  • android/app/google-services.json

On Windows PowerShell, you can generate it with:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("android/app/google-services.json"))

Then add the resulting string as a secure environment variable in CodeMagic.

Without this value, Android builds will fail at :app:processDebugGoogleServices because google-services.json is not committed to the repository.

Android Output

The Android workflow builds:

flutter build apk --debug

Artifact output on CodeMagic:

  • build/app/outputs/flutter-apk/*.apk

How to install:

  1. Open the CodeMagic build
  2. Go to Artifacts
  3. Download the generated .apk
  4. Copy it to an Android device
  5. Enable installation from unknown sources if needed
  6. Open the APK and install

iOS Output

The iOS workflow currently runs:

flutter build ios --release --no-codesign

Artifact output on CodeMagic:

  • build/ios/iphoneos/*.app
  • build/ios/unsigned_ipa/*.ipa

Important:

  • The generated .ipa is unsigned
  • The generated .app is still useful as a raw build artifact
  • This workflow does not use Apple signing
  • Installation still depends on the sideload method you choose later

iOS Strategy Without Paid Apple Developer Account

The current goal is to avoid the Apple Developer Program cost while still keeping an iOS path for MVP testing.

Practical options:

  • TrollStore: only works on supported iOS versions and devices
  • AltStore, SideStore, or Sideloadly: usually require a free Apple ID and periodic refresh
  • Xcode Personal Team: works for personal testing, but still depends on an Apple account and is not a clean CI distribution path

Practical conclusion:

  • Android is the primary installable artifact in CI today
  • iOS CI now produces an unsigned IPA artifact
  • If real iPhone installation is needed, use that IPA with the sideload path you choose, such as TrollStore, AltStore, SideStore, or Sideloadly

After Commit / Push

To keep builds running smoothly on CodeMagic:

  1. Push the branch that CodeMagic is configured to build
  2. Ensure BASE_URL exists in CodeMagic environment variables
  3. Trigger the android_debug workflow for an installable Android artifact
  4. Trigger the ios_release workflow for an unsigned iOS IPA artifact

If Android fails again with missing .env, the first thing to check is whether the CodeMagic environment variables are present for that workflow.

🚨 Local Development Connection Issue

If you are running the backend locally (http://<your-ip>:8080) but the Mobile App (Real device) throws Connection Timeout or SocketException, your Windows Firewall is likely blocking incoming connections to port 8080.

Quick Fix: Run PowerShell as Administrator and execute this command:

New-NetFirewallRule -DisplayName "Allow Port 8080" -Direction Inbound -LocalPort 8080 -Protocol TCP -Action Allow

Expected output: Enabled: True, Action: Allow. Restart your app after applying this rule.

lib/
β”œβ”€β”€ core/                          # Core utilities
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ app_config.dart
β”‚   β”‚   β”œβ”€β”€ route_config.dart
β”‚   β”‚   └── theme_config.dart
β”‚   β”œβ”€β”€ constants/
β”‚   β”‚   β”œβ”€β”€ api_endpoints.dart
β”‚   β”‚   β”œβ”€β”€ enums.dart            # Tα»« DB enums
β”‚   β”‚   └── app_constants.dart
β”‚   β”œβ”€β”€ services/                 # Shared services
β”‚   β”‚   β”œβ”€β”€ api_service.dart      # Dio client
β”‚   β”‚   β”œβ”€β”€ auth_service.dart     # Authentication
β”‚   β”‚   β”œβ”€β”€ location_service.dart # GPS tracking
β”‚   β”‚   β”œβ”€β”€ notification_service.dart # Service notification
β”‚   β”‚   └── storage_service.dart  # Local storage
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ extensions/
β”‚   β”‚   β”œβ”€β”€ validators/
β”‚   β”‚   └── helpers/
β”‚   └── widgets/                  # Shared UI components
β”‚       β”œβ”€β”€ common/
β”‚       β”œβ”€β”€ forms/
β”‚       └── media/
β”‚
β”‚
β”œβ”€β”€ features/                      # Feature-based modules
β”‚   β”œβ”€β”€ auth/                     # Authentication
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ account.dart
β”‚   β”‚   β”‚   └── user_profile.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth_provider.dart
β”‚   β”‚   β”‚   └── profile_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ login_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ register_screen.dart
β”‚   β”‚   β”‚   └── profile_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ login_form.dart
β”‚   β”‚   β”‚   └── profile_card.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── auth_repository.dart  # Single repository per feature
β”‚   β”‚
β”‚   β”œβ”€β”€ emergency/                # SOS & Emergency features
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ snakebite_incident.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ rescue_request.dart
β”‚   β”‚   β”‚   └── rescue_mission.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ emergency_provider.dart
β”‚   β”‚   β”‚   └── tracking_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ sos_form_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ emergency_tracking_screen.dart
β”‚   β”‚   β”‚   └── first_aid_guide_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ symptom_selector.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ location_picker.dart
β”‚   β”‚   β”‚   └── emergency_button.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── emergency_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ snake_catching/           # Snake removal requests
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ catching_request.dart
β”‚   β”‚   β”‚   └── catching_report.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ catching_provider.dart
β”‚   β”‚   β”‚   └── queue_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ catching_request_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ queue_screen.dart
β”‚   β”‚   β”‚   └── report_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ species_selector.dart
β”‚   β”‚   β”‚   └── quantity_input.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── catching_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ consultation/             # Expert consultation
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ consultation_session.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ chat_message.dart
β”‚   β”‚   β”‚   └── expert_profile.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ consultation_provider.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ webrtc_provider.dart
β”‚   β”‚   β”‚   └── chat_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ expert_list_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ consultation_room_screen.dart
β”‚   β”‚   β”‚   └── chat_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ video_call_widget.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ chat_widget.dart
β”‚   β”‚   β”‚   └── expert_card.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── consultation_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ snake_ai/                 # Snake recognition & library
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ snake_species.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ ai_recognition_result.dart
β”‚   β”‚   β”‚   └── first_aid_guideline.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ snake_recognition_provider.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ snake_library_provider.dart
β”‚   β”‚   β”‚   └── ai_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ camera_recognition_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ snake_library_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ species_detail_screen.dart
β”‚   β”‚   β”‚   └── manual_filter_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ camera_widget.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ species_card.dart
β”‚   β”‚   β”‚   └── filter_widget.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── snake_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ payment/                  # Payment & wallet
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ payment_transaction.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ wallet_account.dart
β”‚   β”‚   β”‚   └── payment_method.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ payment_provider.dart
β”‚   β”‚   β”‚   └── wallet_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ payment_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ wallet_screen.dart
β”‚   β”‚   β”‚   └── payment_history_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ payment_form.dart
β”‚   β”‚   β”‚   └── payment_method_card.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── payment_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ rescuer/                  # Rescuer-specific features
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ rescuer_profile.dart
β”‚   β”‚   β”‚   └── mission.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ rescuer_provider.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ mission_provider.dart
β”‚   β”‚   β”‚   └── availability_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ rescuer_dashboard_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ mission_queue_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ active_mission_screen.dart
β”‚   β”‚   β”‚   └── training_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ mission_card.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ availability_toggle.dart
β”‚   β”‚   β”‚   └── location_tracker.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── rescuer_repository.dart
β”‚   β”‚
β”‚   β”œβ”€β”€ expert/                   # Expert-specific features
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ expert_profile.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ expert_schedule.dart
β”‚   β”‚   β”‚   └── certificate.dart
β”‚   β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”‚   β”œβ”€β”€ expert_provider.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ schedule_provider.dart
β”‚   β”‚   β”‚   └── consultation_queue_provider.dart
β”‚   β”‚   β”œβ”€β”€ screens/
β”‚   β”‚   β”‚   β”œβ”€β”€ expert_dashboard_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ consultation_requests_screen.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ schedule_management_screen.dart
β”‚   β”‚   β”‚   └── knowledge_management_screen.dart
β”‚   β”‚   β”œβ”€β”€ widgets/
β”‚   β”‚   β”‚   β”œβ”€β”€ consultation_request_card.dart
β”‚   β”‚   β”‚   β”œβ”€β”€ schedule_calendar.dart
β”‚   β”‚   β”‚   └── certificate_uploader.dart
β”‚   β”‚   └── repository/
β”‚   β”‚       └── expert_repository.dart
β”‚   β”‚
β”‚   └── shared/                   # Shared between roles
β”‚       β”œβ”€β”€ models/
β”‚       β”‚   β”œβ”€β”€ location.dart
β”‚       β”‚   β”œβ”€β”€ media.dart
β”‚       β”‚   └── notification.dart
β”‚       β”œβ”€β”€ providers/
β”‚       β”‚   β”œβ”€β”€ location_provider.dart
β”‚       β”‚   β”œβ”€β”€ media_provider.dart
β”‚       β”‚   └── notification_provider.dart
β”‚       └── widgets/
β”‚           β”œβ”€β”€ map_widget.dart
β”‚           β”œβ”€β”€ media_picker.dart
β”‚           └── notification_badge.dart
β”‚
β”œβ”€β”€ app/                          # App-level configuration
β”‚   β”œβ”€β”€ router.dart              # Go Router configuration
β”‚   β”œβ”€β”€ providers.dart           # Global providers
β”‚   └── theme.dart              # App theme
β”‚
└── main.dart

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages