From dfde4d34e69732935c0ffa72da4d1f15469b6774 Mon Sep 17 00:00:00 2001 From: Gauthier Date: Sat, 9 May 2026 21:03:33 +0200 Subject: [PATCH] refactor: replace react-toast-notifications with react-hot-toast (#3004) --- package.json | 2 +- pnpm-lock.yaml | 177 +++--------------- src/components/Blocklist/index.tsx | 2 +- src/components/BlocklistBlock/index.tsx | 2 +- src/components/CollectionDetails/index.tsx | 2 +- .../Discover/CreateSlider/index.tsx | 2 +- .../Discover/DiscoverSliderEdit/index.tsx | 4 +- src/components/Discover/index.tsx | 6 +- src/components/IssueDetails/index.tsx | 2 +- .../IssueModal/CreateIssueModal/index.tsx | 2 +- src/components/Login/AddEmailModal.tsx | 2 +- src/components/Login/JellyfinLogin.tsx | 2 +- src/components/MovieDetails/index.tsx | 2 +- src/components/RequestCard/index.tsx | 2 +- .../RequestList/RequestItem/index.tsx | 2 +- .../RequestModal/CollectionRequestModal.tsx | 2 +- .../RequestModal/MovieRequestModal.tsx | 2 +- .../RequestModal/TvRequestModal.tsx | 2 +- src/components/Settings/CopyButton.tsx | 2 +- .../Notifications/NotificationsDiscord.tsx | 2 +- .../Notifications/NotificationsEmail.tsx | 2 +- .../NotificationsGotify/index.tsx | 4 +- .../Notifications/NotificationsNtfy/index.tsx | 2 +- .../NotificationsPushbullet/index.tsx | 2 +- .../NotificationsPushover/index.tsx | 2 +- .../NotificationsSlack/index.tsx | 2 +- .../Notifications/NotificationsTelegram.tsx | 2 +- .../NotificationsWebPush/index.tsx | 2 +- .../NotificationsWebhook/index.tsx | 2 +- .../OverrideRule/OverrideRuleModal.tsx | 2 +- src/components/Settings/RadarrModal/index.tsx | 2 +- src/components/Settings/SettingsJellyfin.tsx | 19 +- .../Settings/SettingsJobsCache/index.tsx | 2 +- .../Settings/SettingsLogs/index.tsx | 2 +- .../Settings/SettingsMain/index.tsx | 2 +- src/components/Settings/SettingsMetadata.tsx | 2 +- .../Settings/SettingsNetwork/index.tsx | 2 +- src/components/Settings/SettingsPlex.tsx | 2 +- .../Settings/SettingsUsers/index.tsx | 2 +- src/components/Settings/SonarrModal/index.tsx | 2 +- src/components/Setup/JellyfinSetup.tsx | 2 +- src/components/Setup/index.tsx | 2 +- src/components/TitleCard/index.tsx | 2 +- src/components/Toast/index.tsx | 9 +- src/components/ToastContainer/index.tsx | 18 -- src/components/TvDetails/index.tsx | 4 +- src/components/UserList/BulkEditModal.tsx | 2 +- .../UserList/JellyfinImportModal.tsx | 2 +- src/components/UserList/PlexImportModal.tsx | 2 +- src/components/UserList/index.tsx | 2 +- .../UserGeneralSettings/index.tsx | 2 +- .../UserNotificationsDiscord.tsx | 2 +- .../UserNotificationsEmail.tsx | 2 +- .../UserNotificationsPushbullet.tsx | 2 +- .../UserNotificationsPushover.tsx | 2 +- .../UserNotificationsTelegram.tsx | 2 +- .../UserNotificationsWebPush/index.tsx | 2 +- .../UserSettings/UserPasswordChange/index.tsx | 2 +- .../UserSettings/UserPermissions/index.tsx | 2 +- src/hooks/useDiscover.ts | 2 +- src/hooks/useToasts.tsx | 50 +++++ src/pages/_app.tsx | 40 ++-- 62 files changed, 174 insertions(+), 261 deletions(-) delete mode 100644 src/components/ToastContainer/index.tsx create mode 100644 src/hooks/useToasts.tsx diff --git a/package.json b/package.json index 7761f9793..fc94c7663 100644 --- a/package.json +++ b/package.json @@ -83,12 +83,12 @@ "react-animate-height": "3.2.3", "react-aria": "3.47.0", "react-dom": "^18.3.1", + "react-hot-toast": "^2.6.0", "react-intersection-observer": "10.0.3", "react-intl": "^7.1.14", "react-markdown": "10.1.0", "react-popper-tooltip": "4.4.2", "react-select": "5.10.2", - "react-toast-notifications": "2.5.1", "react-transition-group": "^4.4.5", "react-truncate-markup": "5.1.2", "react-use-clipboard": "1.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7dc12ad98..3143a9e1c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,6 +159,9 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + react-hot-toast: + specifier: ^2.6.0 + version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-intersection-observer: specifier: 10.0.3 version: 10.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -174,9 +177,6 @@ importers: react-select: specifier: 5.10.2 version: 5.10.2(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-toast-notifications: - specifier: 2.5.1 - version: 2.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-transition-group: specifier: ^4.4.5 version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1193,29 +1193,12 @@ packages: '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - '@emotion/cache@10.0.29': - resolution: {integrity: sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==} - '@emotion/cache@11.14.0': resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} - '@emotion/core@10.3.1': - resolution: {integrity: sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==} - peerDependencies: - react: '>=16.3.0' - - '@emotion/css@10.0.27': - resolution: {integrity: sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==} - - '@emotion/hash@0.8.0': - resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} - '@emotion/hash@0.9.2': resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - '@emotion/memoize@0.7.4': - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} - '@emotion/memoize@0.9.0': resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} @@ -1228,41 +1211,23 @@ packages: '@types/react': optional: true - '@emotion/serialize@0.11.16': - resolution: {integrity: sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==} - '@emotion/serialize@1.3.3': resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} - '@emotion/sheet@0.9.4': - resolution: {integrity: sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==} - '@emotion/sheet@1.4.0': resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - '@emotion/stylis@0.8.5': - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - '@emotion/unitless@0.10.0': resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} peerDependencies: react: '>=16.8.0' - '@emotion/utils@0.11.3': - resolution: {integrity: sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==} - '@emotion/utils@1.4.2': resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - '@emotion/weak-memoize@0.2.5': - resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==} - '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} @@ -3140,9 +3105,6 @@ packages: peerDependencies: '@babel/core': ^7.11.0 || ^8.0.0-0 - babel-plugin-emotion@10.2.2: - resolution: {integrity: sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==} - babel-plugin-istanbul@7.0.1: resolution: {integrity: sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==} engines: {node: '>=12'} @@ -3151,9 +3113,6 @@ packages: resolution: {integrity: sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - babel-plugin-macros@2.8.0: - resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==} - babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -3173,9 +3132,6 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-syntax-jsx@6.18.0: - resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==} - babel-preset-current-node-syntax@1.2.0: resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: @@ -3674,10 +3630,6 @@ packages: cosmiconfig: '>=9' typescript: '>=5' - cosmiconfig@6.0.0: - resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} - engines: {node: '>=8'} - cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -3749,9 +3701,6 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - csstype@2.6.21: - resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -4614,6 +4563,11 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} + goober@2.1.18: + resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} + peerDependencies: + csstype: ^3.0.10 + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -6611,6 +6565,13 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + react-hot-toast@2.6.0: + resolution: {integrity: sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + react-intersection-observer@10.0.3: resolution: {integrity: sha512-luICLMbs0zxTO/70Zy7K5jOXkABPEVSAF8T3FdZUlctsrIaPLmx8TZe2SSA+CY2HGWfz2INyNTnp82pxNNsShA==} peerDependencies: @@ -6665,12 +6626,6 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-toast-notifications@2.5.1: - resolution: {integrity: sha512-eYuuiSPGLyuMHojRH2U7CbENvFHsvNia39pLM/s10KipIoNs14T7RIJk4aU2N+l++OsSgtJqnFObx9bpwLMU5A==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 - react-dom: ^16.8.0 || ^17.0.0 - react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: @@ -9001,13 +8956,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@emotion/cache@10.0.29': - dependencies: - '@emotion/sheet': 0.9.4 - '@emotion/stylis': 0.8.5 - '@emotion/utils': 0.11.3 - '@emotion/weak-memoize': 0.2.5 - '@emotion/cache@11.14.0': dependencies: '@emotion/memoize': 0.9.0 @@ -9016,32 +8964,8 @@ snapshots: '@emotion/weak-memoize': 0.4.0 stylis: 4.2.0 - '@emotion/core@10.3.1(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.2 - '@emotion/cache': 10.0.29 - '@emotion/css': 10.0.27 - '@emotion/serialize': 0.11.16 - '@emotion/sheet': 0.9.4 - '@emotion/utils': 0.11.3 - react: 18.3.1 - transitivePeerDependencies: - - supports-color - - '@emotion/css@10.0.27': - dependencies: - '@emotion/serialize': 0.11.16 - '@emotion/utils': 0.11.3 - babel-plugin-emotion: 10.2.2 - transitivePeerDependencies: - - supports-color - - '@emotion/hash@0.8.0': {} - '@emotion/hash@0.9.2': {} - '@emotion/memoize@0.7.4': {} - '@emotion/memoize@0.9.0': {} '@emotion/react@11.14.0(@types/react@18.3.28)(react@18.3.1)': @@ -9060,14 +8984,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@emotion/serialize@0.11.16': - dependencies: - '@emotion/hash': 0.8.0 - '@emotion/memoize': 0.7.4 - '@emotion/unitless': 0.7.5 - '@emotion/utils': 0.11.3 - csstype: 2.6.21 - '@emotion/serialize@1.3.3': dependencies: '@emotion/hash': 0.9.2 @@ -9076,26 +8992,16 @@ snapshots: '@emotion/utils': 1.4.2 csstype: 3.2.3 - '@emotion/sheet@0.9.4': {} - '@emotion/sheet@1.4.0': {} - '@emotion/stylis@0.8.5': {} - '@emotion/unitless@0.10.0': {} - '@emotion/unitless@0.7.5': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': dependencies: react: 18.3.1 - '@emotion/utils@0.11.3': {} - '@emotion/utils@1.4.2': {} - '@emotion/weak-memoize@0.2.5': {} - '@emotion/weak-memoize@0.4.0': {} '@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1))': @@ -11028,21 +10934,6 @@ snapshots: - supports-color optional: true - babel-plugin-emotion@10.2.2: - dependencies: - '@babel/helper-module-imports': 7.28.6 - '@emotion/hash': 0.8.0 - '@emotion/memoize': 0.7.4 - '@emotion/serialize': 0.11.16 - babel-plugin-macros: 2.8.0 - babel-plugin-syntax-jsx: 6.18.0 - convert-source-map: 1.9.0 - escape-string-regexp: 1.0.5 - find-root: 1.1.0 - source-map: 0.5.7 - transitivePeerDependencies: - - supports-color - babel-plugin-istanbul@7.0.1: dependencies: '@babel/helper-plugin-utils': 7.28.6 @@ -11059,12 +10950,6 @@ snapshots: '@types/babel__core': 7.20.5 optional: true - babel-plugin-macros@2.8.0: - dependencies: - '@babel/runtime': 7.29.2 - cosmiconfig: 6.0.0 - resolve: 1.22.11 - babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.29.2 @@ -11095,8 +10980,6 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-syntax-jsx@6.18.0: {} - babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): dependencies: '@babel/core': 7.29.0 @@ -11654,14 +11537,6 @@ snapshots: jiti: 2.6.1 typescript: 5.4.5 - cosmiconfig@6.0.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -11747,8 +11622,6 @@ snapshots: dependencies: css-tree: 2.2.1 - csstype@2.6.21: {} - csstype@3.2.3: {} cy-mobile-commands@0.3.0: {} @@ -12940,6 +12813,10 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 + goober@2.1.18(csstype@3.2.3): + dependencies: + csstype: 3.2.3 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -15405,6 +15282,13 @@ snapshots: react-fast-compare@3.2.2: {} + react-hot-toast@2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + csstype: 3.2.3 + goober: 2.1.18(csstype@3.2.3) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-intersection-observer@10.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 @@ -15491,15 +15375,6 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.6.0(react@18.3.1) - react-toast-notifications@2.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@emotion/core': 10.3.1(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - transitivePeerDependencies: - - supports-color - react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.29.2 diff --git a/src/components/Blocklist/index.tsx b/src/components/Blocklist/index.tsx index addabecdb..a5c7ad652 100644 --- a/src/components/Blocklist/index.tsx +++ b/src/components/Blocklist/index.tsx @@ -7,6 +7,7 @@ import Header from '@app/components/Common/Header'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import useDebouncedState from '@app/hooks/useDebouncedState'; +import useToasts from '@app/hooks/useToasts'; import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; @@ -32,7 +33,6 @@ import type { ChangeEvent } from 'react'; import { useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { FormattedRelativeTime, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.Blocklist', { diff --git a/src/components/BlocklistBlock/index.tsx b/src/components/BlocklistBlock/index.tsx index c53a1c8ad..f8e5eeefd 100644 --- a/src/components/BlocklistBlock/index.tsx +++ b/src/components/BlocklistBlock/index.tsx @@ -3,6 +3,7 @@ import Badge from '@app/components/Common/Badge'; import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import Tooltip from '@app/components/Common/Tooltip'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -13,7 +14,6 @@ import axios from 'axios'; import Link from 'next/link'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('component.BlocklistBlock', { diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx index 191c39b96..c6e1374ab 100644 --- a/src/components/CollectionDetails/index.tsx +++ b/src/components/CollectionDetails/index.tsx @@ -10,6 +10,7 @@ import Slider from '@app/components/Slider'; import StatusBadge from '@app/components/StatusBadge'; import TitleCard from '@app/components/TitleCard'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -28,7 +29,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.CollectionDetails', { diff --git a/src/components/Discover/CreateSlider/index.tsx b/src/components/Discover/CreateSlider/index.tsx index 8eea28653..db803518f 100644 --- a/src/components/Discover/CreateSlider/index.tsx +++ b/src/components/Discover/CreateSlider/index.tsx @@ -4,6 +4,7 @@ import { sliderTitles } from '@app/components/Discover/constants'; import MediaSlider from '@app/components/MediaSlider'; import { WatchProviderSelector } from '@app/components/Selector'; import { encodeURIExtraParams } from '@app/hooks/useDiscover'; +import useToasts from '@app/hooks/useToasts'; import defineMessages from '@app/utils/defineMessages'; import type { TmdbCompanySearchResponse, @@ -19,7 +20,6 @@ import { Field, Form, Formik } from 'formik'; import { useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import AsyncSelect from 'react-select/async'; -import { useToasts } from 'react-toast-notifications'; import * as Yup from 'yup'; const messages = defineMessages('components.Discover.CreateSlider', { diff --git a/src/components/Discover/DiscoverSliderEdit/index.tsx b/src/components/Discover/DiscoverSliderEdit/index.tsx index 41425c788..c24a0591a 100644 --- a/src/components/Discover/DiscoverSliderEdit/index.tsx +++ b/src/components/Discover/DiscoverSliderEdit/index.tsx @@ -3,10 +3,11 @@ import SlideCheckbox from '@app/components/Common/SlideCheckbox'; import Tag from '@app/components/Common/Tag'; import Tooltip from '@app/components/Common/Tooltip'; import CompanyTag from '@app/components/CompanyTag'; -import { sliderTitles } from '@app/components/Discover/constants'; import CreateSlider from '@app/components/Discover/CreateSlider'; +import { sliderTitles } from '@app/components/Discover/constants'; import GenreTag from '@app/components/GenreTag'; import KeywordTag from '@app/components/KeywordTag'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { MagnifyingGlassIcon } from '@heroicons/react/24/outline'; @@ -24,7 +25,6 @@ import axios from 'axios'; import { useRef, useState } from 'react'; import { useDrag, useDrop } from 'react-aria'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; const messages = defineMessages('components.Discover.DiscoverSliderEdit', { deletesuccess: 'Sucessfully deleted slider.', diff --git a/src/components/Discover/index.tsx b/src/components/Discover/index.tsx index bfefd0989..5638d6fb3 100644 --- a/src/components/Discover/index.tsx +++ b/src/components/Discover/index.tsx @@ -3,18 +3,19 @@ import ConfirmButton from '@app/components/Common/ConfirmButton'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import Tooltip from '@app/components/Common/Tooltip'; -import { sliderTitles } from '@app/components/Discover/constants'; import CreateSlider from '@app/components/Discover/CreateSlider'; import DiscoverSliderEdit from '@app/components/Discover/DiscoverSliderEdit'; import MovieGenreSlider from '@app/components/Discover/MovieGenreSlider'; import NetworkSlider from '@app/components/Discover/NetworkSlider'; import PlexWatchlistSlider from '@app/components/Discover/PlexWatchlistSlider'; -import RecentlyAddedSlider from '@app/components/Discover/RecentlyAddedSlider'; import RecentRequestsSlider from '@app/components/Discover/RecentRequestsSlider'; +import RecentlyAddedSlider from '@app/components/Discover/RecentlyAddedSlider'; import StudioSlider from '@app/components/Discover/StudioSlider'; import TvGenreSlider from '@app/components/Discover/TvGenreSlider'; +import { sliderTitles } from '@app/components/Discover/constants'; import MediaSlider from '@app/components/MediaSlider'; import { encodeURIExtraParams } from '@app/hooks/useDiscover'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -31,7 +32,6 @@ import type DiscoverSlider from '@server/entity/DiscoverSlider'; import axios from 'axios'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.Discover', { diff --git a/src/components/IssueDetails/index.tsx b/src/components/IssueDetails/index.tsx index cc4e81421..e272da96b 100644 --- a/src/components/IssueDetails/index.tsx +++ b/src/components/IssueDetails/index.tsx @@ -9,6 +9,7 @@ import IssueDescription from '@app/components/IssueDetails/IssueDescription'; import { issueOptions } from '@app/components/IssueModal/constants'; import useDeepLinks from '@app/hooks/useDeepLinks'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -33,7 +34,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useState } from 'react'; import { FormattedRelativeTime, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/IssueModal/CreateIssueModal/index.tsx b/src/components/IssueModal/CreateIssueModal/index.tsx index eb8d17763..e874889d1 100644 --- a/src/components/IssueModal/CreateIssueModal/index.tsx +++ b/src/components/IssueModal/CreateIssueModal/index.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import Modal from '@app/components/Common/Modal'; import { issueOptions } from '@app/components/IssueModal/constants'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -15,7 +16,6 @@ import axios from 'axios'; import { Field, Formik } from 'formik'; import Link from 'next/link'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Login/AddEmailModal.tsx b/src/components/Login/AddEmailModal.tsx index 3799acc83..efaff053e 100644 --- a/src/components/Login/AddEmailModal.tsx +++ b/src/components/Login/AddEmailModal.tsx @@ -1,4 +1,5 @@ import Modal from '@app/components/Common/Modal'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import defineMessages from '@app/utils/defineMessages'; import { Transition } from '@headlessui/react'; @@ -6,7 +7,6 @@ import { ApiErrorCode } from '@server/constants/error'; import axios from 'axios'; import { Field, Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import { mutate } from 'swr'; import validator from 'validator'; import * as Yup from 'yup'; diff --git a/src/components/Login/JellyfinLogin.tsx b/src/components/Login/JellyfinLogin.tsx index 53c9862a6..5873b87d2 100644 --- a/src/components/Login/JellyfinLogin.tsx +++ b/src/components/Login/JellyfinLogin.tsx @@ -1,6 +1,7 @@ import Button from '@app/components/Common/Button'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import defineMessages from '@app/utils/defineMessages'; import { ArrowLeftOnRectangleIcon } from '@heroicons/react/24/outline'; import { ExclamationTriangleIcon } from '@heroicons/react/24/solid'; @@ -9,7 +10,6 @@ import { MediaServerType, ServerType } from '@server/constants/server'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import * as Yup from 'yup'; const messages = defineMessages('components.Login', { diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index 33a132e3f..4df319d38 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -25,6 +25,7 @@ import StatusBadge from '@app/components/StatusBadge'; import useDeepLinks from '@app/hooks/useDeepLinks'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -60,7 +61,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.MovieDetails', { diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index 8064c22a8..a71842cdf 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -6,6 +6,7 @@ import Tooltip from '@app/components/Common/Tooltip'; import RequestModal from '@app/components/RequestModal'; import StatusBadge from '@app/components/StatusBadge'; import useDeepLinks from '@app/hooks/useDeepLinks'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -28,7 +29,6 @@ import Link from 'next/link'; import { useEffect, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages('components.RequestCard', { diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index fc43fad2f..9a7d2de52 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -6,6 +6,7 @@ import ConfirmButton from '@app/components/Common/ConfirmButton'; import RequestModal from '@app/components/RequestModal'; import StatusBadge from '@app/components/StatusBadge'; import useDeepLinks from '@app/hooks/useDeepLinks'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -28,7 +29,6 @@ import Link from 'next/link'; import { useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { FormattedRelativeTime, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages('components.RequestList.RequestItem', { diff --git a/src/components/RequestModal/CollectionRequestModal.tsx b/src/components/RequestModal/CollectionRequestModal.tsx index cbfeb89e6..f704b09c0 100644 --- a/src/components/RequestModal/CollectionRequestModal.tsx +++ b/src/components/RequestModal/CollectionRequestModal.tsx @@ -5,6 +5,7 @@ import Modal from '@app/components/Common/Modal'; import type { RequestOverrides } from '@app/components/RequestModal/AdvancedRequester'; import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester'; import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -16,7 +17,6 @@ import type { Collection } from '@server/models/Collection'; import axios from 'axios'; import { useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages('components.RequestModal', { diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index 3feb74034..c1595e511 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -3,6 +3,7 @@ import Modal from '@app/components/Common/Modal'; import type { RequestOverrides } from '@app/components/RequestModal/AdvancedRequester'; import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester'; import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -15,7 +16,6 @@ import type { MovieDetails } from '@server/models/Movie'; import axios from 'axios'; import { useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages('components.RequestModal', { diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index 7c1bdca8c..941b8dc71 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -6,6 +6,7 @@ import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester'; import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay'; import SearchByNameModal from '@app/components/RequestModal/SearchByNameModal'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -20,7 +21,6 @@ import type { TvDetails } from '@server/models/Tv'; import axios from 'axios'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages('components.RequestModal', { diff --git a/src/components/Settings/CopyButton.tsx b/src/components/Settings/CopyButton.tsx index 3314a20bc..acafba447 100644 --- a/src/components/Settings/CopyButton.tsx +++ b/src/components/Settings/CopyButton.tsx @@ -1,8 +1,8 @@ import Tooltip from '@app/components/Common/Tooltip'; +import useToasts from '@app/hooks/useToasts'; import { ClipboardDocumentIcon } from '@heroicons/react/24/solid'; import React, { useEffect } from 'react'; import type { Config } from 'react-popper-tooltip'; -import { useToasts } from 'react-toast-notifications'; import useClipboard from 'react-use-clipboard'; type CopyButtonProps = { diff --git a/src/components/Settings/Notifications/NotificationsDiscord.tsx b/src/components/Settings/Notifications/NotificationsDiscord.tsx index 709e6979b..937d2dde1 100644 --- a/src/components/Settings/Notifications/NotificationsDiscord.tsx +++ b/src/components/Settings/Notifications/NotificationsDiscord.tsx @@ -3,6 +3,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import { availableLanguages } from '@app/context/LanguageContext'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -10,7 +11,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsEmail.tsx b/src/components/Settings/Notifications/NotificationsEmail.tsx index a81edb2c5..077762b22 100644 --- a/src/components/Settings/Notifications/NotificationsEmail.tsx +++ b/src/components/Settings/Notifications/NotificationsEmail.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -9,7 +10,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import validator from 'validator'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsGotify/index.tsx b/src/components/Settings/Notifications/NotificationsGotify/index.tsx index 7847c6194..61c3f1f97 100644 --- a/src/components/Settings/Notifications/NotificationsGotify/index.tsx +++ b/src/components/Settings/Notifications/NotificationsGotify/index.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import { availableLanguages } from '@app/context/LanguageContext'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -10,7 +11,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; @@ -141,7 +141,7 @@ const NotificationsGotify = () => { addToast( intl.formatMessage(messages.toastGotifyTestSending), { - autoDsmiss: false, + autoDismiss: false, appearance: 'info', }, (id) => { diff --git a/src/components/Settings/Notifications/NotificationsNtfy/index.tsx b/src/components/Settings/Notifications/NotificationsNtfy/index.tsx index 0450049b2..dc336fc28 100644 --- a/src/components/Settings/Notifications/NotificationsNtfy/index.tsx +++ b/src/components/Settings/Notifications/NotificationsNtfy/index.tsx @@ -3,6 +3,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import { availableLanguages } from '@app/context/LanguageContext'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -12,7 +13,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx b/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx index 971b793fa..7549809f9 100644 --- a/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx +++ b/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -9,7 +10,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsPushover/index.tsx b/src/components/Settings/Notifications/NotificationsPushover/index.tsx index 68b254bff..da5e6f199 100644 --- a/src/components/Settings/Notifications/NotificationsPushover/index.tsx +++ b/src/components/Settings/Notifications/NotificationsPushover/index.tsx @@ -1,6 +1,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -9,7 +10,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsSlack/index.tsx b/src/components/Settings/Notifications/NotificationsSlack/index.tsx index d9687b71a..d74487038 100644 --- a/src/components/Settings/Notifications/NotificationsSlack/index.tsx +++ b/src/components/Settings/Notifications/NotificationsSlack/index.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import { availableLanguages } from '@app/context/LanguageContext'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -9,7 +10,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsTelegram.tsx b/src/components/Settings/Notifications/NotificationsTelegram.tsx index 46f12dc10..68eb4fcde 100644 --- a/src/components/Settings/Notifications/NotificationsTelegram.tsx +++ b/src/components/Settings/Notifications/NotificationsTelegram.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -9,7 +10,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/Notifications/NotificationsWebPush/index.tsx b/src/components/Settings/Notifications/NotificationsWebPush/index.tsx index e14b3e1ec..7b5404609 100644 --- a/src/components/Settings/Notifications/NotificationsWebPush/index.tsx +++ b/src/components/Settings/Notifications/NotificationsWebPush/index.tsx @@ -1,6 +1,7 @@ import Alert from '@app/components/Common/Alert'; import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -8,7 +9,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages( diff --git a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx index cd0ac0fb6..0ff8629ef 100644 --- a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx +++ b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -21,7 +22,6 @@ import dynamic from 'next/dynamic'; import Link from 'next/link'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/OverrideRule/OverrideRuleModal.tsx b/src/components/Settings/OverrideRule/OverrideRuleModal.tsx index 72cc0b546..5cdd4fb9d 100644 --- a/src/components/Settings/OverrideRule/OverrideRuleModal.tsx +++ b/src/components/Settings/OverrideRule/OverrideRuleModal.tsx @@ -7,6 +7,7 @@ import { } from '@app/components/Selector'; import type { DVRTestResponse } from '@app/components/Settings/SettingsServices'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { Transition } from '@headlessui/react'; @@ -17,7 +18,6 @@ import { Field, Formik } from 'formik'; import { useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import Select from 'react-select'; -import { useToasts } from 'react-toast-notifications'; const messages = defineMessages('components.Settings.OverrideRuleModal', { createrule: 'New Override Rule', diff --git a/src/components/Settings/RadarrModal/index.tsx b/src/components/Settings/RadarrModal/index.tsx index 9ddc39262..cad8fb65f 100644 --- a/src/components/Settings/RadarrModal/index.tsx +++ b/src/components/Settings/RadarrModal/index.tsx @@ -1,6 +1,7 @@ import Modal from '@app/components/Common/Modal'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import type { RadarrTestResponse } from '@app/components/Settings/SettingsServices'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -11,7 +12,6 @@ import { Field, Formik } from 'formik'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useIntl } from 'react-intl'; import Select from 'react-select'; -import { useToasts } from 'react-toast-notifications'; import * as Yup from 'yup'; type OptionType = { diff --git a/src/components/Settings/SettingsJellyfin.tsx b/src/components/Settings/SettingsJellyfin.tsx index 8f73689bf..1e26c0222 100644 --- a/src/components/Settings/SettingsJellyfin.tsx +++ b/src/components/Settings/SettingsJellyfin.tsx @@ -4,6 +4,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import LibraryItem from '@app/components/Settings/LibraryItem'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -15,7 +16,6 @@ import axios from 'axios'; import { Field, Formik } from 'formik'; import { useState } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; @@ -93,8 +93,6 @@ const SettingsJellyfin: React.FC = ({ isSetupSettings, }) => { const [isSyncing, setIsSyncing] = useState(false); - const toasts = useToasts(); - const { data, error, @@ -179,7 +177,7 @@ const SettingsJellyfin: React.FC = ({ revalidate(); } catch (e) { if (e?.response?.data?.message === 'SYNC_ERROR_GROUPED_FOLDERS') { - toasts.addToast( + addToast( intl.formatMessage( messages.jellyfinSyncFailedAutomaticGroupedFolders ), @@ -189,7 +187,7 @@ const SettingsJellyfin: React.FC = ({ } ); } else if (e?.response?.data?.message === 'SYNC_ERROR_NO_LIBRARIES') { - toasts.addToast( + addToast( intl.formatMessage(messages.jellyfinSyncFailedNoLibrariesFound), { autoDismiss: true, @@ -197,13 +195,10 @@ const SettingsJellyfin: React.FC = ({ } ); } else { - toasts.addToast( - intl.formatMessage(messages.jellyfinSyncFailedGenericError), - { - autoDismiss: true, - appearance: 'error', - } - ); + addToast(intl.formatMessage(messages.jellyfinSyncFailedGenericError), { + autoDismiss: true, + appearance: 'error', + }); } setIsSyncing(false); revalidate(); diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx index 48e8a8fa1..bbb6ed766 100644 --- a/src/components/Settings/SettingsJobsCache/index.tsx +++ b/src/components/Settings/SettingsJobsCache/index.tsx @@ -8,6 +8,7 @@ import Table from '@app/components/Common/Table'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { formatBytes } from '@app/utils/numberHelpers'; @@ -26,7 +27,6 @@ import humanizeDuration from 'humanize-duration'; import { Fragment, useReducer, useState } from 'react'; import type { MessageDescriptor } from 'react-intl'; import { FormattedRelativeTime, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages: { [messageName: string]: MessageDescriptor } = defineMessages( diff --git a/src/components/Settings/SettingsLogs/index.tsx b/src/components/Settings/SettingsLogs/index.tsx index 840cfece9..6276d161c 100644 --- a/src/components/Settings/SettingsLogs/index.tsx +++ b/src/components/Settings/SettingsLogs/index.tsx @@ -6,6 +6,7 @@ import PageTitle from '@app/components/Common/PageTitle'; import Table from '@app/components/Common/Table'; import Tooltip from '@app/components/Common/Tooltip'; import useDebouncedState from '@app/hooks/useDebouncedState'; +import useToasts from '@app/hooks/useToasts'; import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -29,7 +30,6 @@ import copy from 'copy-to-clipboard'; import { useRouter } from 'next/router'; import { Fragment, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.Settings.SettingsLogs', { diff --git a/src/components/Settings/SettingsMain/index.tsx b/src/components/Settings/SettingsMain/index.tsx index c53bbe977..00703ddd3 100644 --- a/src/components/Settings/SettingsMain/index.tsx +++ b/src/components/Settings/SettingsMain/index.tsx @@ -9,6 +9,7 @@ import CopyButton from '@app/components/Settings/CopyButton'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; import { availableLanguages } from '@app/context/LanguageContext'; import useLocale from '@app/hooks/useLocale'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -21,7 +22,6 @@ import type { AvailableLocale } from '@server/types/languages'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/SettingsMetadata.tsx b/src/components/Settings/SettingsMetadata.tsx index 471647118..d11bece04 100644 --- a/src/components/Settings/SettingsMetadata.tsx +++ b/src/components/Settings/SettingsMetadata.tsx @@ -5,6 +5,7 @@ import PageTitle from '@app/components/Common/PageTitle'; import MetadataSelector, { MetadataProviderType, } from '@app/components/MetadataSelector'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline'; @@ -12,7 +13,6 @@ import axios from 'axios'; import { Form, Formik } from 'formik'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.Settings', { diff --git a/src/components/Settings/SettingsNetwork/index.tsx b/src/components/Settings/SettingsNetwork/index.tsx index eb514cbf0..dd4fd5fe5 100644 --- a/src/components/Settings/SettingsNetwork/index.tsx +++ b/src/components/Settings/SettingsNetwork/index.tsx @@ -3,6 +3,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import Tooltip from '@app/components/Common/Tooltip'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline'; @@ -10,7 +11,6 @@ import type { NetworkSettings } from '@server/lib/settings'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/SettingsPlex.tsx b/src/components/Settings/SettingsPlex.tsx index 7e9ffd19f..7dca6f67f 100644 --- a/src/components/Settings/SettingsPlex.tsx +++ b/src/components/Settings/SettingsPlex.tsx @@ -6,6 +6,7 @@ import PageTitle from '@app/components/Common/PageTitle'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import LibraryItem from '@app/components/Settings/LibraryItem'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -22,7 +23,6 @@ import { Field, Formik } from 'formik'; import { orderBy } from 'lodash'; import { useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/Settings/SettingsUsers/index.tsx b/src/components/Settings/SettingsUsers/index.tsx index bbb02f38b..b69ea2bec 100644 --- a/src/components/Settings/SettingsUsers/index.tsx +++ b/src/components/Settings/SettingsUsers/index.tsx @@ -6,6 +6,7 @@ import PageTitle from '@app/components/Common/PageTitle'; import PermissionEdit from '@app/components/PermissionEdit'; import QuotaSelector from '@app/components/QuotaSelector'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline'; @@ -14,7 +15,6 @@ import type { MainSettings } from '@server/lib/settings'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import * as yup from 'yup'; diff --git a/src/components/Settings/SonarrModal/index.tsx b/src/components/Settings/SonarrModal/index.tsx index c653bc21c..fbc665248 100644 --- a/src/components/Settings/SonarrModal/index.tsx +++ b/src/components/Settings/SonarrModal/index.tsx @@ -1,6 +1,7 @@ import Modal from '@app/components/Common/Modal'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import type { SonarrTestResponse } from '@app/components/Settings/SettingsServices'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { isValidURL } from '@app/utils/urlValidationHelper'; @@ -12,7 +13,6 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useIntl } from 'react-intl'; import type { OnChangeValue } from 'react-select'; import Select from 'react-select'; -import { useToasts } from 'react-toast-notifications'; import * as Yup from 'yup'; type OptionType = { diff --git a/src/components/Setup/JellyfinSetup.tsx b/src/components/Setup/JellyfinSetup.tsx index eb643a6d8..ecde73d50 100644 --- a/src/components/Setup/JellyfinSetup.tsx +++ b/src/components/Setup/JellyfinSetup.tsx @@ -1,5 +1,6 @@ import Button from '@app/components/Common/Button'; import Tooltip from '@app/components/Common/Tooltip'; +import useToasts from '@app/hooks/useToasts'; import defineMessages from '@app/utils/defineMessages'; import { InformationCircleIcon } from '@heroicons/react/24/solid'; import { ApiErrorCode } from '@server/constants/error'; @@ -7,7 +8,6 @@ import { MediaServerType, ServerType } from '@server/constants/server'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { FormattedMessage, useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import validator from 'validator'; import * as Yup from 'yup'; diff --git a/src/components/Setup/index.tsx b/src/components/Setup/index.tsx index 98ca61a2a..947104d35 100644 --- a/src/components/Setup/index.tsx +++ b/src/components/Setup/index.tsx @@ -12,6 +12,7 @@ import SettingsServices from '@app/components/Settings/SettingsServices'; import SetupSteps from '@app/components/Setup/SetupSteps'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import defineMessages from '@app/utils/defineMessages'; import { MediaServerType } from '@server/constants/server'; import type { Library } from '@server/lib/settings'; @@ -20,7 +21,6 @@ import Image from 'next/image'; import { useRouter } from 'next/router'; import { useCallback, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; import SetupLogin from './SetupLogin'; diff --git a/src/components/TitleCard/index.tsx b/src/components/TitleCard/index.tsx index fd81ef783..7f420047f 100644 --- a/src/components/TitleCard/index.tsx +++ b/src/components/TitleCard/index.tsx @@ -8,6 +8,7 @@ import RequestModal from '@app/components/RequestModal'; import ErrorCard from '@app/components/TitleCard/ErrorCard'; import Placeholder from '@app/components/TitleCard/Placeholder'; import { useIsTouch } from '@app/hooks/useIsTouch'; +import useToasts from '@app/hooks/useToasts'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -27,7 +28,6 @@ import axios from 'axios'; import Link from 'next/link'; import { Fragment, useCallback, useEffect, useRef, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import { mutate } from 'swr'; interface TitleCardProps { diff --git a/src/components/Toast/index.tsx b/src/components/Toast/index.tsx index 85bcf7f4a..4d1db5d11 100644 --- a/src/components/Toast/index.tsx +++ b/src/components/Toast/index.tsx @@ -7,7 +7,13 @@ import { } from '@heroicons/react/24/outline'; import { XMarkIcon } from '@heroicons/react/24/solid'; import { Fragment } from 'react'; -import type { ToastProps } from 'react-toast-notifications'; + +export interface ToastProps { + appearance?: 'success' | 'error' | 'info' | 'warning'; + children: React.ReactNode; + onDismiss: () => void; + transitionState: 'entering' | 'entered' | 'exiting' | 'exited'; +} const Toast = ({ appearance, @@ -20,6 +26,7 @@ const Toast = ({ { - return ( -
- ); -}; - -export default ToastContainer; diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 8be419329..4fdb58b38 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -28,6 +28,7 @@ import Season from '@app/components/TvDetails/Season'; import useDeepLinks from '@app/hooks/useDeepLinks'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -55,8 +56,8 @@ import { MediaType, } from '@server/constants/media'; import { MediaServerType } from '@server/constants/server'; -import type { Crew } from '@server/models/common'; import type { TvDetails as TvDetailsType } from '@server/models/Tv'; +import type { Crew } from '@server/models/common'; import axios from 'axios'; import { countries } from 'country-flag-icons'; import 'country-flag-icons/3x2/flags.css'; @@ -64,7 +65,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages('components.TvDetails', { diff --git a/src/components/UserList/BulkEditModal.tsx b/src/components/UserList/BulkEditModal.tsx index 6e7dcfe88..afbf60223 100644 --- a/src/components/UserList/BulkEditModal.tsx +++ b/src/components/UserList/BulkEditModal.tsx @@ -1,5 +1,6 @@ import Modal from '@app/components/Common/Modal'; import PermissionEdit from '@app/components/PermissionEdit'; +import useToasts from '@app/hooks/useToasts'; import type { User } from '@app/hooks/useUser'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; @@ -8,7 +9,6 @@ import { hasPermission } from '@server/lib/permissions'; import axios from 'axios'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; interface BulkEditProps { selectedUserIds: number[]; diff --git a/src/components/UserList/JellyfinImportModal.tsx b/src/components/UserList/JellyfinImportModal.tsx index 4b303de2a..f85756b31 100644 --- a/src/components/UserList/JellyfinImportModal.tsx +++ b/src/components/UserList/JellyfinImportModal.tsx @@ -2,6 +2,7 @@ import Alert from '@app/components/Common/Alert'; import CachedImage from '@app/components/Common/CachedImage'; import Modal from '@app/components/Common/Modal'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { MediaServerType } from '@server/constants/server'; @@ -9,7 +10,6 @@ import type { UserResultsResponse } from '@server/interfaces/api/userInterfaces' import axios from 'axios'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; interface JellyfinImportProps { diff --git a/src/components/UserList/PlexImportModal.tsx b/src/components/UserList/PlexImportModal.tsx index c744219cb..e6fade591 100644 --- a/src/components/UserList/PlexImportModal.tsx +++ b/src/components/UserList/PlexImportModal.tsx @@ -1,13 +1,13 @@ import Alert from '@app/components/Common/Alert'; import Modal from '@app/components/Common/Modal'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import axios from 'axios'; import Image from 'next/image'; import { useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; interface PlexImportProps { diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index 2271e9074..c36d7d692 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -11,6 +11,7 @@ import Table from '@app/components/Common/Table'; import BulkEditModal from '@app/components/UserList/BulkEditModal'; import PlexImportModal from '@app/components/UserList/PlexImportModal'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams'; import type { User } from '@app/hooks/useUser'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; @@ -37,7 +38,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import validator from 'validator'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx index ed09bb634..525dabb07 100644 --- a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx +++ b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx @@ -8,6 +8,7 @@ import RegionSelector from '@app/components/RegionSelector'; import { availableLanguages } from '@app/context/LanguageContext'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -21,7 +22,6 @@ import { Field, Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import validator from 'validator'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx index 251f9bc24..d58c054e4 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx @@ -1,6 +1,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -10,7 +11,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx index 193f0c189..84d4dadef 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx @@ -6,6 +6,7 @@ import NotificationTypeSelector, { } from '@app/components/NotificationTypeSelector'; import { OpenPgpLink } from '@app/components/Settings/Notifications/NotificationsEmail'; import SettingsBadge from '@app/components/Settings/SettingsBadge'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -15,7 +16,6 @@ import axios from 'axios'; import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx index 517f1c52f..2f8d3bc8b 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -10,7 +11,6 @@ import axios from 'axios'; import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx index 080b67f4f..abaee674a 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx @@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -11,7 +12,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx index 427b8f531..3fececa06 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx @@ -1,6 +1,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import NotificationTypeSelector from '@app/components/NotificationTypeSelector'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -10,7 +11,6 @@ import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/index.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/index.tsx index 5f995e87e..db2702b2e 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/index.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/index.tsx @@ -6,6 +6,7 @@ import NotificationTypeSelector, { } from '@app/components/NotificationTypeSelector'; import DeviceItem from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush/DeviceItem'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; @@ -26,7 +27,6 @@ import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useEffect, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR, { mutate } from 'swr'; const messages = defineMessages( diff --git a/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx b/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx index 2ed8ba124..42e7faca4 100644 --- a/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx +++ b/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx @@ -4,6 +4,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import useSettings from '@app/hooks/useSettings'; +import useToasts from '@app/hooks/useToasts'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -13,7 +14,6 @@ import axios from 'axios'; import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; diff --git a/src/components/UserProfile/UserSettings/UserPermissions/index.tsx b/src/components/UserProfile/UserSettings/UserPermissions/index.tsx index 343a5f3fa..2d310a212 100644 --- a/src/components/UserProfile/UserSettings/UserPermissions/index.tsx +++ b/src/components/UserProfile/UserSettings/UserPermissions/index.tsx @@ -3,6 +3,7 @@ import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import PermissionEdit from '@app/components/PermissionEdit'; +import useToasts from '@app/hooks/useToasts'; import { useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import ErrorPage from '@app/pages/_error'; @@ -12,7 +13,6 @@ import axios from 'axios'; import { Form, Formik } from 'formik'; import { useRouter } from 'next/router'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; const messages = defineMessages( diff --git a/src/hooks/useDiscover.ts b/src/hooks/useDiscover.ts index cb0858147..940cd6f5d 100644 --- a/src/hooks/useDiscover.ts +++ b/src/hooks/useDiscover.ts @@ -1,8 +1,8 @@ +import useToasts from '@app/hooks/useToasts'; import globalMessages from '@app/i18n/globalMessages'; import { MediaStatus } from '@server/constants/media'; import { useEffect } from 'react'; import { useIntl } from 'react-intl'; -import { useToasts } from 'react-toast-notifications'; import useSWRInfinite from 'swr/infinite'; import useSettings from './useSettings'; import { Permission, useUser } from './useUser'; diff --git a/src/hooks/useToasts.tsx b/src/hooks/useToasts.tsx new file mode 100644 index 000000000..efb19c40f --- /dev/null +++ b/src/hooks/useToasts.tsx @@ -0,0 +1,50 @@ +import Toast from '@app/components/Toast'; +import { useCallback } from 'react'; +import { toast } from 'react-hot-toast'; + +interface ToastOptions { + appearance?: 'success' | 'error' | 'info' | 'warning'; + autoDismiss?: boolean; +} + +export const useToasts = () => { + const addToast = useCallback( + ( + message: React.ReactNode, + options?: ToastOptions, + callback?: (id: string) => void + ) => { + const id = toast.custom( + (t) => { + // Our custom Toast component handles transitionState internally using `t.visible` + // We will pass appearance from options + return ( + toast.dismiss(t.id)} + transitionState={t.visible ? 'entered' : 'exiting'} + > + {message} + + ); + }, + { + duration: options?.autoDismiss !== false ? 4000 : Infinity, + } + ); + + if (callback) { + callback(id); + } + }, + [] + ); + + const removeToast = useCallback((id: string) => { + toast.dismiss(id); + }, []); + + return { addToast, removeToast }; +}; + +export default useToasts; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 61e91aa09..833ecad66 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -3,8 +3,6 @@ import LoadingBar from '@app/components/LoadingBar'; import PWAHeader from '@app/components/PWAHeader'; import ServiceWorkerSetup from '@app/components/ServiceWorkerSetup'; import StatusChecker from '@app/components/StatusChecker'; -import Toast from '@app/components/Toast'; -import ToastContainer from '@app/components/ToastContainer'; import { InteractionProvider } from '@app/context/InteractionContext'; import { LanguageContext } from '@app/context/LanguageContext'; import { SettingsProvider } from '@app/context/SettingsContext'; @@ -22,8 +20,8 @@ import type { AppInitialProps, AppProps } from 'next/app'; import App from 'next/app'; import Head from 'next/head'; import { useEffect, useState } from 'react'; +import { Toaster } from 'react-hot-toast'; import { IntlProvider } from 'react-intl'; -import { ToastProvider } from 'react-toast-notifications'; import { SWRConfig } from 'swr'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -207,21 +205,27 @@ const CoreApp: Omit = ({ - - - {currentSettings.applicationTitle} - - - - - - {component} - + + {currentSettings.applicationTitle} + + + + + + {component} +