Compare commits

..

96 commits

Author SHA1 Message Date
17b572441d
fix(ci): ignore app for services
Some checks failed
/ build (map[dockerfile:./services/app/Dockerfile name:app]) (push) Failing after 13s
/ build (map[dockerfile:./services/tasks/Dockerfile name:tasks]) (push) Failing after 18s
/ build (map[dockerfile:./services/hasura/Dockerfile name:hasura]) (push) Failing after 21s
/ build (map[dockerfile:./services/api/Dockerfile name:api]) (push) Failing after 13s
/ build (map[dockerfile:./services/files/Dockerfile name:files]) (push) Failing after 15s
/ build (map[dockerfile:./services/watchers/Dockerfile name:watchers]) (push) Failing after 20s
/ build (map[dockerfile:./services/web/Dockerfile name:web]) (push) Failing after 12m58s
/ deploy (push) Has been cancelled
2026-03-09 15:25:37 +01:00
3e56818c1d chore(to-monorepo): import as-app repo into app
git-subtree-dir: app
git-subtree-mainline: b28b08a80b
git-subtree-split: a6c3dc2641
2026-03-09 08:54:57 +01:00
a6c3dc2641
fix(dae): navigation control buttons 2026-03-08 21:20:30 +01:00
58bdb3898b fix(dae): marker and icon 2026-03-08 21:08:34 +01:00
f66685ac25 fix(dae): update error message 2026-03-08 20:42:54 +01:00
aaa5623305 fix(dae): navigation back 2026-03-08 20:28:40 +01:00
4d79a02140 fix(dae): on alert modal 2026-03-08 18:26:53 +01:00
3f51b65610 fix(dae): alert navigation view 2026-03-08 18:09:41 +01:00
dc8bfee4c9 feat(dae): updates (+ lint) 2026-03-08 18:03:19 +01:00
44b276f83e feat(dae): complete pipeline 2026-03-08 15:01:41 +01:00
b28b08a80b
fix: cleanup geodata later 2026-03-02 20:53:50 +01:00
07f23be096
fix: swag username 2026-01-17 13:59:48 +01:00
f4ce6d516f
fix: swag username 2026-01-17 13:59:31 +01:00
d81bcf43cf
fix: wip 2026-01-17 13:42:33 +01:00
e5f6834b9f
chore: clean debug 2026-01-17 13:40:51 +01:00
7b277a8020
chore: debug 2026-01-17 13:36:02 +01:00
e64ecfd023
fix: default jwt role 2026-01-11 15:07:59 +01:00
fc0733998e
chore: local dev tilt wip 2026-01-11 14:40:58 +01:00
4198dc3ad9
fix(up+wip): deps + amqp + valkey + kvrocks 2025-10-23 11:49:43 +02:00
7b4c96b7c3
fix(up-modjo): migrate to valkey with sentinel 2025-10-20 23:23:39 +02:00
e6507349aa
fix: migrate to valkey with sentinel 2025-10-20 22:38:23 +02:00
8d93390466
fix: migrate to kvrocks 2025-10-20 22:13:33 +02:00
b6dcaa87e2
fix: migrate to kvrocks 2025-10-20 19:32:04 +02:00
acbc18b038
fix: migrate to kvrocks 2025-10-20 19:30:26 +02:00
8e0adf6ba0
fix: migrate to kvrocks 2025-10-20 19:26:42 +02:00
7c18522f2e
fix: migrate to kvrocks 2025-10-20 16:57:42 +02:00
d1d8f725ce
chore: use devbox 2025-09-11 11:54:41 +02:00
1f449e9f0c
feat: count people around 2025-09-11 11:53:44 +02:00
74e1b5f10b
fix: multi device lost notifications 2025-08-24 13:01:30 +02:00
1cc35a57c9
fix: multi device lost notifications 2025-08-24 12:55:50 +02:00
e4da0f59b3
fix: opti 2025-08-24 11:53:15 +02:00
d6bd2308a1
fix: typo 2025-08-24 11:18:25 +02:00
dc586e3991
fix(archived-message): text nullable 2025-08-24 10:44:38 +02:00
3e83c7704c
fix: voice message 2025-08-09 15:39:29 +02:00
f42df5ca06
fix: notification icon 2025-08-09 10:30:51 +02:00
042d4040ee
fix: wip 2025-08-08 12:25:20 +02:00
9920f40268
feat(heartbeat): remove 2025-08-02 15:38:33 +02:00
42cddb2aa2
fix(sync): event 2025-07-27 23:12:23 +02:00
a80a5aaa00
fix(cleanup): increase time 2025-07-27 09:02:06 +02:00
5a5a49634a
fix: wip 2025-07-24 19:04:15 +02:00
6c1bb2fa3d
fix(cron): decouple cron from notification window 2025-07-23 15:20:13 +02:00
ace5657057
feat(ios): silent push notification geolocation heartbeat sync 2025-07-23 14:48:44 +02:00
74d999a9b8
feat: add phoneOS field to device (+ reapply hasura convention) 2025-07-23 14:15:30 +02:00
74430f63ba
fix: geodata cleanup cron decouple notification and cleanup 2025-07-23 14:01:57 +02:00
a0cbf8ff4b
chore(clean): disable clean orphan 2025-07-23 13:44:53 +02:00
d5f63107b9
fix: up nominatim to 5.1 2025-07-14 18:01:21 +02:00
d7a148c208
fix: notif bg location lost, avoid night 2025-07-11 08:54:07 +02:00
4cc74845c2
fix: wip 2025-07-09 22:25:27 +02:00
da7a02b282
fix: device geodata max age to 36h 2025-07-06 17:40:41 +02:00
9d7b3176dc
fix: undefined followLocation 2025-07-04 14:27:12 +02:00
f759dc301c fix: bg location lost notif 2025-07-04 09:02:12 +02:00
1c89275a6b fix: yarn.lock 2025-07-02 13:47:37 +02:00
8c88611c6c chore: script 2025-07-02 13:26:03 +02:00
30bc626a76 fix: up 2025-07-02 13:24:47 +02:00
a13b07ec9d chore: debug 2025-07-02 12:58:37 +02:00
6d308bf95d chore: debug 2025-07-02 12:50:23 +02:00
e284f59476 fix(sync): rollback to jwt last exp approach 2025-07-01 13:38:18 +02:00
02cb943a93 fix: wip 2025-07-01 10:05:08 +02:00
83b971890a fix: logger call 2025-06-30 23:20:40 +02:00
306a9faa63 fix: wip 2025-06-30 17:18:31 +02:00
84be7527f2 chore: clean 2025-06-30 17:14:55 +02:00
35bbdf44b4 fix: wip 2025-06-30 15:52:03 +02:00
b330dffa62 chore: debug 2025-06-30 15:49:40 +02:00
e923a2404b fix: wip 2025-06-30 14:03:19 +02:00
2518ced0fa fix: wip 2025-06-30 13:50:26 +02:00
391fd6d380 fix: clean error 2025-06-30 13:47:53 +02:00
11943b667c fix: modjo 2025-06-30 13:24:28 +02:00
3bfa3d78d5 fix: sync handle refresh token + up modjo 2025-06-30 12:34:00 +02:00
c036839233 fix(sync): allow last expired jwt wip 2025-06-30 00:01:26 +02:00
edee8d6bc4 fix(sync): allow last expired jwt 2025-06-29 23:29:33 +02:00
6025bfabff chore: clean dead code 2025-06-29 22:51:45 +02:00
28139f70e9 fix: archive_alert update + remove followLocationRan 2025-06-01 10:53:42 +02:00
a9d60d1c99 fix: alertGeosync place 2025-06-01 10:10:56 +02:00
227b53cd39 feat(follow-location): alert-geosync 2025-06-01 09:58:01 +02:00
7ee0a75b50 feat(follow-location): wip 2025-05-30 18:52:26 +02:00
d152a564ee fix: typo 2025-05-30 18:38:07 +02:00
4eef09b32f fix: typo 2025-05-30 18:35:10 +02:00
ea548112db fix: typo 2025-05-30 18:34:02 +02:00
096314c14c chore: clean 2025-05-30 18:17:28 +02:00
e40b939144 feat(follow-location): geocode move + migrations 2025-05-30 18:12:23 +02:00
91d3258533 feat(follow-location): init 2025-05-25 09:25:04 +02:00
85bc0683a8 docs: fix funding link 2025-05-23 22:38:21 +02:00
cfdea8db4b chore: improve doc + add funding 2025-05-23 22:30:15 +02:00
ad32afd2f8 chore: add funding 2025-05-23 15:20:38 +02:00
6a3471d2cc docs: improve README 2025-05-10 11:24:07 +02:00
ddaff39619 chore: cleanup geodata wip 2025-05-08 09:33:12 +02:00
e9887b29ae fix: archive_alert function 2025-05-04 11:43:48 +02:00
089f71b645 chore: fix terminator-config for dev-logs 2025-04-27 11:56:10 +02:00
f63766314b fix: opti cleanup geodata 2025-04-26 14:02:53 +02:00
dc351b2ed6 feat: bg location lost notify + fix cleanupOrphanedHotGeodata 2025-04-24 17:30:52 +02:00
f4313ce9ed fix(tasks): disable dedup on geocode-device-update 2025-04-23 16:14:09 +02:00
64f2f995f3 chore(dev): replace tmuxp by terminator + fix end yarn-dev-portal removal 2025-04-23 15:40:36 +02:00
cdf45a1301 chore(dev): nodemon exitcrash 2025-04-23 15:13:23 +02:00
c42a406b89 chore(clean): remove yarn-dev-portal 2025-04-23 15:01:15 +02:00
4ddb801574 chore: clean 2025-04-22 12:23:38 +02:00
16b7e7d6aa
chore(init): available sources 2025-04-13 10:46:53 +02:00
1506 changed files with 64717 additions and 11965 deletions

View file

@ -1,80 +1,62 @@
# Ignore everything by default # ai-digest
* .aidigestignore
# First include the source directory # versioning
!src/ CHANGELOG.md
!src/**/ .versionrc.json
!src/**/*.js
!src/**/*.jsx
!src/**/*.ts
!src/**/*.tsx
# Then exclude specific patterns and directories # lint
# Build and dependencies .commitlintrc.json
node_modules/ .eslintrc.js
build/ .editorconfig
dist/ .husky
coverage/
# Platform specific # node
ios/ .yarnrc.yml
android/ .yarn
# Configuration files # docker
*.json .dockerignore
*.lock docker-compose.build.yaml
*.yml
*.yaml
*.env*
*.config.*
.*rc*
Dockerfile*
# Documentation # env
*.md .env.local
*.txt
docs/
# Tests and stories # devbox
**/__tests__/ devbox.lock
**/*.test.* .devbox/
**/*.spec.*
**/*.stories.*
e2e/
# Generated and utility files # git
*.d.ts .gitignore
*.map
# tmux
.tmux.conf
.tmuxp.full-decoupled.yaml
.tmuxp.yaml
# md
README.md
# ci/cd
.forgejo
# binaries
*.png
*.svg
*.jpg
*.jpeg
*.ico
# generic
*.bak
*.tmp
*.log *.log
# Assets and styles # project
src/assets/ tileserver-files
**/*.css .dev-secrets
**/*.scss .osm-files
**/*.style.* osm-files
**/*.styles.* tests
*.svg docs
*.png dockerfile-x
*.jpg
*.ttf
# Common utility/boilerplate directories
src/i18n/
src/theme/
src/utils/
src/lib/
src/components/
src/navigation/
src/hooks/
src/hoc/
# Auto-generated or index files
**/index.js
**/index.ts
**/constants.js
**/constants.ts
**/types.ts
# Deprecated files
*.bak
*.old

5
.commitlintrc.json Normal file
View file

@ -0,0 +1,5 @@
{
"extends": [
"@commitlint/config-conventional"
]
}

6
.dev-secrets/jwk.json Normal file
View file

@ -0,0 +1,6 @@
{
"crv": "Ed25519",
"d": "NuYqgJxxoFye_uIVcu1FYtpzeXhwCBcTP2od3xAQjFs",
"x": "BIoZ8WwlWgplcYSQKUvlzE9dE8jKEOOvH5_Z19N-2zc",
"kty": "OKP"
}

6
.dev-secrets/jwk2.json Normal file
View file

@ -0,0 +1,6 @@
{
"crv": "Ed25519",
"d": "d3F9wKOVQIWXhDckflJs7KoUvI5mFX9jRCpeEbW4LG8",
"x": "H2MyHfvzAnNtnM6sUOhE32OIPPs-Ix6F13HaZ9fhCrg",
"kty": "OKP"
}

View file

