-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(settings): user can disabled plausible analytics
- Loading branch information
Stéphane
committed
Nov 2, 2023
1 parent
f6ddf23
commit b18df0e
Showing
11 changed files
with
198 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
REACT_APP_API_URL=http://localhost:3001 | ||
REACT_APP_API_URL=https://holoplay-serverless.vercel.app | ||
REACT_APP_PLAUSIBLE_ANALYTICS=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { memo, useMemo } from "react"; | ||
import { useScript } from "../hooks/useScript"; | ||
import { useSettings } from "../providers/Settings"; | ||
|
||
const PLAUSIBLE_INSTANCE_SCRIPT_URL = "https://plausible.holoplay.io/js/script.js"; | ||
|
||
export const Scripts = memo(() => { | ||
const settings = useSettings(); | ||
const analyticsEnabled = useMemo(() => process.env.REACT_APP_PLAUSIBLE_ANALYTICS === "true" && settings.analytics, [settings.analytics]); | ||
useScript(analyticsEnabled ? PLAUSIBLE_INSTANCE_SCRIPT_URL : null); | ||
return null | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { memo } from "react" | ||
import { useSetSettings, useSettings } from "../providers/Settings"; | ||
import { Alert, Switch } from "@mantine/core"; | ||
import { useTranslation } from "react-i18next"; | ||
import { db } from "../database"; | ||
import type { Settings } from "../types/interfaces/Settings"; | ||
|
||
export const SwitchPlausibleAnalytics = memo(() => { | ||
const settings = useSettings(); | ||
const setSettings = useSetSettings(); | ||
const { t } = useTranslation(); | ||
|
||
const handleChange = () => { | ||
const analytics = !settings.analytics; | ||
db.update("settings", { ID: 1 }, (data: Settings) => ({ | ||
analytics | ||
})); | ||
db.commit(); | ||
setSettings((previousState) => ({ | ||
...previousState, | ||
analytics, | ||
})); | ||
} | ||
|
||
return ( | ||
<> | ||
<Alert mb="lg"> | ||
{t('settings.general.analytics.info')} <a href="https://plausible.holoplay.io/holoplay.io" target="_blank" rel="noreferrer">{t('settings.general.analytics.link')}</a> | ||
</Alert> | ||
<Switch | ||
size="md" | ||
checked={settings.analytics} | ||
label={t("settings.general.analytics.label")} | ||
onChange={handleChange} | ||
/> | ||
</> | ||
) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import { useEffect, useState } from 'react' | ||
|
||
// Source: https://usehooks-ts.com/react-hook/use-script | ||
|
||
export type UseScriptStatus = 'idle' | 'loading' | 'ready' | 'error' | ||
export interface UseScriptOptions { | ||
shouldPreventLoad?: boolean | ||
removeOnUnmount?: boolean | ||
} | ||
|
||
const cachedScriptStatuses: Record<string, UseScriptStatus | undefined> = {} | ||
|
||
const getScriptNode = (src: string) => { | ||
const node: HTMLScriptElement | null = document.querySelector( | ||
`script[src="${src}"]`, | ||
) | ||
const status = node?.getAttribute('data-status') as | ||
| UseScriptStatus | ||
| undefined | ||
|
||
return { | ||
node, | ||
status, | ||
} | ||
} | ||
|
||
export const useScript = ( | ||
src: string | null, | ||
options?: UseScriptOptions, | ||
): UseScriptStatus => { | ||
const [status, setStatus] = useState<UseScriptStatus>(() => { | ||
if (!src || options?.shouldPreventLoad) { | ||
return 'idle' | ||
} | ||
|
||
if (typeof window === 'undefined') { | ||
// SSR Handling - always return 'loading' | ||
return 'loading' | ||
} | ||
|
||
return cachedScriptStatuses[src] ?? 'loading' | ||
}) | ||
|
||
useEffect(() => { | ||
if (!src || options?.shouldPreventLoad) { | ||
return | ||
} | ||
|
||
const cachedScriptStatus = cachedScriptStatuses[src] | ||
if (cachedScriptStatus === 'ready' || cachedScriptStatus === 'error') { | ||
// If the script is already cached, set its status immediately | ||
setStatus(cachedScriptStatus) | ||
return | ||
} | ||
|
||
// Fetch existing script element by src | ||
// It may have been added by another instance of this hook | ||
const script = getScriptNode(src) | ||
let scriptNode = script.node | ||
|
||
if (!scriptNode) { | ||
// Create script element and add it to document body | ||
scriptNode = document.createElement('script') | ||
scriptNode.src = src | ||
scriptNode.async = true | ||
scriptNode.setAttribute('data-status', 'loading') | ||
document.body.appendChild(scriptNode) | ||
|
||
// Store status in attribute on script | ||
// This can be read by other instances of this hook | ||
const setAttributeFromEvent = (event: Event) => { | ||
const scriptStatus: UseScriptStatus = | ||
event.type === 'load' ? 'ready' : 'error' | ||
|
||
scriptNode?.setAttribute('data-status', scriptStatus) | ||
} | ||
|
||
scriptNode.addEventListener('load', setAttributeFromEvent) | ||
scriptNode.addEventListener('error', setAttributeFromEvent) | ||
} else { | ||
// Grab existing script status from attribute and set to state. | ||
setStatus(script.status ?? cachedScriptStatus ?? 'loading') | ||
} | ||
|
||
// Script event handler to update status in state | ||
// Note: Even if the script already exists we still need to add | ||
// event handlers to update the state for *this* hook instance. | ||
const setStateFromEvent = (event: Event) => { | ||
const newStatus = event.type === 'load' ? 'ready' : 'error' | ||
setStatus(newStatus) | ||
cachedScriptStatuses[src] = newStatus | ||
} | ||
|
||
// Add event listeners | ||
scriptNode.addEventListener('load', setStateFromEvent) | ||
scriptNode.addEventListener('error', setStateFromEvent) | ||
|
||
// Remove event listeners on cleanup | ||
return () => { | ||
if (scriptNode) { | ||
scriptNode.removeEventListener('load', setStateFromEvent) | ||
scriptNode.removeEventListener('error', setStateFromEvent) | ||
} | ||
|
||
if (scriptNode && options?.removeOnUnmount) { | ||
scriptNode.remove() | ||
} | ||
} | ||
}, [src, options?.shouldPreventLoad, options?.removeOnUnmount]) | ||
|
||
return status | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters