chore(init): available sources
80
.aidigestignore
Normal 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
|
57
.detoxrc.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
/** @type {Detox.DetoxConfig} */
|
||||
module.exports = {
|
||||
testRunner: {
|
||||
args: {
|
||||
'$0': 'jest',
|
||||
config: 'e2e/jest.config.js'
|
||||
},
|
||||
jest: {
|
||||
setupTimeout: 120000
|
||||
}
|
||||
},
|
||||
apps: {
|
||||
'android.debug': {
|
||||
type: 'android.apk',
|
||||
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
|
||||
build: 'cd android && ENVFILE=../.env.staging ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
|
||||
reversePorts: [
|
||||
8081
|
||||
]
|
||||
},
|
||||
'android.release': {
|
||||
type: 'android.apk',
|
||||
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
|
||||
build: 'cd android && ENVFILE=../.env.staging ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release'
|
||||
},
|
||||
},
|
||||
devices: {
|
||||
simulator: {
|
||||
type: 'ios.simulator',
|
||||
device: {
|
||||
type: 'iPhone 15',
|
||||
},
|
||||
},
|
||||
attached: {
|
||||
type: 'android.attached',
|
||||
device: {
|
||||
adbName: '.*', // any attached device
|
||||
},
|
||||
},
|
||||
emulator: {
|
||||
type: 'android.emulator',
|
||||
device: {
|
||||
avdName: process.env.ANDROID_EMULATOR_NAME || 'Pixel_6_API_30'
|
||||
}
|
||||
}
|
||||
},
|
||||
configurations: {
|
||||
'android.emu.debug': {
|
||||
device: 'emulator',
|
||||
app: 'android.debug'
|
||||
},
|
||||
'android.emu.release': {
|
||||
device: 'emulator',
|
||||
app: 'android.release'
|
||||
}
|
||||
}
|
||||
};
|
66
.dockerignore
Normal 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
.env.default
Normal 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=your_license_key_here
|
||||
BACKGROUND_GEOLOCATION_HMS_LICENSE=your_hms_license_key_here
|
33
.env.prod.example
Normal file
|
@ -0,0 +1,33 @@
|
|||
APP_OA_FILES_URL=https://files.alertesecours.fr/api/v1/oas
|
||||
APP_MINIO_URL=https://minio.alertesecours.fr
|
||||
APP_GRAPHQL_URL=https://hasura.alertesecours.fr/v1/graphql
|
||||
APP_GRAPHQL_WS_URL=wss://hasura.alertesecours.fr/v1/graphql
|
||||
APP_GEOLOC_SYNC_URL=https://api.alertesecours.fr/api/v1/oas/geoloc/sync
|
||||
|
||||
STAGING_APP_OA_FILES_URL=https://files-staging.alertesecours.fr/api/v1/oas
|
||||
STAGING_APP_MINIO_URL=https://minio-staging.alertesecours.fr
|
||||
STAGING_APP_GRAPHQL_URL=https://hasura-staging.alertesecours.fr/v1/graphql
|
||||
STAGING_APP_GRAPHQL_WS_URL=wss://hasura-staging.alertesecours.fr/v1/graphql
|
||||
STAGING_APP_GEOLOC_SYNC_URL=https://api-staging.alertesecours.fr/api/v1/oas/geoloc/sync
|
||||
|
||||
APP_OSRM_CAR_URL=https://osrm-car.alertesecours.fr
|
||||
APP_OSRM_FOOT_URL=https://osrm-foot.alertesecours.fr
|
||||
APP_OSRM_BICYCLE_URL=https://osrm-bicycle.alertesecours.fr
|
||||
APP_MAPVIEW_STYLE_URL=https://tiles.alertesecours.fr/styles/basic-preview/style.json
|
||||
APP_MAPVIEW_DARK_STYLE_URL=https://tiles.alertesecours.fr/styles/dark-matter/style.json
|
||||
CLAIMS_NAMESPACE=https://alertesecours.fr/claims
|
||||
|
||||
LOCAL_DEV=false
|
||||
SENTRY_DISABLE_AUTO_UPLOAD=false
|
||||
|
||||
# Sentry configuration
|
||||
SENTRY_URL=https://sentry.io
|
||||
SENTRY_DSN=your_sentry_dsn_here
|
||||
SENTRY_ORG=your_sentry_org_here
|
||||
SENTRY_PROJECT=alertesecours-application
|
||||
|
||||
# App Store Connect API credentials
|
||||
ASC_API_KEY_ID=your_asc_api_key_id_here
|
||||
ASC_API_ISSUER_ID=your_asc_api_issuer_id_here
|
||||
ASC_API_KEY_PATH=/path/to/your/private/key.p8
|
||||
PROVIDER_ID=your_provider_id_here
|
26
.env.staging.example
Normal file
|
@ -0,0 +1,26 @@
|
|||
APP_OA_FILES_URL=https://files-staging.alertesecours.fr/api/v1/oas
|
||||
APP_MINIO_URL=https://minio-staging.alertesecours.fr
|
||||
APP_GRAPHQL_URL=https://hasura-staging.alertesecours.fr/v1/graphql
|
||||
APP_GRAPHQL_WS_URL=wss://hasura-staging.alertesecours.fr/v1/graphql
|
||||
APP_GEOLOC_SYNC_URL=https://api-staging.alertesecours.fr/api/v1/oas/geoloc/sync
|
||||
|
||||
APP_OSRM_CAR_URL=https://osrm-car.alertesecours.fr
|
||||
APP_OSRM_FOOT_URL=https://osrm-foot.alertesecours.fr
|
||||
APP_OSRM_BICYCLE_URL=https://osrm-bicycle.alertesecours.fr
|
||||
APP_MAPVIEW_STYLE_URL=https://tiles.alertesecours.fr/styles/basic-preview/style.json
|
||||
APP_MAPVIEW_DARK_STYLE_URL=https://tiles.alertesecours.fr/styles/dark-matter/style.json
|
||||
CLAIMS_NAMESPACE=https://alertesecours.fr/claims
|
||||
|
||||
# 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=false
|
||||
LOCAL_DEV=false
|
||||
|
||||
# App Store Connect API credentials
|
||||
ASC_API_KEY_ID=your_asc_api_key_id_here
|
||||
ASC_API_ISSUER_ID=your_asc_api_issuer_id_here
|
||||
ASC_API_KEY_PATH=/path/to/your/private/key.p8
|
||||
PROVIDER_ID=your_provider_id_here
|
15
.envrc
Normal 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
|
143
.eslintrc.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
"react-native/react-native": 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",
|
||||
"unused-imports",
|
||||
"autoimport-declarative",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
"import/ignore": ["react-native"],
|
||||
"import/resolver": {
|
||||
typescript: {},
|
||||
},
|
||||
},
|
||||
ignorePatterns: ["build", "node_modules", "e2e"],
|
||||
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,
|
||||
"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,
|
||||
},
|
||||
};
|
95
.forgejo/workflows/ci-cd-android.yaml
Normal file
|
@ -0,0 +1,95 @@
|
|||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# push:
|
||||
# tags:
|
||||
# - "**"
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
concurrency:
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.event.ref }}
|
||||
|
||||
jobs:
|
||||
build-apk:
|
||||
env:
|
||||
RUNNER_TOOL_CACHE: /toolcache # see https://about.gitea.com/resources/tutorials/enable-gitea-actions-cache-to-accelerate-cicd and https://gitea.com/gitea/act_runner/issues/70
|
||||
GRADLE_USER_HOME: ${{ github.workspace }}/.gradle
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: devthefuture/act-runner@sha256:49abd1415cb4230866e995154733ad43f6f4c7513268dd25e412c7206d2b9e0e
|
||||
steps:
|
||||
- name: ⏬ Checkout code repository
|
||||
uses: actions/checkout@v4.1.7
|
||||
|
||||
- name: ⬢ Setup node version
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
|
||||
- name: 🔽 Yarn install
|
||||
uses: https://git.devthefuture.org/devthefuture/actions/yarn-install@v0.5.0
|
||||
|
||||
- name: ⛾ Gradle cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/.gradle/caches
|
||||
${{ github.workspace }}/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: 📌 Set metadata output
|
||||
id: vars
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "$GITHUB_HEAD_REF" ]; then
|
||||
tag=$GITHUB_HEAD_REF
|
||||
else
|
||||
tag=$GITHUB_REF
|
||||
fi
|
||||
tag=${tag#refs/heads/}
|
||||
tag=${tag#refs/tags/}
|
||||
echo "tag=$tag" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: ⚙ Setup build env vars
|
||||
shell: bash
|
||||
run: |
|
||||
cat $GITHUB_WORKSPACE/.env.default >> $GITHUB_ENV
|
||||
cat $GITHUB_WORKSPACE/.env.prod >> $GITHUB_ENV
|
||||
echo "BUILD_TIME=$(date +%s000)" >> $GITHUB_ENV
|
||||
|
||||
- name: 📦 Build APK
|
||||
# uses: docker://reactnativecommunity/react-native-android:v12.0 # more recent
|
||||
# uses: docker://reactnativecommunity/react-native-android:9 # actually working
|
||||
uses: docker://ghcr.io/devthefuture-org/docker-android:9 # use mirror to workaround docker rate limit
|
||||
# mirror using https://github.com/containers/skopeo :
|
||||
# skopeo copy docker://reactnativecommunity/react-native-android:9 docker://ghcr.io/devthefuture-org/docker-android:9
|
||||
with:
|
||||
entrypoint: /bin/sh
|
||||
args: |
|
||||
-c "\
|
||||
yarn expo prebuild --no-install; \
|
||||
cd android && ./gradlew assembleRelease --no-daemon && cd ..; \
|
||||
mv android/app/build/outputs/apk/release/app-release.apk alertesecours-${{ steps.vars.outputs.tag }}.apk; \
|
||||
"
|
||||
|
||||
- name: 🎁 Publish release on repo
|
||||
uses: https://codeberg.org/devthefuture/release-action@main
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
title: ${{ steps.vars.outputs.tag }}
|
||||
files: |-
|
||||
alertesecours-${{ steps.vars.outputs.tag }}.apk
|
||||
api_key: "${{secrets.M8A_ORG_BOT_REPO_TOKEN}}"
|
||||
|
||||
- name: 🎀 Publish release on minio-release
|
||||
uses: https://git.devthefuture.org/devthefuture/actions/minio-upload@v0.5.0
|
||||
with:
|
||||
url: https://minio-releases.alertesecours.fr
|
||||
local-path: alertesecours-${{ steps.vars.outputs.tag }}.apk
|
||||
access-key: "${{secrets.MINO_RELEASE_ACCESS_KEY}}"
|
||||
secret-key: "${{secrets.MINO_RELEASE_SECRET_KEY}}"
|
||||
remote-path: "android/alertesecours-${{ steps.vars.outputs.tag }}.apk android/alertesecours.apk"
|
5
.gitattributes
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
ios/AlerteSecours.xcodeproj/project.pbxproj merge=union
|
||||
ios/**/*.pbxproj merge=union
|
||||
|
||||
# Treat these files as binary to prevent Git from trying to merge them
|
||||
*.pbxproj binary merge=union
|
114
.github/workflows/ci-cd-ios.yaml
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# push:
|
||||
# tags:
|
||||
# - "**"
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
concurrency:
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.event.ref }}
|
||||
|
||||
jobs:
|
||||
build-ios:
|
||||
env:
|
||||
GRADLE_USER_HOME: ${{ github.workspace }}/.gradle
|
||||
# SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: ⏬ Checkout code repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ⬢ Setup node version
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
|
||||
- name: 🔽 Yarn install
|
||||
# uses: https://git.devthefuture.org/devthefuture/actions/yarn-install@v0.4.0
|
||||
uses: devthefuture-org/actions/yarn-install@v0.4.0
|
||||
|
||||
- name: ⛾ Gradle cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/.gradle/caches
|
||||
${{ github.workspace }}/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: 📌 Set metadata output
|
||||
id: vars
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "$GITHUB_HEAD_REF" ]; then
|
||||
tag=$GITHUB_HEAD_REF
|
||||
else
|
||||
tag=${GITHUB_REF#refs/heads/}
|
||||
tag=${tag#refs/tags/}
|
||||
fi
|
||||
echo "tag=$tag" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 💎 Setup Ruby (bundle)
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
bundler-cache: true
|
||||
|
||||
- name: ⛾ Restore Pods cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
ios/Pods
|
||||
~/Library/Caches/CocoaPods
|
||||
~/.cocoapods
|
||||
key: ${{ runner.os }}-pods-${{ hashFiles('ios/Podfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pods-
|
||||
|
||||
- name: 🫛 Install Pods
|
||||
run: cd ios && pod install --repo-update && cd ..
|
||||
|
||||
|
||||
- name: ⚙ Setup build env vars
|
||||
shell: bash
|
||||
run: |
|
||||
cat $GITHUB_WORKSPACE/.env.default >> $GITHUB_ENV
|
||||
cat $GITHUB_WORKSPACE/.env.prod >> $GITHUB_ENV
|
||||
echo "BUILD_TIME=$(date +%s000)" >> $GITHUB_ENV
|
||||
|
||||
- name: 📦 Build IOS App
|
||||
uses: yukiarrr/ios-build-action@v1.4.0
|
||||
with:
|
||||
project-path: ios/MyApp.xcodeproj
|
||||
p12-base64: ${{ secrets.IOS_P12_BASE64 }}
|
||||
mobileprovision-base64: ${{ secrets.IOS_MOBILE_PROVISION_BASE64 }}
|
||||
code-signing-identity: "iPhone Distribution"
|
||||
team-id: ${{ secrets.IOS_TEAM_ID }}
|
||||
certificate-password: ${{ secrets.IOS_CERTIFICATE_PASSWORD }}
|
||||
workspace-path: ios/MyApp.xcworkspace
|
||||
scheme: MyApp
|
||||
|
||||
- name: 🏷 Set asset name
|
||||
shell: bash
|
||||
run: |
|
||||
mv output.ipa alertesecours-${{ steps.vars.outputs.tag }}.ipa
|
||||
|
||||
- name: 🎀 Release
|
||||
uses: devthefuture-org/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
alertesecours-${{ steps.vars.outputs.tag }}.ipa
|
||||
|
||||
# - name: 🎁 Upload app to TestFlight
|
||||
# uses: apple-actions/upload-testflight-build@v1
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# with:
|
||||
# app-path: 'alertesecours-${{ steps.vars.outputs.tag }}.ipa'
|
||||
# issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
|
||||
# api-key-id: ${{ secrets.APPSTORE_API_KEY_ID }}
|
||||
# api-private-key: ${{ secrets.APPSTORE_API_PRIVATE_KEY }}
|
97
.gitignore
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
# 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
|
||||
|
||||
# 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
|
1
.node-version
Normal file
|
@ -0,0 +1 @@
|
|||
20
|
35
.versionrc.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
const packageJsonPath = "package.json";
|
||||
|
||||
// Updater for versionCode (as integer)
|
||||
const versionCodeUpdater = {
|
||||
readVersion: (contents) => {
|
||||
const packageJson = JSON.parse(contents);
|
||||
return packageJson.customExpoVersioning.versionCode.toString();
|
||||
},
|
||||
writeVersion: (contents) => {
|
||||
const packageJson = JSON.parse(contents);
|
||||
packageJson.customExpoVersioning.versionCode += 1; // Increment as integer
|
||||
return JSON.stringify(packageJson, null, 2);
|
||||
}
|
||||
};
|
||||
|
||||
// Updater for buildNumber (as integer)
|
||||
const buildNumberUpdater = {
|
||||
readVersion: (contents) => {
|
||||
const packageJson = JSON.parse(contents);
|
||||
return packageJson.customExpoVersioning.buildNumber.toString();
|
||||
},
|
||||
writeVersion: (contents) => {
|
||||
const packageJson = JSON.parse(contents);
|
||||
packageJson.customExpoVersioning.buildNumber += 1; // Increment as integer
|
||||
return JSON.stringify(packageJson, null, 2);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
bumpFiles: [
|
||||
{ filename: packageJsonPath, type: "json" },
|
||||
{ filename: packageJsonPath, updater: versionCodeUpdater },
|
||||
{ filename: packageJsonPath, updater: buildNumberUpdater }
|
||||
]
|
||||
};
|
17
.yarn/patches/expo-modules-core-npm-1.12.23-4ea588b9bf.patch
Normal file
|
@ -0,0 +1,17 @@
|
|||
diff --git a/android/src/main/cpp/JavaScriptModuleObject.cpp b/android/src/main/cpp/JavaScriptModuleObject.cpp
|
||||
index 08c21538ddb638a2b98601bedf5bd00de2ae7c20..5b1bb31151962d8dd377525c6d765c9327d0d374 100644
|
||||
--- a/android/src/main/cpp/JavaScriptModuleObject.cpp
|
||||
+++ b/android/src/main/cpp/JavaScriptModuleObject.cpp
|
||||
@@ -145,7 +145,11 @@ void JavaScriptModuleObject::decorate(jsi::Runtime &runtime, jsi::Object *module
|
||||
for (auto &[name, classInfo]: classes) {
|
||||
auto &[classRef, constructor, ownerClass] = classInfo;
|
||||
auto classObject = classRef->cthis();
|
||||
- auto weakConstructor = std::weak_ptr(constructor);
|
||||
+
|
||||
+ // https://github.com/expo/expo/discussions/29610#discussioncomment-9762642
|
||||
+ // https://github.com/expo/expo/pull/29075/files
|
||||
+ auto weakConstructor = std::weak_ptr<decltype(constructor)::element_type>(constructor);
|
||||
+
|
||||
auto klass = SharedObject::createClass(
|
||||
runtime,
|
||||
name.c_str(),
|
73
.yarn/patches/react-native-drawer-npm-2.5.1-d9da0c325e.patch
Normal file
|
@ -0,0 +1,73 @@
|
|||
diff --git a/index.js b/index.js
|
||||
index ad60eccd16d503a5cdfdf67dcb02208b9ed22721..497a74cbd6e66114a2ecca0f7a7b387a145b483d 100644
|
||||
--- a/index.js
|
||||
+++ b/index.js
|
||||
@@ -117,24 +117,27 @@ export default class Drawer extends Component {
|
||||
this._childDrawer = drawer
|
||||
}
|
||||
|
||||
- componentWillMount() {
|
||||
- if (this.context.drawer) this.context.drawer._registerChildDrawer(this)
|
||||
+ componentDidMount() {
|
||||
+ this.resync(null, this.props);
|
||||
+ }
|
||||
+
|
||||
+ constructor(props) {
|
||||
+ super(props);
|
||||
+ if (this.drawer) this.drawer._registerChildDrawer(this)
|
||||
if (this.props.openDrawerThreshold && process.env.NODE_ENV !== 'production') console.error('react-native-drawer: openDrawerThreshold is obsolete. Use panThreshold instead.')
|
||||
if (this.props.panStartCompensation && process.env.NODE_ENV !== 'production') console.error('react-native-drawer: panStartCompensation is deprecated.')
|
||||
if (this.props.relativeDrag && process.env.NODE_ENV !== 'production') console.error('react-native-drawer: relativeDrag is deprecated.')
|
||||
this.initialize(this.props)
|
||||
}
|
||||
|
||||
- componentWillReceiveProps(nextProps) {
|
||||
- if (this.requiresResync(nextProps)) this.resync(null, nextProps)
|
||||
+ componentDidUpdate() {
|
||||
+ if (this.requiresResync(this.props)) this.resync(null, this.props)
|
||||
|
||||
- if (nextProps.open !== null && this._open !== nextProps.open) {
|
||||
- this._syncAfterUpdate = true
|
||||
- this._open = nextProps.open
|
||||
- }
|
||||
- }
|
||||
+ if (this.props.open !== null && this._open !== this.props.open) {
|
||||
+ this._syncAfterUpdate = true
|
||||
+ this._open = this.props.open
|
||||
+ }
|
||||
|
||||
- componentDidUpdate() {
|
||||
if (this._syncAfterUpdate) {
|
||||
this._syncAfterUpdate = false
|
||||
this._open ? this.open('force') : this.close('force')
|
||||
@@ -194,11 +197,10 @@ export default class Drawer extends Component {
|
||||
onMoveShouldSetPanResponderCapture: this.onMoveShouldSetPanResponderCapture,
|
||||
onPanResponderMove: this.onPanResponderMove,
|
||||
onPanResponderRelease: this.onPanResponderRelease,
|
||||
- onPanResponderTerminate: this.onPanResponderTerminate
|
||||
+ onPanResponderTerminate: this.onPanResponderTerminate
|
||||
})
|
||||
}
|
||||
|
||||
- this.resync(null, props)
|
||||
};
|
||||
|
||||
updatePosition = () => {
|
||||
@@ -398,7 +400,7 @@ export default class Drawer extends Component {
|
||||
duration: this.props.tweenDuration,
|
||||
easingType: this.props.tweenEasing,
|
||||
onFrame: (tweenValue) => {
|
||||
- this._length = Math.round(tweenValue*2)/2;
|
||||
+ this._length = Math.round(tweenValue*2)/2;
|
||||
this.updatePosition()
|
||||
},
|
||||
onEnd: () => {
|
||||
@@ -432,7 +434,7 @@ export default class Drawer extends Component {
|
||||
easingType: this.props.tweenEasing,
|
||||
duration: this.props.tweenDuration,
|
||||
onFrame: (tweenValue) => {
|
||||
- this._length = Math.round(tweenValue*2)/2;
|
||||
+ this._length = Math.round(tweenValue*2)/2;
|
||||
this.updatePosition()
|
||||
},
|
||||
onEnd: () => {
|
16
.yarn/plugins/@yarnpkg/plugin-fetch.cjs
vendored
Normal 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;
|
||||
}
|
||||
};
|
934
.yarn/releases/yarn-4.5.3.cjs
vendored
Executable file
11
.yarnrc.yml
Normal 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
|
22
Dockerfile
Normal file
|
@ -0,0 +1,22 @@
|
|||
FROM reactnativecommunity/react-native-android:9
|
||||
|
||||
RUN groupadd -g 1000 ubuntu && useradd -rm -d /home/ubuntu -s /bin/bash -g ubuntu -G sudo -u 1000 ubuntu
|
||||
|
||||
USER 1000
|
||||
WORKDIR /workspace
|
||||
|
||||
ENV HUSKY=0
|
||||
|
||||
COPY --chown=1000:1000 yarn.lock .yarnrc.yml ./
|
||||
COPY --chown=1000:1000 .yarn .yarn
|
||||
RUN yarn fetch --immutable
|
||||
COPY --chown=1000:1000 . .
|
||||
RUN yarn postinstall
|
||||
|
||||
RUN yarn expo prebuild
|
||||
|
||||
RUN cd android && \
|
||||
./gradlew assemble
|
||||
|
||||
ENV APP_PORT=19000
|
||||
CMD ["/bin/sh", "-c", "adb wait-for-device && yarn run android --port ${APP_PORT} && yarn start --port ${APP_PORT}"]
|
81
LICENSE.md
Normal 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).
|
||||
|
||||
* * *
|
16
android/.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
*.hprof
|
||||
.cxx/
|
||||
|
||||
# Bundle artifacts
|
||||
*.jsbundle
|
3
android/Gemfile
Normal file
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "fastlane"
|
225
android/app/build.gradle
Normal file
|
@ -0,0 +1,225 @@
|
|||
apply plugin: "com.android.application"
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()
|
||||
|
||||
static def versionToNumber(major, minor, patch) {
|
||||
return patch * 100 + minor * 10000 + major * 1000000
|
||||
}
|
||||
|
||||
def getRNVersion() {
|
||||
def version = providers.exec {
|
||||
workingDir(projectDir)
|
||||
commandLine("node", "-e", "console.log(require('react-native/package.json').version);")
|
||||
}.standardOutput.asText.get().trim()
|
||||
|
||||
def coreVersion = version.split("-")[0]
|
||||
def (major, minor, patch) = coreVersion.tokenize('.').collect { it.toInteger() }
|
||||
|
||||
return versionToNumber(
|
||||
major,
|
||||
minor,
|
||||
patch
|
||||
)
|
||||
}
|
||||
def rnVersion = getRNVersion()
|
||||
|
||||
/**
|
||||
* This is the configuration block to customize your React Native Android app.
|
||||
* By default you don't need to apply any configuration, just uncomment the lines you need.
|
||||
*/
|
||||
react {
|
||||
entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
|
||||
reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
|
||||
hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
|
||||
codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
|
||||
|
||||
// Use Expo CLI to bundle the app, this ensures the Metro config
|
||||
// works correctly with Expo projects.
|
||||
cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim())
|
||||
bundleCommand = "export:embed"
|
||||
|
||||
if (rnVersion >= versionToNumber(0, 75, 0)) {
|
||||
/* Autolinking */
|
||||
autolinkLibrariesWithApp()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean()
|
||||
|
||||
/**
|
||||
* The preferred build flavor of JavaScriptCore (JSC)
|
||||
*
|
||||
* For example, to use the international variant, you can use:
|
||||
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
|
||||
*
|
||||
* The international variant includes ICU i18n library and necessary data
|
||||
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
||||
* give correct results when using with locales other than en-US. Note that
|
||||
* this variant is about 6MiB larger per architecture than default.
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@sentry/react-native/package.json')"].execute().text.trim(), "../sentry.gradle")
|
||||
android {
|
||||
// @generated begin react-native-background-geolocation-project - expo prebuild (DO NOT MODIFY) sync-451bbca0f2f08c9fc8b21a201ef5b476b165ba21
|
||||
Project background_geolocation = project(':react-native-background-geolocation')
|
||||
apply from: "${background_geolocation.projectDir}/app.gradle"
|
||||
// @generated end react-native-background-geolocation-project
|
||||
// @generated begin react-native-background-fetch-project - expo prebuild (DO NOT MODIFY) sync-56d2d70cbc3f26369dd5e711d0ab87bf3c0aebb3
|
||||
Project background_fetch = project(':react-native-background-fetch')
|
||||
// @generated end react-native-background-fetch-project
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
// buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
compileSdk rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace 'com.alertesecours'
|
||||
defaultConfig {
|
||||
applicationId 'com.alertesecours'
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 176
|
||||
versionName "1.8.2"
|
||||
multiDexEnabled true
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
storePassword 'android'
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
release {
|
||||
storeFile file(RELEASE_STORE_FILE)
|
||||
storePassword RELEASE_STORE_PASSWORD
|
||||
keyAlias RELEASE_KEY_ALIAS
|
||||
keyPassword RELEASE_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://reactnative.dev/docs/signed-apk-android.
|
||||
signingConfig signingConfigs.release
|
||||
// shrinkResources true // disabled, related to https://github.com/facebook/react-native/issues/25290#issuecomment-507700557
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
// @generated begin react-native-background-geolocation-proguard - expo prebuild (DO NOT MODIFY) sync-606db7f838db1722ea0ff547adceb798272bd706
|
||||
proguardFiles "${background_geolocation.projectDir}/proguard-rules.pro"
|
||||
// @generated end react-native-background-geolocation-proguard
|
||||
// @generated begin react-native-background-fetch-proguard - expo prebuild (DO NOT MODIFY) sync-7cb5d9a88ae03463dcde5b7e8571a725ecd5854f
|
||||
proguardFiles "${background_fetch.projectDir}/proguard-rules.pro"
|
||||
// @generated end react-native-background-fetch-proguard
|
||||
crunchPngs false
|
||||
proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
|
||||
// Enable R8 full mode
|
||||
debuggable false
|
||||
jniDebuggable false
|
||||
renderscriptDebuggable false
|
||||
pseudoLocalesEnabled false
|
||||
zipAlignEnabled true
|
||||
// Generate and preserve the mapping file
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply static values from `gradle.properties` to the `android.packagingOptions`
|
||||
// Accepts values in comma delimited lists, example:
|
||||
// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini
|
||||
["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop ->
|
||||
// Split option: 'foo,bar' -> ['foo', 'bar']
|
||||
def options = (findProperty("android.packagingOptions.$prop") ?: "").split(",");
|
||||
// Trim all elements in place.
|
||||
for (i in 0..<options.size()) options[i] = options[i].trim();
|
||||
// `[] - ""` is essentially `[""].filter(Boolean)` removing all empty strings.
|
||||
options -= ""
|
||||
|
||||
if (options.length > 0) {
|
||||
println "android.packagingOptions.$prop += $options ($options.length)"
|
||||
// Ex: android.packagingOptions.pickFirsts += '**/SCCS/**'
|
||||
options.each {
|
||||
android.packagingOptions[prop] += it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
|
||||
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
|
||||
def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";
|
||||
|
||||
if (isGifEnabled) {
|
||||
// For animated gif support
|
||||
implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}")
|
||||
}
|
||||
|
||||
if (isWebpEnabled) {
|
||||
// For webp support
|
||||
implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}")
|
||||
if (isWebpAnimatedEnabled) {
|
||||
// Animated webp support
|
||||
implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}")
|
||||
}
|
||||
}
|
||||
|
||||
if (hermesEnabled.toBoolean()) {
|
||||
implementation("com.facebook.react:hermes-android")
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
androidTestImplementation('com.wix:detox:+')
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
}
|
||||
|
||||
if (rnVersion < versionToNumber(0, 75, 0)) {
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesAppBuildGradle(project)
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
||||
// Add this at the end of the file
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(com.android.build.OutputFile.ABI)
|
||||
if (abi != null) {
|
||||
output.versionCodeOverride = variant.versionCode * 1000 + versionCodes.get(abi, 0)
|
||||
}
|
||||
|
||||
output.outputFileName = "alertesecours-${variant.versionName}-${variant.buildType.name}.apk"
|
||||
}
|
||||
|
||||
if (variant.buildType.name == 'release') {
|
||||
variant.assembleProvider.get().doLast {
|
||||
copy {
|
||||
from variant.mappingFileProvider.get().singleFile
|
||||
into "${rootProject.buildDir}/outputs/mapping/${variant.name}"
|
||||
rename { String fileName ->
|
||||
"mapping-${variant.name}-${variant.versionName}.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
android/app/debug.keystore
Normal file
31
android/app/google-services.example.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "YOUR_PROJECT_NUMBER_HERE",
|
||||
"project_id": "YOUR_PROJECT_ID_HERE",
|
||||
"storage_bucket": "YOUR_STORAGE_BUCKET_HERE"
|
||||
},
|
||||
"client": [{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "YOUR_MOBILESDK_APP_ID_HERE",
|
||||
"android_client_info": {
|
||||
"package_name": "com.alertesecours"
|
||||
}
|
||||
},
|
||||
"oauth_client": [{
|
||||
"client_id": "YOUR_CLIENT_ID_HERE",
|
||||
"client_type": 3
|
||||
}],
|
||||
"api_key": [{
|
||||
"current_key": "YOUR_API_KEY_HERE"
|
||||
}],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [{
|
||||
"client_id": "YOUR_CLIENT_ID_HERE",
|
||||
"client_type": 3
|
||||
}]
|
||||
}
|
||||
}
|
||||
}],
|
||||
"configuration_version": "1"
|
||||
}
|
14
android/app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# react-native-reanimated
|
||||
-keep class com.swmansion.reanimated.** { *; }
|
||||
-keep class com.facebook.react.turbomodule.** { *; }
|
||||
|
||||
# Add any project specific keep options here:
|
|
@ -0,0 +1,29 @@
|
|||
package com.alertesecours; // (1)
|
||||
|
||||
import com.wix.detox.Detox;
|
||||
import com.wix.detox.config.DetoxConfig;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class DetoxTest {
|
||||
@Rule // (2)
|
||||
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
|
||||
|
||||
@Test
|
||||
public void runDetoxTests() {
|
||||
DetoxConfig detoxConfig = new DetoxConfig();
|
||||
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
|
||||
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
|
||||
detoxConfig.rnContextLoadTimeoutSec = (BuildConfig.DEBUG ? 180 : 60);
|
||||
|
||||
Detox.runTests(mActivityRule, detoxConfig);
|
||||
}
|
||||
}
|
7
android/app/src/debug/AndroidManifest.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" tools:replace="android:usesCleartextTraffic" />
|
||||
</manifest>
|
75
android/app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,75 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.CALL_PHONE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="https"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<data android:scheme="geo"/>
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<data android:scheme="waze"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:allowBackup="true" android:theme="@style/AppTheme" android:networkSecurityConfig="@xml/network_security_config">
|
||||
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/notification_icon_color" tools:replace="android:resource"/>
|
||||
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||
<meta-data android:name="com.transistorsoft.locationmanager.hms.license" android:value="ba479a3c61fbe471c826a39d1ee8b1a088df6d2249fad51f6ab5f24346f6bf87"/>
|
||||
<meta-data android:name="com.transistorsoft.locationmanager.license" android:value="90f34e070bebc8e433a9b604e1728dfa17a62ab484602e3cb7ef7ece784a23eb"/>
|
||||
<meta-data android:name="expo.modules.notifications.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||
<meta-data android:name="expo.modules.notifications.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||
<meta-data android:name="expo.modules.updates.CODE_SIGNING_CERTIFICATE" android:value="-----BEGIN CERTIFICATE-----
MIICzTCCAbWgAwIBAgIJR0KfFDoMJrYZMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNV
BAMTBHRlc3QwIBcNMjQwODE4MTU0OTExWhgPMjEyNDA4MTgxNTQ5MTFaMA8xDTAL
BgNVBAMTBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCk46qR
a0Do2fpBDtif18a/WQNWHm/xseHsh97bZdt8ooV4PQooK6VZUbADUhhJXqqomapa
yFMJX7sZzfBUF7/xMrWDrgS0R4FLbXijAolhpXoqMkBCx3toKUCbU4ljA+Lz/BX1
AEqVWqAweNzNDi4bvd1PG1/sQuuEtoZuSVfTPRAjF8vVkWyn8nfkorTtMYaw2QFu
ugs1wp7YieD4C8CIK5gMX7f8bxx3l7BR50bf+9MHJFI+eTjmoFoJFEVWbCcrOrky
FLM0+NrMI2fZYunrN6jcKc/NKEaDKb1VDO9yrLcFQOtXJJIXz94/lS6kHDjzEgUV
zx3uaDbAdSQsyZxxAgMBAAGjKjAoMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8E
DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEASIjMvS3N9NEPeakUmYXg
MEyjaX+N/62Pbcp4taU4G9vDB/fyDqMMef8+CWBpo/noXqzt4K6k1id7UwdZhRks
xdBTSf1x5yzDB24mbqNAvPa2q8G6KIoNZuvLUDz35366FxR+vTHQmp2d4Yz92kIL
EEmFr8eMHf60tfHG+em97p+evmXDyBjF3CwOvtuzog1wCF/AsJ1d0gbPPMKdAHKC
LZHsiXJ5i/oFuYzWkDDJkO9bb6HaQplt/46iC0CyM6SsT6H8kkDVQbfQCH1JAXsL
Knk10FbAMKJ7GWbAdsdcbNZlDMrzPprw8N/fpGc7RHdHBwKcFm44mNtrMrzEd4eX
pQ==
-----END CERTIFICATE-----
"/>
|
||||
<meta-data android:name="expo.modules.updates.CODE_SIGNING_METADATA" android:value="{"keyid":"main","alg":"rsa-v1_5-sha256"}"/>
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_RUNTIME_VERSION" android:value="@string/expo_runtime_version"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ERROR_RECOVERY_ONLY"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://expo-updates.alertesecours.fr/api/manifest?project=alerte-secours&channel=release"/>
|
||||
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="com.alertesecours"/>
|
||||
<data android:scheme="exp+alerte-secours"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alertesecours.OPEN_ALERT"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alertesecours.OPEN_RELATIVES"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true" data-generated="true">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<data android:scheme="https" android:host="app.alertesecours.fr" android:pathPrefix="/"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
|
||||
</application>
|
||||
</manifest>
|
61
android/app/src/main/java/com/alertesecours/MainActivity.kt
Normal file
|
@ -0,0 +1,61 @@
|
|||
package com.alertesecours
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
||||
import com.facebook.react.ReactActivity
|
||||
import com.facebook.react.ReactActivityDelegate
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate
|
||||
|
||||
import expo.modules.ReactActivityDelegateWrapper
|
||||
|
||||
class MainActivity : ReactActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// This is required for expo-splash-screen.
|
||||
setTheme(R.style.AppTheme);
|
||||
super.onCreate(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
override fun getMainComponentName(): String = "main"
|
||||
|
||||
/**
|
||||
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
|
||||
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
||||
*/
|
||||
override fun createReactActivityDelegate(): ReactActivityDelegate {
|
||||
return ReactActivityDelegateWrapper(
|
||||
this,
|
||||
BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
|
||||
object : DefaultReactActivityDelegate(
|
||||
this,
|
||||
mainComponentName,
|
||||
fabricEnabled
|
||||
){})
|
||||
}
|
||||
|
||||
/**
|
||||
* Align the back button behavior with Android S
|
||||
* where moving root activities to background instead of finishing activities.
|
||||
* @see <a href="https://developer.android.com/reference/android/app/Activity#onBackPressed()">onBackPressed</a>
|
||||
*/
|
||||
override fun invokeDefaultOnBackPressed() {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
if (!moveTaskToBack(false)) {
|
||||
// For non-root activities, use the default implementation to finish them.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Use the default back button implementation on Android S
|
||||
// because it's doing more than [Activity.moveTaskToBack] in fact.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.alertesecours
|
||||
|
||||
import android.app.Application
|
||||
import android.content.res.Configuration
|
||||
|
||||
import com.facebook.react.PackageList
|
||||
import com.facebook.react.ReactApplication
|
||||
import com.facebook.react.ReactNativeHost
|
||||
import com.facebook.react.ReactPackage
|
||||
import com.facebook.react.ReactHost
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
import expo.modules.ApplicationLifecycleDispatcher
|
||||
import expo.modules.ReactNativeHostWrapper
|
||||
|
||||
class MainApplication : Application(), ReactApplication {
|
||||
|
||||
override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
|
||||
this,
|
||||
object : DefaultReactNativeHost(this) {
|
||||
override fun getPackages(): List<ReactPackage> {
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
return PackageList(this).packages
|
||||
}
|
||||
|
||||
override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
|
||||
|
||||
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
|
||||
|
||||
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
||||
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
|
||||
}
|
||||
)
|
||||
|
||||
override val reactHost: ReactHost
|
||||
get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
SoLoader.init(this, false)
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
load()
|
||||
}
|
||||
ApplicationLifecycleDispatcher.onApplicationCreate(this)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
|
||||
}
|
||||
}
|
BIN
android/app/src/main/res/drawable-hdpi/notif_icon.png
Normal file
After Width: | Height: | Size: 692 B |
BIN
android/app/src/main/res/drawable-hdpi/notification_icon.png
Normal file
After Width: | Height: | Size: 903 B |
BIN
android/app/src/main/res/drawable-hdpi/splashscreen_image.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
android/app/src/main/res/drawable-mdpi/notif_icon.png
Normal file
After Width: | Height: | Size: 426 B |
BIN
android/app/src/main/res/drawable-mdpi/notification_icon.png
Normal file
After Width: | Height: | Size: 571 B |
BIN
android/app/src/main/res/drawable-mdpi/splashscreen_image.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/notif_icon.png
Normal file
After Width: | Height: | Size: 985 B |
BIN
android/app/src/main/res/drawable-xhdpi/notification_icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/splashscreen_image.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/notif_icon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/notification_icon.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/notif_icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/notification_icon.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png
Normal file
After Width: | Height: | Size: 160 KiB |
37
android/app/src/main/res/drawable/rn_edit_text_material.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetTop="@dimen/abc_edit_text_inset_top_material"
|
||||
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
|
||||
>
|
||||
|
||||
<selector>
|
||||
<!--
|
||||
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
|
||||
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
|
||||
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
|
||||
|
||||
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
|
||||
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
|
||||
-->
|
||||
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
|
||||
</selector>
|
||||
|
||||
</inset>
|
3
android/app/src/main/res/drawable/splashscreen.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/splashscreen_background"/>
|
||||
</layer-list>
|
BIN
android/app/src/main/res/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
android/app/src/main/res/mipmap-ldpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 30 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 36 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
android/app/src/main/res/playstore-icon.png
Normal file
After Width: | Height: | Size: 28 KiB |
1
android/app/src/main/res/values-night/colors.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<resources/>
|
7
android/app/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
<color name="splashscreen_background">#364fc7</color>
|
||||
<color name="iconBackground">#FFFFFF</color>
|
||||
<color name="colorPrimary">#023c69</color>
|
||||
<color name="colorPrimaryDark">#364fc7</color>
|
||||
<color name="notification_icon_color">#364fc7</color>
|
||||
</resources>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#364fc7</color>
|
||||
</resources>
|
7
android/app/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
<string name="app_name">Alerte Secours</string>
|
||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
|
||||
<string name="expo_runtime_version">1.0.0</string>
|
||||
</resources>
|
17
android/app/src/main/res/values/styles.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
<item name="android:editTextStyle">@style/ResetEditText</item>
|
||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="android:statusBarColor">#364fc7</item>
|
||||
</style>
|
||||
<style name="ResetEditText" parent="@android:style/Widget.EditText">
|
||||
<item name="android:padding">0dp</item>
|
||||
<item name="android:textColorHint">#c8c8c8</item>
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
</style>
|
||||
<style name="Theme.App.SplashScreen" parent="AppTheme">
|
||||
<item name="android:windowBackground">@drawable/splashscreen</item>
|
||||
</style>
|
||||
</resources>
|
7
android/app/src/main/res/xml/network_security_config.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">10.0.2.2</domain>
|
||||
<domain includeSubdomains="true">localhost</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
67
android/build.gradle
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
// @generated begin expo-gradle-ext-vars - expo prebuild (DO NOT MODIFY) sync-a14167d3df9d6380c3d77a8f8070215ea8a94013
|
||||
googlePlayServicesLocationVersion = "21.1.0"
|
||||
appCompatVersion = "1.4.2"
|
||||
// @generated end expo-gradle-ext-vars
|
||||
// buildToolsVersion = findProperty('android.buildToolsVersion') ?: '34.0.0'
|
||||
minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23')
|
||||
compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34')
|
||||
targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34')
|
||||
kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23'
|
||||
|
||||
ndkVersion = "26.1.10909125"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.gms:google-services:4.4.1'
|
||||
classpath('com.android.tools.build:gradle')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "com.facebook.react.rootproject"
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
// @generated begin react-native-background-fetch-maven - expo prebuild (DO NOT MODIFY) sync-b86324ce2eb77b03cc8b69ba206ef8275cd006ff
|
||||
maven { url "${project(":react-native-background-fetch").projectDir}/libs" }
|
||||
// @generated begin react-native-background-geolocation-maven - expo prebuild (DO NOT MODIFY) sync-4b2bae87fd8579c445d8885f6bdc8542d9d0bbca
|
||||
maven { url "${project(":react-native-background-geolocation").projectDir}/libs" }
|
||||
maven { url 'https://developer.huawei.com/repo/' }
|
||||
// @generated end react-native-background-geolocation-maven
|
||||
// @generated end react-native-background-fetch-maven
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android'))
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist'))
|
||||
}
|
||||
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
maven {
|
||||
url "$rootDir/../node_modules/@notifee/react-native/android/libs"
|
||||
}
|
||||
|
||||
// https://github.com/Lyokone/flutterlocation/issues/802#issuecomment-1415980821
|
||||
// configurations.all {
|
||||
// resolutionStrategy {
|
||||
// force "com.google.android.gms:play-services-location:21.0.1"
|
||||
// }
|
||||
// }
|
||||
|
||||
maven {
|
||||
url("$rootDir/../node_modules/detox/Detox-android")
|
||||
}
|
||||
}
|
||||
}
|
2
android/fastlane/Appfile
Normal file
|
@ -0,0 +1,2 @@
|
|||
json_key_file("keys/alerte-secours-449609-469f820e5960.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
|
||||
package_name("com.alertesecours") # e.g. com.krausefx.app
|
38
android/fastlane/Fastfile
Normal file
|
@ -0,0 +1,38 @@
|
|||
# This file contains the fastlane.tools configuration
|
||||
# You can find the documentation at https://docs.fastlane.tools
|
||||
#
|
||||
# For a list of all available actions, check out
|
||||
#
|
||||
# https://docs.fastlane.tools/actions
|
||||
#
|
||||
# For a list of all available plugins, check out
|
||||
#
|
||||
# https://docs.fastlane.tools/plugins/available-plugins
|
||||
#
|
||||
|
||||
# Uncomment the line if you want fastlane to automatically update itself
|
||||
# update_fastlane
|
||||
|
||||
default_platform(:android)
|
||||
|
||||
platform :android do
|
||||
desc "Runs all the tests"
|
||||
lane :test do
|
||||
gradle(task: "test")
|
||||
end
|
||||
|
||||
desc "Submit a new Beta Build to Crashlytics Beta"
|
||||
lane :beta do
|
||||
gradle(task: "clean assembleRelease")
|
||||
crashlytics
|
||||
|
||||
# sh "your_script.sh"
|
||||
# You can also use other beta testing services here
|
||||
end
|
||||
|
||||
desc "Deploy a new version to the Google Play"
|
||||
lane :deploy do
|
||||
gradle(task: "clean assembleRelease")
|
||||
upload_to_play_store
|
||||
end
|
||||
end
|
66
android/gradle.properties
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
|
||||
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
# Enable AAPT2 PNG crunching
|
||||
android.enablePngCrunchInReleaseBuilds=true
|
||||
|
||||
# Use this property to specify which architecture you want to build.
|
||||
# You can also override it from the CLI using
|
||||
# ./gradlew <task> -PreactNativeArchitectures=x86_64
|
||||
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
|
||||
# Use this property to enable support to the new architecture.
|
||||
# This will allow you to use TurboModules and the Fabric render in
|
||||
# your application. You should enable this flag either if you want
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
|
||||
# Use this property to enable or disable the Hermes JS engine.
|
||||
# If set to false, you will be using JSC instead.
|
||||
hermesEnabled=true
|
||||
|
||||
# Enable GIF support in React Native images (~200 B increase)
|
||||
expo.gif.enabled=true
|
||||
# Enable webp support in React Native images (~85 KB increase)
|
||||
expo.webp.enabled=true
|
||||
# Enable animated webp support (~3.4 MB increase)
|
||||
# Disabled by default because iOS doesn't support animated webp
|
||||
expo.webp.animated=false
|
||||
|
||||
# Enable network inspector
|
||||
EX_DEV_CLIENT_NETWORK_INSPECTOR=true
|
||||
|
||||
# Use legacy packaging to compress native libraries in the resulting APK.
|
||||
expo.useLegacyPackaging=false
|
||||
|
||||
android.extraMavenRepos=[]
|
||||
|
||||
android.enableProguardInReleaseBuilds=true
|
||||
|
||||
# fix notifee + expo-update crash, see https://github.com/expo/expo/issues/15298
|
||||
EX_UPDATES_ANDROID_DELAY_LOAD_APP=false
|
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
249
android/gradlew
vendored
Executable file
|
@ -0,0 +1,249 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
92
android/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
19
android/react-settings-plugin/build.gradle.kts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.9.24"
|
||||
id("java-gradle-plugin")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("reactSettingsPlugin") {
|
||||
id = "com.facebook.react.settings"
|
||||
implementationClass = "expo.plugins.ReactSettingsPlugin"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package expo.plugins
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.initialization.Settings
|
||||
|
||||
class ReactSettingsPlugin : Plugin<Settings> {
|
||||
override fun apply(settings: Settings) {
|
||||
// Do nothing, just register the plugin.
|
||||
}
|
||||
}
|
4
android/sentry.properties
Normal file
|
@ -0,0 +1,4 @@
|
|||
defaults.url=https://sentry.io
|
||||
defaults.org=devthefuture-40
|
||||
defaults.project=alertesecours-application
|
||||
# Using SENTRY_AUTH_TOKEN environment variable
|
66
android/settings.gradle
Normal file
|
@ -0,0 +1,66 @@
|
|||
pluginManagement {
|
||||
def version = providers.exec {
|
||||
commandLine("node", "-e", "console.log(require('react-native/package.json').version);")
|
||||
}.standardOutput.asText.get().trim()
|
||||
def (_, reactNativeMinor, reactNativePatch) = version.split("-")[0].tokenize('.').collect { it.toInteger() }
|
||||
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile().toString())
|
||||
if(reactNativeMinor == 74 && reactNativePatch <= 3){
|
||||
includeBuild("react-settings-plugin")
|
||||
}
|
||||
}
|
||||
|
||||
plugins { id("com.facebook.react.settings") }
|
||||
|
||||
def getRNMinorVersion() {
|
||||
def version = providers.exec {
|
||||
commandLine("node", "-e", "console.log(require('react-native/package.json').version);")
|
||||
}.standardOutput.asText.get().trim()
|
||||
|
||||
def coreVersion = version.split("-")[0]
|
||||
def (major, minor, patch) = coreVersion.tokenize('.').collect { it.toInteger() }
|
||||
|
||||
return minor
|
||||
}
|
||||
|
||||
if (getRNMinorVersion() >= 75) {
|
||||
extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
|
||||
if (System.getenv('EXPO_UNSTABLE_CORE_AUTOLINKING') == '1') {
|
||||
println('\u001B[32mUsing expo-modules-autolinking as core autolinking source\u001B[0m')
|
||||
def command = [
|
||||
'node',
|
||||
'--no-warnings',
|
||||
'--eval',
|
||||
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
|
||||
'react-native-config',
|
||||
'--json',
|
||||
'--platform',
|
||||
'android'
|
||||
].toList()
|
||||
ex.autolinkLibrariesFromCommand(command)
|
||||
} else {
|
||||
ex.autolinkLibrariesFromCommand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'Alerte Secours'
|
||||
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
reactAndroidLibs {
|
||||
from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
||||
useExpoModules()
|
||||
|
||||
if (getRNMinorVersion() < 75) {
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
applyNativeModulesSettingsGradle(settings)
|
||||
}
|
||||
|
||||
include ':app'
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile())
|
209
app.config.js
Normal file
|
@ -0,0 +1,209 @@
|
|||
const packageJson = require("./package.json");
|
||||
const { version, customExpoVersioning } = packageJson;
|
||||
const withXcode15Fix = require("./plugins/withXcode15Fix");
|
||||
|
||||
let config = {
|
||||
expo: {
|
||||
name: "Alerte Secours",
|
||||
slug: "alerte-secours",
|
||||
runtimeVersion: `${version.split(".")[0]}.0.0`,
|
||||
version,
|
||||
updates: {
|
||||
url: "https://expo-updates.alertesecours.fr/api/manifest?project=alerte-secours&channel=release",
|
||||
enabled: true,
|
||||
checkAutomatically: "ON_ERROR_RECOVERY",
|
||||
fallbackToCacheTimeout: 0,
|
||||
codeSigningCertificate: "./keys/certificate.pem",
|
||||
codeSigningPrivateKey: "./keys/private-key.pem",
|
||||
codeSigningMetadata: {
|
||||
keyid: "main",
|
||||
alg: "rsa-v1_5-sha256",
|
||||
},
|
||||
},
|
||||
orientation: "portrait",
|
||||
userInterfaceStyle: "automatic",
|
||||
splash: {
|
||||
image: "./src/assets/img/splashscreen.png",
|
||||
backgroundColor: "#364fc7",
|
||||
resizeMode: "contain",
|
||||
},
|
||||
// Add notification configuration at root level
|
||||
notification: {
|
||||
androidMode: "default",
|
||||
androidCollapsedTitle: "#{unread_notifications} nouvelles notifications",
|
||||
// Use mipmap for the notification icon
|
||||
icon: "./src/assets/img/notification-android.png",
|
||||
color: "#364fc7",
|
||||
},
|
||||
platforms: ["ios", "android"],
|
||||
android: {
|
||||
versionCode: customExpoVersioning.versionCode,
|
||||
googleServicesFile:
|
||||
process.env.ANDROID_GOOGLE_SERVICES_FILE_PATH ||
|
||||
"./android/app/google-services.json",
|
||||
package: "com.alertesecours",
|
||||
intentFilters: [
|
||||
{
|
||||
action: "VIEW",
|
||||
data: {
|
||||
scheme: "https",
|
||||
host: "app.alertesecours.fr",
|
||||
pathPrefix: "/",
|
||||
},
|
||||
category: ["BROWSABLE", "DEFAULT"],
|
||||
autoVerify: true,
|
||||
},
|
||||
],
|
||||
permissions: [
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.CALL_PHONE",
|
||||
"android.permission.INTERNET",
|
||||
"android.permission.MODIFY_AUDIO_SETTINGS",
|
||||
"android.permission.READ_CONTACTS",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.RECORD_AUDIO",
|
||||
"android.permission.SYSTEM_ALERT_WINDOW",
|
||||
"android.permission.VIBRATE",
|
||||
"android.permission.WRITE_CONTACTS",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
},
|
||||
ios: {
|
||||
buildNumber: customExpoVersioning.buildNumber.toString(),
|
||||
googleServicesFile:
|
||||
process.env.IOS_GOOGLE_SERVICES_FILE_PATH ||
|
||||
"./ios/GoogleService-Info.plist",
|
||||
userInterfaceStyle: "automatic",
|
||||
supportsTablet: true,
|
||||
bundleIdentifier: "com.alertesecours.alertesecours",
|
||||
associatedDomains: ["applinks:app.alertesecours.fr"],
|
||||
icon: "./src/assets/img/logo.png",
|
||||
entitlements: {
|
||||
"aps-environment": "production",
|
||||
},
|
||||
config: {
|
||||
usesNonExemptEncryption: false,
|
||||
},
|
||||
infoPlist: {
|
||||
NSCameraUsageDescription:
|
||||
"Alerte-Secours requiert l'accès à votre caméra pour vous permettre de prendre une photo de profil. Cette fonctionnalité est utilisée uniquement lors de la personnalisation de votre compte.",
|
||||
NSContactsUsageDescription:
|
||||
"Alerte-Secours demande l'accès à vos contacts pour afficher les noms associés aux numéros de téléphone. Ces informations restent strictement sur votre appareil et ne sont jamais partagées ni transmises à des tiers.",
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription:
|
||||
"Alerte-Secours nécessite la localisation en arrière-plan pour vous alerter en temps réel lorsqu'une personne à proximité a besoin d'aide urgente. Cette fonction est essentielle pour permettre une intervention rapide et efficace en cas d'urgence.",
|
||||
NSLocationWhenInUseUsageDescription:
|
||||
"Alerte-Secours utilise votre localisation pour identifier et vous diriger vers les personnes nécessitant une assistance à proximité. Cette fonction est cruciale pour une intervention rapide et précise en cas d'urgence.",
|
||||
NSLocationAccuracyReduced:
|
||||
"Alerte-Secours nécessite une localisation précise pour optimiser l'assistance aux personnes en détresse. Cette précision est essentielle pour localiser efficacement et rejoindre rapidement les personnes ayant besoin d'aide.",
|
||||
NSMicrophoneUsageDescription:
|
||||
"Alerte-Secours requiert l'accès au microphone pour l'enregistrement de messages vocaux. Cette fonction permet une communication plus rapide et plus claire en situation d'urgence.",
|
||||
NSMotionUsageDescription:
|
||||
"Alerte-Secours utilise la détection de mouvement pour optimiser la géolocalisation en arrière-plan, réduisant ainsi la consommation de batterie. Aucune donnée de mouvement n'est stockée ni transmise.",
|
||||
NSPhotoLibraryUsageDescription:
|
||||
"Alerte-Secours demande l'accès à votre photothèque uniquement pour vous permettre de sélectionner une photo de profil. Cette fonctionnalité est utilisée exclusivement pour la personnalisation de votre compte.",
|
||||
NSUserNotificationUsageDescription:
|
||||
"Alerte-Secours utilise les notifications pour vous informer immédiatement lorsqu'une personne à proximité nécessite une assistance urgente. Ces alertes sont essentielles pour une réponse rapide aux situations d'urgence.",
|
||||
LSApplicationQueriesSchemes: [
|
||||
"http",
|
||||
"https",
|
||||
"comgooglemaps",
|
||||
"maps",
|
||||
"waze",
|
||||
"citymapper",
|
||||
"uber",
|
||||
"lyft",
|
||||
"transit",
|
||||
"truckmap",
|
||||
"waze-na",
|
||||
"yandexnavi",
|
||||
"moovit",
|
||||
"yandexmaps",
|
||||
"kakaomap",
|
||||
"szn-mapy",
|
||||
"mapsme",
|
||||
"osmand",
|
||||
"gett",
|
||||
"nmap",
|
||||
"dgis",
|
||||
"tel",
|
||||
"telprompt",
|
||||
],
|
||||
},
|
||||
UIBackgroundModes: ["location", "fetch", "processing"],
|
||||
BGTaskSchedulerPermittedIdentifiers: [
|
||||
"com.transistorsoft.fetch",
|
||||
"com.transistorsoft.customtask",
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
[
|
||||
"react-native-background-geolocation",
|
||||
{
|
||||
license: process.env.BACKGROUND_GEOLOCATION_LICENSE,
|
||||
hmsLicense: process.env.BACKGROUND_GEOLOCATION_HMS_LICENSE,
|
||||
},
|
||||
],
|
||||
[
|
||||
"expo-gradle-ext-vars",
|
||||
{
|
||||
googlePlayServicesLocationVersion: "21.1.0",
|
||||
appCompatVersion: "1.4.2",
|
||||
},
|
||||
],
|
||||
"react-native-background-fetch",
|
||||
"@maplibre/maplibre-react-native",
|
||||
"expo-location",
|
||||
"react-native-map-link",
|
||||
"expo-localization",
|
||||
"expo-secure-store",
|
||||
[
|
||||
"@sentry/react-native/expo",
|
||||
{
|
||||
url: process.env.SENTRY_URL,
|
||||
organization: process.env.SENTRY_ORG,
|
||||
project: process.env.SENTRY_PROJECT,
|
||||
android: {
|
||||
// Android release name format
|
||||
release: `com.alertesecours@${version}+${customExpoVersioning.versionCode}`,
|
||||
},
|
||||
ios: {
|
||||
// iOS release name format
|
||||
release: `com.alertesecours.alertesecours@${version}+${customExpoVersioning.buildNumber}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
"@react-native-firebase/app",
|
||||
"@react-native-firebase/messaging",
|
||||
[
|
||||
// see https://rnfirebase.io/#configure-react-native-firebase-modules
|
||||
"expo-build-properties",
|
||||
{
|
||||
ios: {
|
||||
useFrameworks: "static",
|
||||
},
|
||||
android: {
|
||||
enableProguardInReleaseBuilds: true,
|
||||
enableDexGuardInReleaseBuilds: true,
|
||||
extraProperties: {
|
||||
"android.nonTransitiveRClass": true,
|
||||
"android.useAndroidX": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"./plugins/withXcode15Fix",
|
||||
"./plugins/withCustomScheme", // Preserve URL schemes during prebuild
|
||||
],
|
||||
// Disable Flipper
|
||||
extra: {
|
||||
flipperEnabled: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Apply plugins
|
||||
config = withXcode15Fix(config);
|
||||
config = require("./plugins/withCustomScheme")(config);
|
||||
|
||||
module.exports = config;
|
82
babel.config.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
const crypto = require("crypto");
|
||||
|
||||
const envVars = [
|
||||
"CLAIMS_NAMESPACE",
|
||||
|
||||
"APP_MINIO_URL",
|
||||
"APP_OA_FILES_URL",
|
||||
"APP_GRAPHQL_URL",
|
||||
"APP_GRAPHQL_WS_URL",
|
||||
"APP_GEOLOC_SYNC_URL",
|
||||
|
||||
"STAGING_APP_MINIO_URL",
|
||||
"STAGING_APP_OA_FILES_URL",
|
||||
"STAGING_APP_GRAPHQL_URL",
|
||||
"STAGING_APP_GRAPHQL_WS_URL",
|
||||
"STAGING_APP_GEOLOC_SYNC_URL",
|
||||
|
||||
"APP_OSRM_CAR_URL",
|
||||
"APP_OSRM_FOOT_URL",
|
||||
"APP_OSRM_BICYCLE_URL",
|
||||
"APP_MAPVIEW_STYLE_URL",
|
||||
"APP_MAPVIEW_DARK_STYLE_URL",
|
||||
"APP_LOG_SCOPES",
|
||||
"APP_LOG_MIN_LEVEL",
|
||||
"LOCAL_DEV",
|
||||
"SENTRY_DSN",
|
||||
"BUILD_TIME",
|
||||
];
|
||||
|
||||
function getEnvHash() {
|
||||
// List of variables used in transform-inline-environment-variables
|
||||
|
||||
// Create a sorted string of env var values
|
||||
const envString = envVars
|
||||
.sort()
|
||||
.map((key) => `${key}=${process.env[key] || ""}`)
|
||||
.join("|");
|
||||
|
||||
// Create hash
|
||||
return crypto.createHash("md5").update(envString).digest("hex");
|
||||
}
|
||||
|
||||
module.exports = function (api) {
|
||||
// Invalidate cache based on env vars hash, see also https://github.com/babel/minify/issues/919
|
||||
api.cache.invalidate(() => getEnvHash());
|
||||
|
||||
return {
|
||||
presets: ["babel-preset-expo"],
|
||||
env: {
|
||||
production: {
|
||||
plugins: ["react-native-paper/babel"],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
["@babel/plugin-transform-flow-strip-types"],
|
||||
["@babel/plugin-proposal-class-properties", { loose: true }],
|
||||
["@babel/plugin-proposal-private-methods", { loose: true }],
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
root: ["./src"],
|
||||
alias: {
|
||||
"~": "./src",
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"transform-inline-environment-variables",
|
||||
{
|
||||
include: envVars,
|
||||
},
|
||||
],
|
||||
[
|
||||
"react-native-reanimated/plugin",
|
||||
{
|
||||
relativeSourceLocation: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
};
|
152
cline_docs/productContext.md
Normal file
|
@ -0,0 +1,152 @@
|
|||
# Product Context
|
||||
|
||||
## 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.
|
||||
|
||||
## Core Features
|
||||
1. Deep Linking:
|
||||
- Alert sharing via URLs
|
||||
- Direct navigation to specific alerts
|
||||
- Support for both:
|
||||
* Universal Links (https://app.alertesecours.fr/...)
|
||||
* Custom scheme (com.alertesecours.alertesecours://)
|
||||
- Seamless user experience from web to app
|
||||
|
||||
2. Authentication & Registration:
|
||||
- Phone number registration with SMS verification
|
||||
- Account connection with SMS verification
|
||||
- Email-based authentication option
|
||||
- Visual feedback for authentication processes
|
||||
- Timeout handling for better user experience
|
||||
|
||||
2. Alert Management:
|
||||
- Alert creation and handling
|
||||
- Real-time updates
|
||||
- Alert information display
|
||||
- Alert level management
|
||||
|
||||
3. Communication:
|
||||
- Chat/Messaging system:
|
||||
* Alert-specific chat rooms
|
||||
* Aggregated message view
|
||||
* Real-time message updates
|
||||
* Message history
|
||||
* User identification in chats
|
||||
* Message status indicators
|
||||
* Audio message support
|
||||
- SMS notifications
|
||||
- Push notifications (via Firebase FCM)
|
||||
|
||||
4. Location & Mapping:
|
||||
- Map integration
|
||||
- Location-based features
|
||||
|
||||
5. User Management:
|
||||
- Profile management
|
||||
- Phone number management
|
||||
- Privacy settings
|
||||
- Account settings
|
||||
|
||||
## User Flows
|
||||
|
||||
### Deep Link Navigation:
|
||||
1. Alert Sharing:
|
||||
- User receives alert link (SMS, email, etc.)
|
||||
- Clicking link opens app directly
|
||||
- App validates alert access code
|
||||
- Navigation to specific alert view
|
||||
- Location coordinates preserved
|
||||
|
||||
2. Web to App Transition:
|
||||
- User visits web URL
|
||||
- Seamless transition to app if installed
|
||||
- Fallback to web if app not installed
|
||||
- Consistent experience across platforms
|
||||
|
||||
### Phone Number Registration:
|
||||
1. User clicks "Enregistrer mon numéro de téléphone"
|
||||
2. SMS disclaimer appears for confirmation
|
||||
3. Upon acceptance:
|
||||
- Navigation to Profile scene
|
||||
- Loading indicator shows on registration button
|
||||
- SMS code is sent
|
||||
- Loading clears on success or timeout
|
||||
|
||||
### Account Connection:
|
||||
1. User clicks "Se connecter"
|
||||
2. SMS disclaimer appears for confirmation
|
||||
3. Upon acceptance:
|
||||
- Navigation to Profile scene
|
||||
- Account management modal opens
|
||||
- Loading indicator shows in modal
|
||||
- SMS code is sent
|
||||
- Loading clears on success or timeout
|
||||
|
||||
### Chat System:
|
||||
1. Alert-Specific Chat:
|
||||
- Users can view messages for a specific alert
|
||||
- Real-time message updates
|
||||
- Message status indicators
|
||||
- Audio message support
|
||||
- User identification
|
||||
|
||||
2. Aggregated Messages:
|
||||
- View messages from all alerts
|
||||
- Alert context with each message
|
||||
- Quick navigation to specific alerts
|
||||
- Distance information
|
||||
- Real-time updates
|
||||
|
||||
3. Message Interactions:
|
||||
- Text message sending
|
||||
- Audio message recording/playback
|
||||
- Message status tracking
|
||||
- User presence indication
|
||||
- Scroll position management
|
||||
- New message indicators
|
||||
|
||||
### Profile Management:
|
||||
- Phone number addition/removal
|
||||
- Privacy settings configuration
|
||||
- Account connection/disconnection
|
||||
- Profile information management
|
||||
|
||||
## Integration Points
|
||||
- Firebase (used only for FCM push notifications)
|
||||
- GraphQL (using Hasura server with federated remote schemas)
|
||||
- Sentry for error tracking
|
||||
|
||||
## User Experience Considerations
|
||||
1. Loading States:
|
||||
- Context-specific loading indicators
|
||||
- Clear visual feedback for actions
|
||||
- Reasonable timeouts (3 minutes)
|
||||
- Automatic clearing on success
|
||||
|
||||
2. Theme Support:
|
||||
- Dark and light theme compatibility
|
||||
- Consistent visual feedback
|
||||
- Accessible color schemes
|
||||
|
||||
3. Error Handling:
|
||||
- Clear error messages
|
||||
- Timeout handling
|
||||
- Network error management
|
||||
- Graceful fallbacks
|
||||
|
||||
4. Chat Experience:
|
||||
- Smooth message delivery
|
||||
- Clear message status
|
||||
- Easy navigation between views
|
||||
- Proper scroll management
|
||||
- Clear user identification
|
||||
- Efficient message loading
|
||||
|
||||
## Target Users
|
||||
*To be documented*
|
||||
|
||||
## Business Objectives
|
||||
*To be documented*
|
||||
|
||||
## Core User Workflows
|
||||
*Additional workflows to be documented*
|
161
cline_docs/progress.md
Normal file
|
@ -0,0 +1,161 @@
|
|||
# Progress Tracking
|
||||
|
||||
## Recently Completed Features
|
||||
|
||||
### Push Notification Improvements
|
||||
1. Background Notification Fixes:
|
||||
- ✅ Added required Android permissions
|
||||
- ✅ Enhanced notification channel configuration
|
||||
- ✅ Consolidated background message handling
|
||||
- ✅ Improved iOS critical notification settings
|
||||
- ✅ Fixed sound playing in all states
|
||||
|
||||
2. Implementation Details:
|
||||
- ✅ High importance notification channel
|
||||
- ✅ Proper background event handling
|
||||
- ✅ Critical notifications for iOS
|
||||
- ✅ Sound configuration for all states
|
||||
|
||||
### Deep Linking Fix
|
||||
1. iOS Configuration:
|
||||
- ✅ Updated Info.plist URL schemes
|
||||
- ✅ Added proper CFBundleURLName entries
|
||||
- ✅ Configured Universal Links support
|
||||
- ✅ Updated apple-app-site-association file
|
||||
- ✅ Created withCustomScheme plugin to preserve URL schemes during prebuild
|
||||
|
||||
2. Implementation:
|
||||
- ✅ Proper URL scheme handling
|
||||
- ✅ Universal Links support
|
||||
- ✅ Expo Linking integration
|
||||
- ✅ Deep link parsing logic
|
||||
- ✅ URL scheme preservation during prebuild
|
||||
|
||||
### Chat System Improvements
|
||||
1. Message Isolation Fix:
|
||||
- ✅ Fixed chat message mixing between views
|
||||
- ✅ Proper subscription cleanup implementation
|
||||
- ✅ Cache isolation between views
|
||||
- ✅ Improved error handling
|
||||
- ✅ Added detailed logging
|
||||
|
||||
2. Component Refactoring:
|
||||
- ✅ Shared utils extraction
|
||||
- ✅ Better state management
|
||||
- ✅ Improved subscription lifecycle
|
||||
|
||||
### Authentication & Registration
|
||||
1. Phone Number Registration:
|
||||
- ✅ Registration button in Relatives scene
|
||||
- ✅ SMS disclaimer modal
|
||||
- ✅ Navigation to Profile with waitingSmsType="R"
|
||||
- ✅ Loading indicator on registration button
|
||||
- ✅ 3-minute timeout
|
||||
- ✅ Loading clears on login request
|
||||
|
||||
2. Account Connection:
|
||||
- ✅ Login button in Relatives scene
|
||||
- ✅ SMS disclaimer modal
|
||||
- ✅ Navigation to Profile with waitingSmsType="C"
|
||||
- ✅ Account management modal auto-opening
|
||||
- ✅ Loading indicator in modal
|
||||
- ✅ 3-minute timeout
|
||||
- ✅ Loading clears on login request
|
||||
|
||||
3. UI Improvements:
|
||||
- ✅ Theme-aware loading animations
|
||||
- ✅ Context-specific loading states
|
||||
- ✅ Proper hook implementations
|
||||
- ✅ Consistent styling
|
||||
|
||||
## In Progress
|
||||
|
||||
### Push Notification Monitoring
|
||||
1. Notification Delivery:
|
||||
- ⏳ Monitor sound consistency
|
||||
- ⏳ Verify notification persistence
|
||||
- ⏳ Test various device states
|
||||
- ⏳ Document edge cases
|
||||
|
||||
### Chat System Monitoring
|
||||
1. Subscription Management:
|
||||
- ⏳ Monitor subscription cleanup logs
|
||||
- ⏳ Verify cache isolation
|
||||
- ⏳ Test view switching behavior
|
||||
- ⏳ Performance impact analysis
|
||||
|
||||
### Testing Requirements
|
||||
1. Registration Flow:
|
||||
- ⏳ SMS sending verification
|
||||
- ⏳ Navigation to Profile
|
||||
- ⏳ Button loading state
|
||||
- ⏳ Loading timeout
|
||||
- ⏳ Login request handling
|
||||
|
||||
2. Login Flow:
|
||||
- ⏳ SMS sending verification
|
||||
- ⏳ Navigation to Profile
|
||||
- ⏳ Modal auto-opening
|
||||
- ⏳ Modal loading state
|
||||
- ⏳ Loading timeout
|
||||
- ⏳ Login request handling
|
||||
|
||||
3. Theme Testing:
|
||||
- ⏳ Light theme loading visibility
|
||||
- ⏳ Dark theme loading visibility
|
||||
- ⏳ Animation color filters
|
||||
|
||||
## Pending
|
||||
1. Documentation:
|
||||
- ⏳ Development setup instructions
|
||||
- ⏳ Complete dependency list
|
||||
- ⏳ Performance constraints
|
||||
- ⏳ Technical limitations
|
||||
|
||||
2. Future Improvements:
|
||||
- ⏳ Multilingual support implementation
|
||||
- ⏳ Additional error handling scenarios
|
||||
- ⏳ Performance optimizations
|
||||
- ⏳ Accessibility improvements
|
||||
|
||||
## Known Issues
|
||||
1. Chat System:
|
||||
- ✅ Message mixing between views (FIXED)
|
||||
- ✅ Subscription cleanup issues (FIXED)
|
||||
- ✅ Cache isolation problems (FIXED)
|
||||
|
||||
2. Deep Linking:
|
||||
- ✅ URL schemes lost during prebuild (FIXED)
|
||||
- ✅ Missing CFBundleURLName entries (FIXED)
|
||||
|
||||
## Testing Status
|
||||
1. Unit Tests:
|
||||
- ⏳ Hook implementations
|
||||
- ⏳ Component rendering
|
||||
- ⏳ Loading state management
|
||||
- ⏳ Deep link parsing logic
|
||||
|
||||
2. Integration Tests:
|
||||
- ⏳ Navigation flows
|
||||
- ⏳ SMS handling
|
||||
- ⏳ Login request handling
|
||||
- ⏳ Chat subscription management
|
||||
- ⏳ Deep linking flows:
|
||||
* Custom URL scheme handling
|
||||
* Universal Links handling
|
||||
* Initial URL processing
|
||||
* Runtime URL handling
|
||||
|
||||
3. E2E Tests:
|
||||
- ⏳ Registration flow
|
||||
- ⏳ Login flow
|
||||
- ⏳ Theme switching
|
||||
- ⏳ Chat view switching
|
||||
|
||||
## Next Steps
|
||||
1. Monitor chat system improvements
|
||||
2. Complete testing requirements
|
||||
3. Document any issues found
|
||||
4. Implement necessary fixes
|
||||
5. Update documentation with findings
|
||||
6. Plan future improvements
|
193
cline_docs/systemPatterns.md
Normal file
|
@ -0,0 +1,193 @@
|
|||
# System Patterns
|
||||
|
||||
## Architecture Overview
|
||||
- React Native mobile application
|
||||
- GraphQL with Hasura backend
|
||||
- Federation of remote schemas
|
||||
- Real-time subscriptions support
|
||||
- Custom business logic through remote schemas
|
||||
- Firebase for FCM push notifications
|
||||
- Component-based architecture
|
||||
|
||||
## Key Technical Patterns
|
||||
|
||||
### GraphQL Subscription Management
|
||||
1. Subscription Lifecycle:
|
||||
- Unique subscriptionKey for each subscription instance
|
||||
- Unconditional cleanup in useEffect hooks
|
||||
- Proper cleanup on:
|
||||
* Component unmount
|
||||
* Variables change
|
||||
* Skip condition change
|
||||
- Detailed logging for debugging
|
||||
|
||||
2. Cache Management:
|
||||
- Isolated cache contexts:
|
||||
* Alert-specific: `alert:${alertId}`
|
||||
* Aggregate view: `aggregate-messages`
|
||||
- Cache cleanup on:
|
||||
* Component mount
|
||||
* Component unmount
|
||||
* Variables change
|
||||
- Strict message filtering by alertId
|
||||
|
||||
3. Message Handling:
|
||||
- Alert-specific filtering
|
||||
- Aggregate view with oneAlert field
|
||||
- Optimistic updates per cache context
|
||||
|
||||
### State Management
|
||||
- Apollo Client for GraphQL state management
|
||||
- Local stores for app state
|
||||
- Loading states tied to specific actions (e.g., SMS type)
|
||||
|
||||
### Component Structure
|
||||
1. Components (src/components/)
|
||||
- Reusable UI components
|
||||
- Presentational components
|
||||
- Theme-aware components (e.g., LittleLoader)
|
||||
|
||||
2. Containers (src/containers/)
|
||||
- Business logic components
|
||||
- Data-fetching components
|
||||
- Feature-specific implementations
|
||||
|
||||
3. Chat Components:
|
||||
- MessagesFetcher:
|
||||
* Data fetching and subscription setup
|
||||
* Cache context management
|
||||
* Message filtering
|
||||
- ChatMessages:
|
||||
* Message display and UI logic
|
||||
* Scroll position management
|
||||
* New message indicators
|
||||
- AggregateMessages:
|
||||
* Cross-alert message display
|
||||
* Alert context integration
|
||||
* Navigation handling
|
||||
|
||||
### Authentication Flow
|
||||
1. SMS Authentication:
|
||||
- Registration SMS (type "R")
|
||||
- Connection SMS (type "C")
|
||||
- Loading states specific to SMS type
|
||||
- 3-minute timeout for loading states
|
||||
- Automatic clearing on login request
|
||||
|
||||
2. Account Management:
|
||||
- Modal-based interface
|
||||
- Support for both phone and email
|
||||
- Loading states based on action type
|
||||
- Login request handling
|
||||
|
||||
### Data Flow
|
||||
- GraphQL queries and mutations
|
||||
- Real-time subscriptions
|
||||
- Event system
|
||||
- Login request monitoring
|
||||
|
||||
### Navigation & Deep Linking
|
||||
- Custom navigation implementation
|
||||
- Parameter passing for state management
|
||||
- Modal coordination
|
||||
- Deep Linking Configuration:
|
||||
1. iOS URL Types:
|
||||
* Custom scheme (com.alertesecours.alertesecours://)
|
||||
* Expo scheme (exp+alerte-secours://)
|
||||
* HTTPS scheme for Universal Links
|
||||
* Each URL type has proper CFBundleURLName configuration
|
||||
|
||||
2. Universal Links:
|
||||
* Associated Domains capability enabled
|
||||
* apple-app-site-association file configuration:
|
||||
- Proper app ID format (TeamID.BundleID)
|
||||
- Wildcard paths pattern
|
||||
- Hosted at /.well-known/apple-app-site-association
|
||||
|
||||
3. Deep Link Handling:
|
||||
* Expo Linking module integration
|
||||
* Initial URL handling
|
||||
* Runtime URL event listening
|
||||
* Custom handleDeepLink implementation
|
||||
|
||||
### Error Handling
|
||||
- Sentry integration for error tracking
|
||||
- Custom error boundaries and components
|
||||
- Timeout handling for loading states
|
||||
- Graceful subscription error handling
|
||||
- Clear error logging for debugging
|
||||
|
||||
### UI/UX Patterns
|
||||
1. Loading States:
|
||||
- Action-specific loading indicators
|
||||
- Timeout mechanisms
|
||||
- Clear loading state triggers
|
||||
|
||||
2. Modal Management:
|
||||
- Contextual modal opening
|
||||
- State preservation
|
||||
- Loading state coordination
|
||||
|
||||
3. Theme Support:
|
||||
- Dark/light theme compatibility
|
||||
- Dynamic color filters for animations
|
||||
- Consistent styling across components
|
||||
|
||||
### Testing
|
||||
- E2E testing with Detox
|
||||
- Component-level testing
|
||||
- Flow-specific testing scenarios
|
||||
|
||||
### Build & Deployment
|
||||
- Fastlane integration
|
||||
- Custom build scripts
|
||||
- Environment-specific configurations
|
||||
|
||||
## Best Practices
|
||||
1. Loading State Management:
|
||||
- Tie loading states to specific actions
|
||||
- Implement timeouts for all loading states
|
||||
- Clear loading states on relevant events
|
||||
- Keep loading states focused and contextual
|
||||
|
||||
2. Component Design:
|
||||
- Clear separation of concerns
|
||||
- Consistent prop patterns
|
||||
- Theme awareness
|
||||
- Proper hook usage
|
||||
- Form state management:
|
||||
* Use react-hook-form for form handling
|
||||
* Track form changes via formState.isDirty
|
||||
* Disable submit buttons when no changes
|
||||
* Consistent disabled state styling (50% opacity)
|
||||
|
||||
3. Navigation:
|
||||
- Clear parameter passing
|
||||
- State management through navigation
|
||||
- Modal coordination
|
||||
|
||||
4. Authentication:
|
||||
- Type-specific SMS handling
|
||||
- Clear loading feedback
|
||||
- Proper timeout handling
|
||||
- Login request monitoring
|
||||
|
||||
5. Subscription Management:
|
||||
- Always provide cleanup functions in useEffect, even for effects that don't seem to need cleanup
|
||||
- Use proper cache isolation between views
|
||||
- Implement strict message filtering
|
||||
- Add detailed logging for debugging
|
||||
- Handle optimistic updates carefully
|
||||
- Clean up subscriptions before setting up new ones
|
||||
- Track component lifecycle with refs instead of let variables
|
||||
- Ensure consistent hook behavior across all effects
|
||||
- Maintain proper cleanup order in effects
|
||||
|
||||
6. Hook Usage Rules:
|
||||
- All useEffect hooks must return cleanup functions consistently
|
||||
- Use refs for mutable state that persists across renders
|
||||
- Track mounted state through refs, not variables
|
||||
- Clean up all subscriptions and side effects on unmount
|
||||
- Keep hook dependencies accurate and complete
|
||||
- Handle async operations safely with mounted checks
|
||||
- Ensure proper cleanup order when multiple effects interact
|
134
cline_docs/techContext.md
Normal file
|
@ -0,0 +1,134 @@
|
|||
# Technical Context
|
||||
|
||||
## Technology Stack
|
||||
- React Native
|
||||
- GraphQL with Hasura
|
||||
- Apollo Client for frontend
|
||||
- Federated remote schemas
|
||||
- Firebase (FCM only for push notifications)
|
||||
- Sentry for error tracking
|
||||
|
||||
## Development Environment
|
||||
- Node.js (specified in .node-version)
|
||||
- Yarn package manager (evidenced by .yarnrc.yml)
|
||||
- ESLint for code linting (.eslintrc.js)
|
||||
- TypeScript configuration (tsconfig.json)
|
||||
|
||||
## Backend Architecture
|
||||
- Hasura GraphQL server
|
||||
- Federation of remote schemas
|
||||
- Real-time subscriptions support
|
||||
- Custom business logic through remote schemas
|
||||
|
||||
## Frontend Architecture
|
||||
- React Native mobile app
|
||||
- Apollo Client for GraphQL state management
|
||||
- Real-time updates via GraphQL subscriptions
|
||||
- Push notifications via Firebase Cloud Messaging
|
||||
|
||||
### Authentication System
|
||||
1. SMS Authentication:
|
||||
- Two distinct SMS types: "R" (Registration) and "C" (Connect)
|
||||
- Type-specific loading states
|
||||
- 3-minute timeout mechanism
|
||||
- Login request monitoring via GraphQL subscription
|
||||
|
||||
2. Account Management:
|
||||
- Modal-based interface
|
||||
- Support for both SMS and email authentication
|
||||
- Loading state coordination based on action type
|
||||
- Login request handling through GraphQL mutations
|
||||
|
||||
### Loading State Management
|
||||
1. Component-Level Loading:
|
||||
- Button built-in loading prop
|
||||
- LittleLoader component with theme support
|
||||
- Loading state timeouts
|
||||
- Login request-based clearing
|
||||
|
||||
2. Theme Integration:
|
||||
- Dark/light theme support
|
||||
- Dynamic color filters for Lottie animations
|
||||
- Theme-aware component styling
|
||||
|
||||
### Navigation & Deep Linking System
|
||||
- Parameter-based state management
|
||||
- Modal coordination
|
||||
- Action-specific navigation flows
|
||||
- Deep Linking Integration:
|
||||
1. Required Configurations:
|
||||
- iOS Universal Links setup
|
||||
- Associated Domains capability
|
||||
- apple-app-site-association file
|
||||
- URL scheme configurations in Info.plist
|
||||
- Custom Expo plugin to preserve URL schemes during prebuild
|
||||
|
||||
2. Technical Requirements:
|
||||
- HTTPS server for apple-app-site-association file
|
||||
- Proper MIME type (application/json)
|
||||
- No redirects for /.well-known/apple-app-site-association
|
||||
- Valid app ID format (TeamID.BundleID)
|
||||
- CFBundleURLName format (following Expo's convention):
|
||||
* Production scheme: com.alertesecours.alertesecours (matches bundle ID)
|
||||
* Development scheme: com.alertesecours.alertesecours.expo (bundle ID + .expo)
|
||||
* Format defined in Expo's source code for consistency
|
||||
|
||||
3. Implementation Components:
|
||||
- Expo Linking module integration
|
||||
- Initial URL handling
|
||||
- URL event listeners
|
||||
- Custom deep link parsing logic
|
||||
- withCustomScheme plugin for URL scheme preservation
|
||||
|
||||
## Build & Deployment Tools
|
||||
- Fastlane for deployment
|
||||
- Custom build scripts
|
||||
- Environment configurations (.env.default, .env.staging, .env.prod)
|
||||
|
||||
## Platform-Specific
|
||||
### iOS
|
||||
- Xcode project configuration
|
||||
- CocoaPods for dependency management
|
||||
- Custom entitlements and capabilities
|
||||
- FCM push notification setup
|
||||
|
||||
### Android
|
||||
- Gradle build system
|
||||
- Custom Gradle plugins
|
||||
- FCM integration for push notifications
|
||||
|
||||
## Development Setup Requirements
|
||||
*To be completed with setup instructions*
|
||||
|
||||
## Technical Constraints
|
||||
- Loading states must be tied to specific actions
|
||||
- Loading timeouts required for all async operations
|
||||
- Theme compatibility required for all UI components
|
||||
- Proper hook usage and dependency management
|
||||
|
||||
## Pending Implementations
|
||||
- Multilingual support (i18n infrastructure exists but not implemented)
|
||||
|
||||
## Recent Technical Improvements
|
||||
1. Loading State Management:
|
||||
- Action-specific loading indicators
|
||||
- Automatic timeout mechanism
|
||||
- Login request-based clearing
|
||||
- Theme-aware loading animations
|
||||
|
||||
2. Component Architecture:
|
||||
- Proper hook dependency management
|
||||
- Consistent prop patterns
|
||||
- Clear separation of concerns
|
||||
- Theme integration
|
||||
|
||||
3. Navigation Flow:
|
||||
- Type-specific parameter passing
|
||||
- Modal state coordination
|
||||
- Loading state synchronization
|
||||
|
||||
*Note: This document needs to be updated with:
|
||||
- Complete dependency list
|
||||
- Development setup instructions
|
||||
- Known technical limitations
|
||||
- Performance constraints
|
48
docs/aab-to-apk.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
# AAB to APK
|
||||
|
||||
install bundletool
|
||||
|
||||
```sh
|
||||
# brew install bundletool
|
||||
```
|
||||
|
||||
or download from https://github.com/google/bundletool/releases
|
||||
```
|
||||
alias bundletool='java -jar /opt/bundletool-all-1.17.1.jar'
|
||||
```
|
||||
|
||||
```sh
|
||||
cd android/app/build/outputs/bundle/release
|
||||
```
|
||||
|
||||
```sh
|
||||
bundletool build-apks --mode universal --bundle ./app-release.aab --output ./app.apks
|
||||
mv app.apks app.zip
|
||||
unzip -o app.zip
|
||||
```
|
||||
|
||||
# ADB
|
||||
|
||||
restart adb
|
||||
```sh
|
||||
adb kill-server && adb start-server
|
||||
```
|
||||
|
||||
list devices
|
||||
```sh
|
||||
adb devices
|
||||
```
|
||||
|
||||
|
||||
# Android
|
||||
|
||||
enable usb debug mode in developer options
|
||||
|
||||
|
||||
# Install
|
||||
|
||||
```sh
|
||||
adb install universal.apk
|
||||
```
|
||||
|
||||
# Shortcut scripts
|
76
docs/config-files-requirements.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Configuration Files Requirements
|
||||
|
||||
This document outlines the configuration files required for the Alerte Secours mobile app and how to set them up.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The app uses environment variables for configuration and sensitive information. There are several environment files:
|
||||
|
||||
### Development Environment
|
||||
|
||||
Copy `.env.default` to `.env.local` (which is git-ignored) and fill in the required values:
|
||||
|
||||
- `BACKGROUND_GEOLOCATION_LICENSE`: License key for react-native-background-geolocation
|
||||
- `BACKGROUND_GEOLOCATION_HMS_LICENSE`: HMS license key for react-native-background-geolocation
|
||||
|
||||
### Production Environment
|
||||
|
||||
Copy `.env.prod.example` to `.env.prod` (which is git-ignored) and fill in the required values:
|
||||
|
||||
- `SENTRY_DSN`: Your Sentry DSN for error tracking
|
||||
- `SENTRY_ORG`: Your Sentry organization
|
||||
- `SENTRY_PROJECT`: Your Sentry project name
|
||||
- `ASC_API_KEY_ID`: Your App Store Connect API Key ID
|
||||
- `ASC_API_ISSUER_ID`: Your App Store Connect API Issuer ID
|
||||
- `ASC_API_KEY_PATH`: Path to your App Store Connect API Key file
|
||||
- `PROVIDER_ID`: Your App Store Connect Provider ID
|
||||
|
||||
### Staging Environment
|
||||
|
||||
Copy `.env.staging.example` to `.env.staging` (which is git-ignored) and fill in the required values with the same information as the production environment, but with staging-specific values where applicable.
|
||||
|
||||
## Google Services Configuration
|
||||
|
||||
### iOS
|
||||
|
||||
1. Copy `ios/GoogleService-Info.example.plist` to `ios/GoogleService-Info.plist`
|
||||
2. Copy `ios/AlerteSecours/GoogleService-Info.example.plist` to `ios/AlerteSecours/GoogleService-Info.plist`
|
||||
3. Fill in the following values:
|
||||
- `API_KEY`: Your Google API key
|
||||
- `GCM_SENDER_ID`: Your GCM sender ID
|
||||
- `PROJECT_ID`: Your Firebase project ID
|
||||
- `STORAGE_BUCKET`: Your Firebase storage bucket
|
||||
- `GOOGLE_APP_ID`: Your Google app ID
|
||||
|
||||
### Android
|
||||
|
||||
1. Copy `android/app/google-services.example.json` to `android/app/google-services.json`
|
||||
2. Fill in the following values:
|
||||
- `project_number`: Your Firebase project number
|
||||
- `project_id`: Your Firebase project ID
|
||||
- `storage_bucket`: Your Firebase storage bucket
|
||||
- `mobilesdk_app_id`: Your Firebase mobile SDK app ID
|
||||
- `client_id`: Your OAuth client ID
|
||||
- `current_key`: Your Google API key
|
||||
|
||||
## Expo Updates Configuration
|
||||
|
||||
1. Copy `ios/AlerteSecours/Supporting/Expo.example.plist` to `ios/AlerteSecours/Supporting/Expo.plist`
|
||||
2. Fill in the `EXUpdatesCodeSigningCertificate` with your Expo code signing certificate
|
||||
|
||||
## How to Obtain These Values
|
||||
|
||||
### Firebase Configuration
|
||||
|
||||
1. Go to the [Firebase Console](https://console.firebase.google.com/)
|
||||
2. Select your project or create a new one
|
||||
3. Add iOS and Android apps to your project
|
||||
4. Download the configuration files for each platform
|
||||
|
||||
### Background Geolocation License
|
||||
|
||||
Purchase a license from [Transistor Software](https://www.transistorsoft.com/shop/products/react-native-background-geolocation)
|
||||
|
||||
### Expo Code Signing Certificate
|
||||
|
||||
Generate a code signing certificate for Expo updates by following the [Expo documentation](https://docs.expo.dev/eas-update/code-signing/)
|
14
docs/create app icon.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# easy free online service
|
||||
|
||||
https://easyappicon.com/
|
||||
|
||||
# old method
|
||||
|
||||
In android sutodio, right click on android/app/src/main/res -> New -> Image Asset -> type: Launcher icon, name: ic_launcher
|
||||
|
||||
AND / OR
|
||||
|
||||
```sh
|
||||
npm install -g yo generator-rn-toolbox
|
||||
yo rn-toolbox:assets --icon <path to your icon>
|
||||
```
|
9
docs/debug-from-device.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
```sh
|
||||
adb logcat *:S ReactNativeJS:V
|
||||
```
|
||||
|
||||
```sh
|
||||
adb logcat -s ReactNative:V ReactNativeJS:V
|
||||
```
|
||||
|
||||
see also https://developer.android.com/tools/logcat?hl=fr
|
5
docs/duns.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# DUNS number
|
||||
|
||||
Lookup service (for all countries): https://www.dnb.com/de-de/upik-en.html
|
||||
|
||||
Alerte Secours: 269751659
|
54
docs/fix-dev-build.md
Normal file
|
@ -0,0 +1,54 @@
|
|||
- clear yarn
|
||||
```sh
|
||||
rm -rf node_modules
|
||||
yarn
|
||||
```
|
||||
|
||||
- clean gradle
|
||||
```sh
|
||||
cd android
|
||||
./gradlew clean
|
||||
```
|
||||
|
||||
- clear gradle cache
|
||||
```sh
|
||||
rm -rf ~/.gradle/caches/
|
||||
rm -rf android/.gradle/
|
||||
```
|
||||
|
||||
- stop gradle daemons
|
||||
```sh
|
||||
cd android && ./gradlew --stop
|
||||
```
|
||||
|
||||
- clear abd cache (useful when not receiving notification on emulator)
|
||||
```sh
|
||||
adb shell pm clear com.alertesecours
|
||||
```
|
||||
|
||||
- rebuild gradle
|
||||
```sh
|
||||
yarn expo run:android
|
||||
```
|
||||
|
||||
- rebuild expo react-native
|
||||
```sh
|
||||
yarn expo prebuild
|
||||
```
|
||||
|
||||
- clear metro cache
|
||||
```sh
|
||||
yarn expo start --dev-client --clear
|
||||
```
|
||||
|
||||
- fix emulator (eg: unavailable FCM getToken)
|
||||
- clear cache / uninstall the app
|
||||
- check emulator datetime
|
||||
- check network connectivity
|
||||
|
||||
- https://github.com/expo/expo/issues/22029#issuecomment-2239751213
|
||||
|
||||
android/local.properties
|
||||
```ini
|
||||
cmake.dir=/opt/Android/Sdk/cmake/3.22.1
|
||||
```
|
32
docs/install-fastlane.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Fastlane
|
||||
|
||||
## Install on laptop
|
||||
|
||||
```sh
|
||||
sudo apt-get install ruby-full
|
||||
sudo gem install fastlane
|
||||
```
|
||||
|
||||
## Init
|
||||
|
||||
```sh
|
||||
cd android
|
||||
fastlane init
|
||||
```
|
||||
|
||||
```sh
|
||||
cd ios
|
||||
fastlane init
|
||||
```
|
||||
|
||||
### Darling (macOS emulator)
|
||||
|
||||
install https://github.com/darlinghq/darling/releases
|
||||
|
||||
then run
|
||||
|
||||
```sh
|
||||
darling shell
|
||||
|
||||
xcode-select --install
|
||||
```
|