@ -1,66 +1,23 @@
.git/ **/*.log
# OSX **/*.md
#
**/.DS_Store **/.DS_Store
**/docker-compose.build.yaml
**/docker-compose.yaml
**/nodemon.json
**/.git
**/.dockerignore
**/Dockerfile
**/Dockerfile.*
**/*.dockerfile
**/node_modules
**/.eslintcache
**/.npm
# Xcode /.osm-files
# /osm-files
**/build/ /tileserver-files
**/*.pbxuser
!**/default.pbxuser
**/*.mode1v3
!**/default.mode1v3
**/*.mode2v3
!**/default.mode2v3
**/*.perspectivev3
!**/default.perspectivev3
**/xcuserdata
**/*.xccheckout
**/*.moved-aside
**/DerivedData
**/*.hmap
**/*.ipa
**/*.xcuserstate
**/project.xcworkspace
# Android/IntelliJ services/*/build
# services/*/dist
**/build/
**/.idea
**/.gradle
**/local.properties
**/*.iml
**/*.hprof
**/.cxx/
**/*.keystore
!**/debug.keystore
# node.js googleServiceAccountKey.json
#
**/node_modules/
**/npm-debug.log
**/yarn-error.log
# Bundle artifacts
**/*.jsbundle
# CocoaPods
ios/Pods/
# Temporary files created by Metro to check the health of the file watcher
**/.metro-health-check*
# Expo
**/.expo/
**/web-build/
**/dist/
# Yarn berry
**/.pnp.*
**/.yarn/*
!**/.yarn/patches
!**/.yarn/plugins
!**/.yarn/releases
!**/.yarn/sdks
!**/.yarn/versions
# !.yarn/cache

10
.editorconfig Normal file
View file

@ -0,0 +1,10 @@
root = true
[*]
end_of_line = lf
insert_final_newline = false
charset = utf-8
[*.js]
indent_style = space
indent_size = 2

54
.env Normal file
View file

@ -0,0 +1,54 @@
# DEV PORTS
API_PORT=4200
WEB_PORT=4203
SERVICE_APP_PORT=4209
FILES_PORT=4292
EXPOSE_API_PORT=4200
EXPOSE_HASURA_PORT=4201
EXPOSE_PG_PORT=4204
EXPOSE_MINO_PORT=4290
EXPOSE_MINIO_PORT=4290
EXPOSE_MINO_CONSOLE_PORT=4291
EXPOSE_MINIO_CONSOLE_PORT=4291
MINIO_ROOT_USER=minio-admin
MINIO_ROOT_PASSWORD=minio-admin
EXPOSE_FILES_PORT=4292
EXPOSE_REDIS_QD_PORT=4278
EXPOSE_REDIS_HG_PORT=4279
EXPOSE_KVROCKS_CG_PORT=4277
EXPOSE_RABBITMQ_NODE_PORT=4272
EXPOSE_RABBITMQ_MANAGEMENT_PORT_PORT=4273
OSRM_CAR_PORT=4261
OSRM_FOOT_PORT=4262
OSRM_BICYCLE_PORT=4263
TILESERVERGL_PORT=4282
NOMINATIM_PORT=4283
HASURA_CONSOLE_PORT=4295
HASURA_CONSOLE_API_PORT=4293
# JWT
CLAIMS_NAMESPACE=https://alertesecours.fr/claims
# APP
APP_OA_FILES_URL=http://10.0.2.2:4292/api/v1/oas
APP_GRAPHQL_URL=http://10.0.2.2:4201/v1/graphql
APP_GRAPHQL_WS_URL=ws://10.0.2.2:4201/v1/graphql
APP_OSRM_CAR_URL=http://10.0.2.2:4261
APP_OSRM_FOOT_URL=http://10.0.2.2:4262
APP_OSRM_BICYCLE_URL=http://10.0.2.2:4263
APP_GEOLOC_SYNC_URL=http://10.0.2.2:4200/api/v1/oas/geoloc/sync
# APP_MAPVIEW_STYLE_URL=https://tiles.alertesecours.fr/styles/basic-preview/style.json
APP_MAPVIEW_STYLE_URL=http://10.0.2.2:4203/app/style.json
# APP_MAPVIEW_STYLE_URL=https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json
# API KEY
WHAT3WORDS_API_KEY=
# GoogleServices
ANDROID_GOOGLE_SERVICES_FILE_PATH=/home/jo/.lab/alertesecours/google-services.json
ANDROID_GOOGLE_SERVICES_FILE_PATH=/home/jo/.lab/alertesecours/GoogleService-Info.plist

View file

@ -1,20 +1,54 @@
# Sentry configuration # DEV PORTS
SENTRY_URL=https://sentry.io API_PORT=4200
SENTRY_DSN=your_sentry_dsn_here WEB_PORT=4203
SENTRY_ORG=your_sentry_org_here SERVICE_APP_PORT=4209
FILES_PORT=4292
SENTRY_PROJECT=alertesecours-application EXPOSE_API_PORT=4200
SENTRY_DISABLE_AUTO_UPLOAD=true EXPOSE_HASURA_PORT=4201
LOCAL_DEV=true EXPOSE_PG_PORT=4204
EXPOSE_MINO_PORT=4290
EXPOSE_MINIO_PORT=4290
EXPOSE_MINO_CONSOLE_PORT=4291
EXPOSE_MINIO_CONSOLE_PORT=4291
MINIO_ROOT_USER=minio-admin
MINIO_ROOT_PASSWORD=minio-admin
EXPOSE_FILES_PORT=4292
EXPOSE_REDIS_QD_PORT=4278
EXPOSE_REDIS_HG_PORT=4279
EXPOSE_KVROCKS_CG_PORT=4277
# Android Emulator Configuration EXPOSE_RABBITMQ_NODE_PORT=4272
ANDROID_EMULATOR_NAME=Pixel_6_API_30 EXPOSE_RABBITMQ_MANAGEMENT_PORT_PORT=4273
ASC_API_KEY_ID= OSRM_CAR_PORT=4261
ASC_API_ISSUER_ID= OSRM_FOOT_PORT=4262
ASC_API_KEY_PATH= OSRM_BICYCLE_PORT=4263
PROVIDER_ID=
# Background Geolocation License Keys TILESERVERGL_PORT=4282
BACKGROUND_GEOLOCATION_LICENSE_ANDROID=your_license_key_here NOMINATIM_PORT=4283
BACKGROUND_GEOLOCATION_LICENSE_IOS=your_license_key_here
HASURA_CONSOLE_PORT=4295
HASURA_CONSOLE_API_PORT=4293
# JWT
CLAIMS_NAMESPACE=https://alertesecours.fr/claims
# APP
APP_OA_FILES_URL=http://10.0.2.2:4292/api/v1/oas
APP_GRAPHQL_URL=http://10.0.2.2:4201/v1/graphql
APP_GRAPHQL_WS_URL=ws://10.0.2.2:4201/v1/graphql
APP_OSRM_CAR_URL=http://10.0.2.2:4261
APP_OSRM_FOOT_URL=http://10.0.2.2:4262
APP_OSRM_BICYCLE_URL=http://10.0.2.2:4263
APP_GEOLOC_SYNC_URL=http://10.0.2.2:4200/api/v1/oas/geoloc/sync
# APP_MAPVIEW_STYLE_URL=https://tiles.alertesecours.fr/styles/basic-preview/style.json
APP_MAPVIEW_STYLE_URL=http://10.0.2.2:4203/app/style.json
# APP_MAPVIEW_STYLE_URL=https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json
# API KEY
WHAT3WORDS_API_KEY=
# GoogleServices
ANDROID_GOOGLE_SERVICES_FILE_PATH=/home/jo/.lab/alertesecours/google-services.json
ANDROID_GOOGLE_SERVICES_FILE_PATH=/home/jo/.lab/alertesecours/GoogleService-Info.plist

17
.envrc
View file

@ -1,15 +1,2 @@
export PATH=$PWD/bin:$PWD/scripts:$PATH # Automatically load the Devbox environment
export PROJECT_WORKINGDIR=$PWD eval "$(devbox generate direnv --print-envrc)"
# appli
export JAVA_HOME=${JAVA_HOME:-"/opt/android-studio/jbr"}
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
export NODE_OPTIONS"=--openssl-legacy-provider"
# dotenv
dotenv_if_exists .env.default
dotenv_if_exists .env.local

View file

@ -1,157 +1,111 @@
const path = require("path"); const path = require("path")
const fs = require("fs")
// see https://github.com/import-js/eslint-plugin-import/issues/1174
const packageDirs = ["libs", "services"]
const packageDir = []
for (const dir of packageDirs) {
for (const d of fs
.readdirSync(path.resolve(__dirname, dir))
.filter(
(entry) =>
entry.slice(0, 1) !== "." &&
fs.lstatSync(path.resolve(__dirname, dir, entry)).isDirectory()
)) {
const p = path.resolve(dir, d)
packageDir.push(p)
}
}
module.exports = { module.exports = {
root: true, ignorePatterns: ["**/build/*", "modjo", "**/as-back"],
env: { settings: {
"react-native/react-native": true, "import/resolver": {
jest: true, alias: true,
},
}, },
extends: [ extends: [
"airbnb-base",
"prettier",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"plugin:import/recommended", "plugin:import/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended",
], ],
parser: "@babel/eslint-parser", plugins: ["sql-pretty"],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2021,
sourceType: "module",
babelOptions: {
configFile: path.resolve(__dirname, "babel.config.js"),
},
},
plugins: [
"babel",
"sort-keys-fix",
"react",
"react-native",
"react-native-a11y",
"unused-imports",
"autoimport-declarative",
],
settings: {
react: {
version: "detect",
},
"import/ignore": ["react-native"],
"import/resolver": {
// Ensure ESLint can resolve regular JS packages under Yarn PnP as well.
// Without this, some deps (ex: expo-sqlite) may be incorrectly flagged
// by import/no-unresolved even though they're present.
node: {
extensions: [".js", ".jsx", ".ts", ".tsx", ".json"],
},
typescript: {},
},
},
ignorePatterns: ["build", "node_modules", "e2e", "**/*.bak.js"],
rules: { rules: {
"no-undef": [2], "no-undef": [2],
"react/forbid-prop-types": [0], "sql-pretty/format": [1, { tags: ["sql"] }],
"react/jsx-uses-react": 1, "no-shadow": [2, { allow: ["sql", "error"] }],
"react/jsx-uses-vars": 1, "node/no-extraneous-require": [0],
"react-hooks/exhaustive-deps": "error", "import/no-commonjs": [0],
"jsx-a11y/no-autofocus": 0, "import/no-dynamic-require": [0],
"import/no-extraneous-dependencies": [0],
// React-Native accessibility: start as warnings to enable gradual adoption "import/order": [
// without breaking the build; we will tighten to errors as we fix surfaces. "error",
"react-native-a11y/has-accessibility-hint": "error",
"react-native-a11y/has-valid-accessibility-descriptors": "error",
"import/no-named-as-default": 0,
"import/no-named-as-default-member": 0,
// 'unused-imports/no-unused-imports-ts': 1, # enable and run yarn lint --fix to autoremove all unused imports
"autoimport-declarative/autoimport": [
1,
{ {
packages: { groups: [
react: [ "builtin",
"useState", "external",
"useEffect", "internal",
"useContext", "parent",
"useReducer", "index",
"useCallback", "sibling",
"useMemo", "object",
"useRef", ],
"useImperativeHandle", pathGroups: [
"useLayoutEffect",
"useDebugValue",
"createRef",
"forwardRef",
{ {
name: "React", group: "internal",
isDefault: true, pattern: "~/**",
},
{
group: "internal",
pattern: "~**",
}, },
], ],
"react-native": [ pathGroupsExcludedImportTypes: [],
"useWindowDimensions",
"View",
"TouchableOpacity",
"TouchableHighlight",
"Image",
"StyleSheet",
],
"@react-navigation/native": [
"useNavigation",
"useFocusEffect",
"useIsFocused",
],
"@maplibre/maplibre-react-native": [
{
name: "Maplibre",
isDefault: true,
}, },
], ],
"@expo/vector-icons": [ "global-require": [0],
"MaterialCommunityIcons", "no-restricted-syntax": [0],
"MaterialIcons", "no-async-promise-executor": [0],
"Entypo", "no-nested-ternary": [0],
"FeatherMaterialIcons", "no-loop-func": [0],
], "no-new": [0],
"react-native-paper": ["ToggleButton", "Button", "FAB"], "func-names": [0],
"@apollo/client": ["useQuery", "useMutation", "useLazyQuery"], "no-plusplus": [0],
"react-hook-form": [ "no-param-reassign": [0],
"FormProvider", "no-continue": [0],
"Controller", "no-unused-vars": [
"useForm", 2,
"useFormContext",
"useFieldArray",
"useField",
],
moment: [
{ {
name: "moment", vars: "all",
isDefault: true, args: "after-used",
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
}, },
], ],
"hooks/useStreamQueryWithSubscription": [ "no-console": [0],
"no-throw-literal": [0],
"no-await-in-loop": [0],
"consistent-return": [0],
semi: ["error", "never"],
"prettier/prettier": [
"error",
{ {
name: "useStreamQueryWithSubscription", semi: false,
isDefault: true,
},
],
"~/theme": ["useTheme", "createStyles"],
"~/lib/toast-notifications": ["useToast"],
"~/lib/geo/humanizeDistance": [
{
name: "humanizeDistance",
isDefault: true,
},
],
"~/components/Text": [
{
name: "Text",
isDefault: true,
}, },
], ],
}, },
parserOptions: {
ecmaVersion: "latest",
sourceType: "script",
env: [
{
node: true,
}, },
], ],
}, },
globals: { globals: {
AbortController: true, AggregateError: true,
dbug: true,
}, },
}; }

