Skip to content

Commit

Permalink
Implement First Run Notify (#831)
Browse files Browse the repository at this point in the history
* Implement Dashboard Notify

* Revert code & Correct flow for Welcom Modal

* update PR request change

---------

Co-authored-by: ElementalCrisis <[email protected]>
  • Loading branch information
duehoa1211 and ElementalCrisis authored Mar 23, 2024
1 parent d5fbab5 commit fe30efa
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 70 deletions.
153 changes: 84 additions & 69 deletions src/pages/dashboard/DashboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { Responsive, WidthProvider } from 'react-grid-layout';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { mdiLoading, mdiMenuDown } from '@mdi/js';
import { Icon } from '@mdi/react';
import { produce } from 'immer';
Expand All @@ -12,6 +13,7 @@ import { usePatchSettingsMutation } from '@/core/react-query/settings/mutations'
import { useSettingsQuery } from '@/core/react-query/settings/queries';
import { setLayoutEditMode } from '@/core/slices/mainpage';
import useEventCallback from '@/hooks/useEventCallback';
import WelcomeModal from '@/pages/dashboard/components/WelcomeModal';

import CollectionStats from './panels/CollectionStats';
import ContinueWatching from './panels/ContinueWatching';
Expand Down Expand Up @@ -122,6 +124,16 @@ function DashboardPage() {
toast.dismiss('layoutEditMode');
});

const location = useLocation();
const [showWelcomeModal, setShowWelcomeModal] = useState(false);

useEffect(() => {
const locationState = location.state as { firstRun?: boolean } ?? { firstRun: false };
if (locationState.firstRun) {
setShowWelcomeModal(true);
}
}, [location]);

