diff --git a/fusionMobile/.eslintrc.js b/fusionMobile/.eslintrc.js index 5525ab94..f44e5388 100644 --- a/fusionMobile/.eslintrc.js +++ b/fusionMobile/.eslintrc.js @@ -2,9 +2,10 @@ module.exports = { extends: [ "universe/native", "universe/shared/typescript-analysis", + "plugin:@tanstack/eslint-plugin-query/recommended", "prettier", ], - plugins: ["@typescript-eslint", "unused-imports"], + plugins: ["@typescript-eslint", "unused-imports", "@tanstack/query"], ignorePatterns: ["ios", "android"], overrides: [ { @@ -15,6 +16,8 @@ module.exports = { rules: { "prettier/prettier": "off", "unused-imports/no-unused-imports": "error", + "@tanstack/query/exhaustive-deps": "error", + "@tanstack/query/prefer-query-object-syntax": "error", "import/order": [ 1, { diff --git a/fusionMobile/App.tsx b/fusionMobile/App.tsx index 537ab4f4..c821b6c4 100644 --- a/fusionMobile/App.tsx +++ b/fusionMobile/App.tsx @@ -1,20 +1,23 @@ import { PortalProvider } from "@gorhom/portal"; import { useNavigation } from "@react-navigation/native"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import dayjs from "dayjs"; import { Logs } from "expo"; import Constants from "expo-constants"; import * as Notifications from "expo-notifications"; -import * as SplashScreen from "expo-splash-screen"; import React from "react"; -import { Alert, Platform, StatusBar } from "react-native"; +import { Alert, Linking, Platform, StatusBar } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; +import Toast from "react-native-toast-message"; import { FontLoader } from "./FontLoader"; import { CustomNavigation } from "./src/navigation"; import { maskPromptId, appInsights } from "./src/utils"; +import { QUERY_OPTIONS_DEFAULT } from "~/config"; import { PromptContextProvider } from "~/contexts"; import { notificationService, promptService } from "~/services"; +import { toastConfig } from "~/theme"; Logs.enableExpoCliLogging(); @@ -23,11 +26,21 @@ const registerForPushNotificationsAsync = async () => { const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== "granted") { - const { status } = await Notifications.requestPermissionsAsync(); - finalStatus = status; + Alert.alert( + "Notification Permission", + "We need your permission to send you notifications based on your prompt settings.", + [ + { + text: "OK", + onPress: async () => { + const { status } = await Notifications.requestPermissionsAsync(); + finalStatus = status; + }, + }, + ] + ); } if (finalStatus !== "granted") { - Alert.alert("Error", "Failed to get push token for push notification!"); return false; } @@ -44,7 +57,7 @@ const registerForPushNotificationsAsync = async () => { }; Notifications.setNotificationHandler({ - handleNotification: async (notification) => { + handleNotification: async () => { return { shouldShowAlert: true, shouldPlaySound: false, @@ -53,7 +66,12 @@ Notifications.setNotificationHandler({ }, }); -SplashScreen.preventAutoHideAsync(); +// SplashScreen.preventAutoHideAsync(); - temp remove since asking for notification permission on first load causes hiding splash screen to fail + +// Create a client +const queryClient = new QueryClient({ + defaultOptions: QUERY_OPTIONS_DEFAULT, +}); function App() { const responseListener = React.useRef< @@ -67,8 +85,16 @@ function App() { const permissionStatus = await registerForPushNotificationsAsync(); if (!permissionStatus) { Alert.alert( - "Error", - "Failed to register for push notifications, please quit, turn on notifications for fusion & restart the app" + "Enable notifications", + "We only notify you based on your prompt settings. Please enable notifications in your settings to continue.", + [ + { + text: "OK", + onPress: async () => { + Linking.openURL("app-settings:Fusion"); + }, + }, + ] ); return; } @@ -232,12 +258,15 @@ function App() { - - - - - + + + + + + + + ); } diff --git a/fusionMobile/FontLoader.tsx b/fusionMobile/FontLoader.tsx index a23db8cc..3c4639d8 100644 --- a/fusionMobile/FontLoader.tsx +++ b/fusionMobile/FontLoader.tsx @@ -8,8 +8,6 @@ interface Props extends PropsWithChildren { onFontsLoaded?: () => void; // callback for displaying the splash screen once background view has loaded } -SplashScreen.preventAutoHideAsync(); - export const FontLoader = ({ onFontsLoaded, children }: Props) => { const insets = useSafeAreaInsets(); const [fontsLoaded] = useFonts({ @@ -23,9 +21,9 @@ export const FontLoader = ({ onFontsLoaded, children }: Props) => { }); const onLayoutRootView = useCallback(async () => { - if (fontsLoaded) { - await SplashScreen.hideAsync(); //hide the splashscreen - } + // if (fontsLoaded) { + // await SplashScreen.hideAsync(); //hide the splashscreen + // } }, [fontsLoaded, onFontsLoaded]); if (!fontsLoaded) { diff --git a/fusionMobile/README.md b/fusionMobile/README.md index cd9d6fd6..8cc7ff0a 100644 --- a/fusionMobile/README.md +++ b/fusionMobile/README.md @@ -13,7 +13,7 @@ Data is currently stored using AsyncStorage (SQLite) uuid promptText responseType - "number", "yesno", "text", "customOptions" - additionalMeta - json.stringify of dictionary for customOption maps + additionalMeta - {category, isNotificationActive, customOptionsText} notificationConfig_days - json.stringify of "{"monday": true, "tuesday": false ....., "sunday": true}" notificationConfig_startTime notificationConfig_endTime @@ -21,6 +21,8 @@ Data is currently stored using AsyncStorage (SQLite) } ``` +customOptionText will look like - 'optionA;optionB;optionC' + After a prompt is created, a notification is generated. Response to prompts are saved in format @@ -28,12 +30,18 @@ Response to prompts are saved in format ```json { triggerTimestamp - endTimestamp + responseTimestamp value promptUuid + additionalMeta { + note: string + } } ``` +when responseType == customOption, +value can contain "valA;valB" + They can eventually exported in fusion Event schema [doc](../README.md) Mapping Fusion event schema to prompt_response @@ -259,3 +267,8 @@ Prompt response view - Share screen should eventually allow users select what prompts & who they want to share the results to in Fusion :) + +# Setting environment variables + +Expo handles environment variables a little different than regular web app. We set them in the app.config.ts file. +and then use constants. See appInsights.js for an example. More docs - https://docs.expo.dev/build-reference/variables/ diff --git a/fusionMobile/android/app/build.gradle b/fusionMobile/android/app/build.gradle index 47aca9c9..db00991b 100644 --- a/fusionMobile/android/app/build.gradle +++ b/fusionMobile/android/app/build.gradle @@ -118,7 +118,7 @@ android { applicationId 'com.neurofusion.fusion' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 10 + versionCode 27 versionName "1.0.0" } diff --git a/fusionMobile/android/app/src/main/AndroidManifest.xml b/fusionMobile/android/app/src/main/AndroidManifest.xml index 8b58b39a..db47b727 100644 --- a/fusionMobile/android/app/src/main/AndroidManifest.xml +++ b/fusionMobile/android/app/src/main/AndroidManifest.xml @@ -20,7 +20,7 @@ - + diff --git a/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index aca65f4c..5154bd8c 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 14c57547..6e0677dc 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/fusionMobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index e530df93..1e9637d8 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index 6a8a9cf3..bc8f3bb3 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/fusionMobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 13fed14f..fdb30437 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 3efd2d44..941b0d42 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/fusionMobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 1ab329eb..fc23fe99 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index e3fc4668..742e48c5 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/fusionMobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d8e89a4..284b1a01 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index caa62f1b..d51d7f7a 100644 Binary files a/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/fusionMobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/fusionMobile/android/app/src/main/res/values/colors.xml b/fusionMobile/android/app/src/main/res/values/colors.xml index bb2087f7..b8b4c2d2 100644 --- a/fusionMobile/android/app/src/main/res/values/colors.xml +++ b/fusionMobile/android/app/src/main/res/values/colors.xml @@ -1,6 +1,7 @@ - #ffffff - #FFFFFF + #0B0816 + #0B0816 #023c69 - #ffffff + #0B0816 + #0B0816 \ No newline at end of file diff --git a/fusionMobile/android/app/src/main/res/values/styles.xml b/fusionMobile/android/app/src/main/res/values/styles.xml index f03e23f8..7a7430bf 100644 --- a/fusionMobile/android/app/src/main/res/values/styles.xml +++ b/fusionMobile/android/app/src/main/res/values/styles.xml @@ -5,6 +5,7 @@ @drawable/rn_edit_text_material @color/colorPrimary @color/colorPrimaryDark + @color/activityBackground