View file

@ -0,0 +1,108 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
on:
workflow_dispatch:
push:
branches:
- "main"
paths:
- "**"
- "!app/**"
tags:
- "**"
jobs:
build:
outputs:
tags: ${{ steps.meta.outputs.tags }}
runs-on: ubuntu-latest
container:
image: devthefuture/act-runner:latest
volumes:
- /buildkit-certs:/buildkit-certs
strategy:
matrix:
build:
- name: hasura
dockerfile: ./services/hasura/Dockerfile
- name: api
dockerfile: ./services/api/Dockerfile
- name: files
dockerfile: ./services/files/Dockerfile
- name: tasks
dockerfile: ./services/tasks/Dockerfile
- name: watchers
dockerfile: ./services/watchers/Dockerfile
- name: web
dockerfile: ./services/web/Dockerfile
- name: app
dockerfile: ./services/app/Dockerfile
steps:
- name: ⏬ Checkout code repository
uses: actions/checkout@v4
with:
token: ${{ secrets.M8A_ORG_BOT_REPO_TOKEN }} # Required for private repositories to works consistently, avoiding random errors
- name: 📌 Extract metadata (tags, labels) for Docker
id: meta
uses: https://git.devthefuture.org/devthefuture/docker-metadata-action@v5
with:
images: git.devthefuture.org/${{ github.repository }}/${{ matrix.build.name }}
tags: |
type=semver,pattern={{version}},priority=900
type=semver,pattern=v{{version}},priority=900
type=sha,priority=890
type=ref,event=branch,priority=600
type=ref,event=pr,priority=600
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }},priority=200
- name: 📦 Build and push Docker image
uses: https://git.devthefuture.org/devthefuture/actions/buildkit@main
with:
context: ${{ matrix.build.context || '.' }}
dockerfile: ${{ matrix.build.dockerfile }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
registry: git.devthefuture.org
registry-username: "org-bot-${{ github.repository_owner }}"
registry-password: ${{ secrets.M8A_ORG_BOT_PACKAGE_TOKEN }}
deploy:
needs: [build]
runs-on: ubuntu-latest
container:
image: devthefuture/act-runner:latest@sha256:f326ce2f586d4f55757b87d3de7baf29715ef6cbc5af7bdf6313bcf7a90e7b3d
steps:
- name: 🎡 Check out the Helm chart repository
uses: actions/checkout@v4
with:
repository: "${{ github.repository_owner }}/appsets"
token: ${{ secrets.M8A_ORG_BOT_REPO_TOKEN }}
ref: "main"
- name: 🚀 Upgrade images tag
uses: https://git.devthefuture.org/devthefuture/actions/uptag@v0.2.3
with:
app: |
---
name: hasura
key: graphql-engine.image.tag
---
name: api
key: modjo-microservice.image.tag
---
name: files
key: modjo-microservice.image.tag
---
name: tasks
key: modjo-microservice.image.tag
---
name: watchers
key: modjo-microservice.image.tag
---
name: app
key: nginx.image.tag
---
env: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || 'staging' }}
meta-tags: ${{ needs.build.outputs.tags }}
commit: "true"
push: "true"

115
.gitignore vendored
View file