useEffect(() => {
if (!layoutEditMode) {
toast.dismiss('layoutEditMode');
Expand Down Expand Up @@ -159,75 +171,78 @@ function DashboardPage() {
}

return (
<ResponsiveGridLayout
layouts={currentLayout}
breakpoints={{ lg: 1024, md: 768, sm: 640 }} // These match tailwind breakpoints (for consistency)
cols={{ lg: 12, md: 10, sm: 6 }}
rowHeight={0}
margin={[24, 24]}
className="w-full"
onLayoutChange={(_layout, layouts) => setCurrentLayout(layouts)}
isDraggable={layoutEditMode}
isResizable={layoutEditMode}
resizeHandle={renderResizeHandle()}
containerPadding={[0, 0]}
>
{!hideQueueProcessor && (
<div key="queueProcessor">
<QueueProcessor />
</div>
)}
{!hideUnrecognizedFiles && (
<div key="unrecognizedFiles">
<UnrecognizedFiles />
</div>
)}
{!hideRecentlyImported && (
<div key="recentlyImported">
<RecentlyImported />
</div>
)}
{!hideCollectionStats && (
<div key="collectionBreakdown">
<CollectionStats />
</div>
)}
{!hideMediaType && (
<div key="collectionTypeBreakdown">
<MediaType />
</div>
)}
{!hideImportFolders && (
<div key="importFolders">
<ImportFolders />
</div>
)}
{!hideShokoNews && (
<div key="shokoNews">
<ShokoNews />
</div>
)}
{(!hideContinueWatching && !combineContinueWatching) && (
<div key="continueWatching">
<ContinueWatching />
</div>
)}
{!hideNextUp && (
<div key="nextUp">
<NextUp />
</div>
)}
{!hideUpcomingAnime && (
<div key="upcomingAnime">
<UpcomingAnime />
</div>
)}
{!hideRecommendedAnime && (
<div key="recommendedAnime">
<RecommendedAnime />
</div>
)}
</ResponsiveGridLayout>
<>
<ResponsiveGridLayout
layouts={currentLayout}
breakpoints={{ lg: 1024, md: 768, sm: 640 }} // These match tailwind breakpoints (for consistency)
cols={{ lg: 12, md: 10, sm: 6 }}
rowHeight={0}
margin={[24, 24]}
className="w-full"
onLayoutChange={(_layout, layouts) => setCurrentLayout(layouts)}
isDraggable={layoutEditMode}
isResizable={layoutEditMode}
resizeHandle={renderResizeHandle()}
containerPadding={[0, 0]}
>
{!hideQueueProcessor && (
<div key="queueProcessor">
<QueueProcessor />
</div>
)}
{!hideUnrecognizedFiles && (
<div key="unrecognizedFiles">
<UnrecognizedFiles />
</div>
)}
{!hideRecentlyImported && (
<div key="recentlyImported">
<RecentlyImported />
</div>
)}
{!hideCollectionStats && (
<div key="collectionBreakdown">
<CollectionStats />
</div>
)}
{!hideMediaType && (
<div key="collectionTypeBreakdown">
<MediaType />
</div>
)}
{!hideImportFolders && (
<div key="importFolders">
<ImportFolders />
</div>
)}
{!hideShokoNews && (
<div key="shokoNews">
<ShokoNews />
</div>
)}
{(!hideContinueWatching && !combineContinueWatching) && (
<div key="continueWatching">
<ContinueWatching />
</div>
)}
{!hideNextUp && (
<div key="nextUp">
<NextUp />
</div>
)}
{!hideUpcomingAnime && (
<div key="upcomingAnime">
<UpcomingAnime />
</div>
)}
{!hideRecommendedAnime && (
<div key="recommendedAnime">
<RecommendedAnime />
</div>
)}
</ResponsiveGridLayout>
<WelcomeModal onClose={() => setShowWelcomeModal(false)} show={showWelcomeModal} />
</>
);
}

Expand Down
75 changes: 75 additions & 0 deletions src/pages/dashboard/components/WelcomeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import Modal from 'react-modal';

import Button from '@/components/Input/Button';

type Props = {
onClose: () => void;
show: boolean;
};

const SuccessNotifyModal = (props: Props) => {
const {
onClose,
show,
} = props;

Modal.setAppElement('#app-root');

return (
<Modal
isOpen={show}
onRequestClose={onClose}
shouldCloseOnEsc={false}
overlayClassName="fixed inset-0 bg-black/50 z-[110]"
shouldCloseOnOverlayClick={false}
className="flex h-full items-center justify-center"
>
<div className="flex h-fit w-full items-center justify-center">
<div
className="flex h-[66%] w-[37.5rem] flex-col rounded-lg border border-panel-border bg-panel-background drop-shadow-lg"
onClick={e => e.stopPropagation()}
>
<div>
<div className="rounded-t-lg border-b border-panel-border bg-panel-background-alt p-6 text-xl font-semibold">
<div className="flex text-xl font-semibold">Hello From The Shoko Team!</div>
</div>
</div>
<div className="flex grow flex-col gap-y-6">
<div className="flex flex-col gap-y-[24px] p-[24px]">
<p>
{`Congratulations, Shoko appears to be up and running smoothly, assuming the setup was done correctly. Now is
the perfect opportunity to familiarize yourself with the Web UI's various features. Below, we've included some
recommended links to explore, along with information on media player integration and support resources.`}
</p>
<p>
{`If you're all set, you can click the button below to close this modal permanently. Remember, you can always
find these links under your username in the top-right corner for future reference.`}
</p>
<p className="flex flex-col">
<a className="font-semibold text-panel-text-primary" href="https://docs.shokoanime.com/">
Using Shoko | ShokoDocs
</a>
<a className="font-semibold text-panel-text-primary" href="https://docs.shokoanime.com/faq/">
Frequently Asked Questions | Shoko Docs
</a>
</p>
<p className="flex flex-col">
<a className="font-semibold text-panel-text-primary" href="https://docs.shokoanime.com/">
Media Player Integrations | Shoko Docs
</a>
<a className="font-semibold text-panel-text-primary" href="https://discord.gg/vpeHDsg">
Community & Staff Support | Discord
</a>
</p>

<Button buttonSize="normal" buttonType="primary" onClick={onClose}>Set Me Free!</Button>
</div>
</div>
</div>
</div>
</Modal>
);
};

export default SuccessNotifyModal;
2 changes: 1 addition & 1 deletion src/pages/firstrun/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function Footer(props: Props) {
{finish
? (
<Button
onClick={() => navigate('/', { replace: true })}
onClick={() => navigate('/webui/dashboard', { replace: true, state: { firstRun: true } })}
buttonType="primary"
className="w-1/2 px-4 py-2"
disabled={nextDisabled}
Expand Down

0 comments on commit fe30efa

Please sign in to comment.