From 306b7b1ecc4360a2efee456c2e24be339ed5c736 Mon Sep 17 00:00:00 2001 From: kibagateaux Date: Tue, 26 Dec 2023 18:25:52 -0600 Subject: [PATCH] clean up project and multiple app variant infra --- .gitignore | 3 +- app.config.js | 6 +-- build.md | 27 ++++++++++ eas.json | 16 +++--- package-lock.json | 21 ++++++-- package.json | 9 ++-- src/app/_layout.tsx | 10 +++- src/app/inventory/[item].tsx | 41 +++++++++------ src/app/inventory/_layout.tsx | 6 +-- src/app/inventory/index.tsx | 25 +++++---- src/assets/game-content/index.ts | 2 + src/assets/game-content/inventory.ts | 28 ++++++++++ src/components/common/Link.tsx | 3 +- .../modals/CreateSpellbookModal.tsx | 1 - src/components/screens/(auth)/__layout.tsx | 18 ------- .../tzolkin/index.tsx => tzolkin/screen.tsx} | 0 src/contexts/GameContentContext.tsx | 2 +- src/hooks/index.ts | 1 + src/hooks/useDeepLinks.ts | 52 +++++++++++++++++++ src/inventory/spotify.ts | 18 +++++-- src/types/GameMechanics.ts | 29 ++++++++++- src/utils/logging.ts | 4 +- src/utils/oauth.ts | 3 +- src/utils/rendering.tsx | 3 +- 24 files changed, 243 insertions(+), 85 deletions(-) create mode 100644 build.md delete mode 100644 src/components/screens/(auth)/__layout.tsx rename src/components/{screens/tzolkin/index.tsx => tzolkin/screen.tsx} (100%) create mode 100644 src/hooks/useDeepLinks.ts diff --git a/.gitignore b/.gitignore index 34becf0..a514905 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ ios/ *.p12 *.key *.mobileprovision - + # Metro .metro-health-check* @@ -27,6 +27,7 @@ ios/ npm-debug.* yarn-debug.* yarn-error.* +.hypothesis # macOS .DS_Store diff --git a/app.config.js b/app.config.js index 80b5bef..d2b2a1f 100644 --- a/app.config.js +++ b/app.config.js @@ -1,6 +1,6 @@ // eslint-ignore-next-line no-undef -const VARIANT = process.env.EXPO_PUBLIC_APP_VARIANT; -// console.log('GENERATING APP CONFIG FOR VARIANT:', VARIANT); +const VARIANT = process.env.APP_VARIANT || 'development'; +// console.log("GENERATING APP CONFIG FOR VARIANT:", VARIANT); const isProd = VARIANT === 'production'; const packageName = isProd ? 'com.jinnihealth' : `com.jinnihealth.${VARIANT}`; const appName = isProd ? 'Jinni Health' : `Jinni (${VARIANT}) `; @@ -57,7 +57,7 @@ export default { ], hooks: { postPublish: [ - VARIANT === 'development' + !isProd ? {} : { file: 'sentry-expo/upload-sourcemaps', diff --git a/build.md b/build.md new file mode 100644 index 0000000..ee3e16e --- /dev/null +++ b/build.md @@ -0,0 +1,27 @@ +# Android +Make sure to add app variants to `android/app/build.gradle` if starting from scratch +```java +android { + ... + // project.ext.sentryCli = [ flavorAware: true ] + flavorDimensions "env" + productFlavors { + production { + dimension "env" + applicationId 'com.jinnihealth' + } + staging { + dimension "env" + applicationId 'com.jinnihealth.staging' + } + development { + dimension "env" + applicationId 'com.jinnihealth.development' + } + } +} +``` + +# iOS +TODO + \ No newline at end of file diff --git a/eas.json b/eas.json index 92b4bdd..dd7509c 100644 --- a/eas.json +++ b/eas.json @@ -7,28 +7,28 @@ "developmentClient": true, "distribution": "internal", "env": { - "EXPO_PUBLIC_APP_VARIANT": "development", - "EXPO_PUBLIC_API_URL": "apprentice.scryer.jinni.health" + "APP_VARIANT": "development", + "EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health" }, "android": { "buildType": "apk", "gradleCommand": ":app:assembleDebug" } }, - "testing": { + "staging": { "env": { - "EXPO_PUBLIC_APP_VARIANT": "testing", - "EXPO_PUBLIC_API_URL": "apprentice.scryer.jinni.health" + "APP_VARIANT": "staging", + "EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health" }, "android": { "buildType": "apk", - "gradleCommand": ":app:assembleDebug" + "gradleCommand": ":app:assembleRelease" } }, "production": { "env": { - "EXPO_PUBLIC_APP_VARIANT": "production", - "EXPO_PUBLIC_API_URL": "master.scryer.jinni.health" + "APP_VARIANT": "production", + "EXPO_PUBLIC_API_URL": "master-scryer.jinni.health" }, "android": { "buildType": "app-bundle", diff --git a/package-lock.json b/package-lock.json index 7ac567e..6e42ff6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "expo-auth-session": "~5.0.2", "expo-contacts": "~12.2.0", "expo-crypto": "~12.4.1", - "expo-dev-client": "~2.4.12", "expo-file-system": "~15.4.4", "expo-linking": "~5.0.2", "expo-location": "~16.1.0", @@ -80,6 +79,7 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "expo-build-properties": "^0.8.3", + "expo-dev-client": "~2.4.12", "husky": "^8.0.3", "install": "^0.13.0", "jest": "^29.7.0", @@ -15757,6 +15757,7 @@ "version": "2.4.12", "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-2.4.12.tgz", "integrity": "sha512-3+xg0yb/0g6+JQaWq5+xn2uHoOXP4oSX33aWkaZPSNJLoyzfRaHNDF5MLcrMBbEHCw5T5qZRU291K+uQeMMC0g==", + "dev": true, "dependencies": { "expo-dev-launcher": "2.4.14", "expo-dev-menu": "3.2.2", @@ -15772,6 +15773,7 @@ "version": "2.4.14", "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-2.4.14.tgz", "integrity": "sha512-SlUf+fEX9sKzDzY1Ui8j5775eLKpO0xPVoI89G7CRsrpUv6ZRvRF836cMFesxkU5d+3bXHpKzDQiEPDSI1G/WQ==", + "dev": true, "dependencies": { "expo-dev-menu": "3.2.2", "resolve-from": "^5.0.0", @@ -15785,6 +15787,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -15796,6 +15799,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -15809,12 +15813,14 @@ "node_modules/expo-dev-launcher/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/expo-dev-menu": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-3.2.2.tgz", "integrity": "sha512-q0IDlCGkZMsDIFV+Mgnz0Q3u/bcnrF8IFMglJ0onF09e5csLk5Ts7hKoQyervOJeThyI402r9OQsFNaru2tgtg==", + "dev": true, "dependencies": { "expo-dev-menu-interface": "1.3.0", "semver": "^7.5.3" @@ -15827,6 +15833,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.3.0.tgz", "integrity": "sha512-WtRP7trQ2lizJJTTFXUSGGn1deIeHaYej0sUynvu/uC69VrSP4EeSnYOxbmEO29kuT/MsQBMGu0P/AkMQOqCOg==", + "dev": true, "peerDependencies": { "expo": "*" } @@ -15835,6 +15842,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -15846,6 +15854,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -15859,7 +15868,8 @@ "node_modules/expo-dev-menu/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/expo-device": { "version": "5.6.0", @@ -15935,7 +15945,8 @@ "node_modules/expo-json-utils": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.7.1.tgz", - "integrity": "sha512-L0lyH8diXQtV0q5BLbFlcoxTqPF5im79xDHPhybB0j36xYdm65hjwRJ4yMrPIN5lR18hj48FUZeONiDHRyEvIg==" + "integrity": "sha512-L0lyH8diXQtV0q5BLbFlcoxTqPF5im79xDHPhybB0j36xYdm65hjwRJ4yMrPIN5lR18hj48FUZeONiDHRyEvIg==", + "dev": true }, "node_modules/expo-keep-awake": { "version": "12.3.0", @@ -15969,6 +15980,7 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.7.2.tgz", "integrity": "sha512-xlhL0XI2zw3foJ0q2Ra4ieBhU0V2yz+Rv6GpVEaaIHFlIC/Dbx+mKrX5dgenZEMERr/MG7sRJaRbAVB2PaAYhA==", + "dev": true, "dependencies": { "expo-json-utils": "~0.7.0" } @@ -16173,6 +16185,7 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-0.10.1.tgz", "integrity": "sha512-I6JMR7EgjXwckrydDmrkBEX/iw750dcqpzQVsjznYWfi0HTEOxajLHB90fBFqQkUV5i5s4Fd3hYQ1Cn0oMzUbA==", + "dev": true, "peerDependencies": { "expo": "*" } diff --git a/package.json b/package.json index ba9f4f6..4fca35e 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,8 @@ "test": "jest", "test:ci": "jest --ci --colors", "postinstall": "patch-package && rn-nodeify --install all --hack", - "run:android": "expo run:android --variant development --dev-client", - "install:android": "source .env; EXPO_PUBLIC_APP_VARIANT=testing; expo run:android -d", - "build:android": "source .env; eas build --local --platform android -e production", + "android": "APP_VARIANT=development npx expo run:android -d --variant developmentDebug", + "install:android": "source .env; APP_VARIANT=production npx eas build --local --platform android -e staging --output app.apk; adb install ./app.apk", "deploy:secrets": "eas secret:push --scope jinni-health --env-file ./.env", "ios": "expo run:ios", "lint:dry": "eslint ./src/ .eslintrc.js --ext .ts,.tsx && prettier ./src/ --config .prettierrc --check", @@ -66,8 +65,7 @@ "readable-stream": "^1.0.33", "sentry-expo": "~7.0.0", "stream-browserify": "^1.0.0", - "util": "^0.10.4", - "expo-dev-client": "~2.4.12" + "util": "^0.10.4" }, "peerDependencies": { "ethers": "5.7.0" @@ -90,6 +88,7 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "expo-build-properties": "^0.8.3", + "expo-dev-client": "~2.4.12", "husky": "^8.0.3", "install": "^0.13.0", "jest": "^29.7.0", diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 25e1054..46baa33 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -14,6 +14,8 @@ import { WidgetConfig } from 'types/UserConfig'; import { getIconForWidget } from 'utils/rendering'; export default function HomeLayout() { + // has to be in nested _layout https://docs.expo.dev/router/reference/authentication/#after + // useDeepLinks(); const homeConfig = useHomeConfig(); const [tabConfig, setTabConfig] = useState([]); @@ -23,10 +25,14 @@ export default function HomeLayout() { } }, [homeConfig, tabConfig]); - // console.log("Home:tabs", tabConfig) + console.log('pg:home:layout: no deep links'); return ( - + {tabConfig.map((tab) => ( = () => { const [itemOauthConfig, setItemOauth] = useState(oauthConfigs.undefined); const [activeAbilities, setActiveAbilities] = useState([]); + console.log('pg:inventory:item:Load', id, item?.tags); + const [request, , promptAsync] = useAuthRequest( { clientId: itemOauthConfig.clientId, @@ -66,18 +68,23 @@ const ItemPage: React.FC = () => { item!.checkStatus().then((newStatus: ItemStatus) => { console.log('pg:Inv:Item check item status', newStatus); setStatus(newStatus); - Promise.all( - item.abilities?.filter(async (ability) => { - (await ability.canDo(newStatus)) === 'doable'; - }) ?? [], - ).then((active) => { - console.log('pb:Inv:Item post item status abilitiy check', active); - setActiveAbilities(active); - }); }); } }, [item, status]); + useMemo(() => { + if (item?.abilities?.length && status) { + Promise.all( + item.abilities?.filter(async (ability) => { + (await ability.canDo(status!)) === 'doable'; + }) ?? [], + ).then((active) => { + console.log('pb:Inv:Item post item status abilitiy check', active); + setActiveAbilities(active); + }); + } + }, [item, status]); + // console.log('Item: item', id, item); // console.log('Item: status & modal', status, activeModal); @@ -118,13 +125,13 @@ const ItemPage: React.FC = () => { : await item.equip(); // if result.error = "transceive fail" try majik ritual again if (result) { - setStatus('post-equip'); + // setStatus('post-equip'); // TODO api request to add item to their avatar (:DataProvider or :Resource?) setStatus('equipped'); + } else { + // assume failure + setStatus('unequipped'); } - - // assume failure - setStatus('unequipped'); } catch (e) { console.log('Error Equipping:', e); setStatus('unequipped'); @@ -241,7 +248,7 @@ const ItemPage: React.FC = () => { }; const renderActiveItemAbilities = () => ( - Abilities + Active Abilities {activeAbilities.length ? ( {activeAbilities.map((ability) => ( @@ -349,11 +356,11 @@ const ItemPage: React.FC = () => { return ( - {/* */} + /> diff --git a/src/app/inventory/_layout.tsx b/src/app/inventory/_layout.tsx index 131ede6..e845d71 100644 --- a/src/app/inventory/_layout.tsx +++ b/src/app/inventory/_layout.tsx @@ -5,11 +5,7 @@ import { Stack } from 'expo-router'; export default function Layout() { return ( - + diff --git a/src/app/inventory/index.tsx b/src/app/inventory/index.tsx index cf21343..56fef04 100644 --- a/src/app/inventory/index.tsx +++ b/src/app/inventory/index.tsx @@ -6,6 +6,7 @@ import { useInventory } from 'hooks'; import { Card } from 'components'; import { InventoryItem } from 'types/GameMechanics'; +import { Stack } from 'expo-router'; const InventoryScreen: React.FC = () => { const { inventory, loading } = useInventory(); @@ -53,15 +54,21 @@ const InventoryScreen: React.FC = () => { return loading ? ( ) : ( - // TODO https://reactnative.dev/docs/optimizing-flatlist-configuration - } - renderSectionHeader={renderCategoryHeader} - renderItem={({ item }) => renderItem({ item })} - /> + <> + + {/* TODO https://reactnative.dev/docs/optimizing-flatlist-configuration */} + } + renderSectionHeader={renderCategoryHeader} + renderItem={({ item }) => renderItem({ item })} + /> + ); }; diff --git a/src/assets/game-content/index.ts b/src/assets/game-content/index.ts index b5633b1..8c4a8ac 100644 --- a/src/assets/game-content/index.ts +++ b/src/assets/game-content/index.ts @@ -1,7 +1,9 @@ import inventory from './inventory'; import onboarding from './onboarding'; +import modals from './modals'; export default { inventory, onboarding, + modals, }; diff --git a/src/assets/game-content/inventory.ts b/src/assets/game-content/inventory.ts index c06f212..1a38e8a 100644 --- a/src/assets/game-content/inventory.ts +++ b/src/assets/game-content/inventory.ts @@ -81,4 +81,32 @@ export default { }, }, }, + Github: { + meta: { + description: + 'Login to Github so your Jinni learn from your dev skills and automagically evolve', + perks: `1. Train your Jinni on how you think +2. Track your daily work routines +3. Expand your network effect with other devs + `, + }, + equipping: { + modal: { + title: 'You are equipping an item', + text: `Suctioning 🐙 on to your giga🧠`, + }, + }, + equipped: { + modal: { + title: 'You have sucessfully equipped your item!', + text: `Your Jinni is succing on your sweet brain juice`, + }, + }, + 'post-equip': { + modal: { + title: 'Congrats on acquiring your new item!', + text: ``, + }, + }, + }, }; diff --git a/src/components/common/Link.tsx b/src/components/common/Link.tsx index 06d0f15..256b8b0 100644 --- a/src/components/common/Link.tsx +++ b/src/components/common/Link.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { Link } from 'expo-router'; import { Linking, TouchableOpacity } from 'react-native'; -// import { useNavigation } from '@react-navigation/native'; import { track } from 'utils/logging'; interface LinkProps { @@ -13,11 +12,11 @@ interface LinkProps { } const LinkButton = ({ children, to, trackingId, styleOverride }: LinkProps) => { - // const navigation = useNavigation(); const isInternal = !to.startsWith('http'); const handlePress = () => { if (to) { + // TODO use expo-linking instead? Linking.openURL(to); trackNavigation(); } diff --git a/src/components/modals/CreateSpellbookModal.tsx b/src/components/modals/CreateSpellbookModal.tsx index b5c71d5..e694856 100644 --- a/src/components/modals/CreateSpellbookModal.tsx +++ b/src/components/modals/CreateSpellbookModal.tsx @@ -11,7 +11,6 @@ export interface CreateSpellbookModalProps { const CreateSpellbookModal = ({ dialogueData = {} }: CreateSpellbookModalProps) => { const content = useGameContent().onboarding.modals['create-spellbook']; - console.log('game item content', content); if (!content) return null; const titleTemplate = content.title; diff --git a/src/components/screens/(auth)/__layout.tsx b/src/components/screens/(auth)/__layout.tsx deleted file mode 100644 index 4b3ba2c..0000000 --- a/src/components/screens/(auth)/__layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { Stack } from 'expo-router'; - -export interface AuthStackProps {} - -const AuthStack: React.FC = () => { - return ( - - - - ); -}; - -export default AuthStack; diff --git a/src/components/screens/tzolkin/index.tsx b/src/components/tzolkin/screen.tsx similarity index 100% rename from src/components/screens/tzolkin/index.tsx rename to src/components/tzolkin/screen.tsx diff --git a/src/contexts/GameContentContext.tsx b/src/contexts/GameContentContext.tsx index 72f81ec..96c8ec7 100644 --- a/src/contexts/GameContentContext.tsx +++ b/src/contexts/GameContentContext.tsx @@ -1,6 +1,6 @@ //theme.tsx import React, { createContext } from 'react'; -import { GameContent } from 'types'; +import { GameContent } from 'types/GameMechanics'; import content from 'assets/game-content'; const GameContentContext = createContext(content); diff --git a/src/hooks/index.ts b/src/hooks/index.ts index fe7f6aa..110de20 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,3 +1,4 @@ export * from './useHomeConfig'; export * from './useInventory'; export * from './useNetworkState'; +export * from './useDeepLinks'; diff --git a/src/hooks/useDeepLinks.ts b/src/hooks/useDeepLinks.ts new file mode 100644 index 0000000..13c5b1d --- /dev/null +++ b/src/hooks/useDeepLinks.ts @@ -0,0 +1,52 @@ +// import { useState, useEffect } from 'react'; +// import * as Linking from 'expo-linking'; +// import Constants from 'expo-constants'; +// import { router } from 'expo-router'; +// import * as SplashScreen from 'expo-splash-screen'; + +// const prefix = Linking.createURL('/'); +// const deepLinkScheme = Constants.expoConfig?.scheme ?? 'jinni-health'; +// const universalLinkScheme = 'https://app.jinni.health/'; + +// // OK apparently deep linking *is* working but keep for now until fully tested in prod and know its unneeded +// export const useDeepLinks = () => { +// // Prevent hiding the splash screen after the navigation has mounted. +// SplashScreen.preventAutoHideAsync(); + +// const [redirectUrl, setRedirectUri] = useState(); +// const linkedInto = Linking.useURL(); +// useEffect(() => { +// const { scheme, hostname, path } = linkedInto ? Linking.parse(linkedInto) : {}; +// const isRedirect = scheme === Constants.expoConfig?.scheme; + +// console.log('hook:deepLLink:past', redirectUrl); +// console.log('hook:deepLLink:now', linkedInto, isRedirect); +// // console.log('use deep link 2', scheme, isRedirect, hostname, '---', path ); + +// if (linkedInto !== redirectUrl && isRedirect && path) { +// const params = path +// ?.split('/') +// .reduce((obj, param) => ({ ...obj, [param]: param }), {}); + +// router.replace({ +// pathname: hostname, +// params, +// }); +// setRedirectUri(Linking.createURL(hostname, params)); +// } +// // always unmount splash screen after loading +// SplashScreen.hideAsync(); +// }, [redirectUrl, linkedInto]); +// }; + +// // TODO should we make deepLinks use query params? +// // e.g. jinni-health://?path=inventory?id=Spotify&ability=spotify-share-profile +// const mapPathToParams = (page: string, path: string) => { +// const params = path.split('/'); +// switch(page) { +// case 'inventory': +// return { id: path } +// default: +// return {} +// } +// } diff --git a/src/inventory/spotify.ts b/src/inventory/spotify.ts index 96b3f75..7b72382 100644 --- a/src/inventory/spotify.ts +++ b/src/inventory/spotify.ts @@ -1,5 +1,6 @@ import { Platform, Share } from 'react-native'; -import { getProviderId, qu } from 'utils/api'; +import { qu } from 'utils/api'; +import { getProviderId } from 'utils/oauth'; import { InventoryIntegration, @@ -122,16 +123,25 @@ const item: InventoryItem = { }); const pid = await getCached({ slot: ID_PLAYER_SLOT }); console.log('Spotify:Ability:ShareProfile:pid', pid); - if (!pid) return async () => false; + if (!pid) { + track(SHARE_CONTENT, { + ability: ABILITY_SHARE_PROFILE, + activityType: 'unauthenticated', + success: false, + }); + return async () => false; + } try { - const providerId = await getProviderId(pid)('Spotify'); + const providerId = await getProviderId({ playerId: pid, provider: ITEM_ID }); console.log('Spotify:Ability:ShareProfile:pid', providerId); if (!providerId) { track(SHARE_CONTENT, { ability: ABILITY_SHARE_PROFILE, activityType: 'unequipped', providerId, + success: false, }); + return async () => false; } const profileUrl = `https://open.spotify.com/user/${providerId}`; const { action, activityType } = await Share.share({ @@ -149,6 +159,7 @@ const item: InventoryItem = { ability: ABILITY_SHARE_PROFILE, activityType: activityType ?? 'shared', providerId, + success: true, }); return async () => true; } @@ -165,6 +176,7 @@ const item: InventoryItem = { track(SHARE_CONTENT, { ability: ABILITY_SHARE_PROFILE, activityType: 'failed', + success: false, }); debug({ extra: { ability: ABILITY_SHARE_PROFILE }, diff --git a/src/types/GameMechanics.ts b/src/types/GameMechanics.ts index 9a61a82..7c33198 100644 --- a/src/types/GameMechanics.ts +++ b/src/types/GameMechanics.ts @@ -8,11 +8,38 @@ export interface Avatar { * @notice - all text content for guiding users through the game * @TODO - integrate i18n */ +export type ModalContentProps = { + // key = ItemIds + modal: { + title: string | ((dialogueData: object) => string); + text: string | ((dialogueData: object) => string); + }; +}; export type GameContent = { inventory: { [key: string]: { // key = ItemIds - [key: string]: string; // key = ItemStatus + [key: string]: + | { + // key = meta + description: string; + perks: string; + } + | ModalContentProps; // key = ItemStatus + }; + }; + onboarding: { + modals: { + [key: string]: { + // key = OnboardinFlowId + [key: string]: string; // key = ModalId + }; + }; + }; + modals: { + [key: string]: { + // key = ModalId + [key: string]: ModalContentProps; }; }; }; diff --git a/src/utils/logging.ts b/src/utils/logging.ts index 6db450a..f50ed54 100644 --- a/src/utils/logging.ts +++ b/src/utils/logging.ts @@ -19,7 +19,7 @@ export const getSentry = (): SentryClient => { if (!sentryClient && process.env.EXPO_PUBLIC_SENTRY_DSN) { Sentry.init({ dsn: process.env.EXPO_PUBLIC_SENTRY_DSN!, - environment: process.env.EXPO_PUBLIC_APP_VARIANT, + environment: process.env.NODE_ENV, // release: 'my release name', // dist: 'my dist', tracesSampleRate: 1.0, @@ -84,6 +84,6 @@ export const track = (eventName: string, data: JsonMap) => !__DEV__ && getSegment()?.track(eventName, { ...data, - environment: process.env.EXPO_PUBLIC_APP_VARIANT, + environment: process.env.NODE_ENV, platform: Platform.OS, }); diff --git a/src/utils/oauth.ts b/src/utils/oauth.ts index 37fd12d..aae1d11 100644 --- a/src/utils/oauth.ts +++ b/src/utils/oauth.ts @@ -106,9 +106,10 @@ export const QU_PROVIDER_ID = cleanGql(` * @param provider * @returns id on provider or null */ -export const getProviderId = memoize(async ({ playerId, provider }) => { +export const getProviderId = memoize(async ({ playerId, provider }): Promise => { const response = await qu({ query: QU_PROVIDER_ID })({ playerId, provider }); const id = response?.data ? response.data.provider_id : null; console.log('util:oauth:getProviderId', response, id); id && (await saveStorage(ID_PROVIDER_TEMPLATE_SLOT + provider, id, false)); + return id; }, JSON.stringify); diff --git a/src/utils/rendering.tsx b/src/utils/rendering.tsx index 77ead77..5e5a7d4 100644 --- a/src/utils/rendering.tsx +++ b/src/utils/rendering.tsx @@ -17,8 +17,7 @@ export const getIconForWidget = (widgetId: string, iconOptions: WidgetIconProps) ?.symbol ?? '¿' ); - const { color } = iconOptions ?? { focused: true, color: 'black', size: 1 }; - const svgProps = { color }; + const svgProps = iconOptions ?? { focused: true, color: 'black', size: 1 }; switch (widgi) { case 'page-home': return 🧞‍♂️ ;