Skip to content

Commit

Permalink
finalize onboarding wizard
Browse files Browse the repository at this point in the history
  • Loading branch information
kibagateaux committed Jan 30, 2024
1 parent 8a9b84b commit a8a35a3
Show file tree
Hide file tree
Showing 15 changed files with 589 additions and 190 deletions.
9 changes: 6 additions & 3 deletions eas.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"distribution": "internal",
"env": {
"APP_VARIANT": "development",
"EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health"
"EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health",
"EXPO_PUBLIC_REDIRECT_URL": "apprentice-scryer.jinni.health"
},
"android": {
"buildType": "apk",
Expand All @@ -18,7 +19,8 @@
"staging": {
"env": {
"APP_VARIANT": "staging",
"EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health"
"EXPO_PUBLIC_API_URL": "apprentice-scryer.jinni.health",
"EXPO_PUBLIC_REDIRECT_URL": "apprentice-scryer.jinni.health"
},
"android": {
"buildType": "apk",
Expand All @@ -28,7 +30,8 @@
"production": {
"env": {
"APP_VARIANT": "production",
"EXPO_PUBLIC_API_URL": "master-scryer.jinni.health"
"EXPO_PUBLIC_API_URL": "master-scryer.jinni.health",
"EXPO_PUBLIC_REDIRECT_URL": "master-scryer.jinni.health"
},
"android": {
"buildType": "app-bundle",
Expand Down
1 change: 0 additions & 1 deletion sample.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
EXPO_PUBLIC_API_URL="{someapi.domain.com}"
EXPO_PUBLIC_API_KEY="!believeme!"
EXPO_ETH_RPC_PROVIDER="{alchemy/infura/etc}"

EXPO_PUBLIC_SEGMENT_API_KEY="{some_key}"
Expand Down
74 changes: 65 additions & 9 deletions src/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-na
import { isEmpty } from 'lodash/fp';

import { useHomeConfig } from 'hooks';
import { useTheme } from 'contexts';
import { WidgetConfig } from 'types/UserConfig';
import { WidgetConfig, obj } from 'types/UserConfig';
import { getIconForWidget } from 'utils/rendering';
import { saveHomeConfig } from 'utils/api';
import { getActivityData } from 'inventory/android-health-connect';

import { AvatarViewer, WidgetIcon } from 'components/index';
import DefaultAvatar from 'assets/avatars/red-yellow-egg';
import WidgetContainer from 'components/home/WidgetContainer';
import OnboardingWizard from 'components/wizards/OnboardingWizard';
import {
STAGE_AVATAR_CONFIG,
TRACK_ONBOARDING_STAGE,
filterOutDefaultWidgets,
getStorage,
saveStorage,
} from 'utils/config';
import { debug } from 'utils/logging';

const HomeScreen = () => {
const homeConfig = useHomeConfig();
Expand All @@ -21,13 +29,22 @@ const HomeScreen = () => {
transform: [{ rotate: `${eggRollAngle.value}deg` }],
}));
const [widgetConfig, setWidgetConfig] = useState<WidgetConfig[]>([]);
const [onboardingStage, setOnboardingStage] = useState<string>();

useMemo(() => {
if (isEmpty(widgetConfig) && homeConfig?.widgets) {
setWidgetConfig(homeConfig.widgets);
}
}, [homeConfig, widgetConfig]);

useMemo(async () => {
const currentStage = await getStorage<obj>(TRACK_ONBOARDING_STAGE);
console.log('onboarding stage', onboardingStage, currentStage);
if (!onboardingStage && !currentStage?.[STAGE_AVATAR_CONFIG]) {
setOnboardingStage(STAGE_AVATAR_CONFIG);
}
}, [onboardingStage]);

useEffect(() => {
const intervalId = setInterval(() => {
const otherSide = eggRollAngle.value < 0 ? 30 : -30;
Expand All @@ -52,11 +69,23 @@ const HomeScreen = () => {
[setWidgetConfig],
);

const finalizeRenovation = () =>
// TODO widgetConfig is not updated when adding/removing widgets
saveHomeConfig({
widgets: widgetConfig,
});
const finalizeRenovation = useCallback(
(widgets?: WidgetConfig[]) =>
// TODO widgetConfig is not updated when adding/removing widgets
saveHomeConfig({
widgets: widgets ?? widgetConfig,
}),
[widgetConfig],
);

const completeWizardStage = useCallback(
(stage: string) => {
saveStorage(TRACK_ONBOARDING_STAGE, { [stage]: String(true) }, true, {}).then(() =>
setOnboardingStage(undefined),
);
},
[setOnboardingStage],
);

const HomeWidget = ({ id, title, path }: WidgetConfig) => {
return (
Expand All @@ -82,8 +111,35 @@ const HomeScreen = () => {

console.log('eggroll ', eggRollAngle.value);

if (onboardingStage === STAGE_AVATAR_CONFIG)
return (
<OnboardingWizard
startIndex={0}
onComplete={async (config) => {
try {
await finalizeRenovation([
...widgetConfig,
{
id: 'maliksmajik-avatar-viewer',
provider: 'MaliksMajik',
routeName: 'index', // home page
title: 'Avatar Viewer',
path: '/',
config,
// They can't have registered yet so no jinni id to specify for config
// eventually need to link with jiini. Could do in activate_jinni but :Widget wont be there if they start from desktop flow (github/facrcaster)
// target_uuid: await getStorage(ID_JINNI_SLOT)
},
]);
completeWizardStage(STAGE_AVATAR_CONFIG);
} catch (e) {
debug(e, { extra: { onboardingStage } });
}
}}
/>
);
return (
<View style={{ flex: 1, ...useTheme() }}>
<View style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.avatarContainer}>
<Animated.View style={[styles.avatar, eggAnimatedStyles]}>
Expand All @@ -92,7 +148,7 @@ const HomeScreen = () => {
<Button color="purple" title="Speak Intention" onPress={onIntentionPress} />
</View>
<WidgetContainer
widgets={widgetConfig}
widgets={filterOutDefaultWidgets(widgetConfig) as WidgetConfig[]}
WidgetRenderer={HomeWidget}
saveWidgets={saveWidgets}
finalizeRenovation={finalizeRenovation}
Expand Down
7 changes: 6 additions & 1 deletion src/app/inventory/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export default function Layout() {
title: 'Inventory',
}}
/>
<Stack.Screen name="[item]" />
<Stack.Screen
name="[item]"
options={{
headerBackButtonMenuEnabled: true,
}}
/>
</Stack>
);
}
2 changes: 1 addition & 1 deletion src/assets/game-content/modals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default {
text: 'You could not perform the ability at this time 🙈',
},
'select-multi': {
title: ({ title }) => `Select All Options${title ? ' For ' + title : ''}`,
title: ({ title }) => `Select All Options\n\n${title}`,
text: '',
},
};
8 changes: 8 additions & 0 deletions src/assets/game-content/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ export default {
title: '',
text: '',
},
2: {
title: '',
text: '',
},
3: {
title: '',
text: '',
},
},
modals: {
'create-spellbook': {
Expand Down
1 change: 1 addition & 0 deletions src/components/home/WidgetContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const WidgetContainer = ({
}),
);

console.log('widgets selected for homepage', newSettings);
if (finalizeRenovation) {
onRenovateEnd({ data: newSettings });
finalizeRenovation();
Expand Down
43 changes: 20 additions & 23 deletions src/components/modals/BaseModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,16 @@ import React, { useState, ReactNode } from 'react';
import { Text, Modal, View, TouchableOpacity, StyleSheet, Button } from 'react-native';

interface ModalProps {
children: ReactNode;
children: React.JSX.Element;
onClose?: () => void;
primaryButton?: { title: string; onPress: () => void };
secondaryButton?: { title: string; onPress: () => void };
primaryButton?: { button?: ReactNode; title?: string; onPress?: () => void };
secondaryButton?: { button?: ReactNode; title?: string; onPress?: () => void };
}

const BaseModal: React.FC<ModalProps> = ({ children, onClose, primaryButton, secondaryButton }) => {
const [visible, setVisible] = useState(true);
const theme = useTheme();

// const { height, width } = Dimensions.get('window');
// const modalStyle = {
// ...styles.modal,
// height: size === 'lg' ? height : size === 'md' ? height * 0.6 : 'auto',
// width: size === 'lg' ? width : size === 'md' ? width * 0.8 : 'auto',
// };

const closeModal = () => {
setVisible(false);
onClose && onClose();
Expand All @@ -28,7 +21,21 @@ const BaseModal: React.FC<ModalProps> = ({ children, onClose, primaryButton, sec
const textStyles = {
color: theme.primaryTextColor,
};
const renderButton = (config) => {
console.log('base modal button', config);

if (!config) return null;
if (config.button) return config.button;
if (config.title && config.onPress)
return (
<TouchableOpacity
style={[styles.button, { backgroundColor: theme.primaryBackgroundColor }]}
onPress={config.onPress}
>
<Text style={[styles.text, textStyles]}>{config.title}</Text>
</TouchableOpacity>
);
};
return !visible ? null : (
<Modal
animationType="fade"
Expand All @@ -40,17 +47,7 @@ const BaseModal: React.FC<ModalProps> = ({ children, onClose, primaryButton, sec
{children}
<View>
<View style={styles.ctaContainer}>
{primaryButton && (
<TouchableOpacity
style={[
styles.button,
{ backgroundColor: theme.primaryBackgroundColor },
]}
onPress={primaryButton.onPress}
>
<Text style={[styles.text, textStyles]}>{primaryButton.title}</Text>
</TouchableOpacity>
)}
{renderButton(primaryButton)}
{secondaryButton && (
<TouchableOpacity
style={[styles.button, { backgroundColor: theme.secondaryColor }]}
Expand All @@ -71,10 +68,10 @@ const BaseModal: React.FC<ModalProps> = ({ children, onClose, primaryButton, sec

const styles = StyleSheet.create({
modalSize: {
top: '15%',
top: '8%',
left: '10%',
right: '10%',
bottom: '15%',
bottom: '10%',
// shadowColor: '#FFC1CB',
// shadowOffset: { width: 5, height: 10 },
// shadowOpacity: 1,
Expand Down
Loading

0 comments on commit a8a35a3

Please sign in to comment.