diff --git a/src/providers/AudioProvider.tsx b/src/providers/AudioProvider.tsx
new file mode 100644
index 0000000..e03b729
--- /dev/null
+++ b/src/providers/AudioProvider.tsx
@@ -0,0 +1,97 @@
+import React, { ReactNode } from 'react';
+import { useStoreInLS } from './StorageProvider';
+
+// eslint-disable-next-line react-refresh/only-export-components
+export enum MyAudio {
+ BING = '/src/audio/bing.mp3',
+}
+
+const AudioContext = React.createContext({
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ playAudio: (_audio: MyAudio) => {},
+ toggleAudio: () => {},
+ isAudioEnabled: (): boolean => {
+ return false;
+ },
+});
+
+// eslint-disable-next-line react-refresh/only-export-components
+export function usePlayAudio() {
+ const context = React.useContext(AudioContext);
+ if (!context) {
+ throw new Error('usePlayAudio must be used within a AudioProvider');
+ }
+ return context.playAudio;
+}
+
+// eslint-disable-next-line react-refresh/only-export-components
+export function useToggleAudio() {
+ const context = React.useContext(AudioContext);
+ if (!context) {
+ throw new Error('useToggleAudio must be used within a AudioProvider');
+ }
+ return context.toggleAudio;
+}
+
+// eslint-disable-next-line react-refresh/only-export-components
+export function useIsAudioEnabled() {
+ const context = React.useContext(AudioContext);
+ if (!context) {
+ throw new Error(
+ 'useIsAudioEnabled must be used within a AudioProvider'
+ );
+ }
+ return context.isAudioEnabled;
+}
+
+interface Props {
+ children: ReactNode;
+}
+
+/**
+ * A provider that plays audio
+ */
+export function AudioProvider({ children }: Props) {
+ const [enabled, setEnabled] = React.useState(false);
+
+ const storeInLS = useStoreInLS();
+
+ React.useEffect(() => {
+ if (localStorage.getItem('audio-allowed') === 'true') {
+ setEnabled(true);
+ }
+ }, []);
+
+ const play = (audio: MyAudio) => {
+ if (!enabled) {
+ return;
+ }
+ const a = new Audio(audio);
+ a.addEventListener('canplaythrough', () => {
+ /* the audio is now playable; play it if permissions allow */
+ a.play();
+ });
+ a.play();
+ };
+
+ const toggle = () => {
+ storeInLS('audio-allowed', JSON.stringify(!enabled));
+ setEnabled(!enabled);
+ };
+
+ const isEnabled = () => {
+ return enabled;
+ };
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/providers/DocBaseTaskProvider.tsx b/src/providers/DocBaseTaskProvider.tsx
index 50528fa..3eadada 100644
--- a/src/providers/DocBaseTaskProvider.tsx
+++ b/src/providers/DocBaseTaskProvider.tsx
@@ -2,9 +2,14 @@
import React, { ReactNode } from 'react';
import DocbaseViewer from '../components/DocbaseViewer/DocbaseViewer';
import DocBase from '../types/DocBase';
-import { useSetLoadingScreen } from './LoadingScreenProvider';
+import {
+ useSetLoadingScreen,
+ useSetLoadingScreenLock,
+} from './LoadingScreenProvider';
import APIService from '../utils/ApiService';
import { useShowNotification } from './NotificationProvider';
+import Logger from '../utils/Logger';
+import { MyAudio, usePlayAudio } from './AudioProvider';
const DocBaseTaskContext = React.createContext({
isDocbaseTaskRunning: (): boolean => {
@@ -48,7 +53,9 @@ interface Props {
*/
export function DocBaseTaskProvider({ children }: Props) {
const setLoadingScreen = useSetLoadingScreen();
+ const setLoadingScreenLock = useSetLoadingScreenLock();
const showNotification = useShowNotification();
+ const playAudio = usePlayAudio();
const [isRunning, setIsRunning] = React.useState(false);
const [docBase, setDocBase] = React.useState
(
@@ -67,13 +74,15 @@ export function DocBaseTaskProvider({ children }: Props) {
'Please wait...',
taskId
);
+ setLoadingScreenLock(true);
setIsRunning(true);
const updateInterval = setInterval(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
APIService.getTaskStatus(taskId).then((res): any => {
- console.log(res);
+ Logger.log(res);
if (res == undefined || res.state === 'FAILURE') {
+ setLoadingScreenLock(false);
setLoadingScreen(false);
showNotification(
'Error',
@@ -87,11 +96,14 @@ export function DocBaseTaskProvider({ children }: Props) {
}
if (res.state === 'SUCCESS') {
+ setLoadingScreenLock(false);
setLoadingScreen(false);
+ // play sound
+ playAudio(MyAudio.BING);
+
const docBase = new DocBase(basename, attList);
for (const nugget of res.meta.document_base_to_ui.msg
.nuggets) {
- console.log(nugget);
try {
docBase.addNugget(
nugget.document.name,
@@ -132,7 +144,8 @@ export function DocBaseTaskProvider({ children }: Props) {
true,
'Creating Docbase ' + basename + '...',
info,
- taskId
+ taskId,
+ true
);
});
}, 1000);
diff --git a/src/providers/LoadingScreenProvider.tsx b/src/providers/LoadingScreenProvider.tsx
index 1f27c02..9dfb860 100644
--- a/src/providers/LoadingScreenProvider.tsx
+++ b/src/providers/LoadingScreenProvider.tsx
@@ -7,8 +7,10 @@ const LoadingScreenContext = React.createContext({
_loading: boolean,
_heading = 'Loading...',
_info = 'Please wait',
- _id = ''
+ _id = '',
+ _force = false
) => {},
+ setLoadingScreenLock: (_lock: boolean) => {},
});
// eslint-disable-next-line react-refresh/only-export-components
@@ -22,6 +24,17 @@ export function useSetLoadingScreen() {
return context.setLoadingScreen;
}
+// eslint-disable-next-line react-refresh/only-export-components
+export function useSetLoadingScreenLock() {
+ const context = React.useContext(LoadingScreenContext);
+ if (!context) {
+ throw new Error(
+ 'useSetLoadingScreenLock must be used within a LoadingScreenProvider'
+ );
+ }
+ return context.setLoadingScreenLock;
+}
+
interface Props {
children: ReactNode;
}
@@ -31,6 +44,7 @@ interface Props {
*/
export function LoadingScreenProvider({ children }: Props) {
const [loading, setLoading] = React.useState(false);
+ const [lock, setLock] = React.useState(false);
const [heading, setHeading] = React.useState('');
const [info, setInfo] = React.useState('');
const [id, setId] = React.useState('');
@@ -39,18 +53,25 @@ export function LoadingScreenProvider({ children }: Props) {
loading: boolean,
heading = 'Loading...',
info = 'Please wait',
- id = ''
+ id = '',
+ force = false
) => {
+ if (lock && !force) return;
setLoading(loading);
setHeading(heading);
setInfo(info);
setId(id);
};
+ const setLoadingScreenLock = (lock: boolean) => {
+ setLock(lock);
+ };
+
return (
{loading && }
diff --git a/src/providers/Providers.tsx b/src/providers/Providers.tsx
index 59384e7..55c135d 100644
--- a/src/providers/Providers.tsx
+++ b/src/providers/Providers.tsx
@@ -6,6 +6,7 @@ import { ThemeProvider } from './ThemeProvider';
import { UserProvider } from './UserProvider';
import { LoadingScreenProvider } from './LoadingScreenProvider';
import { DocBaseTaskProvider } from './DocBaseTaskProvider';
+import { AudioProvider } from './AudioProvider';
interface Props {
children: ReactNode;
@@ -20,13 +21,15 @@ export function Providers({ children }: Props) {
-
-
-
- {children}
-
-
-
+
+
+
+
+ {children}
+
+
+
+
diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts
new file mode 100644
index 0000000..39f1027
--- /dev/null
+++ b/src/utils/Logger.ts
@@ -0,0 +1,32 @@
+/**
+ * A logger class to log messages to the console only if the environment variable VITE_APP_LOG is set to true
+ */
+class Logger {
+ /**
+ * Log a message to the console
+ * @param message The message to log
+ */
+ public static log(message: unknown): void {
+ if (import.meta.env.VITE_APP_LOG === 'false') return;
+ console.log(message);
+ }
+
+ /**
+ * Log a error to the console
+ * @param message The message to log
+ */
+ public static error(message: unknown): void {
+ if (import.meta.env.VITE_APP_LOG === 'false') return;
+ console.error(message);
+ }
+ /**
+ * Log a error to the console
+ * @param message The message to log
+ */
+ public static warn(message: unknown): void {
+ if (import.meta.env.VITE_APP_LOG === 'false') return;
+ console.warn(message);
+ }
+}
+
+export default Logger;
diff --git a/src/views/Settings/Settings.tsx b/src/views/Settings/Settings.tsx
index b149462..d03192d 100644
--- a/src/views/Settings/Settings.tsx
+++ b/src/views/Settings/Settings.tsx
@@ -1,4 +1,8 @@
import Navbar from '../../components/Navbar/Navbar';
+import {
+ useIsAudioEnabled,
+ useToggleAudio,
+} from '../../providers/AudioProvider';
import {
useAcceptCookie,
useCookieAllowed,
@@ -18,6 +22,9 @@ function Settings() {
const isDarkMode = useIsDarkTheme();
const toggleTheme = useToggleTheme();
+ const isSoundEnabled = useIsAudioEnabled();
+ const toggleSound = useToggleAudio();
+
return (
@@ -41,6 +48,11 @@ function Settings() {
earance
+
+ {isDarkMode
+ ? 'Dark Mode is enabled'
+ : 'Light Mode is enabled'}
+
+
+ Sound
+
+ {isSoundEnabled() ? 'Sound is On' : 'Sound is Off'}
+
Storage