Skip to content

Commit

Permalink
Merge pull request #869 from WatWowMap/user-disable-holidays
Browse files Browse the repository at this point in the history
Disable Holidays Client Side
  • Loading branch information
TurtIeSocks authored Nov 2, 2023
2 parents 9852b68 + 15be28b commit 3c8bf8c
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 64 deletions.
5 changes: 3 additions & 2 deletions packages/locales/lib/human/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -671,5 +671,6 @@
"done": "Done",
"fast": "Fast",
"charged": "Charged",
"offline_mode": "Offline Mode"
}
"offline_mode": "Offline Mode",
"disable": "Disable {{- name}}"
}
7 changes: 5 additions & 2 deletions src/components/Config.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { setLoadingText } from '@services/functions/setLoadingText'
import Utility from '@services/Utility'
import { deepMerge } from '@services/functions/deepMerge'
import { Navigate } from 'react-router-dom'
import { checkHoliday } from '@services/functions/checkHoliday'

const rootLoading = document.getElementById('loader')

Expand Down Expand Up @@ -109,13 +110,15 @@ export default function Config({ children }) {
userBackupLimits: data.database.settings.userBackupLimits || 0,
},
theme: data.map.theme,
holidayEffects: data.map.holidayEffects || [],
ui: data.ui,
menus: data.menus,
extraUserFields: data.database.settings.extraUserFields,
userSettings: data.clientMenus,
timeOfDay: Utility.timeCheck(...location),
config: data.map,
config: {
...data.map,
holidayEffects: (data.map.holidayEffects || []).filter(checkHoliday),
},
polling: data.api.polling,
settings,
gymValidDataLimit: data.api.gymValidDataLimit,
Expand Down
87 changes: 35 additions & 52 deletions src/components/HolidayEffects.jsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,56 @@
// @ts-check
import * as React from 'react'
import HolidayAnimations from '@services/HolidayAnimations'
import { useStatic } from '@hooks/useStore'
import { useStatic, useStore } from '@hooks/useStore'