@ -1,66 +1,25 @@
# OSX node_modules
# .vscode/notes.txt
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# project.xcworkspace
ios/AlerteSecours.xcodeproj/project.xcworkspace/**
!ios/AlerteSecours.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
# bunlde sourcemaps
ios/*.map
ios/*.hbc
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/
*.keystore
!debug.keystore
# node.js
#
node_modules/
npm-debug.log
yarn-error.log yarn-error.log
*.logs
.DS_Store
.env.local
.env.yaml
.eslintcache
# Bundle artifacts .devbox/
*.jsbundle
# CocoaPods .archive
/ios/Pods/ /.osm-files
/osm-files
/tileserver-files
# Temporary files created by Metro to check the health of the file watcher googleServiceAccountKey.json
.metro-health-check*
services/*/build
services/*/dist
# Expo
.expo/
web-build/
dist/
# Yarn berry
.pnp.*
.yarn/* .yarn/*
!.yarn/patches !.yarn/patches
!.yarn/plugins !.yarn/plugins
@ -69,46 +28,6 @@ dist/
!.yarn/versions !.yarn/versions
# !.yarn/cache # !.yarn/cache
# secrets
/keys
/.env.local
/.env.prod
/.env.staging
## Build generated
build/
DerivedData
/**/*.xcarchive/**
# aidigest
codebase.md codebase.md
# Build logs /bin
logs/
# Sensitive configuration files
ios/GoogleService-Info.plist
ios/AlerteSecours/GoogleService-Info.plist
ios/AlerteSecours/Supporting/Expo.plist
android/app/google-services.json
# Keep example files
!ios/GoogleService-Info.example.plist
!ios/AlerteSecours/GoogleService-Info.example.plist
!ios/AlerteSecours/Supporting/Expo.example.plist
!android/app/google-services.example.json
screenshot-*.png
/.data
# Geodae preprocessing
scripts/dae/node_modules/
scripts/dae/.yarn/*
!scripts/dae/.yarn/patches
!scripts/dae/.yarn/plugins
!scripts/dae/.yarn/releases
!scripts/dae/.yarn/sdks
!scripts/dae/.yarn/versions
src/assets/db/*.db

7
.husky/commit-msg Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
. "$(dirname $0)/_/husky.sh"
export PATH=$PATH:$HOME/.yarn/bin
yarn commitlint --edit $1

6
.husky/pre-commit Executable file
View file

@ -0,0 +1,6 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
export PATH=$PATH:$HOME/.yarn/bin
yarn lint-staged

9
.tiltignore Normal file
View file

@ -0,0 +1,9 @@
**/node_modules/**
**/.git/**
**/.cache/**
**/.dev-secrets/**
**/android/**
**/ios/**
**/*.log
osm-files/**
tileserver-files/**

68
.versionrc.json Normal file
View file

@ -0,0 +1,68 @@
{
"bumpFiles": [
{
"filename": "package.json",
"type": "json"
},
{
"filename": "alerte-secours/package.json",
"type": "json"
},
{
"filename": "services/api/package.json",
"type": "json"
},
{
"filename": "services/tasks/package.json",
"type": "json"
},
{
"filename": "services/watchers/package.json",
"type": "json"
},
{
"filename": "services/web/package.json",
"type": "json"
},
{
"filename": "services/hasura/version.json",
"type": "json"
}
],
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Bug Fixes"
},
{
"type": "chore",
"hidden": true
},
{
"type": "docs",
"hidden": true
},
{
"type": "style",
"hidden": true
},
{
"type": "refactor",
"hidden": true
},
{
"type": "perf",
"hidden": true
},
{
"type": "test",
"hidden": true
}
],
"commitUrlFormat": "https://github.com/mokkapps/changelog-generator-demo/commits/{{hash}}",
"compareUrlFormat": "https://github.com/mokkapps/changelog-generator-demo/compare/{{previousTag}}...{{currentTag}}"
}

5
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"recommendations": [
"dbaeumer.vscode-eslint"
]
}

27
.vscode/settings.json vendored
View file

@ -1,6 +1,25 @@
{ {
"i18n-ally.localesPaths": [ "path-autocomplete.pathMappings": {
"src/i18n", "~": "${folder}/src"
"src/i18n/locales" },
] "editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript"
],
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"eslint.workingDirectories": [{ "mode": "auto" }],
"files.associations": {
".env.{default,local}": "dotenv",
"package.json.*": "json"
},
"javascript.suggest.autoImports": true,
"typescript.suggest.autoImports": true,
"editor.suggestSelection": "first",
"vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
"editor.inlineSuggest.enabled": true
} }

View file

@ -3,14 +3,17 @@
module.exports = { module.exports = {
name: "@yarnpkg/plugin-fetch", name: "@yarnpkg/plugin-fetch",
factory: function (require) { factory: function (require) {
var plugin=(()=>{var M=Object.defineProperty;var R=(n,t,e)=>t in n?M(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var o=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+n+'" is not supported')});var f=(n,t)=>()=>(t||n((t={exports:{}}).exports,t),t.exports);var g=(n,t,e)=>(R(n,typeof t!="symbol"?t+"":t,e),e);var P=f((ce,F)=>{"use strict";F.exports=function(t){return t.map(function(e){return e&&typeof e=="object"?e.op.replace(/(.)/g,"\\$1"):/["\s]/.test(e)&&!/'/.test(e)?"'"+e.replace(/(['\\])/g,"\\$1")+"'":/["'\s]/.test(e)?'"'+e.replace(/(["\\$`!])/g,"\\$1")+'"':String(e).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g,"$1\\$2")}).join(" ")}});var E=f((oe,J)=>{var j=o("fs"),z=o("path"),{parseSyml:G}=o("@yarnpkg/parsers");J.exports=function(){let t=j.readFileSync("yarn.lock","utf8"),e=G(t),d=Object.keys(e).filter(i=>i.includes("@workspace:")),s=d.map(i=>{let[,p]=e[i].resolution.trim().split("@workspace:");return p==="."?null:p}).filter(Boolean);d.forEach(i=>{let{dependencies:p,dependenciesMeta:r,peerDependencies:q,peerDependenciesMeta:w,resolution:C,bin:Y}=e[i],[B,b]=C.trim().split("@workspace:"),H=z.join(b,"package.json"),h={name:B,version:"0.0.0",description:"**DON'T COMMIT** Generated file for caching",private:!0,dependencies:p,peerDependencies:q,peerDependenciesMeta:w,bin:Y};if(r){let m={};Object.keys(r).forEach(k=>{m[k]=p[k],delete p[k]}),h.optionalDependencies=m}if(b==="."){s.length>0&&(h.workspaces={packages:s});let m=Object.keys(e),k=c=>{let a=c.trim().split("@");return c.startsWith("@")?a=a.slice(0,2):a=a.slice(0,1),a.join("@")};h.resolutions=m.filter(c=>{if(c.includes("@workspace:")||c.includes(", ")||!c.includes("@npm:"))return!1;let a=k(c);return m.every(y=>c===y?!0:y.split(",").map(l=>k(l)).every(l=>l!==a))}).reduce((c,a)=>{let[y,l]=a.trim().split("@npm:");return c[y]=l.includes("@")?`npm:${l}`:l,c},{})}j.mkdirSync(b,{recursive:!0}),j.writeFileSync(H,`${JSON.stringify(h,null,2)} var plugin=(()=>{var le=Object.defineProperty;var pe=(s,e,t)=>e in s?le(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var c=(s=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(s,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):s)(function(s){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+s+'" is not supported')});var i=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports);var f=(s,e,t)=>(pe(s,typeof e!="symbol"?e+"":e,t),t);var $=i((Ue,A)=>{"use strict";A.exports=function(e){return e.map(function(t){return t&&typeof t=="object"?t.op.replace(/(.)/g,"\\$1"):/["\s]/.test(t)&&!/'/.test(t)?"'"+t.replace(/(['\\])/g,"\\$1")+"'":/["'\s]/.test(t)?'"'+t.replace(/(["\\$`!])/g,"\\$1")+'"':String(t).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g,"$1\\$2")}).join(" ")}});var H=i((Ve,v)=>{var C=c("fs"),ue=c("path"),{parseSyml:fe}=c("@yarnpkg/parsers"),ke=["patch","npm","portal","link"],B=s=>{let e=s.trim().split("@");return s.startsWith("@")?e=e.slice(0,2):e=e.slice(0,1),e.join("@")},Y=(s,e)=>{let[t,r]=s.trim().split(`@${e}:`);return{key:t,version:r}},de=s=>{let[,e]=s.split("::")[0].split("#");return e};v.exports=function(){let e=C.readFileSync("yarn.lock","utf8"),t=fe(e),r=Object.keys(t).filter(o=>o.includes("@workspace:")),n=r.map(o=>{let[,l]=t[o].resolution.trim().split("@workspace:");return l==="."?null:l}).filter(Boolean);r.forEach(o=>{let{dependencies:l,dependenciesMeta:u,peerDependencies:b,peerDependenciesMeta:P,resolution:D,bin:ce}=t[o],[ae,w]=D.trim().split("@workspace:"),ie=ue.join(w,"package.json"),y={name:ae,version:"0.0.0",description:"**DON'T COMMIT** Generated file for caching",private:!0,dependencies:l,peerDependencies:b,peerDependenciesMeta:P,bin:ce};if(u){let m={};Object.keys(u).forEach(d=>{m[d]=l[d],delete l[d]}),y.optionalDependencies=m}if(w==="."){n.length>0&&(y.workspaces={packages:n});let m=Object.keys(t),d=new Map;m.forEach(p=>{p.split(",").forEach(k=>{if(k.includes("builtin<compat/"))return;let a=B(k);d.has(a)||d.set(a,[]),d.get(a).push(k)})}),y.resolutions=m.filter(p=>{var a;if(p.includes("@workspace:"))return!1;if(p.includes("@patch:"))return!((a=de(Y(p,"patch").version).match(/(\.\.\/)+/))!=null&&a.length);if(p.includes(", "))return!1;let k=B(p);return d.get(k).length===1}).reduce((p,k)=>(ke.forEach(a=>{if(!k.includes(`@${a}:`))return;let{key:x,version:g}=Y(k,a);switch(a){case"npm":p[x]=g.includes("@")?`${a}:${g}`:g;break;case"patch":k.includes("builtin<compat/")||(p[x]=`${a}:${g.split("::")[0]}`);break;case"portal":case"link":p[x]=`${a}:${g.split("::")[0]}`;break}}),p),{})}C.mkdirSync(w,{recursive:!0}),C.writeFileSync(ie,`${JSON.stringify(y,null,2)}
`)})}});var S=f((ae,T)=>{var I=E();T.exports=n=>{n.context.stdout.write(`[YARN-FETCH] extracting package.json file(s) from yarn.lock `)})}});var j=i((Ze,R)=>{var he=H();R.exports=s=>{s.context.stdout.write(`[YARN-FETCH] extracting package.json file(s) from yarn.lock
`),I()}});var O=f((pe,N)=>{var u=o("fs"),K=o("path"),{execSync:U}=o("child_process"),{parseSyml:W}=o("@yarnpkg/parsers"),{BaseCommand:Z}=o("@yarnpkg/cli"),{Command:Q,Option:D}=o("clipanion"),V=P(),X=S(),x;N.exports=(x=class extends Z{protectPackageJson=D.Boolean("--protect-package-json");args=D.Proxy();async execute(){let{protectPackageJson:t=process.stdout.isTTY}=this,e=[];if(t){this.context.stdout.write(`[YARN-FETCH] backup possible package.json file(s) `),he()}});var K=i((Xe,L)=>{var h=c("fs"),me=c("path"),{execSync:ge}=c("child_process"),{parseSyml:ye}=c("@yarnpkg/parsers"),{BaseCommand:xe}=c("@yarnpkg/cli"),{Command:qe,Option:M}=c("clipanion"),be=$(),Pe=j(),q;L.exports=(q=class extends xe{protectPackageJson=M.Boolean("--protect-package-json");args=M.Proxy();async execute(){let{protectPackageJson:e=process.stdout.isTTY}=this,t=[];if(e){this.context.stdout.write(`[YARN-FETCH] backup possible package.json file(s)
`);let s=u.readFileSync("yarn.lock","utf8"),i=W(s);e=Object.keys(i).filter(r=>r.includes("@workspace:")).map(r=>{let{resolution:q}=i[r],[,w]=q.trim().split("@workspace:");return K.join(w,"package.json")}),e.forEach(r=>{u.existsSync(r)&&!u.existsSync(`${r}.yarn-plugin-fetch-bak`)&&u.copyFileSync(r,`${r}.yarn-plugin-fetch-bak`)})}X(this);let d=`yarn ${V(this.args)}`;this.context.stdout.write(`[YARN-FETCH] ${d} `);let n=h.readFileSync("yarn.lock","utf8"),o=ye(n);t=Object.keys(o).filter(u=>u.includes("@workspace:")).map(u=>{let{resolution:b}=o[u],[,P]=b.trim().split("@workspace:");return me.join(P,"package.json")}),t.forEach(u=>{h.existsSync(u)&&!h.existsSync(`${u}.yarn-plugin-fetch-bak`)&&h.copyFileSync(u,`${u}.yarn-plugin-fetch-bak`)})}Pe(this);let r=`yarn ${be(this.args)}`;this.context.stdout.write(`[YARN-FETCH] ${r}
`);try{U(d,{stdio:"inherit"})}catch(s){throw s}finally{t&&(this.context.stdout.write(`[YARN-FETCH] restoring possible package.json file(s) `);try{ge(r,{stdio:"inherit"})}catch(n){throw n}finally{e&&(this.context.stdout.write(`[YARN-FETCH] restoring possible package.json file(s)
`),e.forEach(s=>{u.existsSync(`${s}.yarn-plugin-fetch-bak`)?u.renameSync(`${s}.yarn-plugin-fetch-bak`,s):u.unlinkSync(s)}))}}},g(x,"paths",[["fetch"]]),g(x,"usage",Q.Usage({description:"fetch dependencies from yarn.lock in Docker build",details:` `),t.forEach(n=>{h.existsSync(`${n}.yarn-plugin-fetch-bak`)?h.renameSync(`${n}.yarn-plugin-fetch-bak`,n):h.unlinkSync(n)}))}}},f(q,"paths",[["fetch"]]),f(q,"usage",qe.Usage({description:"fetch dependencies from yarn.lock in Docker build",details:`
expand yarn.lock to package.json file(s) and install dependencies in Docker build. expand yarn.lock to package.json file(s) and install dependencies in Docker build.
`,examples:[["yarn fetch --immutable","yarn fetch workspace my-package focus"]]})),x)});var A=f((ke,v)=>{var{BaseCommand:_}=o("@yarnpkg/cli"),ee=S(),$;v.exports=($=class extends _{async execute(){ee(this)}},g($,"paths",[["expand-lock"]]),$)});var se=f((de,L)=>{var te=O(),ne=A();L.exports={commands:[te,ne]}});return se();})(); `,examples:[["yarn fetch --immutable","yarn fetch workspace my-package focus"]]})),q)});var W=i((st,I)=>{var{BaseCommand:we}=c("@yarnpkg/cli"),$e=j(),S;I.exports=(S=class extends we{async execute(){$e(this)}},f(S,"paths",[["fetch-tools","expand-lock"]]),S)});var z=i((rt,_)=>{function Ce(s,e,t){let r=e.split("."),n=s;for(let o of r){if(n[o]===void 0)return t;n=n[o]}return n}function je(s,e,t){let r=e.split("."),n=s;for(let o=0;o<r.length-1;o++){let l=r[o];(!n[l]||typeof n[l]!="object")&&(n[l]={}),n=n[l]}return n[r[r.length-1]]=t,s}function Se(s,e){let t=e.split("."),r=s;for(let n=0;n<t.length-1;n++){let o=t[n];if(!r[o])return!1;r=r[o]}return delete r[t[t.length-1]],!0}_.exports={get:Ce,set:je,unset:Se}});var E=i((ot,U)=>{var G=c("fs"),{get:Ee,set:Fe,unset:Je}=z();U.exports=function(e,t){let r=JSON.parse(G.readFileSync("package.json","utf-8")),n=Ee(r,e);n!==void 0&&(Fe(r,t,n),Je(r,e),G.writeFileSync("package.json",JSON.stringify(r,null,2)))}});var F=i((ct,V)=>{var Ne=E();V.exports=function(){Ne("scripts._postinstall","scripts.postinstall")}});var Q=i((it,Z)=>{var{BaseCommand:Te}=c("@yarnpkg/cli"),Oe=F(),J;Z.exports=(J=class extends Te{async execute(){Oe()}},f(J,"paths",[["fetch-tools","disable-postinstall"]]),J)});var N=i((pt,X)=>{var De=E();X.exports=function(){De("scripts.postinstall","scripts._postinstall")}});var te=i((ft,ee)=>{var{BaseCommand:Ae}=c("@yarnpkg/cli"),Be=N(),T;ee.exports=(T=class extends Ae{async execute(){Be()}},f(T,"paths",[["fetch-tools","disable-postinstall"]]),T)});var re=i((ht,ne)=>{var{execSync:Ye}=c("child_process"),{BaseCommand:ve}=c("@yarnpkg/cli"),{Option:se}=c("clipanion"),He=$(),Re=F(),Me=N(),O;ne.exports=(O=class extends ve{postinstall=se.Boolean("--postinstall");args=se.Proxy();async execute(){this.postinstall||(this.context.stdout.write(`[YARN-FETCH] disable postinstall command in package.json
`),Me());let e=`yarn workspaces focus --production ${He(this.args)}`;this.context.stdout.write(`[YARN-FETCH] ${e}
`),Ye(e,{stdio:"inherit"}),this.postinstall||(this.context.stdout.write(`[YARN-FETCH] re-enable postinstall command in package.json
`),Re())}},f(O,"paths",[["fetch-tools","production"]]),O)});var ze=i((gt,oe)=>{var Le=K(),Ke=W(),Ie=Q(),We=te(),_e=re();oe.exports={commands:[Le,Ke,We,Ie,_e]}});return ze();})();
return plugin; return plugin;
} }
}; };

942
.yarn/releases/yarn-4.10.3.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,8 @@ enableGlobalCache: false
nodeLinker: node-modules nodeLinker: node-modules
plugins: plugins:
- path: .yarn/plugins/@yarnpkg/plugin-fetch.cjs - checksum: 240d225dd5bf1e25068497140ced7a3b7658a4c3754c08ea57162c9fe3335d757af0eae55555f96150a3015cdd0337852401f3fae69c1edd05221cb32f038d8c
spec: "https://raw.githubusercontent.com/devthejo/yarn-plugin-fetch/master/bundles/@yarnpkg/plugin-fetch.js" path: .yarn/plugins/@yarnpkg/plugin-fetch.cjs
spec: "https://codeberg.org/devthefuture/yarn-plugin-fetch/raw/branch/master/bundles/@yarnpkg/plugin-fetch.js"
yarnPath: .yarn/releases/yarn-4.5.3.cjs yarnPath: .yarn/releases/yarn-4.10.3.cjs

View file

@ -1,266 +1,191 @@
# Alerte Secours Mobile App - Developer Documentation # Alerte-Secours Services - Developer Documentation
This document contains technical information for developers working on the Alerte Secours mobile application. This document contains technical information for developers working on the Alerte-Secours microservices backend.
## Table of Contents
- [Project Overview](#project-overview)
- [Technical Stack](#technical-stack)
- [Development Quick Start](#development-quick-start)
- [Installation](#installation)
- [Android](#android)
- [iOS](#ios)
- [Project Structure](#project-structure)
- [Accessibility](#accessibility)
- [Troubleshooting](#troubleshooting)
## Project Overview
Alerte Secours is a mobile application built with React Native that handles alerts and emergency-related functionality. The app supports both iOS and Android platforms and includes features such as:
- Alert creation and management with real-time updates
- Location-based features with mapping integration
- Chat/Messaging system with alert-specific chat rooms
- Authentication via SMS verification
- Deep linking for alert sharing
- Push notifications
## Technical Stack
- React Native
- Expo framework
- GraphQL with Hasura
- Apollo Client for frontend
- Federated remote schemas
- Real-time subscriptions support
- Firebase Cloud Messaging (FCM) for push notifications only
- Sentry for error tracking
- MapLibre for mapping functionality
- Zustand for state management
- i18next for internationalization
- React Navigation for navigation
- Expo Updates for OTA updates
- Background Geolocation for location tracking
- Lottie for animations
- React Hook Form for form handling
- Axios for HTTP requests
- Yarn Berry as package manager
- ESLint and Prettier for code quality
- Fastlane for deployment automation
## Development Quick Start ## Development Quick Start
### Prerequisites ### Requirements
- Node.js (version specified in `.node-version`) - Docker
- Yarn package manager - Devbox
- Android Studio (for Android development) - Android SDK (for mobile development)
- Xcode (for iOS development) - Java 8+ (for Android development)
- Physical device or emulator/simulator
### Environment Setup ### Installation
1. Clone the repository 1. Clone the repository:
2. Install dependencies: ```sh
```bash git clone https://codeberg.org/alerte-secours/alerte-secours
yarn cd alerte-secours
```
3. Copy the staging environment file:
```bash
cp .env.staging.example .env.staging
```
4. Start the development server with staging environment:
```bash
yarn start:staging
```
### Running on Devices
#### Android
```bash
yarn android:staging
``` ```
#### iOS 2. Install devbox if not already installed:
```bash ```sh
yarn ios:staging curl -fsSL https://get.jetpack.io/devbox | bash
``` ```
### Staging URLs 3. Enter devbox shell (this will automatically install Node.js 20 and Yarn 4.6.0):
```sh
The staging environment uses the following URLs: devbox shell
- GraphQL API: `https://hasura-staging.alertesecours.fr/v1/graphql`
- WebSocket: `wss://hasura-staging.alertesecours.fr/v1/graphql`
- Files API: `https://files-staging.alertesecours.fr/api/v1/oas`
- Minio: `https://minio-staging.alertesecours.fr`
- Geolocation Sync: `https://api-staging.alertesecours.fr/api/v1/oas/geoloc/sync`
## Installation
### Android
#### Using the Yarn Script
The easiest way to install the app is to use the provided yarn script:
```bash
# Set the device ID (emulator or physical device)
export DEVICE=emulator-5554
# Run the installation script
yarn install:android
``` ```
This script (`install-android.sh`) handles the entire installation process, including building APKs with signing, extracting them, and installing on the device. 4. Install dependencies:
```sh
yarn
```
#### Manual Installation 5. Set up environment variables:
```sh
cp .env.default .env
```
If you need to install the app manually, you can examine the `install-android.sh` script in the project root to see the detailed steps involved. ### Start Services
### iOS Start all services with Tilt:
```sh
yarn dev
# or
devbox run dev
# or run a subset of services:
tilt up api files hasura
```
#### Authentication Key Setup View logs in Tilt UI (web HUD opens automatically). CLI alternative:
```sh
yarn dev:logs
# or
tilt logs
```
1. Go to https://appstoreconnect.apple.com/access/integrations/api Stop services:
2. Click the "+" button to generate a new API key ```sh
3. Give it a name (e.g., "AlerteSecours Build Key") # If running in the foreground terminal:
4. Download the .p8 file when prompted Ctrl-C
5. Store the .p8 file in a secure location # Or explicitly:
6. Note down the Key ID and Issuer ID shown on the website tilt down
7. Set up environment variables: ```
```sh
export ASC_API_KEY_ID="YOUR_KEY_ID"
export ASC_API_ISSUER_ID="YOUR_ISSUER_ID"
export ASC_API_KEY_PATH="/path/to/your/AuthKey.p8"
```
#### Building and Running Compose fallback (legacy):
```sh
yarn compose:up
yarn compose:down
# or via devbox:
devbox run compose:up
devbox run compose:down
```
To build and run the iOS app: ### Using Devbox
```bash Once you're in the devbox shell, you have access to:
# Run in development mode with staging environment - Node.js 20 (automatically installed)
yarn ios:staging - Yarn 4.6.0 (automatically installed)
- All project scripts and environment variables
- PostgreSQL client tools
# Build for production (version + clean + archive + export) To exit the devbox shell:
yarn bundle:ios:build ```sh
exit
```
# Upload the last build to App Store Connect To run commands from outside the shell:
yarn bundle:ios:upload ```sh
devbox run <command>
```
# Build + upload Available devbox scripts:
yarn bundle:ios:release - `devbox run dev` - Start development environment
``` - `devbox run dev:up` - Start all services
- `devbox run dev:logs` - View development logs
- `devbox run console` - Open development console
Notes on versioning: ### Public Staging Environment
- `yarn bundle:ios:build` updates iOS `CFBundleShortVersionString` and `CFBundleVersion` to a timestamp in `Europe/Paris` timezone (format `YYYYMMDDHHMM`) before archiving/exporting.
- `yarn bundle:ios` is an alias of `yarn bundle:ios:build`.
The `bundle:ios` command uses the scripts in the `scripts` directory: For development and testing, you can use our public staging environment:
- `ios-archive.sh` - Archives the iOS app
- `ios-export.sh` - Exports the archived app - API: https://api-staging.alerte-secours.fr
- `ios-upload.sh` - Uploads the app to App Store Connect (used by `bundle:ios:upload`) - GraphQL: https://graphql-staging.alerte-secours.fr
- Web Interface: https://web-staging.alerte-secours.fr
### Endpoints (Local Development)
#### Services
- API: http://localhost:4200
- Files: http://localhost:4292
- Hasura: http://localhost:4201
- Tasks Service
- Watchers Service
- Web: http://localhost:4203
#### Consoles
- [Hasura Console](http://localhost:4295)
- [Minio Console](http://localhost:4291)
- [API Swagger](http://localhost:4200/api/v1/swagger/)
- [API GraphQL](http://localhost:4200/api/v1/graphql)
- [Files API](http://localhost:4292/api/v1/swagger/)
#### API URLs
- `/api/v1`
- `/spec` - API Specification
- `/oas` - OpenAPI Service
- `/swagger` - Swagger Documentation
- `/graphql` - GraphQL Endpoint
- `/status` - Service Status
- `/` - Root Endpoint
## Technical Stack
### Backend
- **Node.js** (>=20) - Core runtime
- **PostgreSQL** - Primary database
- **Redis** - Caching and queue deduplication
- **RabbitMQ** - Message queue
- **Hasura** - GraphQL engine
- **OpenAPI** - API specification and documentation
- **Modjo Framework** - Microservices architecture
### Frontend
- **React** - Web interface
- **React Native** - Mobile application
- **Apollo Client** - GraphQL integration
- **MapView** - Geolocation visualization
### Infrastructure
- **Docker** - Containerization
- **Microservices Architecture** - Separate services for API, files, tasks, etc.
- **CQRS Pattern** - Command Query Responsibility Segregation
- **Event-Driven Architecture** - Using message queues
### Key Features
- Real-time alerts and notifications
- Geolocation tracking and mapping
- Emergency services integration
- User authentication and authorization
- File storage and management
- Background task processing
## Project Structure ## Project Structure
- `/android` - Android-specific code and configuration ```
- `/ios` - iOS-specific code and configuration services/
- `/src` - Main application source code ├── api/ # Main API service
- `/app` - App initialization and configuration ├── app/ # Frontend application
- `/assets` - Static assets (images, fonts, animations) ├── files/ # File handling service
- `/auth` - Authentication-related code ├── hasura/ # GraphQL engine
- `/biz` - Business logic and constants ├── tasks/ # Background task processing
- `/components` - Reusable UI components ├── watchers/ # Event monitoring
- `/containers` - Container components └── web/ # Web interface
- `/data` - Data management
- `/events` - Event handling libs/
- `/finders` - Search and finder utilities ├── common/ # Shared utilities
- `/gql` - GraphQL queries and mutations ├── postgres-types/ # Database type definitions
- `/hoc` - Higher-order components ├── redis-queue-dedup/ # Redis queue deduplication
- `/hooks` - Custom React hooks └── utils/ # General utilities
- `/i18n` - Internationalization ```
- `/layout` - Layout components
- `/lib` - Library code
- `/location` - Location-related functionality
- `/misc` - Miscellaneous utilities
- `/navigation` - Navigation configuration
- `/network` - Network-related code
- `/notifications` - Notification handling
- `/permissions` - Permission handling
- `/scenes` - Scene components
- `/screens` - Screen components
- `/sentry` - Sentry error tracking configuration
- `/stores` - State management stores
- `/theme` - Styling and theming
- `/updates` - Update handling
- `/utils` - Utility functions
- `/docs` - Documentation files
- `/scripts` - Utility scripts for building, deployment, and development
- `/e2e` - End-to-end tests
## Contributing ## Contributing
Guidelines for contributing to the project: We welcome contributions to Alerte-Secours. Please read our contribution guidelines before submitting pull requests.
1. Follow the code style and conventions used in the project ## Support
2. Write tests for new features
3. Update documentation as needed
4. Use the ESLint and Prettier configurations
## Accessibility For technical support, please open an issue on our [Codeberg issue tracker](https://codeberg.org/alerte-secours/alerte-secours/-/issues) or [GitHub issue tracker](https://github.com/alerte-secours/alerte-secours/issues).
This app has an accessibility baseline (WCAG 2.2 AA, VoiceOver/TalkBack) and app-specific conventions.
### Docs
- Baseline checklist: [`docs/a11y-wcag22-aa.md`](docs/a11y-wcag22-aa.md:1)
- Code conventions + helpers: [`docs/a11y-usage.md`](docs/a11y-usage.md:1)
- Color contrast guidance: [`docs/a11y-color-contrast.md`](docs/a11y-color-contrast.md:1)
- `testID` conventions: [`docs/testids.md`](docs/testids.md:1)
- QA runbook (iOS VoiceOver): [`docs/qa-voiceover.md`](docs/qa-voiceover.md:1)
- QA runbook (Android TalkBack): [`docs/qa-talkback.md`](docs/qa-talkback.md:1)
### PR checklist (required for any UI change)
- [ ] **Roles / labels / hints / states**: all interactive controls expose correct `accessibilityRole`, meaningful `accessibilityLabel`, helpful `accessibilityHint` (especially icon-only actions), and state where applicable.
- [ ] **Focus management**: any modal/dialog/sheet sets initial focus on open, returns focus on close, and avoids focus traps.
- [ ] **Touch target size**: critical tap targets are comfortably tappable (aim ~44x44pt minimum).
- [ ] **Color contrast**: text + icons meet WCAG AA contrast; do not rely on color alone for meaning.
- [ ] **`testID`s for critical controls**: stable `testID` added/updated for key actions and navigation chrome (per [`docs/testids.md`](docs/testids.md:1)).
- [ ] **Tests**: add/update tests covering the new UI behavior (and its states). Prefer assertions that dont depend on translated text; include E2E coverage for critical flows when applicable.
### Manual validation (screen readers)
When a PR changes UI or navigation, do a quick pass with the platform screen reader:
- iOS: follow [`docs/qa-voiceover.md`](docs/qa-voiceover.md:1) and validate labels/hints, navigation order, and activation behavior on the affected screens.
- Android: follow [`docs/qa-talkback.md`](docs/qa-talkback.md:1) with the same focus on discoverability, focus order, and activation.
## Troubleshooting
### Common Issues
#### Development Environment
- **Clearing Yarn Cache**: Use `yarn clean` (removes node_modules and reinstalls dependencies)
- **Cleaning Gradle**: Run `cd android && ./gradlew clean`
- **Clearing Gradle Cache**: Remove gradle caches with `rm -rf ~/.gradle/caches/ android/.gradle/`
- **Stopping Gradle Daemons**: Run `cd android && ./gradlew --stop`
- **Clearing ADB Cache**: Run `adb shell pm clear com.alertesecours`
- **Rebuilding Gradle**: Use `yarn expo run:android`
- **Rebuilding Expo React Native**: Use `yarn expo prebuild`
- **Clearing Metro Cache**: Use `yarn expo start --dev-client --clear`
#### Screenshots and Testing
- For Android screenshots: Use `scripts/screenshot-android.sh`
- For iOS screenshots: Use `scripts/screenshot-ios.sh`
- For Android emulator: Use `scripts/android-emulator`
#### Emulator Issues
- Clear cache / uninstall the app
- Check emulator datetime
- Check network connectivity
For more troubleshooting tips, see the documentation in the `/docs` directory.

View file

@ -1,57 +1,38 @@
# Alerte Secours - Le Réflexe qui Sauve # Alerte-Secours - Le Réflexe qui Sauve
[![Liberapay](https://img.shields.io/liberapay/receives/alerte-secours.svg?logo=liberapay)](https://liberapay.com/alerte-secours) [![Liberapay](https://img.shields.io/liberapay/receives/alerte-secours.svg?logo=liberapay)](https://liberapay.com/alerte-secours)
[![Buy Me a Coffee](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?logo=buy-me-a-coffee)](https://buymeacoffee.com/alertesecours) [![Buy Me a Coffee](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?logo=buy-me-a-coffee)](https://buymeacoffee.com/alertesecours)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/alerte-secours?style=social)](https://github.com/sponsors/alerte-secours) [![GitHub Sponsors](https://img.shields.io/github/sponsors/alerte-secours?style=social)](https://github.com/sponsors/alerte-secours)
Une application mobile pour la gestion des alertes et des fonctionnalités liées aux urgences, supportant les plateformes iOS et Android. Alerte-Secours est un système d'alerte et de réponse d'urgence basé sur une architecture de microservices, conçu pour fournir une assistance rapide en situation d'urgence.
**Site Web Officiel :** [alerte-secours.fr](https://alerte-secours.fr) ## Site Web Officiel
## Aperçu du Projet Visitez notre site web officiel sur [alerte-secours.fr](https://alerte-secours.fr)
Alerte Secours est une application mobile construite avec React Native qui gère les alertes et les fonctionnalités liées aux urgences. L'application supporte les plateformes iOS et Android et inclut des fonctionnalités telles que :
- Création et gestion d'alertes avec mises à jour en temps réel
- Fonctionnalités basées sur la localisation avec intégration cartographique
- Système de chat/messagerie avec salles de discussion spécifiques aux alertes
- Authentification via vérification SMS
- Liens profonds pour le partage d'alertes
- Notifications push
## Documentation Développeur ## Documentation Développeur
Pour les développeurs souhaitant contribuer au projet ou déployer l'application, consultez la [documentation technique complète](DEVELOPER.md) qui contient : Pour les développeurs souhaitant contribuer au projet ou déployer les services, consultez la [documentation technique complète](DEVELOPER.md) qui contient :
- Aperçu du projet et fonctionnalités
- Stack technique détaillé
- Guide de démarrage rapide - Guide de démarrage rapide
- Instructions d'installation (Android/iOS) - Stack technique détaillé
- Instructions d'installation
- Documentation des API
- Structure du projet - Structure du projet
- Guide de dépannage - Endpoints de développement
- Instructions de build et déploiement
## Licence ## Licence
Alerte Secours est sous licence **DevTheFuture Ethical Use License (DEF License)**. Points clés : Alerte-Secours est sous licence **DevTheFuture Ethical Use License (DEF License)**.
### Usage à but non lucratif Points clés :
- Licence perpétuelle, libre de redevances et non exclusive pour usage à but non lucratif - **Usage à but non lucratif** : Gratuit pour les usages à but non lucratif
- Permet l'utilisation, la modification et la distribution à des fins non lucratives - **Usage commercial** : Nécessite une licence payante
- **Données personnelles** : Ne doivent pas être monétisées ou exploitées
- **Propriété** : Tous les droits de propriété intellectuelle restent au concédant
- **Restriction concurrentielle** : Les concurrents doivent obtenir une autorisation explicite
### Usage commercial Pour les détails complets de la licence, voir [LICENSE.md](LICENSE.md).
- Nécessite l'obtention d'une licence payante
- Conditions déterminées par le Concédant (DevTheFuture.org)
### Restrictions sur les données personnelles
- Ne doit pas être utilisé pour monétiser, vendre ou exploiter les données personnelles
- Les données personnelles ne peuvent pas être utilisées pour le marketing, la publicité ou l'influence politique
- L'agrégation de données n'est autorisée que si c'est une fonctionnalité explicite divulguée aux utilisateurs
### Restriction concurrentielle
- Les concurrents sont interdits d'utiliser le logiciel sans consentement explicite
Pour le texte complet de la licence, voir [LICENSE.md](LICENSE.md).
## 💙 Soutenir le projet ## 💙 Soutenir le projet
@ -70,13 +51,8 @@ Si vous souhaitez contribuer à son développement, sa maintenance et son indép
## Contribuer ## Contribuer
Directives pour contribuer au projet : Nous accueillons les contributions à Alerte-Secours. Veuillez lire nos directives de contribution avant de soumettre des pull requests.
1. Suivez le style de code et les conventions utilisées dans le projet
2. Écrivez des tests pour les nouvelles fonctionnalités
3. Mettez à jour la documentation si nécessaire
4. Utilisez les configurations ESLint et Prettier
## Support ## Support
Pour obtenir de l'aide, veuillez ouvrir un ticket sur notre tracker d'issues ou consulter la documentation dans le répertoire `/docs`. Pour obtenir de l'aide, veuillez ouvrir un ticket sur notre [tracker d'issues Codeberg](https://codeberg.org/alerte-secours/alerte-secours/-/issues) ou [tracker d'issues GitHub](https://github.com/alerte-secours/alerte-secours/issues).

38
Tiltfile Normal file
View file

@ -0,0 +1,38 @@
# Tiltfile for as-services
# Orchestrates docker-compose services with Tilt, providing a unified UI/logs and incremental workflows.
# Watch ignores are configured via .tiltignore
# Ensure .env exists so docker-compose gets expected env
local_resource(
name="ensure-env",
cmd="bash -lc 'if [ ! -f .env ] && [ -f .env.default ]; then cp .env.default .env && echo Created .env from .env.default; fi'",
allow_parallel=True,
auto_init=True,
)
# Optional: pre-pull builder image used in Dockerfiles
local_resource(
name="pull-builder",
cmd="docker pull devthefuture/dockerfile-x",
allow_parallel=True,
auto_init=True,
)
# Drive docker-compose with Tilt
dc = docker_compose('./docker-compose.yaml')
# Compose services are registered via docker_compose; explicit resource dependencies
# removed for compatibility with Tilt v0.35 (resource_deps not available).
# Optional groups for readability (requires Tilt Teams; keep commented if not used)
# set_team_ui_settings({
# 'resource_groups': {
# 'core': ['db', 'rabbitmq', 'redis-q-dedup', 'redis-hot-geodata', 'kvrocks-cold-geodata', 'maildev'],
# 'object-storage': ['minio', 'minio-setup'],
# 'hasura': ['hasura', 'hasura_console'],
# 'api-stack': ['api', 'files', 'tasks', 'watchers'],
# 'geo': ['osrm-car', 'osrm-foot', 'tileserver-gl', 'nominatim', 'nominatim-pg'],
# 'frontends': ['web', 'app'],
# }
# })

80
app/.aidigestignore Normal file
View file

@ -0,0 +1,80 @@
# Ignore everything by default
*
# First include the source directory
!src/
!src/**/
!src/**/*.js
!src/**/*.jsx
!src/**/*.ts
!src/**/*.tsx
# Then exclude specific patterns and directories
# Build and dependencies
node_modules/
build/
dist/
coverage/
# Platform specific
ios/
android/
# Configuration files
*.json
*.lock
*.yml
*.yaml
*.env*
*.config.*
.*rc*
Dockerfile*
# Documentation
*.md
*.txt
docs/
# Tests and stories
**/__tests__/
**/*.test.*
**/*.spec.*
**/*.stories.*
e2e/
# Generated and utility files
*.d.ts
*.map
*.log
# Assets and styles
src/assets/
**/*.css
**/*.scss
**/*.style.*
**/*.styles.*
*.svg
*.png
*.jpg
*.ttf
# Common utility/boilerplate directories
src/i18n/
src/theme/
src/utils/
src/lib/
src/components/
src/navigation/
src/hooks/
src/hoc/
# Auto-generated or index files
**/index.js
**/index.ts
**/constants.js
**/constants.ts
**/types.ts
# Deprecated files
*.bak
*.old

