Use react-hot-toast for important notifications

This commit is contained in:
Richard Roberson 2025-02-05 15:07:24 -07:00
parent 6e96aeb821
commit e3167a18ea
5 changed files with 55 additions and 11 deletions

28
package-lock.json generated
View file

@ -21,6 +21,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-dropzone": "^14.3.5",
"react-hot-toast": "^2.5.1",
"react-pdf": "^9.2.1",
"string-similarity": "^4.0.4",
"uuid": "^11.0.5"
@ -2186,7 +2187,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"devOptional": true,
"license": "MIT"
},
"node_modules/damerau-levenshtein": {
@ -3537,6 +3537,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/goober": {
"version": "2.1.16",
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
"integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==",
"license": "MIT",
"peerDependencies": {
"csstype": "^3.0.10"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@ -5521,6 +5530,23 @@
"react": ">= 16.8 || 18.0.0"
}
},
"node_modules/react-hot-toast": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.5.1.tgz",
"integrity": "sha512-54Gq1ZD1JbmAb4psp9bvFHjS7lje+8ubboUmvKZkCsQBLH6AOpZ9JemfRvIdHcfb9AZXRaFLrb3qUobGYDJhFQ==",
"license": "MIT",
"dependencies": {
"csstype": "^3.1.3",
"goober": "^2.1.16"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"react": ">=16",
"react-dom": ">=16"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",

View file

@ -22,6 +22,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-dropzone": "^14.3.5",
"react-hot-toast": "^2.5.1",
"react-pdf": "^9.2.1",
"string-similarity": "^4.0.4",
"uuid": "^11.0.5"

View file

@ -3,6 +3,7 @@ import { Providers } from "./providers";
import { Metadata } from "next";
import Script from "next/script";
import { Footer } from "@/components/Footer";
import { Toaster } from 'react-hot-toast';
export const metadata: Metadata = {
title: "OpenReader WebUI",
@ -69,6 +70,7 @@ export default function RootLayout({
{!isDev && <Footer />}
</div>
</div>
<Toaster />
</Providers>
</body>
</html>

View file

@ -1,11 +1,17 @@
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import toast from 'react-hot-toast';
export function PDFSkeleton() {
const [showNotification, setShowNotification] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
setShowNotification(true);
toast('There might be an issue with the file import. Please try again.', {
icon: '⚠️',
style: {
background: 'var(--background)',
color: 'var(--accent)',
},
duration: 5000,
});
}, 3000);
return () => clearTimeout(timer);
@ -13,11 +19,6 @@ export function PDFSkeleton() {
return (
<div className="flex flex-col items-center justify-center min-h-[50vh] w-full">
{showNotification && (
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-2 rounded shadow-lg z-50">
There might be an issue with the file import. Please try again.
</div>
)}
<div className="flex flex-col items-center gap-4">
<div className="w-12 h-12 border-4 border-accent border-t-transparent rounded-full animate-spin"></div>
</div>

View file

@ -25,6 +25,7 @@ import React, {
} from 'react';
import OpenAI from 'openai';
import { Howl } from 'howler';
import toast from 'react-hot-toast';
import { useConfig } from '@/contexts/ConfigContext';
import { splitIntoSentences, preprocessSentenceForAudio } from '@/utils/nlp';
@ -136,8 +137,21 @@ export function TTSProvider({ children }: { children: React.ReactNode }) {
// If skipBlank is enabled and there's no text and we are playing audio, automatically move to next page
if (isPlaying && skipBlank && newSentences.length === 0 && currDocPage < currDocPages!) {
console.log('Skipping blank page:', currDocPage);
incrementPage();
toast.success(`Skipping blank page ${currDocPage}`, {
id: `page-${currDocPage}`,
iconTheme: {
primary: 'var(--accent)',
secondary: 'var(--background)',
},
style: {
background: 'var(--background)',
color: 'var(--accent)',
},
duration: 1000,
position: 'top-center',
});
return;
}