/**
*
* @param {import("@rm/types").Config['map']['holidayEffects'][number]} props
* @returns
*/
export function HolidayEffect({
enabled,
endDay,
endMonth,
images,
name,
startDay,
startMonth,
css,
imageScale,
}) {
export function HolidayEffect({ images, name, css, imageScale }) {
const [element, setElement] = React.useState(
/** @type {React.ReactNode} */ (null),
)
const userDisabled = useStore((s) => s.holidayEffects[name] === true)

React.useLayoutEffect(() => {
const date = new Date()
const start = new Date(
date.getFullYear() - (startMonth > endMonth ? 1 : 0),
startMonth - 1,
startDay,
0,
0,
0,
)
const end = new Date(date.getFullYear(), endMonth - 1, endDay, 23, 59, 59)
if (enabled && date >= start && date <= end) {
switch (css) {
case 'snow':
setElement(
<div className="winter-is-coming" key={name}>
<div className="snow snow--near" />
<div className="snow snow--near snow--alt" />
<div className="snow snow--mid" />
<div className="snow snow--mid snow--alt" />
<div className="snow snow--far" />
<div className="snow snow--far snow--alt" />
</div>,
)
return () => setElement(null)
case 'fireworks':
setElement(
<div className="pyro" key={name}>
<div className="before" />
<div className="after" />
</div>,
)
return () => setElement(null)
default: {
if (images?.length) {
const animation = new HolidayAnimations(images, imageScale)
animation.initialize()
return () => {
animation.stop()
}
if (userDisabled) {
setElement(null)
return () => {}
}
switch (css) {
case 'snow':
setElement(
<div className="winter-is-coming">
<div className="snow snow--near" />
<div className="snow snow--near snow--alt" />
<div className="snow snow--mid" />
<div className="snow snow--mid snow--alt" />
<div className="snow snow--far" />
<div className="snow snow--far snow--alt" />
</div>,
)
return () => setElement(null)
case 'fireworks':
setElement(
<div className="pyro">
<div className="before" />
<div className="after" />
</div>,
)
return () => setElement(null)
default: {
if (images?.length) {
const animation = new HolidayAnimations(images, imageScale)
animation.initialize()
return () => {
animation.stop()
}
}
}
}
}, [])
}, [userDisabled])

return element
}
Expand Down
23 changes: 16 additions & 7 deletions src/components/layout/drawer/BoolToggle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Switch from '@mui/material/Switch'
import { useStore } from '@hooks/useStore'
import { useTranslation } from 'react-i18next'
import { fromSnakeCase } from '@services/functions/fromSnakeCase'
import dlv from 'dlv'
import { setDeep } from '@services/functions/setDeep'

/**
* @param {{
Expand All @@ -23,20 +25,27 @@ export default function BoolToggle({
disabled = false,
children,
}) {
const value = useStore((s) => s[field])
const value = useStore((s) => dlv(s, field))
const { t } = useTranslation()

const onChange = React.useCallback(
(
/** @type {React.ChangeEvent<HTMLInputElement>} */ _,
/** @type {boolean} */ checked,
) => {
useStore.setState((prev) => setDeep(prev, field, checked))
},
[field],
)
return (
<ListItem>
{children}
<ListItemText
primary={
t(label, fromSnakeCase(label)) ?? t(field, fromSnakeCase(field))
}
/>
<ListItemText sx={{ maxWidth: 150 }}>
{t(label, fromSnakeCase(label)) ?? t(field, fromSnakeCase(field))}
</ListItemText>
<Switch
edge="end"
onChange={(_e, v) => useStore.setState({ [field]: v })}
onChange={onChange}
checked={!!value}
disabled={disabled}
/>
Expand Down
22 changes: 22 additions & 0 deletions src/components/layout/drawer/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import NavIcon from '@mui/icons-material/Navigation'
import StyleIcon from '@mui/icons-material/Style'
import DevicesOtherIcon from '@mui/icons-material/DevicesOther'
import Brightness7Icon from '@mui/icons-material/Brightness7'
import CakeIcon from '@mui/icons-material/Cake'

import { useTranslation } from 'react-i18next'

Expand Down Expand Up @@ -59,6 +60,7 @@ export default function Settings() {
const separateDrawerActions = useStatic(
(s) => s.config.general.separateDrawerActions,
)
const holidayEffects = useStatic((s) => s.config.holidayEffects) || []

const settings = useStore((s) => s.settings)
const icons = useStore((s) => s.icons)
Expand Down Expand Up @@ -140,6 +142,26 @@ export default function Settings() {
<Brightness7Icon />
</ListItemIcon>
</BoolToggle>
{holidayEffects.map(({ name, images }) => (
<BoolToggle
key={name}
field={`holidayEffects.${name}`}
label={t('disable', { name })}
>
<ListItemIcon>
{images?.length > 0 ? (
<img
src={images[0]}
alt={name}
width={24}
className={darkMode ? '' : 'darken-image'}
/>
) : (
<CakeIcon />
)}
</ListItemIcon>
</BoolToggle>
))}
{!separateDrawerActions && (
<>
<Divider style={{ margin: '10px 0' }} />
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { persist } from 'zustand/middleware'
* tileServers: string
* },
* menus: Record<string, boolean>,
* holidayEffects: Record<string, boolean>,
* motdIndex: number
* tutorial: boolean,
* searchTab: string,
Expand Down Expand Up @@ -69,6 +70,7 @@ export const useStore = create(
})
}
},
holidayEffects: {},
settings: {},
userSettings: {},
icons: {},
Expand Down Expand Up @@ -189,7 +191,6 @@ export const useStatic = create((set) => ({
menuFilters: {},
userSettings: undefined,
settings: undefined,
holidayEffects: [],
available: {
gyms: [],
pokemon: [],
Expand Down
28 changes: 28 additions & 0 deletions src/services/functions/checkHoliday.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @ts-check
/**
*
* @param {import("packages/types/lib").Config['map']['holidayEffects'][number]} holiday
* @returns
*/
export function checkHoliday(holiday) {
if (!holiday.enabled) return false

const date = new Date()
const start = new Date(
date.getFullYear() - (holiday.startMonth > holiday.endMonth ? 1 : 0),
holiday.startMonth - 1,
holiday.startDay,
0,
0,
0,
)
const end = new Date(
date.getFullYear(),
holiday.endMonth - 1,
holiday.endDay,
23,
59,
59,
)
return date >= start && date <= end
}
26 changes: 26 additions & 0 deletions src/services/functions/setDeep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @ts-check
/**
*
* @param {object} obj
* @param {string | string[]} path
* @param {any} value
*/
export function setDeep(obj, path, value) {
if (typeof path === 'string') {
path = path.split('.')
}
if (path.length > 1) {
const e = path.shift()
setDeep(
(obj[e] =
Object.prototype.toString.call(obj[e]) === '[object Object]'
? { ...obj[e] }
: {}),
path,
value,
)
} else {
obj[path[0]] = value
}
return { ...obj }
}

0 comments on commit 3c8bf8c

Please sign in to comment.