chore(init): available sources

This commit is contained in:
devthejo 2025-04-13 10:23:48 +02:00
commit ccd8373edb
Signed by: devthejo
GPG key ID: C04215C627711F5C
793 changed files with 68464 additions and 0 deletions

80
.aidigestignore Normal file
View file

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

57
.detoxrc.js Normal file
View 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
View file

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

20
.env.default Normal file
View file

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

33
.env.prod.example Normal file
View 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
View 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
View file

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

143
.eslintrc.js Normal file
View 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,
},
};

View 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
View 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
View 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
View 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
View file

@ -0,0 +1 @@
20

35
.versionrc.js Normal file
View 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 }
]
};

View 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(),

View 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
View file

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

934
.yarn/releases/yarn-4.5.3.cjs vendored Executable file

File diff suppressed because one or more lines are too long

11
.yarnrc.yml Normal file
View file

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

22
Dockerfile Normal file
View 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
View file

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

16
android/.gitignore vendored Normal file
View 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
View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

225
android/app/build.gradle Normal file
View 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

Binary file not shown.

View 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
View 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:

View file

@ -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);
}
}

View 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>

View 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-----&#xD;&#xA;MIICzTCCAbWgAwIBAgIJR0KfFDoMJrYZMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNV&#xD;&#xA;BAMTBHRlc3QwIBcNMjQwODE4MTU0OTExWhgPMjEyNDA4MTgxNTQ5MTFaMA8xDTAL&#xD;&#xA;BgNVBAMTBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCk46qR&#xD;&#xA;a0Do2fpBDtif18a/WQNWHm/xseHsh97bZdt8ooV4PQooK6VZUbADUhhJXqqomapa&#xD;&#xA;yFMJX7sZzfBUF7/xMrWDrgS0R4FLbXijAolhpXoqMkBCx3toKUCbU4ljA+Lz/BX1&#xD;&#xA;AEqVWqAweNzNDi4bvd1PG1/sQuuEtoZuSVfTPRAjF8vVkWyn8nfkorTtMYaw2QFu&#xD;&#xA;ugs1wp7YieD4C8CIK5gMX7f8bxx3l7BR50bf+9MHJFI+eTjmoFoJFEVWbCcrOrky&#xD;&#xA;FLM0+NrMI2fZYunrN6jcKc/NKEaDKb1VDO9yrLcFQOtXJJIXz94/lS6kHDjzEgUV&#xD;&#xA;zx3uaDbAdSQsyZxxAgMBAAGjKjAoMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8E&#xD;&#xA;DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEASIjMvS3N9NEPeakUmYXg&#xD;&#xA;MEyjaX+N/62Pbcp4taU4G9vDB/fyDqMMef8+CWBpo/noXqzt4K6k1id7UwdZhRks&#xD;&#xA;xdBTSf1x5yzDB24mbqNAvPa2q8G6KIoNZuvLUDz35366FxR+vTHQmp2d4Yz92kIL&#xD;&#xA;EEmFr8eMHf60tfHG+em97p+evmXDyBjF3CwOvtuzog1wCF/AsJ1d0gbPPMKdAHKC&#xD;&#xA;LZHsiXJ5i/oFuYzWkDDJkO9bb6HaQplt/46iC0CyM6SsT6H8kkDVQbfQCH1JAXsL&#xD;&#xA;Knk10FbAMKJ7GWbAdsdcbNZlDMrzPprw8N/fpGc7RHdHBwKcFm44mNtrMrzEd4eX&#xD;&#xA;pQ==&#xD;&#xA;-----END CERTIFICATE-----&#xD;&#xA;"/>
<meta-data android:name="expo.modules.updates.CODE_SIGNING_METADATA" android:value="{&quot;keyid&quot;:&quot;main&quot;,&quot;alg&quot;:&quot;rsa-v1_5-sha256&quot;}"/>
<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&amp;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>

View 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()
}
}

View file

@ -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)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View 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>

View file

@ -0,0 +1,3 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/splashscreen_background"/>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -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>

View file

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1 @@
<resources/>

View 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#364fc7</color>
</resources>

View 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>

View 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>

View 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
View 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
View 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
View 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
View 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

Binary file not shown.

View 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
View 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
View 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

View 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"
}
}
}

View file

@ -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.
}
}

View 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
View 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
View 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
View 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,
},
],
],
};
};

View 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
View 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

View 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
View 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
View 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

View 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
View 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>
```

View 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
View 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
View 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
View 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
```

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