Skip to content

Commit

Permalink
Merge pull request #6 from bennett-diaz/dev
Browse files Browse the repository at this point in the history
Set up context providers
  • Loading branch information
bennett-diaz authored Aug 11, 2024
2 parents 2526890 + c5e81cd commit 3ac0e9e
Show file tree
Hide file tree
Showing 32 changed files with 579 additions and 52 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/firebase-hosting-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ jobs:
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_STAGING }}'
projectId: instacap-staging
channelId: live
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_INSTACAP_GEMINI_FIREBASE }}
projectId: instacap-gemini-firebase
channelId: pr-${{ github.event.number }}
Binary file added public/images/apple-splash-1125-2436.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1170-2532.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1179-2556.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1242-2208.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1242-2688.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1284-2778.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1290-2796.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1488-2266.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1536-2048.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1620-2160.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1640-2360.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1668-2224.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-1668-2388.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-2048-2732.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-640-1136.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-750-1334.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/apple-splash-828-1792.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/hero-mobile-v1.png
Binary file not shown.
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"short_name": "React App",
"short_name": "React Boilerplate",
"name": "Create React App Sample",
"icons": [
{
Expand Down
29 changes: 18 additions & 11 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import { GluestackUIProvider, Box, Button, ButtonText, Text } from '@gluestack-u
import { config } from "./styles/gluestack_config/gluestack-ui.config"
import Results from './components/Results';
import WebOverlay from './components/WebOverlay';
import BottomBar from './components/BottomBar';
import { perf } from './firebaseConfig'
import { ImageProvider } from "./contexts/imageContext"
import { useLayout } from './contexts/layoutContext';




function App() {
console.log('hello world')
const [isWeb, setIsWeb] = useState(true);
const { isWeb, setIsWeb } = useLayout();

const handleOverlayClose = () => {
setIsWeb(false);
Expand All @@ -17,15 +21,18 @@ function App() {

return (
<GluestackUIProvider config={config}>
<Box>
{isWeb && <WebOverlay onClose={handleOverlayClose} />}
<Text>Hello Instacap!</Text>
<Results />
<Button>
<ButtonText>Hello world</ButtonText>
</Button>

</Box>
<ImageProvider>
<Box>
{isWeb && <WebOverlay onClose={handleOverlayClose} />}
<Text>Hello Instacap!</Text>
<Results />
<Button>
<ButtonText>Hello world</ButtonText>
</Button>
{/* <BottomBar/> */}

</Box>
</ImageProvider>
</GluestackUIProvider>
);
}
Expand Down
84 changes: 84 additions & 0 deletions src/components/BottomBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { useContext, useEffect, useState, useMemo } from 'react';
import { AppContext, useLayout } from '../contexts/layoutContext';
import { Box, HStack, Button, ButtonText, ButtonIcon, VStack, Text, Icon, Pressable } from '@gluestack-ui/themed';
import { defaultTabs } from '../contexts/remoteConfigContext';


const BottomBar = () => {

const { tabs, activeTab, setActiveTab, tabContent, setTabContent, setSelectedContent } = useContext(AppContext)
const { TabColorMapping, IconMapping } = useLayout();

const handleTabChange = (tabId) => {
if (activeTab !== tabId) {

setActiveTab(tabId);
setSelectedContent(null);
}
if ((tabId !== tabs.MoreTab?.fixed_id || defaultTabs.MoreTab?.fixed_id) && tabContent !== tabId) {
setTabContent(tabId);
}
};
const tabLayout = useMemo(() => {
const currentTabs = tabs || defaultTabs;

return [
{ icon: currentTabs.HomeTab?.icon, label: currentTabs.HomeTab?.label, fixed_id: currentTabs.HomeTab?.fixed_id },
{ icon: currentTabs.AccountTab?.icon, label: currentTabs.AccountTab?.label, fixed_id: currentTabs.AccountTab?.fixed_id },
{ icon: currentTabs.MoreTab?.icon, label: currentTabs.MoreTab?.label, fixed_id: currentTabs.MoreTab?.fixed_id },
];
}, [tabs]);

return (
<Box
display="flex"
flexDirection="row"
justifyContent="space-between"
position="sticky"
bottom={0}
w="100%"
py="$3"
// px="$12"
bg="$backgroundLight0"
borderTopWidth="$1"
borderColor="$borderLight300"
softShadow="1"
zIndex="999"
// gap={56}
sx={{
"@md": {
display: 'none',
}
}}
>
<Box flex={1} display="flex" justifyContent="flex-start">
{tabLayout[0] && renderTab(tabLayout[0])}
</Box>

<Box display="flex" justifyContent="center" px="1rem">
{tabLayout[1] && renderTab(tabLayout[1])}
</Box>

<Box flex={1} display="flex" justifyContent="flex-end">
{tabLayout[2] && renderTab(tabLayout[2])}
</Box>
</Box>
);

function renderTab(tab) {
const IconFile = IconMapping[tab.icon];
const activeColor = TabColorMapping[tab.fixed_id];
return (
<Pressable key={tab.label} onPress={() => handleTabChange(tab.fixed_id)}>
<VStack alignItems="center">
<Icon as={IconFile} strokeWidth={2.25} color={activeTab === tab.fixed_id ? activeColor : "$textLight400"} size={24} />
<Text fontSize="0.85rem" fontWeight='$semibold' color={activeTab === tab.fixed_id ? activeColor : "$textLight400"}>
{tab.label}
</Text>
</VStack>
</Pressable>
);
}
};

export default BottomBar;
21 changes: 21 additions & 0 deletions src/components/FallbackUI.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Box } from '@gluestack-ui/themed';

export const errorPage = ({ error, resetErrorBoundary }) => {

return (
<Box>
<h1>Custom fallback UI</h1>
<p>Something went wrong:</p>
<pre>{error.message}</pre>
{/* <button onClick={resetErrorBoundary}>Try again</button> */}
</Box>

);
};

export const logErrorToService = ({ error, info }) => {
// console.error("BD FallbackUI error:", error, info);
}


export default { errorPage, logErrorToService };
8 changes: 7 additions & 1 deletion src/components/Results.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { Button, ButtonText } from '@gluestack-ui/themed';
import { startChat, sendMessage } from '../utils/geminiTemp';
import { testFile } from '../utils/geminiApi';
import { useImage } from '../contexts/imageContext';




const Results = () => {
Expand All @@ -10,6 +13,9 @@ const Results = () => {
const [messages, setMessages] = useState([]);
const [isLoading, setIsLoading] = useState(false);

const { urlBox, isUrlBoxValid } = useImage()


// const fileInfo = testFile(process.env.REACT_APP_API_KEY);
// console.log(fileInfo);

Expand Down
126 changes: 126 additions & 0 deletions src/contexts/authContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { createContext, useContext, useEffect, useState } from 'react';
import { myAuthObj } from '../firebaseConfig'
import { onAuthStateChanged, signOut, deleteUser, PhoneAuthProvider, AnonymousAuthProvider } from 'firebase/auth';
import * as firebaseui from 'firebaseui';

export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {

myAuthObj.useDeviceLanguage();
myAuthObj.settings.appVerificationDisabledForTesting = false;

// represents currently authenticated user
// firebase SDK operations (like signing-in) are done on myAuthObj
const [curUser, setCurUser] = useState(null);

const firebaseUI = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(myAuthObj);

useEffect(() => {
// triggered for signin, signout, load, token expire, change pw, reauth
const unsubscribe = onAuthStateChanged(myAuthObj, (user) => {
if (user) {
setCurUser(user);
console.log('Firebase user found; setting current user');
} else {
console.log('Firebase user not found');
}
});
return () => {
console.log('Unsubscribing from auth state monitoring');
unsubscribe();
};
}, []);

useEffect(() => {
if (curUser) {
console.log('LIFECYCLE: curUser uid:', curUser.uid);
} else {
console.log('LIFECYCLE: no curUser');
}
}, [curUser]);


const handleSuccessfulSignIn = (authResult, redirectUrl) => {
console.log('SUCCESS')
if (authResult.additionalUserInfo.isNewUser) {
console.log('New user signed in with UID:', authResult.user.uid);
}
return true
};

const handleSignOut = async () => {
try {
await signOut(myAuthObj);
setCurUser(null);
console.log('Sign-out successful');
} catch (error) {
console.error('Sign-out error: ', error);
}
};

const handleDeleteAccount = async () => {
if (!curUser) {
console.error('No user to delete.');
return;
}
try {
console.log('curUser to be deleted:', curUser)
await deleteUser(curUser);
console.log('User deleted successfully');
await handleSignOut();
} catch (error) {
console.error('Account deletion error: ', error);
}
};


const handleSignInFailure = (error) => {
console.log('FAILURE')
console.log('Sign-in error: ', error)
}

const handleUIRender = () => {
// hide the loader when widget is rendered
document.getElementById('loader').style.display = 'none';
}


const firebaseUIConfig = {
callbacks: {
signInSuccessWithAuthResult: handleSuccessfulSignIn,
signInFailure: handleSignInFailure,
uiShown: handleUIRender,
},
signInFlow: 'popup', // 'popup' or 'redirect'
// signInSuccessUrl: 'instacap.ai', // only relevant for redirect flow
signInOptions: [
{
provider: PhoneAuthProvider.PROVIDER_ID,
fullLabel: 'Continue with SMS',
recaptchaParameters: {
type: 'image', // 'audio'
size: 'normal', // 'normal' 'invisible' or 'compact'
badge: 'inline', // 'bottomright' or 'inline'
},
defaultCountry: 'US',
// defaultNationalNumber: '1234567890',
// loginHint: '+11234567890',
// whitelistedCountries: ['US']
},

firebaseui.auth.AnonymousAuthProvider.PROVIDER_ID
],
immediateFederatedRedirect: false,
tosUrl: 'https://instacap.ai/terms',
privacyPolicyUrl: 'https://instacap.ai/privacy'
};


return (
<AuthContext.Provider value={{ firebaseUI, firebaseUIConfig, curUser, handleSignOut, handleDeleteAccount }}>
{children}
</AuthContext.Provider>
);
};

export const useAuth = () => useContext(AuthContext);
26 changes: 26 additions & 0 deletions src/contexts/imageContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createContext, useContext, useState } from 'react';

// TODO: may not need this if using Google File API

export const ImageContext = createContext();

export const ImageProvider = ({ children }) => {

const [urlBox, setUrlBox] = useState('')
const [isUrlBoxValid, setIsUrlBoxValid] = useState(false)
const [imgUrl, setImgUrl] = useState('')
const [imgForm, setImgForm] = useState(null)
const [imgSrc, setImgSrc] = useState(null)
const [imgBox, setImgBox] = useState('')


return (
<ImageContext.Provider value={{ urlBox, setUrlBox, isUrlBoxValid, setIsUrlBoxValid, imgUrl, setImgUrl, imgForm, setImgForm, imgSrc, setImgSrc, imgBox, setImgBox }}>
{children}
</ImageContext.Provider>
);

}


export const useImage = () => useContext(ImageContext);
Loading

0 comments on commit 3ac0e9e

Please sign in to comment.