66
app/.dockerignore Normal file
View file

@ -0,0 +1,66 @@
.git/
# OSX
#
**/.DS_Store
# Xcode
#
**/build/
**/*.pbxuser
!**/default.pbxuser
**/*.mode1v3
!**/default.mode1v3
**/*.mode2v3
!**/default.mode2v3
**/*.perspectivev3
!**/default.perspectivev3
**/xcuserdata
**/*.xccheckout
**/*.moved-aside
**/DerivedData
**/*.hmap
**/*.ipa
**/*.xcuserstate
**/project.xcworkspace
# Android/IntelliJ
#
**/build/
**/.idea
**/.gradle
**/local.properties
**/*.iml
**/*.hprof
**/.cxx/
**/*.keystore
!**/debug.keystore
# node.js
#
**/node_modules/
**/npm-debug.log
**/yarn-error.log
# Bundle artifacts
**/*.jsbundle
# CocoaPods
ios/Pods/
# Temporary files created by Metro to check the health of the file watcher
**/.metro-health-check*
# Expo
**/.expo/
**/web-build/
**/dist/
# Yarn berry
**/.pnp.*
**/.yarn/*
!**/.yarn/patches
!**/.yarn/plugins
!**/.yarn/releases
!**/.yarn/sdks
!**/.yarn/versions
# !.yarn/cache

