From 86c609f49f3ec05a04984749a580aeba1f70a188 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Mon, 6 Sep 2021 16:26:13 +0200 Subject: [PATCH] media dashboard implementation --- src/commands/Dashboard.ts | 29 ++++++- src/models/MediaPaths.ts | 1 + src/pagesView/DashboardCommand.ts | 3 +- src/pagesView/DashboardMessage.ts | 1 + .../components/Contents/Contents.tsx | 36 +++++++++ .../components/{ => Contents}/Overview.tsx | 20 ++--- src/pagesView/components/Dashboard.tsx | 35 ++++----- src/pagesView/components/Header/Header.tsx | 75 ++++++++++++------- src/pagesView/components/Media/Media.tsx | 51 +++++++++++++ src/pagesView/components/SponsorMsg.tsx | 2 +- src/pagesView/components/Startup.tsx | 4 +- src/pagesView/state/atom/DashboardViewAtom.ts | 6 ++ src/pagesView/state/atom/index.ts | 1 + .../state/selectors/DashboardViewSelector.ts | 9 +++ src/pagesView/state/selectors/index.ts | 1 + 15 files changed, 211 insertions(+), 63 deletions(-) create mode 100644 src/models/MediaPaths.ts create mode 100644 src/pagesView/components/Contents/Contents.tsx rename src/pagesView/components/{ => Contents}/Overview.tsx (84%) create mode 100644 src/pagesView/components/Media/Media.tsx create mode 100644 src/pagesView/state/atom/DashboardViewAtom.ts create mode 100644 src/pagesView/state/selectors/DashboardViewSelector.ts diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index 9ad90629..b677ab41 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -1,6 +1,6 @@ import { SETTINGS_CONTENT_STATIC_FOLDERS, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART } from './../constants/settings'; import { ArticleHelper } from './../helpers/ArticleHelper'; -import { join } from "path"; +import { basename, extname, join } from "path"; import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace } from "vscode"; import { SettingsHelper } from '../helpers'; import { TaxonomyType } from '../models'; @@ -17,6 +17,7 @@ import { Extension } from '../helpers/Extension'; import { parseJSON } from 'date-fns'; import { ViewType } from '../pagesView/state'; import { WebviewHelper } from '@estruyf/vscode'; +import { MediaPaths } from '../models/MediaPaths'; export class Dashboard { @@ -129,6 +130,9 @@ export class Dashboard { case DashboardMessage.setPageViewType: Extension.getInstance().setState(EXTENSION_STATE_PAGES_VIEW, msg.data); break; + case DashboardMessage.getMedia: + Dashboard.getMedia(); + break; } }); } @@ -161,6 +165,29 @@ export class Dashboard { Dashboard.getSettings(); } + /** + * Retrieve all media files + */ + private static async getMedia() { + const config = SettingsHelper.getConfig(); + const staticFolder = config.get(SETTINGS_CONTENT_STATIC_FOLDERS); + + workspace.findFiles(`${staticFolder || ""}/**/*`).then(async (files) => { + const media = files.filter(file => { + const ext = extname(file.fsPath); + return ['.jpg', '.jpeg', '.png', '.gif', '.svg'].includes(ext); + }).map((file) => ({ + fsPath: file.fsPath, + vsPath: Dashboard.webview?.webview.asWebviewUri(file).toString() + } as MediaPaths)); + + Dashboard.postWebviewMessage({ + command: DashboardCommand.media, + data: media + }); + }); + } + /** * Retrieve all the markdown pages */ diff --git a/src/models/MediaPaths.ts b/src/models/MediaPaths.ts new file mode 100644 index 00000000..9c5f62f0 --- /dev/null +++ b/src/models/MediaPaths.ts @@ -0,0 +1 @@ +export interface MediaPaths { fsPath: string; vsPath: string | undefined; } \ No newline at end of file diff --git a/src/pagesView/DashboardCommand.ts b/src/pagesView/DashboardCommand.ts index 987fc7d8..927864df 100644 --- a/src/pagesView/DashboardCommand.ts +++ b/src/pagesView/DashboardCommand.ts @@ -1,5 +1,6 @@ export enum DashboardCommand { loading = "loading", pages = "pages", - settings = "settings" + settings = "settings", + media = "media", } \ No newline at end of file diff --git a/src/pagesView/DashboardMessage.ts b/src/pagesView/DashboardMessage.ts index 2c923a42..f5ad3df3 100644 --- a/src/pagesView/DashboardMessage.ts +++ b/src/pagesView/DashboardMessage.ts @@ -7,4 +7,5 @@ export enum DashboardMessage { initializeProject = 'initializeProject', reload = 'reload', setPageViewType = 'setPageViewType', + getMedia = 'getMedia', } \ No newline at end of file diff --git a/src/pagesView/components/Contents/Contents.tsx b/src/pagesView/components/Contents/Contents.tsx new file mode 100644 index 00000000..f7a7d2de --- /dev/null +++ b/src/pagesView/components/Contents/Contents.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { useRecoilValue } from 'recoil'; +import { Page } from '../../models'; +import { SettingsSelector } from '../../state'; +import { Header } from '../Header'; +import { Overview } from './Overview'; +import { Spinner } from '../Spinner'; +import { SponsorMsg } from '../SponsorMsg'; + +export interface IContentsProps { + pages: Page[]; + loading: boolean; +} + +export const Contents: React.FunctionComponent = ({pages, loading}: React.PropsWithChildren) => { + const settings = useRecoilValue(SettingsSelector); + + const pageFolders = [...new Set(pages.map(page => page.fmFolder))]; + + return ( +
+
+
+ +
+ { loading ? : } +
+ + +
+
+ ); +}; \ No newline at end of file diff --git a/src/pagesView/components/Overview.tsx b/src/pagesView/components/Contents/Overview.tsx similarity index 84% rename from src/pagesView/components/Overview.tsx rename to src/pagesView/components/Contents/Overview.tsx index cdd261fb..4269b256 100644 --- a/src/pagesView/components/Overview.tsx +++ b/src/pagesView/components/Contents/Overview.tsx @@ -2,18 +2,18 @@ import { Disclosure } from '@headlessui/react'; import { ChevronRightIcon } from '@heroicons/react/solid'; import * as React from 'react'; import { useRecoilValue } from 'recoil'; -import { groupBy } from '../../helpers/GroupBy'; -import { FrontMatterIcon } from '../../viewpanel/components/Icons/FrontMatterIcon'; -import { GroupOption } from '../constants/GroupOption'; -import { Page } from '../models/Page'; -import { Settings } from '../models/Settings'; -import { GroupingSelector } from '../state'; -import { Item } from './Item'; -import { List } from './List'; +import { groupBy } from '../../../helpers/GroupBy'; +import { FrontMatterIcon } from '../../../viewpanel/components/Icons/FrontMatterIcon'; +import { GroupOption } from '../../constants/GroupOption'; +import { Page } from '../../models/Page'; +import { Settings } from '../../models/Settings'; +import { GroupingSelector } from '../../state'; +import { Item } from '../Item'; +import { List } from '../List'; export interface IOverviewProps { pages: Page[]; - settings: Settings; + settings: Settings | null; } export const Overview: React.FunctionComponent = ({pages, settings}: React.PropsWithChildren) => { @@ -25,7 +25,7 @@ export const Overview: React.FunctionComponent = ({pages, settin
{ - settings?.folders?.length > 0 ? ( + settings && settings?.folders?.length > 0 ? (

No Markdown to show

) : ( <> diff --git a/src/pagesView/components/Dashboard.tsx b/src/pagesView/components/Dashboard.tsx index 1a024005..01331f5f 100644 --- a/src/pagesView/components/Dashboard.tsx +++ b/src/pagesView/components/Dashboard.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; import { Spinner } from './Spinner'; import useMessages from '../hooks/useMessages'; -import { Overview } from './Overview'; -import { Header } from './Header'; import useDarkMode from '../../hooks/useDarkMode'; import usePages from '../hooks/usePages'; -import { SponsorMsg } from './SponsorMsg'; import { WelcomeScreen } from './WelcomeScreen'; +import { useRecoilValue } from 'recoil'; +import { DashboardViewSelector } from '../state'; +import { Contents } from './Contents/Contents'; +import { Media } from './Media/Media'; export interface IDashboardProps { showWelcome: boolean; @@ -15,10 +16,9 @@ export interface IDashboardProps { export const Dashboard: React.FunctionComponent = ({showWelcome}: React.PropsWithChildren) => { const { loading, pages, settings } = useMessages(); const { pageItems } = usePages(pages); + const view = useRecoilValue(DashboardViewSelector); useDarkMode(); - const pageFolders = [...new Set(pages.map(page => page.fmFolder))]; - if (!settings) { return ; } @@ -30,21 +30,14 @@ export const Dashboard: React.FunctionComponent = ({showWelcome if (!settings.initialized || settings.folders?.length === 0) { return ; } - - return ( -
-
-
-
- { loading ? : } -
- - -
-
- ); + if (view === "contents") { + return ( + + ); + } else { + return ( + + ); + } }; \ No newline at end of file diff --git a/src/pagesView/components/Header/Header.tsx b/src/pagesView/components/Header/Header.tsx index e34228ca..5a02d5d4 100644 --- a/src/pagesView/components/Header/Header.tsx +++ b/src/pagesView/components/Header/Header.tsx @@ -11,23 +11,26 @@ import { Navigation } from '../Navigation'; import { Grouping } from '.'; import { ViewSwitch } from './ViewSwitch'; import { useRecoilState } from 'recoil'; -import { CategoryAtom, TagAtom } from '../../state'; +import { CategoryAtom, DashboardViewAtom, TagAtom } from '../../state'; import { Messenger } from '@estruyf/vscode/dist/client'; import { ClearFilters } from './ClearFilters'; +import { MarkdownIcon } from '../../../viewpanel/components/Icons/MarkdownIcon'; +import { PhotographIcon } from '@heroicons/react/outline'; export interface IHeaderProps { - settings: Settings; + settings: Settings | null; // Navigation - totalPages: number; + totalPages?: number; // Page folders - folders: string[]; + folders?: string[]; } export const Header: React.FunctionComponent = ({totalPages, folders, settings }: React.PropsWithChildren) => { const [ crntTag, setCrntTag ] = useRecoilState(TagAtom); const [ crntCategory, setCrntCategory ] = useRecoilState(CategoryAtom); + const [ view, setView ] = useRecoilState(DashboardViewAtom); const createContent = () => { Messenger.send(DashboardMessage.createContent); @@ -35,39 +38,57 @@ export const Header: React.FunctionComponent = ({totalPages, folde return (
-
- - -
- - - + +
+
+ +
-
-
- -
+ { + view === "contents" && ( + <> +
+ -
- -
-
+
+ + + +
+
-
- +
+
+ +
- +
+ +
+
- setCrntTag(value)} /> +
+ - setCrntCategory(value)} /> + - + setCrntTag(value)} /> - -
+ setCrntCategory(value)} /> + + + + +
+ + ) + }
); }; \ No newline at end of file diff --git a/src/pagesView/components/Media/Media.tsx b/src/pagesView/components/Media/Media.tsx new file mode 100644 index 00000000..1d0cca71 --- /dev/null +++ b/src/pagesView/components/Media/Media.tsx @@ -0,0 +1,51 @@ +import { Messenger } from '@estruyf/vscode/dist/client'; +import * as React from 'react'; +import { useRecoilValue } from 'recoil'; +import { MediaPaths } from '../../../models/MediaPaths'; +import { DashboardCommand } from '../../DashboardCommand'; +import { DashboardMessage } from '../../DashboardMessage'; +import { SettingsSelector } from '../../state'; +import { Header } from '../Header'; + +export interface IMediaProps {} + +const LIMIT = 25; + +export const Media: React.FunctionComponent = (props: React.PropsWithChildren) => { + const settings = useRecoilValue(SettingsSelector); + const [ media, setMedia ] = React.useState([]); + const [ page, setPage ] = React.useState(0); + + const crntMedia = media.splice(page * LIMIT, LIMIT); + + React.useEffect(() => { + Messenger.send(DashboardMessage.getMedia); + + Messenger.listen((message) => { + if (message.command === DashboardCommand.media) { + setMedia(message.data); + setPage(0); + } + }); + }, ['']); + + console.log(crntMedia) + + return ( +
+
+
+ +
+ { + crntMedia.map((media) => ( +
+ +
+ )) + } +
+
+
+ ); +}; \ No newline at end of file diff --git a/src/pagesView/components/SponsorMsg.tsx b/src/pagesView/components/SponsorMsg.tsx index 1c8bd485..b93700d8 100644 --- a/src/pagesView/components/SponsorMsg.tsx +++ b/src/pagesView/components/SponsorMsg.tsx @@ -4,7 +4,7 @@ import { REVIEW_LINK, SPONSOR_LINK } from '../../constants/Links'; import { VersionInfo } from '../../models'; export interface ISponsorMsgProps { - version: VersionInfo; + version: VersionInfo | undefined; } export const SponsorMsg: React.FunctionComponent = ({version}: React.PropsWithChildren) => { diff --git a/src/pagesView/components/Startup.tsx b/src/pagesView/components/Startup.tsx index 77f45332..79e25e66 100644 --- a/src/pagesView/components/Startup.tsx +++ b/src/pagesView/components/Startup.tsx @@ -5,7 +5,7 @@ import { DashboardMessage } from '../DashboardMessage'; import { Settings } from '../models/Settings'; export interface IStartupProps { - settings: Settings; + settings: Settings | null; } export const Startup: React.FunctionComponent = ({settings}: React.PropsWithChildren) => { @@ -17,7 +17,7 @@ export const Startup: React.FunctionComponent = ({settings}: Reac }; React.useEffect(() => { - setIsChecked(!!settings.openOnStart); + setIsChecked(!!settings?.openOnStart); }, [settings?.openOnStart]); return ( diff --git a/src/pagesView/state/atom/DashboardViewAtom.ts b/src/pagesView/state/atom/DashboardViewAtom.ts new file mode 100644 index 00000000..bbfb3ca4 --- /dev/null +++ b/src/pagesView/state/atom/DashboardViewAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const DashboardViewAtom = atom<"contents" | "media">({ + key: 'DashboardViewAtom', + default: "contents" +}); \ No newline at end of file diff --git a/src/pagesView/state/atom/index.ts b/src/pagesView/state/atom/index.ts index 96ad9ca3..ee0a7477 100644 --- a/src/pagesView/state/atom/index.ts +++ b/src/pagesView/state/atom/index.ts @@ -1,4 +1,5 @@ export * from './CategoryAtom'; +export * from './DashboardViewAtom'; export * from './FolderAtom'; export * from './GroupingAtom'; export * from './SearchAtom'; diff --git a/src/pagesView/state/selectors/DashboardViewSelector.ts b/src/pagesView/state/selectors/DashboardViewSelector.ts new file mode 100644 index 00000000..28d3b3ce --- /dev/null +++ b/src/pagesView/state/selectors/DashboardViewSelector.ts @@ -0,0 +1,9 @@ +import { selector } from 'recoil'; +import { DashboardViewAtom } from '..'; + +export const DashboardViewSelector = selector({ + key: 'DashboardViewSelector', + get: ({get}) => { + return get(DashboardViewAtom); + } +}); \ No newline at end of file diff --git a/src/pagesView/state/selectors/index.ts b/src/pagesView/state/selectors/index.ts index 990c9abb..805935a0 100644 --- a/src/pagesView/state/selectors/index.ts +++ b/src/pagesView/state/selectors/index.ts @@ -1,4 +1,5 @@ export * from './CategorySelector'; +export * from './DashboardViewSelector'; export * from './FolderSelector'; export * from './GroupingSelector'; export * from './SearchSelector';