Skip to content

Commit

Permalink
Merge pull request #136 from weaponsforge/dev
Browse files Browse the repository at this point in the history
v2.0.3
  • Loading branch information
weaponsforge authored May 28, 2023
2 parents 068dacc + 9df4ce2 commit 82589f7
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 130 deletions.
11 changes: 6 additions & 5 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
"next": "13.2.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"use-sync-v": "^2.0.19"
"use-sync-v": "^2.2.0"
}
}
21 changes: 16 additions & 5 deletions client/src/common/layout/page/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Box from '@mui/material/Box'
import Header from '@/common/layout/header'
import Section from '@/common/layout/section'
import { useSyncLocalStorage } from '@/lib/hooks/useSync'
import { setSyncLocalStorage, useSyncLocalStorage } from '@/lib/hooks/useSync'
import { Sidebar } from '../sidebar'
import { updateSyncV, useSyncV } from 'use-sync-v'
import { Divider, useMediaQuery } from '@mui/material'
import { useEffect } from 'react'
import { LoadingLinear } from '@/common/ui/loadingLinear'

const Background = () => {
const activeTheme = useSyncLocalStorage('activeTheme')
Expand All @@ -20,8 +21,7 @@ const Background = () => {
top: 0,
width: '100%',
height: '100%',
animation: `animate 90s linear infinite, ${
activeTheme === 'dark' ? 'darkColorSwitcher' : 'lightColorSwitcher'
animation: `animate 90s linear infinite, ${activeTheme === 'dark' ? 'darkColorSwitcher' : 'lightColorSwitcher'
} 42s linear infinite`,
},
'&:after': {
Expand Down Expand Up @@ -72,13 +72,23 @@ function Page({ children }) {
const animate = useSyncLocalStorage('animate')
const showSidebar = useSyncV('show.sidebar')
const isMobile = useMediaQuery('(max-width:900px)')
const loading = useSyncV('show.loading')


useEffect(() => {
if (isMobile) {
updateSyncV('show.sidebar', false)
} else {
updateSyncV('show.sidebar', true)
}
}, [isMobile])

useEffect(() => {
if (typeof animate === 'undefined') {
setSyncLocalStorage('animate', true)
}
}, [animate])

return (
<>
{animate && <Background />}
Expand All @@ -94,14 +104,15 @@ function Page({ children }) {
}}
>
<Header />
<LoadingLinear/>
<Box
sx={{
flex: 1,
display: 'flex',
overflowY:'scroll'
overflowY: 'scroll'
}}
>
{showSidebar && auth.authStatus === 'signedIn' && <Sidebar />}
{(!loading && showSidebar && auth.authStatus === 'signedIn' && !auth.authLoading) && <Sidebar />}
<Divider orientation="vertical" variant="middle" flexItem />

<Section>{children}</Section>
Expand Down
41 changes: 34 additions & 7 deletions client/src/common/ui/loadingLinear/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
import { LinearProgress } from '@mui/material'
import { Box, LinearProgress } from '@mui/material'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { updateSyncV, useSyncV } from 'use-sync-v'

export const LoadingLinear = () => {
const authLoading = useSyncV('auth.authLoading')
const loadingContacts = useSyncV('contacts.loading')
const loading = useSyncV('show.loading')

const router = useRouter()
useEffect(() => {
const changeStartHandler = () => {
updateSyncV('show.loading', true)
}
const changeCompleteHandler = () => {
updateSyncV('show.loading', false)
}
router.events.on('routeChangeStart', changeStartHandler)
router.events.on('routeChangeComplete', changeCompleteHandler)
// If the component is unmounted, unsubscribe
// from the event with the `off` method:
return () => {
router.events.off('routeChangeStart', changeStartHandler)
router.events.off('routeChangeComplete', changeCompleteHandler)
}
}, [router])
return (
<LinearProgress
sx={{
position: 'fixed',
width: '100%',
}}
/>
<Box sx={{ zIndex: 100 }}>
{(loadingContacts || authLoading || loading) && <LinearProgress
sx={{
position: 'fixed',
width: '100%',
}}
/>}
</Box>

)
}
5 changes: 0 additions & 5 deletions client/src/components/contacts/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import Page from '@/common/layout/page'
import { LoadingLinear } from '@/common/ui/loadingLinear'
import { Box } from '@mui/material'
import { useAsyncV } from 'use-sync-v'
import { ContactListDisplay } from './display'

function ContactsComponent() {
const { loading } = useAsyncV('contacts')

return (
<Page>
{loading && <LoadingLinear />}
<Box
sx={{
flex: 1,
Expand Down
100 changes: 10 additions & 90 deletions client/src/lib/hooks/useSync.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useCallback, useSyncExternalStore } from 'react'

const useSyncLocalStorageSubscribers = {}
const useSyncStoreSubscribers = {}
const store = {}

export const useSyncLocalStorage = (saveDirectory = 'global') => {
const subscribe = useCallback(
Expand Down Expand Up @@ -34,7 +32,11 @@ export const useSyncLocalStorage = (saveDirectory = 'global') => {

const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)

return state ? JSON.parse(state) : undefined
try {
return JSON.parse(state)
} catch (e) {
return state
}
}

export const setSyncLocalStorage = (saveDirectory = 'global', updatedValue) => {
Expand All @@ -43,94 +45,12 @@ export const setSyncLocalStorage = (saveDirectory = 'global', updatedValue) => {
subscriber()
}
}
localStorage[saveDirectory] = JSON.stringify(updatedValue)
emitChange()
}

// this is an attempt to solve the bug, and detach getter from setter, so calling setter won't neccesarily subscribe the component to the store
/**
* Returns the state of the given save directory in the store, by subscribing to the save directory
* and using an external state manager to manage state updates.
*
* @param {string} saveDirectory - The save directory to be subscribed to.
* @returns {*} The state of the given save directory in the store.
*/
export const useSyncStore = (saveDirectory = 'global') => {
/**
* Subscribes to the given save directory and returns a function to unsubscribe from the
* save directory.
*
* @param {Function} callback - The callback function to be called when the save directory changes.
* @returns {Function} A function to unsubscribe from the save directory.
*/
const subscribe = useCallback(
(callback) => {
if (!useSyncStoreSubscribers[saveDirectory]) {
useSyncStoreSubscribers[saveDirectory] = []
}

// Adds the callback function to the list of subscribers for the save directory
useSyncStoreSubscribers[saveDirectory] = [
...useSyncStoreSubscribers[saveDirectory],
callback,
]

// Returns a function to remove the callback function from the list of subscribers
return () => {
useSyncStoreSubscribers[saveDirectory] = useSyncStoreSubscribers[
saveDirectory
].filter((el) => el !== callback)
}
},
[saveDirectory]
)

/**
* Returns a snapshot of the state of the given save directory in the store.
*
* @returns {*} A snapshot of the state of the given save directory in the store.
*/
const getSnapshot = () => {
return JSON.stringify(store[saveDirectory])
}

/**
* Returns a snapshot of the state of the given save directory in the server.
*
* @returns {*} A snapshot of the state of the given save directory in the server.
*/
const getServerSnapshot = () => {
return JSON.stringify(store[saveDirectory])
}


// Uses an external state manager to manage state updates and returns the state of the given save directory
const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)

// Returns the parsed state of the given save directory
return state ? JSON.parse(state) : undefined
}

/**
* Sets the updated value to the given save directory in the store, and notifies all subscribers
* subscribed to the save directory.
*
* @param {string} saveDirectory - The save directory in which to set the updated value.
* @param {*} updatedValue - The updated value to be set in the save directory.
*/
export const setSyncStore = (saveDirectory = 'global', updatedValue) => {
/**
* Emits change event to all subscribers subscribed to the save directory.
*/
const emitChange = () => {
for (let subscriber of useSyncStoreSubscribers[saveDirectory]) {
subscriber()
}
try {
const data = JSON.stringify(updatedValue)
localStorage[saveDirectory] = data
} catch(e) {
localStorage[saveDirectory] = updatedValue
}

// Sets the updated value to the given save directory in the store
store[saveDirectory] = updatedValue

// Notifies all subscribers subscribed to the save directory
emitChange()
}
24 changes: 16 additions & 8 deletions client/src/pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import PropTypes from 'prop-types'
import Head from 'next/head'
import { ThemeProvider } from '@mui/material/styles'
import CssBaseline from '@mui/material/CssBaseline'
import { CacheProvider } from '@emotion/react'
import '@/styles/globals.css'
import { CacheProvider } from '@emotion/react'
import CssBaseline from '@mui/material/CssBaseline'
import { ThemeProvider } from '@mui/material/styles'
import Head from 'next/head'
import PropTypes from 'prop-types'

// MUI
import useInitAuth from '@/hooks/useInitAuth'
import { setSyncLocalStorage, useSyncLocalStorage } from '@/lib/hooks/useSync'
import createEmotionCache from '@/lib/mui/createEmotionCache'
import { lightTheme, darkTheme } from '@/lib/mui/theme'
import { useSyncLocalStorage } from '@/lib/hooks/useSync'
import { darkTheme, lightTheme } from '@/lib/mui/theme'
import { init } from '@/lib/store'
import useInitAuth from '@/hooks/useInitAuth'
import { useEffect } from 'react'


init()
// Source: https://github.com/mui/material-ui/tree/master/examples/material-next
Expand All @@ -21,7 +23,13 @@ const clientSideEmotionCache = createEmotionCache()
export default function MyApp(props) {
const activeTheme = useSyncLocalStorage('activeTheme')
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props

useInitAuth()
useEffect(()=>{
if (typeof activeTheme === 'undefined') {
setSyncLocalStorage('activeTheme', 'light')
}
}, [activeTheme])

return (
<CacheProvider value={emotionCache}>
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/contacts/edit/[doc_id].js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useRouter } from 'next/router'
import { useEffect, useMemo, useState } from 'react'
import { deleteSyncV, updateSyncV, useAsyncV, useSyncV } from 'use-sync-v'
import { deleteSyncV, useAsyncV, useSyncV } from 'use-sync-v'

import { FirebaseFirestore } from '@/lib/utils/firebase/firestore'
import { deleteFileFromStorage, uploadFileToStorage } from '@/lib/utils/firebase/storageutils'
Expand Down Expand Up @@ -87,7 +87,7 @@ const EditContact = () => {
setIsFormChanged(true)
}
}
updateSyncV('contacts.loading', true)

const saveHandler = async () => {
const createdContact = {
...form,
Expand Down
7 changes: 3 additions & 4 deletions client/src/pages/contacts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { useEffect } from 'react'
import { updateAsyncV, useSyncV } from 'use-sync-v'

function Contacts() {
const user = useSyncV('auth')
const showExportPopup = useSyncV('show.exportPopup')
const auth = useSyncV('auth')

useEffect(() => {
FirebaseFirestore.subscribeCol(
`users/${user.authUser.uid}/contacts`,
`users/${auth.authUser.uid}/contacts`,
(querySnapshot) => {
const data = []
querySnapshot.forEach((doc) => {
Expand All @@ -24,8 +24,7 @@ function Contacts() {
},
orderBy('sorting')
)
}, [user.authUser.uid])

}, [auth.authUser.uid])
return (
<>
{showExportPopup && <ExportPopup/>}
Expand Down
12 changes: 12 additions & 0 deletions client/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import HomeComponent from '@/components/home'
import { useSyncLocalStorage } from '@/lib/hooks/useSync'
import { getRandomJoke } from '@/lib/services/random'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { useSyncV } from 'use-sync-v'

const defaultState = {
joke:undefined,
Expand All @@ -11,7 +13,17 @@ const defaultState = {
function Index() {
const [state, setState] = useState(defaultState)
const activeTheme = useSyncLocalStorage('activeTheme')
const auth = useSyncV('auth')
const router = useRouter()

useEffect(()=>{
if (auth.authLoading) return
if (auth.authStatus === 'signedIn') {
router.push('/contacts')
} else {
router.push('/login')
}
},[auth.authLoading, auth.authStatus, router])
useEffect(()=>{
(async()=>{
const randomJoke = await getRandomJoke()
Expand Down
Loading

0 comments on commit 82589f7

Please sign in to comment.