20
app/.env.default Normal file
View file

@ -0,0 +1,20 @@
# Sentry configuration
SENTRY_URL=https://sentry.io
SENTRY_DSN=your_sentry_dsn_here
SENTRY_ORG=your_sentry_org_here
SENTRY_PROJECT=alertesecours-application
SENTRY_DISABLE_AUTO_UPLOAD=true
LOCAL_DEV=true
# Android Emulator Configuration
ANDROID_EMULATOR_NAME=Pixel_6_API_30
ASC_API_KEY_ID=
ASC_API_ISSUER_ID=
ASC_API_KEY_PATH=
PROVIDER_ID=
# Background Geolocation License Keys
BACKGROUND_GEOLOCATION_LICENSE_ANDROID=your_license_key_here
BACKGROUND_GEOLOCATION_LICENSE_IOS=your_license_key_here

15
app/.envrc Normal file
View file

@ -0,0 +1,15 @@
export PATH=$PWD/bin:$PWD/scripts:$PATH
export PROJECT_WORKINGDIR=$PWD
# appli
export JAVA_HOME=${JAVA_HOME:-"/opt/android-studio/jbr"}
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
export NODE_OPTIONS"=--openssl-legacy-provider"
# dotenv
dotenv_if_exists .env.default
dotenv_if_exists .env.local

157
app/.eslintrc.js Normal file
View file

@ -0,0 +1,157 @@
const path = require("path");
module.exports = {
root: true,
env: {
"react-native/react-native": true,
jest: true,
},
extends: [
"plugin:prettier/recommended",
"plugin:import/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended",
],
parser: "@babel/eslint-parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2021,
sourceType: "module",
babelOptions: {
configFile: path.resolve(__dirname, "babel.config.js"),
},
},
plugins: [
"babel",
"sort-keys-fix",
"react",
"react-native",
"react-native-a11y",
"unused-imports",
"autoimport-declarative",
],
settings: {
react: {
version: "detect",
},
"import/ignore": ["react-native"],
"import/resolver": {
// Ensure ESLint can resolve regular JS packages under Yarn PnP as well.
// Without this, some deps (ex: expo-sqlite) may be incorrectly flagged
// by import/no-unresolved even though they're present.
node: {
extensions: [".js", ".jsx", ".ts", ".tsx", ".json"],
},
typescript: {},
},
},
ignorePatterns: ["build", "node_modules", "e2e", "**/*.bak.js"],
rules: {
"no-undef": [2],
"react/forbid-prop-types": [0],
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react-hooks/exhaustive-deps": "error",
"jsx-a11y/no-autofocus": 0,
// React-Native accessibility: start as warnings to enable gradual adoption
// without breaking the build; we will tighten to errors as we fix surfaces.
"react-native-a11y/has-accessibility-hint": "error",
"react-native-a11y/has-valid-accessibility-descriptors": "error",
"import/no-named-as-default": 0,
"import/no-named-as-default-member": 0,
// 'unused-imports/no-unused-imports-ts': 1, # enable and run yarn lint --fix to autoremove all unused imports
"autoimport-declarative/autoimport": [
1,
{
packages: {
react: [
"useState",
"useEffect",
"useContext",
"useReducer",
"useCallback",
"useMemo",
"useRef",
"useImperativeHandle",
"useLayoutEffect",
"useDebugValue",
"createRef",
"forwardRef",
{
name: "React",
isDefault: true,
},
],
"react-native": [
"useWindowDimensions",
"View",
"TouchableOpacity",
"TouchableHighlight",
"Image",
"StyleSheet",
],
"@react-navigation/native": [
"useNavigation",
"useFocusEffect",
"useIsFocused",
],
"@maplibre/maplibre-react-native": [
{
name: "Maplibre",
isDefault: true,
},
],
"@expo/vector-icons": [
"MaterialCommunityIcons",
"MaterialIcons",
"Entypo",
"FeatherMaterialIcons",
],
"react-native-paper": ["ToggleButton", "Button", "FAB"],
"@apollo/client": ["useQuery", "useMutation", "useLazyQuery"],
"react-hook-form": [
"FormProvider",
"Controller",
"useForm",
"useFormContext",
"useFieldArray",
"useField",
],
moment: [
{
name: "moment",
isDefault: true,
},
],
"hooks/useStreamQueryWithSubscription": [
{
name: "useStreamQueryWithSubscription",
isDefault: true,
},
],
"~/theme": ["useTheme", "createStyles"],
"~/lib/toast-notifications": ["useToast"],
"~/lib/geo/humanizeDistance": [
{
name: "humanizeDistance",
isDefault: true,
},
],
"~/components/Text": [
{
name: "Text",
isDefault: true,
},
],
},
},
],
},
globals: {
AbortController: true,
},
};

