Republish setup: fastlane + Forgejo CI, signing/version fixes, Play-policy link
- support_page: repoint comunes.org link to project page (Play re-approval) - build.gradle: conditional release signing (debug fallback), versionCode/Name from pubspec, drop duplicate google-services plugin - pubspec: version 1.10.0+10 (versionCode must exceed last uploaded) - track AndroidManifest.xml (no secrets in it) - fastlane: Appfile/Fastfile (deploy_play/deploy_metadata/promote_production) + Gemfile + es/en/gl store metadata - .forgejo: ci.yml (analyze+test) + release.yml (tag v* -> signed AAB -> Play internal) - README + RELEASE.md
This commit is contained in:
parent
cea395007d
commit
4461481668
24 changed files with 446 additions and 15 deletions
54
.forgejo/workflows/ci.yml
Normal file
54
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Per-push gate for git.comunes.org (Forgejo Actions): analyze + tests.
|
||||
# Flutter pinned to the developer toolchain (3.41.9).
|
||||
#
|
||||
# NOTE: `runs-on` must match a label your Forgejo runner registered with.
|
||||
# We check out with plain git (a `run:` step) instead of actions/checkout@v4:
|
||||
# the cirruslabs/flutter image has no Node.js, and JS-based actions need it
|
||||
# ("exec: node: not found"). Manual checkout keeps the workflow Node-free.
|
||||
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: ghcr.io/cirruslabs/flutter:3.41.9
|
||||
steps:
|
||||
- name: Checkout
|
||||
env:
|
||||
TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
git init -q .
|
||||
git remote add origin "http://x-access-token:${TOKEN}@forgejo:3000/${GITHUB_REPOSITORY}.git"
|
||||
git fetch -q --depth 1 origin "${GITHUB_SHA}"
|
||||
git checkout -q FETCH_HEAD
|
||||
- run: flutter pub get
|
||||
- name: Generate code (json_serializable)
|
||||
run: dart run build_runner build --delete-conflicting-outputs
|
||||
- run: flutter analyze
|
||||
|
||||
test:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: ghcr.io/cirruslabs/flutter:3.41.9
|
||||
steps:
|
||||
- name: Checkout
|
||||
env:
|
||||
TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
git init -q .
|
||||
git remote add origin "http://x-access-token:${TOKEN}@forgejo:3000/${GITHUB_REPOSITORY}.git"
|
||||
git fetch -q --depth 1 origin "${GITHUB_SHA}"
|
||||
git checkout -q FETCH_HEAD
|
||||
- run: flutter pub get
|
||||
- name: Generate code + test
|
||||
run: |
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
flutter test
|
||||
91
.forgejo/workflows/release.yml
Normal file
91
.forgejo/workflows/release.yml
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Release automation for git.comunes.org (Forgejo Actions).
|
||||
#
|
||||
# Password-free: pushing a tag `v*` builds a signed AAB and uploads it to
|
||||
# Google Play's internal track via fastlane. All credentials come from repo
|
||||
# secrets (Settings > Actions > Secrets), never typed:
|
||||
# FIRES_KEYSTORE_BASE64 base64 of the org.comunes.fires upload keystore
|
||||
# FIRES_KEYSTORE_PASSWORD store password
|
||||
# FIRES_KEY_ALIAS key alias
|
||||
# FIRES_KEY_PASSWORD key password
|
||||
# SUPPLY_JSON_KEY_DATA Google Play service-account JSON (shared Comunes)
|
||||
# FIRES_PRIVATE_SETTINGS_JSON contents of assets/private-settings.json
|
||||
# FIRES_GOOGLE_SERVICES_JSON base64 of android/app/google-services.json
|
||||
#
|
||||
# Build + deploy live in ONE job so the AAB never has to cross a job boundary.
|
||||
# NOTE: `runs-on` must match a label your Forgejo runner registered with.
|
||||
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
android:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: ghcr.io/cirruslabs/flutter:3.41.9
|
||||
steps:
|
||||
# Manual git checkout (no Node): the flutter image has no node, so JS
|
||||
# actions like actions/checkout@v4 fail with "exec: node: not found".
|
||||
- name: Checkout
|
||||
env:
|
||||
TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
git init -q .
|
||||
git remote add origin "http://x-access-token:${TOKEN}@forgejo:3000/${GITHUB_REPOSITORY}.git"
|
||||
git fetch -q --depth 1 origin "${GITHUB_SHA}"
|
||||
git checkout -q FETCH_HEAD
|
||||
|
||||
- name: Materialize runtime secrets (Firebase + private settings)
|
||||
env:
|
||||
FIRES_GOOGLE_SERVICES_JSON: ${{ secrets.FIRES_GOOGLE_SERVICES_JSON }}
|
||||
FIRES_PRIVATE_SETTINGS_JSON: ${{ secrets.FIRES_PRIVATE_SETTINGS_JSON }}
|
||||
run: |
|
||||
echo "$FIRES_GOOGLE_SERVICES_JSON" | base64 -d > android/app/google-services.json
|
||||
printf '%s' "$FIRES_PRIVATE_SETTINGS_JSON" > assets/private-settings.json
|
||||
|
||||
- name: Materialize signing material from secrets
|
||||
env:
|
||||
FIRES_KEYSTORE_BASE64: ${{ secrets.FIRES_KEYSTORE_BASE64 }}
|
||||
FIRES_KEYSTORE_PASSWORD: ${{ secrets.FIRES_KEYSTORE_PASSWORD }}
|
||||
FIRES_KEY_ALIAS: ${{ secrets.FIRES_KEY_ALIAS }}
|
||||
FIRES_KEY_PASSWORD: ${{ secrets.FIRES_KEY_PASSWORD }}
|
||||
run: |
|
||||
echo "$FIRES_KEYSTORE_BASE64" | base64 -d > "$GITHUB_WORKSPACE/fires-upload.jks"
|
||||
cat > android/key.properties <<EOF
|
||||
storeFile=$GITHUB_WORKSPACE/fires-upload.jks
|
||||
storePassword=$FIRES_KEYSTORE_PASSWORD
|
||||
keyAlias=$FIRES_KEY_ALIAS
|
||||
keyPassword=$FIRES_KEY_PASSWORD
|
||||
EOF
|
||||
|
||||
- name: Generate code (json_serializable)
|
||||
run: |
|
||||
flutter pub get
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
|
||||
- name: Build signed AAB + APK (production flavor)
|
||||
run: |
|
||||
flutter build appbundle --release --flavor production -t lib/main_prod.dart
|
||||
flutter build apk --release --flavor production -t lib/main_prod.dart
|
||||
|
||||
- name: Install fastlane
|
||||
run: |
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq ruby ruby-dev build-essential
|
||||
gem install bundler --no-document
|
||||
bundle install
|
||||
|
||||
- name: Publish to Google Play (internal track)
|
||||
env:
|
||||
SUPPLY_JSON_KEY_DATA: ${{ secrets.SUPPLY_JSON_KEY_DATA }}
|
||||
run: bundle exec fastlane deploy_play
|
||||
|
||||
- name: Scrub secrets
|
||||
if: always()
|
||||
run: |
|
||||
rm -f android/key.properties "$GITHUB_WORKSPACE/fires-upload.jks"
|
||||
rm -f android/app/google-services.json assets/private-settings.json
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -21,7 +21,6 @@ pubspec.lock
|
|||
doc/api/
|
||||
|
||||
assets/private-settings.json
|
||||
android/app/src/main/AndroidManifest.xml
|
||||
|
||||
.flutter-plugins
|
||||
android/app/src/main/gen/
|
||||
|
|
|
|||
5
Gemfile
Normal file
5
Gemfile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Ruby toolchain for release automation (fastlane supply -> Google Play).
|
||||
# Run from android/: bundle install && bundle exec fastlane deploy_play
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "fastlane"
|
||||
11
README.md
11
README.md
|
|
@ -22,14 +22,21 @@ also you can run with `watch` instead of `build` to build with any code change.
|
|||
|
||||
Generate apk with:
|
||||
```
|
||||
flutter build apk -t lib/mainProd.dart --flavor production
|
||||
flutter build apk --release -t lib/main_prod.dart --flavor production
|
||||
```
|
||||
also you can run with `-t lib/mainDev.dart --flavor development`. More info about flavors [here](https://medium.com/@salvatoregiordanoo/flavoring-flutter-392aaa875f36).
|
||||
also you can run with `-t lib/main_dev.dart --flavor development`. More info about flavors [here](https://medium.com/@salvatoregiordanoo/flavoring-flutter-392aaa875f36).
|
||||
|
||||
## Testing
|
||||
|
||||
Run `flutter test` for doing unit testing.
|
||||
|
||||
## Release
|
||||
|
||||
Publishing to Google Play is automated and password-free via Forgejo Actions on
|
||||
`git.comunes.org`. See [RELEASE.md](RELEASE.md). TL;DR: bump `version:` in
|
||||
`pubspec.yaml`, then `git tag vX.Y && git push origin vX.Y` — CI builds a signed
|
||||
AAB and uploads it to the Play *internal* track.
|
||||
|
||||
## Data source acknowledgements
|
||||
|
||||
*We acknowledge the use of data and imagery from LANCE FIRMS operated by the NASA/GSFC/Earth Science Data and Information System (ESDIS) with funding provided by NASA/HQ*.
|
||||
|
|
|
|||
85
RELEASE.md
Normal file
85
RELEASE.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Releasing Tod@s contra el Fuego
|
||||
|
||||
Publishing to Google Play is **automated and password-free**: pushing a signed
|
||||
git tag to `git.comunes.org` triggers Forgejo Actions, which builds a signed AAB
|
||||
and uploads it to Play's **internal** track. Modeled on the `tane` pipeline.
|
||||
|
||||
## TL;DR — cut a release
|
||||
|
||||
```bash
|
||||
# bump version in pubspec.yaml (version: X.Y.Z+CODE), add changelogs/<CODE>.txt
|
||||
git tag v1.10 && git push origin v1.10
|
||||
```
|
||||
|
||||
[`.forgejo/workflows/release.yml`](.forgejo/workflows/release.yml) builds the
|
||||
signed AAB/APK (production flavor, `lib/main_prod.dart`) and uploads via
|
||||
`fastlane deploy_play`. No passwords are typed.
|
||||
|
||||
## Versioning
|
||||
|
||||
- `version:` in [`pubspec.yaml`](pubspec.yaml) as `MAJOR.MINOR.PATCH+CODE`.
|
||||
Flutter maps `+CODE` to Android `versionCode` (read via `flutter.versionCode`
|
||||
in `android/app/build.gradle`) and the rest to `versionName`.
|
||||
- **`versionCode` must be strictly greater than the highest ever uploaded** to
|
||||
the `org.comunes.fires` listing. This re-launch starts at `+10` (was 9).
|
||||
- Add a per-locale note under
|
||||
`fastlane/metadata/android/<locale>/changelogs/<versionCode>.txt`.
|
||||
|
||||
## One-time setup
|
||||
|
||||
### Signing keystore
|
||||
|
||||
The app already exists in Play with **Play App Signing**, so releases MUST be
|
||||
signed with the **existing upload key** that signed `org.comunes.fires` before
|
||||
(`android/app/key.jks` → shared Comunes signing dir). Do **not** generate a new
|
||||
one. Get the alias with:
|
||||
|
||||
```bash
|
||||
keytool -list -v -keystore android/app/key.jks
|
||||
```
|
||||
|
||||
Local signed builds read a **gitignored** `android/key.properties`:
|
||||
|
||||
```properties
|
||||
storeFile=/abs/path/to/key.jks
|
||||
storePassword=…
|
||||
keyAlias=…
|
||||
keyPassword=…
|
||||
```
|
||||
|
||||
Without `key.properties`, release builds fall back to **debug** signing so
|
||||
contributors/CI can still build.
|
||||
|
||||
### CI secrets (Forgejo → repo → Settings → Actions → Secrets)
|
||||
|
||||
| Secret | Contents |
|
||||
|---|---|
|
||||
| `FIRES_KEYSTORE_BASE64` | `base64 -w0 android/app/key.jks` |
|
||||
| `FIRES_KEYSTORE_PASSWORD` / `FIRES_KEY_ALIAS` / `FIRES_KEY_PASSWORD` | keystore credentials |
|
||||
| `SUPPLY_JSON_KEY_DATA` | Google Play service-account JSON (shared Comunes account) |
|
||||
| `FIRES_PRIVATE_SETTINGS_JSON` | raw contents of `assets/private-settings.json` |
|
||||
| `FIRES_GOOGLE_SERVICES_JSON` | `base64 -w0 android/app/google-services.json` |
|
||||
|
||||
### First upload
|
||||
|
||||
The app was removed by Google and an update was rejected. Before the API accepts
|
||||
uploads: resolve any enforcement flag in the Play Console (appeal / re-submit),
|
||||
and confirm the flagged content is addressed (the `comunes.org` support link was
|
||||
repointed to the project page — see `lib/support_page.dart`). After the listing
|
||||
accepts a build again, `fastlane deploy_play` is fully automated.
|
||||
|
||||
## Manual / local fallback
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
flutter build appbundle --release --flavor production -t lib/main_prod.dart
|
||||
# AAB: build/app/outputs/bundle/productionRelease/app-production-release.aab
|
||||
SUPPLY_JSON_KEY_DATA="$(cat play-service-account.json)" bundle exec fastlane deploy_play
|
||||
```
|
||||
|
||||
Promote internal → production (reuses the reviewed AAB, no rebuild):
|
||||
|
||||
```bash
|
||||
bundle exec fastlane promote_production
|
||||
```
|
||||
|
|
@ -12,9 +12,14 @@ if (localPropertiesFile.exists()) {
|
|||
}
|
||||
}
|
||||
|
||||
// Release signing is opt-in: only load key.properties if it exists. Without it
|
||||
// (CI analyze/test jobs, contributors) builds fall back to debug signing.
|
||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||
def keystoreProperties = new Properties()
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
def hasReleaseKeystore = keystorePropertiesFile.exists()
|
||||
if (hasReleaseKeystore) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 36
|
||||
|
|
@ -29,23 +34,28 @@ android {
|
|||
applicationId "org.comunes.fires"
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion 36
|
||||
versionCode 9
|
||||
versionName "1.9"
|
||||
// versionCode/versionName come from pubspec.yaml (version: X.Y.Z+CODE)
|
||||
// so a `v*` git tag maps the release version, matching the tane flow.
|
||||
versionCode flutter.versionCode
|
||||
versionName flutter.versionName
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile file(keystoreProperties['storeFile'])
|
||||
storePassword keystoreProperties['storePassword']
|
||||
if (hasReleaseKeystore) {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile file(keystoreProperties['storeFile'])
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
// Sign with the release key when available, else debug (contributors/CI).
|
||||
signingConfig hasReleaseKeystore ? signingConfigs.release : signingConfigs.debug
|
||||
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
|
|
@ -83,5 +93,3 @@ dependencies {
|
|||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
|
|
|||
47
android/app/src/main/AndroidManifest.xml
Normal file
47
android/app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.comunes.fires">
|
||||
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<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"/>
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/launch_image"
|
||||
android:enableOnBackInvokedCallback="true">
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
until Flutter renders its first frame. It can be removed if
|
||||
there is no splash screen (such as the default splash screen
|
||||
defined in @style/LaunchTheme). -->
|
||||
<!-- <meta-data
|
||||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||
android:value="true" /> -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
9
fastlane/Appfile
Normal file
9
fastlane/Appfile
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Google Play identity + credentials for `fastlane supply`.
|
||||
#
|
||||
# The service-account JSON is injected from CI as the SUPPLY_JSON_KEY_DATA
|
||||
# secret (raw file contents) and is NEVER committed. Locally you can instead
|
||||
# export SUPPLY_JSON_KEY_DATA, or drop a gitignored play-service-account.json
|
||||
# and point json_key_file at it.
|
||||
package_name("org.comunes.fires")
|
||||
|
||||
json_key_data_raw(ENV["SUPPLY_JSON_KEY_DATA"]) if ENV["SUPPLY_JSON_KEY_DATA"]
|
||||
54
fastlane/Fastfile
Normal file
54
fastlane/Fastfile
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Fastlane lanes for Tod@s contra el Fuego (org.comunes.fires).
|
||||
#
|
||||
# Publishing is automated and password-free: a git tag triggers CI, which builds
|
||||
# a signed AAB and runs `deploy_play`. Credentials come from CI secrets, never
|
||||
# typed by hand:
|
||||
# SUPPLY_JSON_KEY_DATA Google Play service-account JSON (raw contents)
|
||||
#
|
||||
# The store listing (titles, descriptions, changelogs, screenshots) is read
|
||||
# straight from fastlane/metadata/android/<locale>/.
|
||||
|
||||
default_platform(:android)
|
||||
|
||||
# Release bundle produced by `flutter build appbundle --release --flavor
|
||||
# production`, relative to the project root (where fastlane runs).
|
||||
AAB_PATH = "build/app/outputs/bundle/productionRelease/app-production-release.aab".freeze
|
||||
|
||||
platform :android do
|
||||
desc "Upload the signed AAB + store listing to Google Play (internal track)"
|
||||
lane :deploy_play do
|
||||
supply(
|
||||
track: "internal",
|
||||
aab: AAB_PATH,
|
||||
release_status: "completed", # internal testing has no review delay
|
||||
skip_upload_apk: true, # we ship the AAB, not a raw APK
|
||||
skip_upload_changelogs: false,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Push only the store listing (text + images), no binary"
|
||||
lane :deploy_metadata do
|
||||
supply(
|
||||
skip_upload_aab: true,
|
||||
skip_upload_apk: true,
|
||||
)
|
||||
end
|
||||
|
||||
# Promote the release currently on the internal track to production, reusing
|
||||
# the SAME already-reviewed AAB (no rebuild, no new versionCode). Requires the
|
||||
# service account to have "Release to production" permission in Play Console.
|
||||
# Usage: bundle exec fastlane promote_production
|
||||
desc "Promote the internal-track release to production (no rebuild)"
|
||||
lane :promote_production do
|
||||
supply(
|
||||
track: "internal",
|
||||
track_promote_to: "production",
|
||||
skip_upload_aab: true,
|
||||
skip_upload_apk: true,
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_changelogs: true,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true,
|
||||
)
|
||||
end
|
||||
end
|
||||
2
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
All Against The Fire! is back. Upgraded to a recent Flutter, stability
|
||||
improvements and code cleanup. Fire alerts in your area based on NASA FIRMS data.
|
||||
17
fastlane/metadata/android/en-US/full_description.txt
Normal file
17
fastlane/metadata/android/en-US/full_description.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
All Against The Fire! notifies you about fires detected in an area of your
|
||||
interest. It helps the early detection of fires and facilitates local
|
||||
mobilization while the professional extinction services arrive.
|
||||
|
||||
HOW IT WORKS
|
||||
• Pick the area you want to watch.
|
||||
• Get notified when a heat spot is detected in that area.
|
||||
• See active fires on the map, with their location and time.
|
||||
• Share an alert to mobilise people around you.
|
||||
|
||||
DATA
|
||||
Heat spots come from data and imagery from LANCE FIRMS operated by the
|
||||
NASA/GSFC/Earth Science Data and Information System (ESDIS) with funding
|
||||
provided by NASA/HQ.
|
||||
|
||||
Free software (GNU AGPL-3.0). No ads, non-profit: a community tool to prevent
|
||||
and respond to wildfires.
|
||||
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Fire alerts in your area for early detection and local response.
|
||||
1
fastlane/metadata/android/en-US/title.txt
Normal file
1
fastlane/metadata/android/en-US/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
All Against The Fire!
|
||||
3
fastlane/metadata/android/es-ES/changelogs/10.txt
Normal file
3
fastlane/metadata/android/es-ES/changelogs/10.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Vuelve ¡Tod@s contra el Fuego! Actualización a Flutter reciente, mejoras de
|
||||
estabilidad y limpieza de código. Avisos de incendios en tu zona basados en
|
||||
datos de NASA FIRMS.
|
||||
17
fastlane/metadata/android/es-ES/full_description.txt
Normal file
17
fastlane/metadata/android/es-ES/full_description.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
¡Tod@s contra el Fuego! te avisa de los incendios detectados en una zona de tu
|
||||
interés. Ayuda a la detección temprana de incendios y facilita la movilización
|
||||
local mientras llegan los servicios profesionales de extinción.
|
||||
|
||||
CÓMO FUNCIONA
|
||||
• Elige la zona que quieres vigilar.
|
||||
• Recibe notificaciones cuando se detecta un foco de calor en esa zona.
|
||||
• Consulta los incendios activos sobre el mapa, con su ubicación y hora.
|
||||
• Comparte un aviso para movilizar a la gente de tu entorno.
|
||||
|
||||
DATOS
|
||||
Los focos de calor proceden de datos e imágenes de LANCE FIRMS, operado por el
|
||||
Sistema de Datos e Información de Ciencias de la Tierra (ESDIS) de NASA/GSFC,
|
||||
con financiación de NASA/HQ.
|
||||
|
||||
Software libre (GNU AGPL-3.0). Sin anuncios y sin ánimo de lucro: una
|
||||
herramienta comunitaria para prevenir y responder a los incendios.
|
||||
1
fastlane/metadata/android/es-ES/short_description.txt
Normal file
1
fastlane/metadata/android/es-ES/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Avisos de incendios en tu zona para la detección temprana y la respuesta local.
|
||||
1
fastlane/metadata/android/es-ES/title.txt
Normal file
1
fastlane/metadata/android/es-ES/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
¡Tod@s contra el Fuego!
|
||||
3
fastlane/metadata/android/gl-ES/changelogs/10.txt
Normal file
3
fastlane/metadata/android/gl-ES/changelogs/10.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Volve Tod@s contra o Lume! Actualización a Flutter recente, melloras de
|
||||
estabilidade e limpeza de código. Avisos de lumes na túa zona baseados en datos
|
||||
de NASA FIRMS.
|
||||
17
fastlane/metadata/android/gl-ES/full_description.txt
Normal file
17
fastlane/metadata/android/gl-ES/full_description.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
Tod@s contra o Lume! avísache dos lumes detectados nunha zona do teu interese.
|
||||
Axuda á detección temperá de incendios e facilita a mobilización local mentres
|
||||
chegan os servizos profesionais de extinción.
|
||||
|
||||
COMO FUNCIONA
|
||||
• Escolle a zona que queres vixiar.
|
||||
• Recibe notificacións cando se detecta un foco de calor nesa zona.
|
||||
• Consulta os lumes activos sobre o mapa, coa súa localización e hora.
|
||||
• Comparte un aviso para mobilizar á xente do teu contorno.
|
||||
|
||||
DATOS
|
||||
Os focos de calor proceden de datos e imaxes de LANCE FIRMS, operado polo
|
||||
Sistema de Datos e Información de Ciencias da Terra (ESDIS) de NASA/GSFC, con
|
||||
financiamento de NASA/HQ.
|
||||
|
||||
Software libre (GNU AGPL-3.0). Sen anuncios e sen ánimo de lucro: unha
|
||||
ferramenta comunitaria para previr e responder aos incendios.
|
||||
1
fastlane/metadata/android/gl-ES/short_description.txt
Normal file
1
fastlane/metadata/android/gl-ES/short_description.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Avisos de lumes na túa zona para a detección temperá e a resposta local.
|
||||
1
fastlane/metadata/android/gl-ES/title.txt
Normal file
1
fastlane/metadata/android/gl-ES/title.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Tod@s contra o Lume!
|
||||
|
|
@ -26,7 +26,11 @@ class _SupportPageState extends State<SupportPage> {
|
|||
icon: const Icon(Icons.favorite_border),
|
||||
label: Text(S.of(context).comunesSupportBtn),
|
||||
onPressed: () async {
|
||||
final Uri url = Uri.parse('https://comunes.org/');
|
||||
// Play policy: la app fue retirada por enlazar a comunes.org (que
|
||||
// tiene página de donaciones). Apuntamos a la página del proyecto
|
||||
// (sin donaciones) para la re-aprobación. Reversible una vez aprobada.
|
||||
final Uri url = Uri.parse(
|
||||
'https://git.comunes.org/comunes/todos-contra-el-fuego-mobile');
|
||||
if (await canLaunchUrl(url)) {
|
||||
await launchUrl(url);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
name: fires_flutter
|
||||
description: All Against Fire
|
||||
# MAJOR.MINOR.PATCH+versionCode — Flutter maps +CODE to Android versionCode.
|
||||
# Must be strictly greater than the highest versionCode ever uploaded to Play.
|
||||
version: 1.10.0+10
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue