Update maximum file size for caching in service worker to 6MB

This commit is contained in:
Mo Tarbin 2024-12-26 18:54:23 -05:00
parent bcd32a8616
commit 8f93cc5e62
3 changed files with 353 additions and 318 deletions

View file

@ -1,6 +1,6 @@
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { API_URL } from '../Config' import { API_URL } from '../Config'
import { login, RefreshToken } from './Fetcher' import { RefreshToken } from './Fetcher'
import { Preferences } from '@capacitor/preferences' import { Preferences } from '@capacitor/preferences'
@ -13,12 +13,12 @@ class ApiManager {
if (this.initialized) { if (this.initialized) {
return return
} }
const { value: serverURL } = await Preferences.get({ key: 'customServerUrl' }); const { value: serverURL } = await Preferences.get({
key: 'customServerUrl',
})
this.customServerURL = serverURL || this.apiURL this.customServerURL = serverURL || this.apiURL
this.initialized = true this.initialized = true
} }
getApiURL() { getApiURL() {
return this.customServerURL return this.customServerURL
@ -28,28 +28,25 @@ class ApiManager {
} }
} }
export const apiManager = new ApiManager()
export const apiManager = new ApiManager();
export function Fetch(url, options) { export function Fetch(url, options) {
if (!isTokenValid()) { if (!isTokenValid()) {
// store current location in cookie // store current location in cookie
Cookies.set('ca_redirect', window.location.pathname); Cookies.set('ca_redirect', window.location.pathname)
// Assuming you have a function isTokenValid() that checks token validity // Assuming you have a function isTokenValid() that checks token validity
window.location.href = '/login'; // Redirect to login page window.location.href = '/login' // Redirect to login page
// return Promise.reject("Token is not valid"); // return Promise.reject("Token is not valid");
} }
if (!options) { if (!options) {
options = {}; options = {}
} }
options.headers = { ...options.headers, ...HEADERS() }; options.headers = { ...options.headers, ...HEADERS() }
const baseURL = apiManager.getApiURL(); const baseURL = apiManager.getApiURL()
const fullURL = `${baseURL}${url}`; const fullURL = `${baseURL}${url}`
return fetch(fullURL, options); return fetch(fullURL, options)
} }
export const HEADERS = () => { export const HEADERS = () => {
@ -81,8 +78,7 @@ export const isTokenValid = () => {
} }
export const refreshAccessToken = () => { export const refreshAccessToken = () => {
RefreshToken() RefreshToken().then(res => {
.then(res => {
if (res.status === 200) { if (res.status === 200) {
res.json().then(data => { res.json().then(data => {
localStorage.setItem('ca_token', data.token) localStorage.setItem('ca_token', data.token)

View file

@ -1,13 +1,30 @@
import { Box, Button, Card, Checkbox, Divider, FormControl, FormHelperText, FormLabel, IconButton, Input, List, ListItem, Option, Select, Snackbar, Switch, Typography } from '@mui/joy' import { Capacitor } from '@capacitor/core'
import { LocalNotifications } from '@capacitor/local-notifications'
import { Preferences } from '@capacitor/preferences'
import { Close } from '@mui/icons-material'
import {
Box,
Button,
Card,
Divider,
FormControl,
FormHelperText,
FormLabel,
IconButton,
Input,
Option,
Select,
Snackbar,
Switch,
Typography,
} from '@mui/joy'
import React, { useContext, useEffect, useState } from 'react' import React, { useContext, useEffect, useState } from 'react'
import { UserContext } from '../../contexts/UserContext' import { UserContext } from '../../contexts/UserContext'
import { GetUserProfile, UpdateUserDetails } from '../../utils/Fetcher' import {
import { Capacitor } from '@capacitor/core' GetUserProfile,
import { Preferences } from '@capacitor/preferences' UpdateNotificationTarget,
import { LocalNotifications } from '@capacitor/local-notifications' UpdateUserDetails,
import { Close } from '@mui/icons-material' } from '../../utils/Fetcher'
import { PushNotifications } from '@capacitor/push-notifications'
import { UpdateNotificationTarget } from '../../utils/Fetcher'
const NotificationSetting = () => { const NotificationSetting = () => {
const [isSnackbarOpen, setIsSnackbarOpen] = useState(false) const [isSnackbarOpen, setIsSnackbarOpen] = useState(false)
@ -23,50 +40,53 @@ const NotificationSetting = () => {
} }
}, []) }, [])
const getNotificationPreferences = async () => { const getNotificationPreferences = async () => {
const ret = await Preferences.get({ key: 'notificationPreferences' }); const ret = await Preferences.get({ key: 'notificationPreferences' })
return JSON.parse(ret.value); return JSON.parse(ret.value)
}; }
const setNotificationPreferences = async (value) => { const setNotificationPreferences = async value => {
if (value.granted === false) { if (value.granted === false) {
await Preferences.set({ key: 'notificationPreferences', value: JSON.stringify({ granted: false }) }); await Preferences.set({
key: 'notificationPreferences',
value: JSON.stringify({ granted: false }),
})
return return
} }
const currentSettings = await getNotificationPreferences(); const currentSettings = await getNotificationPreferences()
await Preferences.set({ key: 'notificationPreferences', value: JSON.stringify({ ...currentSettings, ...value }) }); await Preferences.set({
}; key: 'notificationPreferences',
value: JSON.stringify({ ...currentSettings, ...value }),
})
}
const getPushNotificationPreferences = async () => { const getPushNotificationPreferences = async () => {
const ret = await Preferences.get({ key: 'pushNotificationPreferences' }); const ret = await Preferences.get({ key: 'pushNotificationPreferences' })
return JSON.parse(ret.value); return JSON.parse(ret.value)
}; }
const setPushNotificationPreferences = async (value) => { const setPushNotificationPreferences = async value => {
await Preferences.set({ key: 'pushNotificationPreferences', value: JSON.stringify(value) }); await Preferences.set({
}; key: 'pushNotificationPreferences',
value: JSON.stringify(value),
})
}
const [deviceNotification, setDeviceNotification] = useState( const [deviceNotification, setDeviceNotification] = useState(false)
false
)
const [dueNotification, setDueNotification] = useState(true) const [dueNotification, setDueNotification] = useState(true)
const [preDueNotification, setPreDueNotification] = useState(false) const [preDueNotification, setPreDueNotification] = useState(false)
const [naggingNotification, setNaggingNotification] = useState(false) const [naggingNotification, setNaggingNotification] = useState(false)
const [pushNotification, setPushNotification] = useState( const [pushNotification, setPushNotification] = useState(false)
false
)
useEffect(() => { useEffect(() => {
getNotificationPreferences().then((resp) => { getNotificationPreferences().then(resp => {
setDeviceNotification(resp.granted) setDeviceNotification(resp.granted)
setDueNotification(resp.dueNotification) setDueNotification(resp.dueNotification)
setPreDueNotification(resp.preDueNotification) setPreDueNotification(resp.preDueNotification)
setNaggingNotification(resp.naggingNotification) setNaggingNotification(resp.naggingNotification)
} })
) getPushNotificationPreferences().then(resp => {
getPushNotificationPreferences().then((resp) => {
setPushNotification(resp.granted) setPushNotification(resp.granted)
} })
)
}, []) }, [])
const [notificationTarget, setNotificationTarget] = useState( const [notificationTarget, setNotificationTarget] = useState(
@ -126,37 +146,37 @@ const NotificationSetting = () => {
<Typography level='body-md'>Manage your Device Notificaiton</Typography> <Typography level='body-md'>Manage your Device Notificaiton</Typography>
<FormControl <FormControl
orientation="horizontal" orientation='horizontal'
sx={{ width: 400, justifyContent: 'space-between' }} sx={{ width: 400, justifyContent: 'space-between' }}
> >
<div> <div>
<FormLabel>Device Notification</FormLabel> <FormLabel>Device Notification</FormLabel>
<FormHelperText sx={{ mt: 0 }}>{Capacitor.isNativePlatform()? 'Receive notification on your device when a task is due' : 'This feature is only available on mobile devices'} </FormHelperText> <FormHelperText sx={{ mt: 0 }}>
{Capacitor.isNativePlatform()
? 'Receive notification on your device when a task is due'
: 'This feature is only available on mobile devices'}{' '}
</FormHelperText>
</div> </div>
<Switch <Switch
disabled={!Capacitor.isNativePlatform()} disabled={!Capacitor.isNativePlatform()}
checked={deviceNotification} checked={deviceNotification}
onClick={(event) =>{ onClick={event => {
event.preventDefault() event.preventDefault()
if (deviceNotification === false) { if (deviceNotification === false) {
LocalNotifications.requestPermissions().then((resp) => { LocalNotifications.requestPermissions().then(resp => {
if (resp.display === 'granted') { if (resp.display === 'granted') {
setDeviceNotification(true) setDeviceNotification(true)
setNotificationPreferences({ granted: true }) setNotificationPreferences({ granted: true })
} } else if (resp.display === 'denied') {
else if (resp.display === 'denied') {
setIsSnackbarOpen(true) setIsSnackbarOpen(true)
setDeviceNotification(false) setDeviceNotification(false)
setNotificationPreferences({ granted: false }) setNotificationPreferences({ granted: false })
} }
}) })
} } else {
else{
setDeviceNotification(false) setDeviceNotification(false)
} }
} }}
}
color={deviceNotification ? 'success' : 'neutral'} color={deviceNotification ? 'success' : 'neutral'}
variant={deviceNotification ? 'solid' : 'outlined'} variant={deviceNotification ? 'solid' : 'outlined'}
endDecorator={deviceNotification ? 'On' : 'Off'} endDecorator={deviceNotification ? 'On' : 'Off'}
@ -173,33 +193,33 @@ const NotificationSetting = () => {
<Card> <Card>
{[ {[
{ {
'title': 'Due Date Notification', title: 'Due Date Notification',
'checked': dueNotification, checked: dueNotification,
'set': setDueNotification, set: setDueNotification,
'label': 'Notification when the task is due', label: 'Notification when the task is due',
'property': 'dueNotification', property: 'dueNotification',
'disabled': false disabled: false,
}, },
{ {
'title': 'Pre-Due Date Notification', title: 'Pre-Due Date Notification',
'checked': preDueNotification, checked: preDueNotification,
'set': setPreDueNotification, set: setPreDueNotification,
'label': 'Notification a few hours before the task is due', label: 'Notification a few hours before the task is due',
'property': 'preDueNotification', property: 'preDueNotification',
'disabled': true disabled: true,
}, },
{ {
'title': 'Overdue Notification', title: 'Overdue Notification',
'checked': naggingNotification, checked: naggingNotification,
'set': setNaggingNotification, set: setNaggingNotification,
'label': 'Notification when the task is overdue', label: 'Notification when the task is overdue',
'property': 'naggingNotification', property: 'naggingNotification',
'disabled': true disabled: true,
} },
] ].map(item => (
.map(item => (
<FormControl <FormControl
orientation="horizontal" key={item.property}
orientation='horizontal'
sx={{ width: 385, justifyContent: 'space-between' }} sx={{ width: 385, justifyContent: 'space-between' }}
> >
<div> <div>
@ -207,14 +227,18 @@ const NotificationSetting = () => {
<FormHelperText sx={{ mt: 0 }}>{item.label} </FormHelperText> <FormHelperText sx={{ mt: 0 }}>{item.label} </FormHelperText>
</div> </div>
<Switch checked={item.checked} <Switch
checked={item.checked}
disabled={item.disabled} disabled={item.disabled}
onClick={() => { onClick={() => {
setNotificationPreferences({ [item.property]: !item.checked }) setNotificationPreferences({ [item.property]: !item.checked })
item.set(!item.checked) item.set(!item.checked)
}} }}
color={item.checked ? 'success' : ''} color={item.checked ? 'success' : ''}
variant='solid' endDecorator={item.checked ? 'On' : 'Off'} slotProps={{ endDecorator: { sx: { minWidth: 24 } } }} /> variant='solid'
endDecorator={item.checked ? 'On' : 'Off'}
slotProps={{ endDecorator: { sx: { minWidth: 24 } } }}
/>
</FormControl> </FormControl>
))} ))}
</Card> </Card>
@ -274,7 +298,6 @@ const NotificationSetting = () => {
width: '210px', width: '210px',
mb: 1, mb: 1,
}} }}
onClick={() => { onClick={() => {
// schedule a local notification in 5 seconds // schedule a local notification in 5 seconds
LocalNotifications.schedule({ LocalNotifications.schedule({
@ -290,30 +313,34 @@ const NotificationSetting = () => {
extra: null, extra: null,
}, },
], ],
}); })
} }}
}>Test Notification </Button> >
Test Notification{' '}
</Button>
<Typography level='h3'>Custom Notification</Typography> <Typography level='h3'>Custom Notification</Typography>
<Divider /> <Divider />
<Typography level='body-md'>Notificaiton through other platform like Telegram or Pushover</Typography> <Typography level='body-md'>
Notificaiton through other platform like Telegram or Pushover
</Typography>
<FormControl <FormControl
orientation="horizontal" orientation='horizontal'
sx={{ width: 400, justifyContent: 'space-between' }} sx={{ width: 400, justifyContent: 'space-between' }}
> >
<div> <div>
<FormLabel>Custom Notification</FormLabel> <FormLabel>Custom Notification</FormLabel>
<FormHelperText sx={{ mt: 0 }}>Receive notification on other platform</FormHelperText> <FormHelperText sx={{ mt: 0 }}>
Receive notification on other platform
</FormHelperText>
</div> </div>
<Switch <Switch
checked={chatID !== 0} checked={chatID !== 0}
onClick={(event) =>{ onClick={event => {
event.preventDefault() event.preventDefault()
if (chatID !== 0) { if (chatID !== 0) {
setChatID(0) setChatID(0)
} } else {
else{
setChatID('') setChatID('')
UpdateUserDetails({ UpdateUserDetails({
chatID: Number(0), chatID: Number(0),
@ -325,10 +352,7 @@ const NotificationSetting = () => {
} }
setNotificationTarget('0') setNotificationTarget('0')
handleSave() handleSave()
}}
}
}
color={chatID !== 0 ? 'success' : 'neutral'} color={chatID !== 0 ? 'success' : 'neutral'}
variant={chatID !== 0 ? 'solid' : 'outlined'} variant={chatID !== 0 ? 'solid' : 'outlined'}
endDecorator={chatID !== 0 ? 'On' : 'Off'} endDecorator={chatID !== 0 ? 'On' : 'Off'}
@ -343,14 +367,12 @@ const NotificationSetting = () => {
</FormControl> </FormControl>
{chatID !== 0 && ( {chatID !== 0 && (
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: 2, gap: 2,
}} }}
> >
<Select <Select
value={notificationTarget} value={notificationTarget}
sx={{ maxWidth: '200px' }} sx={{ maxWidth: '200px' }}
@ -363,8 +385,8 @@ const NotificationSetting = () => {
{notificationTarget === '1' && ( {notificationTarget === '1' && (
<> <>
<Typography level='body-xs'> <Typography level='body-xs'>
You need to initiate a message to the bot in order for the Telegram You need to initiate a message to the bot in order for the
notification to work{' '} Telegram notification to work{' '}
<a <a
style={{ style={{
textDecoration: 'underline', textDecoration: 'underline',
@ -388,8 +410,8 @@ const NotificationSetting = () => {
}} }}
/> />
<Typography mt={0} level='body-xs'> <Typography mt={0} level='body-xs'>
If you don't know your Chat ID, start chat with userinfobot and it If you don't know your Chat ID, start chat with userinfobot and
will send you your Chat ID.{' '} it will send you your Chat ID.{' '}
<a <a
style={{ style={{
textDecoration: 'underline', textDecoration: 'underline',
@ -433,11 +455,27 @@ const NotificationSetting = () => {
</Button> </Button>
</Box> </Box>
)} )}
<Snackbar open={isSnackbarOpen} autoHideDuration={8000} onClose={() => setIsSnackbarOpen(false)} endDecorator={<IconButton size='md' onClick={() => setIsSnackbarOpen(false)}><Close/></IconButton>}> <Snackbar
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}> open={isSnackbarOpen}
autoHideDuration={8000}
onClose={() => setIsSnackbarOpen(false)}
endDecorator={
<IconButton size='md' onClick={() => setIsSnackbarOpen(false)}>
<Close />
</IconButton>
}
>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Typography level='title-md'>Permission Denied</Typography> <Typography level='title-md'>Permission Denied</Typography>
<Typography level='body-md'> <Typography level='body-md'>
You have denied the permission to receive notification on this device. Please enable it in your device settings You have denied the permission to receive notification on this
device. Please enable it in your device settings
</Typography> </Typography>
</div> </div>
</Snackbar> </Snackbar>

View file

@ -61,6 +61,7 @@ export default defineConfig({
workbox: { workbox: {
skipWaiting: true, // Force the waiting service worker to become the active service worker skipWaiting: true, // Force the waiting service worker to become the active service worker
clientsClaim: true, // Take control of uncontrolled clients as soon as the service worker becomes active clientsClaim: true, // Take control of uncontrolled clients as soon as the service worker becomes active
maximumFileSizeToCacheInBytes: 6000000, // 6MB
}, },
}), }),
], ],