3
app/.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,3 @@
liberapay: alerte-secours
github: alerte-secours
buy_me_a_coffee: alertesecours

114
app/.gitignore vendored Normal file
View file

@ -0,0 +1,114 @@
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# project.xcworkspace
ios/AlerteSecours.xcodeproj/project.xcworkspace/**
!ios/AlerteSecours.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
# bunlde sourcemaps
ios/*.map
ios/*.hbc
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/
*.keystore
!debug.keystore
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# Bundle artifacts
*.jsbundle
# CocoaPods
/ios/Pods/
# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
# Expo
.expo/
web-build/
dist/
# Yarn berry
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# !.yarn/cache
# secrets
/keys
/.env.local
/.env.prod
/.env.staging
## Build generated
build/
DerivedData
/**/*.xcarchive/**
# aidigest
codebase.md
# Build logs
logs/
# Sensitive configuration files
ios/GoogleService-Info.plist
ios/AlerteSecours/GoogleService-Info.plist
ios/AlerteSecours/Supporting/Expo.plist
android/app/google-services.json
# Keep example files
!ios/GoogleService-Info.example.plist
!ios/AlerteSecours/GoogleService-Info.example.plist
!ios/AlerteSecours/Supporting/Expo.example.plist
!android/app/google-services.example.json
screenshot-*.png
/.data
# Geodae preprocessing
scripts/dae/node_modules/
scripts/dae/.yarn/*
!scripts/dae/.yarn/patches
!scripts/dae/.yarn/plugins
!scripts/dae/.yarn/releases
!scripts/dae/.yarn/sdks
!scripts/dae/.yarn/versions
src/assets/db/*.db

1
app/.node-version Normal file
View file

@ -0,0 +1 @@
20

6
app/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"i18n-ally.localesPaths": [
"src/i18n",
"src/i18n/locales"
]
}

View file

@ -0,0 +1,16 @@
/* eslint-disable */
//prettier-ignore
module.exports = {
name: "@yarnpkg/plugin-fetch",
factory: function (require) {
var plugin=(()=>{var M=Object.defineProperty;var R=(n,t,e)=>t in n?M(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var o=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+n+'" is not supported')});var f=(n,t)=>()=>(t||n((t={exports:{}}).exports,t),t.exports);var g=(n,t,e)=>(R(n,typeof t!="symbol"?t+"":t,e),e);var P=f((ce,F)=>{"use strict";F.exports=function(t){return t.map(function(e){return e&&typeof e=="object"?e.op.replace(/(.)/g,"\\$1"):/["\s]/.test(e)&&!/'/.test(e)?"'"+e.replace(/(['\\])/g,"\\$1")+"'":/["'\s]/.test(e)?'"'+e.replace(/(["\\$`!])/g,"\\$1")+'"':String(e).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g,"$1\\$2")}).join(" ")}});var E=f((oe,J)=>{var j=o("fs"),z=o("path"),{parseSyml:G}=o("@yarnpkg/parsers");J.exports=function(){let t=j.readFileSync("yarn.lock","utf8"),e=G(t),d=Object.keys(e).filter(i=>i.includes("@workspace:")),s=d.map(i=>{let[,p]=e[i].resolution.trim().split("@workspace:");return p==="."?null:p}).filter(Boolean);d.forEach(i=>{let{dependencies:p,dependenciesMeta:r,peerDependencies:q,peerDependenciesMeta:w,resolution:C,bin:Y}=e[i],[B,b]=C.trim().split("@workspace:"),H=z.join(b,"package.json"),h={name:B,version:"0.0.0",description:"**DON'T COMMIT** Generated file for caching",private:!0,dependencies:p,peerDependencies:q,peerDependenciesMeta:w,bin:Y};if(r){let m={};Object.keys(r).forEach(k=>{m[k]=p[k],delete p[k]}),h.optionalDependencies=m}if(b==="."){s.length>0&&(h.workspaces={packages:s});let m=Object.keys(e),k=c=>{let a=c.trim().split("@");return c.startsWith("@")?a=a.slice(0,2):a=a.slice(0,1),a.join("@")};h.resolutions=m.filter(c=>{if(c.includes("@workspace:")||c.includes(", ")||!c.includes("@npm:"))return!1;let a=k(c);return m.every(y=>c===y?!0:y.split(",").map(l=>k(l)).every(l=>l!==a))}).reduce((c,a)=>{let[y,l]=a.trim().split("@npm:");return c[y]=l.includes("@")?`npm:${l}`:l,c},{})}j.mkdirSync(b,{recursive:!0}),j.writeFileSync(H,`${JSON.stringify(h,null,2)}
`)})}});var S=f((ae,T)=>{var I=E();T.exports=n=>{n.context.stdout.write(`[YARN-FETCH] extracting package.json file(s) from yarn.lock
`),I()}});var O=f((pe,N)=>{var u=o("fs"),K=o("path"),{execSync:U}=o("child_process"),{parseSyml:W}=o("@yarnpkg/parsers"),{BaseCommand:Z}=o("@yarnpkg/cli"),{Command:Q,Option:D}=o("clipanion"),V=P(),X=S(),x;N.exports=(x=class extends Z{protectPackageJson=D.Boolean("--protect-package-json");args=D.Proxy();async execute(){let{protectPackageJson:t=process.stdout.isTTY}=this,e=[];if(t){this.context.stdout.write(`[YARN-FETCH] backup possible package.json file(s)
`);let s=u.readFileSync("yarn.lock","utf8"),i=W(s);e=Object.keys(i).filter(r=>r.includes("@workspace:")).map(r=>{let{resolution:q}=i[r],[,w]=q.trim().split("@workspace:");return K.join(w,"package.json")}),e.forEach(r=>{u.existsSync(r)&&!u.existsSync(`${r}.yarn-plugin-fetch-bak`)&&u.copyFileSync(r,`${r}.yarn-plugin-fetch-bak`)})}X(this);let d=`yarn ${V(this.args)}`;this.context.stdout.write(`[YARN-FETCH] ${d}
`);try{U(d,{stdio:"inherit"})}catch(s){throw s}finally{t&&(this.context.stdout.write(`[YARN-FETCH] restoring possible package.json file(s)
`),e.forEach(s=>{u.existsSync(`${s}.yarn-plugin-fetch-bak`)?u.renameSync(`${s}.yarn-plugin-fetch-bak`,s):u.unlinkSync(s)}))}}},g(x,"paths",[["fetch"]]),g(x,"usage",Q.Usage({description:"fetch dependencies from yarn.lock in Docker build",details:`
expand yarn.lock to package.json file(s) and install dependencies in Docker build.
`,examples:[["yarn fetch --immutable","yarn fetch workspace my-package focus"]]})),x)});var A=f((ke,v)=>{var{BaseCommand:_}=o("@yarnpkg/cli"),ee=S(),$;v.exports=($=class extends _{async execute(){ee(this)}},g($,"paths",[["expand-lock"]]),$)});var se=f((de,L)=>{var te=O(),ne=A();L.exports={commands:[te,ne]}});return se();})();
return plugin;
}
};

11
app/.yarnrc.yml Normal file
View file

@ -0,0 +1,11 @@
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-fetch.cjs
spec: "https://raw.githubusercontent.com/devthejo/yarn-plugin-fetch/master/bundles/@yarnpkg/plugin-fetch.js"
yarnPath: .yarn/releases/yarn-4.5.3.cjs

266
app/DEVELOPER.md Normal file
View file

@ -0,0 +1,266 @@
# Alerte Secours Mobile App - Developer Documentation
This document contains technical information for developers working on the Alerte Secours mobile application.
## Table of Contents
- [Project Overview](#project-overview)
- [Technical Stack](#technical-stack)
- [Development Quick Start](#development-quick-start)
- [Installation](#installation)
- [Android](#android)
- [iOS](#ios)
- [Project Structure](#project-structure)
- [Accessibility](#accessibility)
- [Troubleshooting](#troubleshooting)
## Project Overview
Alerte Secours is a mobile application built with React Native that handles alerts and emergency-related functionality. The app supports both iOS and Android platforms and includes features such as:
- Alert creation and management with real-time updates
- Location-based features with mapping integration
- Chat/Messaging system with alert-specific chat rooms
- Authentication via SMS verification
- Deep linking for alert sharing
- Push notifications
## Technical Stack
- React Native
- Expo framework
- GraphQL with Hasura
- Apollo Client for frontend
- Federated remote schemas
- Real-time subscriptions support
- Firebase Cloud Messaging (FCM) for push notifications only
- Sentry for error tracking
- MapLibre for mapping functionality
- Zustand for state management
- i18next for internationalization
- React Navigation for navigation
- Expo Updates for OTA updates
- Background Geolocation for location tracking
- Lottie for animations
- React Hook Form for form handling
- Axios for HTTP requests
- Yarn Berry as package manager
- ESLint and Prettier for code quality
- Fastlane for deployment automation
## Development Quick Start
### Prerequisites
- Node.js (version specified in `.node-version`)
- Yarn package manager
- Android Studio (for Android development)
- Xcode (for iOS development)
- Physical device or emulator/simulator
### Environment Setup
1. Clone the repository
2. Install dependencies:
```bash
yarn
```
3. Copy the staging environment file:
```bash
cp .env.staging.example .env.staging
```
4. Start the development server with staging environment:
```bash
yarn start:staging
```
### Running on Devices
#### Android
```bash
yarn android:staging
```
#### iOS
```bash
yarn ios:staging
```
### Staging URLs
The staging environment uses the following URLs:
- GraphQL API: `https://hasura-staging.alertesecours.fr/v1/graphql`
- WebSocket: `wss://hasura-staging.alertesecours.fr/v1/graphql`
- Files API: `https://files-staging.alertesecours.fr/api/v1/oas`
- Minio: `https://minio-staging.alertesecours.fr`
- Geolocation Sync: `https://api-staging.alertesecours.fr/api/v1/oas/geoloc/sync`
## Installation
### Android
#### Using the Yarn Script
The easiest way to install the app is to use the provided yarn script:
```bash
# Set the device ID (emulator or physical device)
export DEVICE=emulator-5554
# Run the installation script
yarn install:android
```
This script (`install-android.sh`) handles the entire installation process, including building APKs with signing, extracting them, and installing on the device.
#### Manual Installation
If you need to install the app manually, you can examine the `install-android.sh` script in the project root to see the detailed steps involved.
### iOS
#### Authentication Key Setup
1. Go to https://appstoreconnect.apple.com/access/integrations/api
2. Click the "+" button to generate a new API key
3. Give it a name (e.g., "AlerteSecours Build Key")
4. Download the .p8 file when prompted
5. Store the .p8 file in a secure location
6. Note down the Key ID and Issuer ID shown on the website
7. Set up environment variables:
```sh
export ASC_API_KEY_ID="YOUR_KEY_ID"
export ASC_API_ISSUER_ID="YOUR_ISSUER_ID"
export ASC_API_KEY_PATH="/path/to/your/AuthKey.p8"
```
#### Building and Running
To build and run the iOS app:
```bash
# Run in development mode with staging environment
yarn ios:staging
# Build for production (version + clean + archive + export)
yarn bundle:ios:build
# Upload the last build to App Store Connect
yarn bundle:ios:upload
# Build + upload
yarn bundle:ios:release
```
Notes on versioning:
- `yarn bundle:ios:build` updates iOS `CFBundleShortVersionString` and `CFBundleVersion` to a timestamp in `Europe/Paris` timezone (format `YYYYMMDDHHMM`) before archiving/exporting.
- `yarn bundle:ios` is an alias of `yarn bundle:ios:build`.
The `bundle:ios` command uses the scripts in the `scripts` directory:
- `ios-archive.sh` - Archives the iOS app
- `ios-export.sh` - Exports the archived app
- `ios-upload.sh` - Uploads the app to App Store Connect (used by `bundle:ios:upload`)
## Project Structure
- `/android` - Android-specific code and configuration
- `/ios` - iOS-specific code and configuration
- `/src` - Main application source code
- `/app` - App initialization and configuration
- `/assets` - Static assets (images, fonts, animations)
- `/auth` - Authentication-related code
- `/biz` - Business logic and constants
- `/components` - Reusable UI components
- `/containers` - Container components
- `/data` - Data management
- `/events` - Event handling
- `/finders` - Search and finder utilities
- `/gql` - GraphQL queries and mutations
- `/hoc` - Higher-order components
- `/hooks` - Custom React hooks
- `/i18n` - Internationalization
- `/layout` - Layout components
- `/lib` - Library code
- `/location` - Location-related functionality
- `/misc` - Miscellaneous utilities
- `/navigation` - Navigation configuration
- `/network` - Network-related code
- `/notifications` - Notification handling
- `/permissions` - Permission handling
- `/scenes` - Scene components
- `/screens` - Screen components
- `/sentry` - Sentry error tracking configuration
- `/stores` - State management stores
- `/theme` - Styling and theming
- `/updates` - Update handling
- `/utils` - Utility functions
- `/docs` - Documentation files
- `/scripts` - Utility scripts for building, deployment, and development
- `/e2e` - End-to-end tests
## Contributing
Guidelines for contributing to the project:
1. Follow the code style and conventions used in the project
2. Write tests for new features
3. Update documentation as needed
4. Use the ESLint and Prettier configurations
## Accessibility
This app has an accessibility baseline (WCAG 2.2 AA, VoiceOver/TalkBack) and app-specific conventions.
### Docs
- Baseline checklist: [`docs/a11y-wcag22-aa.md`](docs/a11y-wcag22-aa.md:1)
- Code conventions + helpers: [`docs/a11y-usage.md`](docs/a11y-usage.md:1)
- Color contrast guidance: [`docs/a11y-color-contrast.md`](docs/a11y-color-contrast.md:1)
- `testID` conventions: [`docs/testids.md`](docs/testids.md:1)
- QA runbook (iOS VoiceOver): [`docs/qa-voiceover.md`](docs/qa-voiceover.md:1)
- QA runbook (Android TalkBack): [`docs/qa-talkback.md`](docs/qa-talkback.md:1)
### PR checklist (required for any UI change)
- [ ] **Roles / labels / hints / states**: all interactive controls expose correct `accessibilityRole`, meaningful `accessibilityLabel`, helpful `accessibilityHint` (especially icon-only actions), and state where applicable.
- [ ] **Focus management**: any modal/dialog/sheet sets initial focus on open, returns focus on close, and avoids focus traps.
- [ ] **Touch target size**: critical tap targets are comfortably tappable (aim ~44x44pt minimum).
- [ ] **Color contrast**: text + icons meet WCAG AA contrast; do not rely on color alone for meaning.
- [ ] **`testID`s for critical controls**: stable `testID` added/updated for key actions and navigation chrome (per [`docs/testids.md`](docs/testids.md:1)).
- [ ] **Tests**: add/update tests covering the new UI behavior (and its states). Prefer assertions that dont depend on translated text; include E2E coverage for critical flows when applicable.
### Manual validation (screen readers)
When a PR changes UI or navigation, do a quick pass with the platform screen reader:
- iOS: follow [`docs/qa-voiceover.md`](docs/qa-voiceover.md:1) and validate labels/hints, navigation order, and activation behavior on the affected screens.
- Android: follow [`docs/qa-talkback.md`](docs/qa-talkback.md:1) with the same focus on discoverability, focus order, and activation.
## Troubleshooting
### Common Issues
#### Development Environment
- **Clearing Yarn Cache**: Use `yarn clean` (removes node_modules and reinstalls dependencies)
- **Cleaning Gradle**: Run `cd android && ./gradlew clean`
- **Clearing Gradle Cache**: Remove gradle caches with `rm -rf ~/.gradle/caches/ android/.gradle/`
- **Stopping Gradle Daemons**: Run `cd android && ./gradlew --stop`
- **Clearing ADB Cache**: Run `adb shell pm clear com.alertesecours`
- **Rebuilding Gradle**: Use `yarn expo run:android`
- **Rebuilding Expo React Native**: Use `yarn expo prebuild`
- **Clearing Metro Cache**: Use `yarn expo start --dev-client --clear`
#### Screenshots and Testing
- For Android screenshots: Use `scripts/screenshot-android.sh`
- For iOS screenshots: Use `scripts/screenshot-ios.sh`
- For Android emulator: Use `scripts/android-emulator`
#### Emulator Issues
- Clear cache / uninstall the app
- Check emulator datetime
- Check network connectivity
For more troubleshooting tips, see the documentation in the `/docs` directory.

81
app/LICENSE.md Normal file
View file

@ -0,0 +1,81 @@
# DevTheFuture Ethical Use License (DEF License)
**Effective Date:** 2025
**Licensor:** DevTheFuture.org
**License URL:** [https://devthefuture.org/DEF-LICENSE.md](https://devthefuture.org/DEF-LICENSE.md)
**Licensed Software:** Alerte-Secours
* * *
## 1. **Definitions**
* **Software:** The original software provided under this license, including all parts, components, and any modifications or derivatives, as defined by the Licensor.
* **Nonprofit Use:** For the purposes of this Agreement, “Nonprofit Use” is defined in a manner consistent with similar provisions in licenses such as the PolyForm Noncommercial License. It refers to usage that does not primarily aim to generate financial gain, including activities by educational institutions, public organizations, or private individuals where any incidental revenue is purely ancillary to the primary noncommercial purpose.
* **Profit Use:** Any use of the Software that is intended to generate revenue, provide a commercial advantage, or otherwise support a for-profit enterprise. This includes, but is not limited to, integration into commercial products, services, or platforms where the primary goal is financial gain.
* **Personal Data Monetization:** The process by which personal data collected through the operation of the Software is exploited for commercial gain. For clarity, the License expressly prohibits any use of personal data for:
* Marketing, advertising, or political influence campaigns.
* The creation, maintenance, or enhancement of databases or data aggregation services that are not directly tied to the explicitly exposed functionalities of the Software as communicated to the end user.
* **Competitor:** Any individual, organization, or entity that develops, distributes, or monetizes software that directly competes with the Software in its intended field or market.
* * *
## 2. **Grant of License**
1. **Nonprofit Use:**
* The Licensor grants a perpetual, royalty-free, non-exclusive, and non-transferable license to use, modify, and distribute the Software for Nonprofit Use, provided that all users comply with Section 3 and any additional terms specified herein.
2. **Profit Use:**
* Use of the Software for Profit Use requires obtaining a paid license. The Licensor reserves the exclusive right to determine the terms, cost, and approval of any Profit Use license at its sole discretion.
* All requests for a Profit Use license must be submitted in writing, and the Licensor may approve or deny such requests based on factors including the intended use, the nature of the entity, and other relevant considerations.
* * *
## 3. **Restrictions on Personal Data Monetization**
* The Software **must not be used to monetize, sell, or exploit any personal data** collected through its operation.
* Specifically, any personal data obtained through the Software:
* **May not be used for any marketing or advertising purposes.**
* **May not be used to influence public opinion or political processes.**
* **May not be compiled into databases or used for data aggregation unless such use is an explicit and integral feature of the Software, as clearly disclosed to end users.**
* All users and licensees agree to these conditions. Violation of this section shall be considered a material breach of this Agreement.
* * *
## 4. **Ownership and Intellectual Property**
* The Software and all related intellectual property rights remain the exclusive property of the Licensor.
* Users are prohibited from removing or altering any copyright, trademark, or other proprietary notices contained within the Software.
* * *
## 5. **No Warranty**
* The Software is provided “as is,” without any express or implied warranties, including but not limited to warranties of merchantability, fitness for a particular purpose, or non-infringement.
* Under no circumstances shall the Licensor be liable for any claims, damages, or liabilities arising from the use or inability to use the Software.
* * *
## 6. **Termination and Cure Period**
* In the event of a breach of Sections 2, 3, or 8, the Licensor shall notify the Licensee of the breach and provide a cure period of **30 days** during which the Licensee may remedy the breach.
* If the breach is not remedied within this cure period, or if the breach is of a nature that the Licensor determines is irreparable, this license shall automatically terminate without further notice.
* Profit Use licenses may be terminated or revoked by the Licensor in accordance with the specific terms outlined in each Profit Use agreement.
* * *
## 7. **Governing Law and Dispute Resolution**
* This Agreement shall be governed by and construed in accordance with internationally recognized principles of commercial law, as well as any applicable local laws governing the use or distribution of the Software.
* In the event of any disputes, the parties agree to attempt resolution through negotiation before pursuing legal remedies in a competent jurisdiction.
* * *
## 8. **Competitor Restriction**
* **Competitor Limitation:** Any Competitor is prohibited from using, accessing, or distributing the Software in any capacity (whether under Nonprofit or Profit Use) without the explicit, prior written consent of the Licensor.
* **Profit Use Licensing for Competitors:** The Licensor reserves the right to evaluate and either approve or deny any Profit Use license request from a Competitor at its sole discretion, without obligation to justify the decision.
* * *
By using or accessing the Software, you acknowledge that you have read, understood, and agree to be bound by the terms of this DevTheFuture Ethical Use License (DEF License).
* * *

82
app/README.md Normal file
View file

@ -0,0 +1,82 @@
# Alerte Secours - Le Réflexe qui Sauve
[![Liberapay](https://img.shields.io/liberapay/receives/alerte-secours.svg?logo=liberapay)](https://liberapay.com/alerte-secours)
[![Buy Me a Coffee](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg?logo=buy-me-a-coffee)](https://buymeacoffee.com/alertesecours)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/alerte-secours?style=social)](https://github.com/sponsors/alerte-secours)
Une application mobile pour la gestion des alertes et des fonctionnalités liées aux urgences, supportant les plateformes iOS et Android.
**Site Web Officiel :** [alerte-secours.fr](https://alerte-secours.fr)
## Aperçu du Projet
Alerte Secours est une application mobile construite avec React Native qui gère les alertes et les fonctionnalités liées aux urgences. L'application supporte les plateformes iOS et Android et inclut des fonctionnalités telles que :
- Création et gestion d'alertes avec mises à jour en temps réel
- Fonctionnalités basées sur la localisation avec intégration cartographique
- Système de chat/messagerie avec salles de discussion spécifiques aux alertes
- Authentification via vérification SMS
- Liens profonds pour le partage d'alertes
- Notifications push
## Documentation Développeur
Pour les développeurs souhaitant contribuer au projet ou déployer l'application, consultez la [documentation technique complète](DEVELOPER.md) qui contient :
- Aperçu du projet et fonctionnalités
- Stack technique détaillé
- Guide de démarrage rapide
- Instructions d'installation (Android/iOS)
- Structure du projet
- Guide de dépannage
- Instructions de build et déploiement
## Licence
Alerte Secours est sous licence **DevTheFuture Ethical Use License (DEF License)**. Points clés :
### Usage à but non lucratif
- Licence perpétuelle, libre de redevances et non exclusive pour usage à but non lucratif
- Permet l'utilisation, la modification et la distribution à des fins non lucratives
### Usage commercial
- Nécessite l'obtention d'une licence payante
- Conditions déterminées par le Concédant (DevTheFuture.org)
### Restrictions sur les données personnelles
- Ne doit pas être utilisé pour monétiser, vendre ou exploiter les données personnelles
- Les données personnelles ne peuvent pas être utilisées pour le marketing, la publicité ou l'influence politique
- L'agrégation de données n'est autorisée que si c'est une fonctionnalité explicite divulguée aux utilisateurs
### Restriction concurrentielle
- Les concurrents sont interdits d'utiliser le logiciel sans consentement explicite
Pour le texte complet de la licence, voir [LICENSE.md](LICENSE.md).
## 💙 Soutenir le projet
Alerte-Secours est une application mobile citoyenne, librement accessible, sans publicité ni exploitation de données.
Si vous souhaitez contribuer à son développement, sa maintenance et son indépendance :
- 🟡 **[Liberapay Soutien régulier](https://liberapay.com/alerte-secours)**
Pour un soutien **récurrent et engagé**. Chaque don contribue à assurer la stabilité du service sur le long terme.
- ☕ **[Buy Me a Coffee Don ponctuel](https://buymeacoffee.com/alertesecours)**
Pour un **coup de pouce ponctuel**, un café virtuel pour encourager le travail accompli !
- 🧑‍💻 **[GitHub Sponsors](https://github.com/sponsors/alerte-secours)**
Pour les développeurs et utilisateurs de GitHub : soutenez le projet directement via votre compte.
## Contribuer
Directives pour contribuer au projet :
1. Suivez le style de code et les conventions utilisées dans le projet
2. Écrivez des tests pour les nouvelles fonctionnalités
3. Mettez à jour la documentation si nécessaire
4. Utilisez les configurations ESLint et Prettier
## Support
Pour obtenir de l'aide, veuillez ouvrir un ticket sur notre tracker d'issues ou consulter la documentation dans le répertoire `/docs`.

View file

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 692 B

View file

Before

Width:  |  Height:  |  Size: 903 B

After

Width:  |  Height:  |  Size: 903 B

View file

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 426 B

View file

Before

Width:  |  Height:  |  Size: 571 B

After

Width:  |  Height:  |  Size: 571 B

View file

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View file

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

Before

Width:  |  Height:  |  Size: 985 B

After

Width:  |  Height:  |  Size: 985 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View file

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View file

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View file

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Some files were not shown because too many files have changed in this diff Show more