diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index b677ab41..41284e82 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -1,7 +1,8 @@ import { SETTINGS_CONTENT_STATIC_FOLDERS, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART } from './../constants/settings'; import { ArticleHelper } from './../helpers/ArticleHelper'; -import { basename, extname, join } from "path"; -import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace } from "vscode"; +import { dirname, extname, join } from "path"; +import { existsSync, statSync } from "fs"; +import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace, env } from "vscode"; import { SettingsHelper } from '../helpers'; import { TaxonomyType } from '../models'; import { Folders } from './Folders'; @@ -17,12 +18,13 @@ 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'; +import { MediaInfo, MediaPaths } from './../models/MediaPaths'; export class Dashboard { private static webview: WebviewPanel | null = null; private static isDisposed: boolean = true; + private static media: MediaInfo[] = []; /**  * Init the dashboard @@ -131,7 +133,10 @@ export class Dashboard { Extension.getInstance().setState(EXTENSION_STATE_PAGES_VIEW, msg.data); break; case DashboardMessage.getMedia: - Dashboard.getMedia(); + Dashboard.getMedia(msg?.data?.page, msg?.data?.folder) + break; + case DashboardMessage.copyToClipboard: + env.clipboard.writeText(msg.data); break; } }); @@ -142,15 +147,19 @@ export class Dashboard { */ private static async getSettings() { const ext = Extension.getInstance(); + const config = SettingsHelper.getConfig(); + const wsFolder = Folders.getWorkspaceFolder(); Dashboard.postWebviewMessage({ command: DashboardCommand.settings, data: { + wsFolder: wsFolder ? wsFolder.fsPath : '', + staticFolder: config.get(SETTINGS_CONTENT_STATIC_FOLDERS), folders: Folders.get(), initialized: await Template.isInitialized(), tags: SettingsHelper.getTaxonomy(TaxonomyType.Tag), categories: SettingsHelper.getTaxonomy(TaxonomyType.Category), - openOnStart: SettingsHelper.getConfig().get(SETTINGS_DASHBOARD_OPENONSTART), + openOnStart: config.get(SETTINGS_DASHBOARD_OPENONSTART), versionInfo: ext.getVersion(), pageViewType: await ext.getState(EXTENSION_STATE_PAGES_VIEW) } as Settings @@ -168,23 +177,80 @@ export class Dashboard { /** * Retrieve all media files */ - private static async getMedia() { + private static async getMedia(page: number = 0, folder: string = '') { + const wsFolder = Folders.getWorkspaceFolder(); 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 + if (Dashboard.media.length === 0) { + const contentFolder = Folders.get(); + let allMedia: MediaInfo[] = []; + + if (staticFolder) { + const files = await workspace.findFiles(`${staticFolder || ""}/**/*`); + const media = Dashboard.filterMedia(files); + + allMedia = [...media]; + } + + if (contentFolder && wsFolder) { + for (let i = 0; i < contentFolder.length; i++) { + const folder = contentFolder[i]; + const relFolderPath = folder.path.substring(wsFolder.fsPath.length + 1); + const files = await workspace.findFiles(`${relFolderPath}/**/*`); + const media = Dashboard.filterMedia(files); + + allMedia = [...allMedia, ...media]; + } + } + + allMedia = allMedia.sort((a, b) => { + if (b.fsPath < a.fsPath) { + return -1; + } + if (b.fsPath > a.fsPath) { + return 1; + } + return 0; }); + + Dashboard.media = Object.assign([], allMedia); + } + + // Filter the media + let files = Dashboard.media; + if (folder) { + files = files.filter(f => f.fsPath.includes(folder)); + } + + // Retrieve the total after filtering and before the slicing happens + const total = files.length; + + // Get media set + files = files.slice(page * 16, ((page + 1) * 16)); + files = files.map((file) => ({ + ...file, + stats: statSync(file.fsPath) + })); + + const folders = [...new Set(Dashboard.media.map((file) => { + let relFolderPath = wsFolder ? file.fsPath.substring(wsFolder.fsPath.length + 1) : file.fsPath; + if (staticFolder && relFolderPath.startsWith(staticFolder)) { + relFolderPath = relFolderPath.substring(staticFolder.length); + } + if (relFolderPath?.startsWith('/')) { + relFolderPath = relFolderPath.substring(1); + } + return dirname(relFolderPath); + }))]; + + Dashboard.postWebviewMessage({ + command: DashboardCommand.media, + data: { + media: files, + total: total, + folders + } as MediaPaths }); } @@ -228,10 +294,22 @@ export class Dashboard { }; if (article?.data.preview && wsFolder) { - const previewPath = join(wsFolder.fsPath, staticFolder || "", article?.data.preview); - const previewUri = Uri.file(previewPath); - const preview = Dashboard.webview?.webview.asWebviewUri(previewUri); - page.preview = preview?.toString() || ""; + const staticPath = join(wsFolder.fsPath, staticFolder || "", article?.data.preview); + const contentFolderPath = join(dirname(file.filePath), article?.data.preview); + + let previewUri = null; + if (existsSync(staticPath)) { + previewUri = Uri.file(staticPath); + } else if (existsSync(contentFolderPath)) { + previewUri = Uri.file(contentFolderPath); + } + + if (previewUri) { + const preview = Dashboard.webview?.webview.asWebviewUri(previewUri); + page.preview = preview?.toString() || ""; + } else { + page.preview = ""; + } } pages.push(page); @@ -250,6 +328,20 @@ export class Dashboard { }); } + /** + * Filter the media files + */ + private static filterMedia(files: Uri[]) { + return 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(), + stats: undefined + } as MediaInfo)); + } + /** * Post data to the dashboard * @param msg diff --git a/src/models/MediaPaths.ts b/src/models/MediaPaths.ts index 9c5f62f0..3f992892 100644 --- a/src/models/MediaPaths.ts +++ b/src/models/MediaPaths.ts @@ -1 +1,13 @@ -export interface MediaPaths { fsPath: string; vsPath: string | undefined; } \ No newline at end of file +import { Stats } from "fs"; + +export interface MediaPaths { + media: MediaInfo[]; + total: number; + folders: string[]; +} + +export interface MediaInfo { + fsPath: string; + vsPath: string | undefined; + stats: Stats | undefined; +} \ No newline at end of file diff --git a/src/pagesView/DashboardMessage.ts b/src/pagesView/DashboardMessage.ts index f5ad3df3..3b315439 100644 --- a/src/pagesView/DashboardMessage.ts +++ b/src/pagesView/DashboardMessage.ts @@ -8,4 +8,5 @@ export enum DashboardMessage { reload = 'reload', setPageViewType = 'setPageViewType', getMedia = 'getMedia', + copyToClipboard = 'copyToClipboard', } \ No newline at end of file diff --git a/src/pagesView/components/Item.tsx b/src/pagesView/components/Contents/Item.tsx similarity index 89% rename from src/pagesView/components/Item.tsx rename to src/pagesView/components/Contents/Item.tsx index 8180d3f5..a01250e5 100644 --- a/src/pagesView/components/Item.tsx +++ b/src/pagesView/components/Contents/Item.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import { useRecoilValue } from 'recoil'; -import { MarkdownIcon } from '../../viewpanel/components/Icons/MarkdownIcon'; -import { DashboardMessage } from '../DashboardMessage'; -import { Page } from '../models/Page'; -import { ViewSelector, ViewType } from '../state'; -import { DateField } from './DateField'; -import { Status } from './Status'; +import { MarkdownIcon } from '../../../viewpanel/components/Icons/MarkdownIcon'; +import { DashboardMessage } from '../../DashboardMessage'; +import { Page } from '../../models/Page'; +import { ViewSelector, ViewType } from '../../state'; +import { DateField } from '../DateField'; +import { Status } from '../Status'; import { Messenger } from '@estruyf/vscode/dist/client'; export interface IItemProps extends Page {} diff --git a/src/pagesView/components/List.tsx b/src/pagesView/components/Contents/List.tsx similarity index 95% rename from src/pagesView/components/List.tsx rename to src/pagesView/components/Contents/List.tsx index 289aa1bf..e131a2db 100644 --- a/src/pagesView/components/List.tsx +++ b/src/pagesView/components/Contents/List.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { useRecoilValue } from 'recoil'; -import { ViewSelector, ViewType } from '../state'; +import { ViewSelector, ViewType } from '../../state'; export interface IListProps {} diff --git a/src/pagesView/components/Contents/Overview.tsx b/src/pagesView/components/Contents/Overview.tsx index 4269b256..f30c728b 100644 --- a/src/pagesView/components/Contents/Overview.tsx +++ b/src/pagesView/components/Contents/Overview.tsx @@ -8,8 +8,8 @@ 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 { Item } from './Item'; +import { List } from './List'; export interface IOverviewProps { pages: Page[]; diff --git a/src/pagesView/components/Header/Header.tsx b/src/pagesView/components/Header/Header.tsx index 5a02d5d4..ca9ab459 100644 --- a/src/pagesView/components/Header/Header.tsx +++ b/src/pagesView/components/Header/Header.tsx @@ -16,6 +16,7 @@ import { Messenger } from '@estruyf/vscode/dist/client'; import { ClearFilters } from './ClearFilters'; import { MarkdownIcon } from '../../../viewpanel/components/Icons/MarkdownIcon'; import { PhotographIcon } from '@heroicons/react/outline'; +import { Pagination } from '../Media/Pagination'; export interface IHeaderProps { settings: Settings | null; @@ -37,15 +38,15 @@ export const Header: React.FunctionComponent = ({totalPages, folde }; return ( -
+
-
-
- -
@@ -89,6 +90,12 @@ export const Header: React.FunctionComponent = ({totalPages, folde ) } + + { + view === "media" && ( + + ) + }
); }; \ No newline at end of file diff --git a/src/pagesView/components/Media/FolderSelection.tsx b/src/pagesView/components/Media/FolderSelection.tsx new file mode 100644 index 00000000..2281a011 --- /dev/null +++ b/src/pagesView/components/Media/FolderSelection.tsx @@ -0,0 +1,77 @@ +import { Menu } from '@headlessui/react'; +import { XIcon } from '@heroicons/react/outline'; +import Downshift from 'downshift'; +import * as React from 'react'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { MediaFoldersSelector, SelectedMediaFolderAtom } from '../../state'; + +export interface IFolderSelectionProps {} + +export const FolderSelection: React.FunctionComponent = (props: React.PropsWithChildren) => { + const folders = useRecoilValue(MediaFoldersSelector); + const [ selectedFolder, setSelectedFolder ] = useRecoilState(SelectedMediaFolderAtom); + const [ focus, setFocus ] = React.useState(false); + + let allFolders: string[] = Object.assign([], folders); + allFolders = allFolders.sort((a: string, b: string) => { + if (a.toLowerCase() < b.toLowerCase()) return -1; + if (a.toLowerCase() > b.toLowerCase()) return 1; + return 0; + }); + + return ( +
+ setFocus(false)} + onSelect={(selFolder) => { + setSelectedFolder(selFolder); + setFocus(false); + }}> + { + ({ + getInputProps, + getItemProps, + getMenuProps, + isOpen, + inputValue, + getRootProps + }) => ( +
+ + +
+ setFocus(true)} className={`ml-2 py-1 px-2 sm:text-sm bg-white dark:bg-vulcan-300 border border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none`} {...getInputProps()} /> + + { + selectedFolder && ( + + ) + } +
+ +
+ {isOpen + ? allFolders + .filter((item: string) => !inputValue || item.includes(inputValue)) + .map((item, index) => ( +
+ {item} +
+ )) + : null} +
+
+ ) + } +
+
+ ); +}; \ No newline at end of file diff --git a/src/pagesView/components/Media/Item.tsx b/src/pagesView/components/Media/Item.tsx new file mode 100644 index 00000000..0e27d563 --- /dev/null +++ b/src/pagesView/components/Media/Item.tsx @@ -0,0 +1,84 @@ +import { Messenger } from '@estruyf/vscode/dist/client'; +import { ClipboardCopyIcon, FolderIcon, PhotographIcon } from '@heroicons/react/outline'; +import { basename, dirname } from 'path'; +import * as React from 'react'; +import { useRecoilValue } from 'recoil'; +import { MediaInfo } from '../../../models/MediaPaths'; +import { DashboardMessage } from '../../DashboardMessage'; +import { SettingsSelector } from '../../state'; + +export interface IItemProps { + media: MediaInfo; +} + +export const Item: React.FunctionComponent = ({media}: React.PropsWithChildren) => { + const settings = useRecoilValue(SettingsSelector); + + const getFolder = () => { + if (settings?.wsFolder && media.fsPath) { + let relPath = media.fsPath.split(settings.wsFolder).pop(); + + if (settings.staticFolder && relPath) { + relPath = relPath.split(settings.staticFolder).pop(); + } + + return dirname(relPath || ""); + } + return ""; + }; + + const copyToClipboard = () => { + let relPath: string | undefined = ""; + if (settings?.wsFolder && media.fsPath) { + relPath = media.fsPath.split(settings.wsFolder).pop(); + + if (settings.staticFolder && relPath) { + relPath = relPath.split(settings.staticFolder).pop(); + } + } + + Messenger.send(DashboardMessage.copyToClipboard, relPath || ""); + }; + + const calculateSize = () => { + if (media?.stats?.size) { + const size = media.stats.size / (1024*1024); + if (size > 1) { + return `${size.toFixed(2)} MB`; + } else { + return `${(size * 1024).toFixed(2)} KB`; + } + } + }; + + return ( +
  • +
    + {basename(media.fsPath)} +
    +
    +
    + +
    +

    + {basename(media.fsPath)} +

    +

    + {getFolder()} +

    + { + media?.stats?.size && ( +

    + {calculateSize()} +

    + ) + } +
    +
  • + ); +}; \ No newline at end of file diff --git a/src/pagesView/components/Media/List.tsx b/src/pagesView/components/Media/List.tsx new file mode 100644 index 00000000..abf0746b --- /dev/null +++ b/src/pagesView/components/Media/List.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; + +export interface IListProps {} + +export const List: React.FunctionComponent = ({children}: React.PropsWithChildren) => { + return ( +
      + {children} +
    + ); +}; \ No newline at end of file diff --git a/src/pagesView/components/Media/Media.tsx b/src/pagesView/components/Media/Media.tsx index 1d0cca71..cca18f06 100644 --- a/src/pagesView/components/Media/Media.tsx +++ b/src/pagesView/components/Media/Media.tsx @@ -1,35 +1,32 @@ import { Messenger } from '@estruyf/vscode/dist/client'; import * as React from 'react'; -import { useRecoilValue } from 'recoil'; -import { MediaPaths } from '../../../models/MediaPaths'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { MediaInfo, MediaPaths } from '../../../models/MediaPaths'; import { DashboardCommand } from '../../DashboardCommand'; -import { DashboardMessage } from '../../DashboardMessage'; -import { SettingsSelector } from '../../state'; +import { MediaFoldersAtom, MediaTotalAtom, SettingsSelector } from '../../state'; import { Header } from '../Header'; +import { Item } from './Item'; +import { List } from './List'; export interface IMediaProps {} -const LIMIT = 25; +export const LIMIT = 16; 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); + const [ media, setMedia ] = React.useState([]); + const [ , setTotal ] = useRecoilState(MediaTotalAtom); + const [ , setFolders ] = useRecoilState(MediaFoldersAtom); React.useEffect(() => { - Messenger.send(DashboardMessage.getMedia); - - Messenger.listen((message) => { + Messenger.listen((message) => { if (message.command === DashboardCommand.media) { - setMedia(message.data); - setPage(0); + setMedia(message.data.media); + setTotal(message.data.total); + setFolders(message.data.folders); } }); }, ['']); - - console.log(crntMedia) return (
    @@ -37,13 +34,13 @@ export const Media: React.FunctionComponent = (props: React.PropsWi
    - { - crntMedia.map((media) => ( -
    - -
    - )) - } + + { + media.map((file) => ( + + )) + } +
    diff --git a/src/pagesView/components/Media/Pagination.tsx b/src/pagesView/components/Media/Pagination.tsx new file mode 100644 index 00000000..88443e9d --- /dev/null +++ b/src/pagesView/components/Media/Pagination.tsx @@ -0,0 +1,116 @@ +import { Messenger } from '@estruyf/vscode/dist/client'; +import * as React from 'react'; +import { useRecoilValue } from 'recoil'; +import { DashboardMessage } from '../../DashboardMessage'; +import { MediaTotalSelector, SelectedMediaFolderSelector } from '../../state'; +import { FolderSelection } from './FolderSelection'; +import { LIMIT } from './Media'; +import { PaginationButton } from './PaginationButton'; + +export interface IPaginationProps {} + +export const Pagination: React.FunctionComponent = ({}: React.PropsWithChildren) => { + const selectedFolder = useRecoilValue(SelectedMediaFolderSelector); + const totalMedia = useRecoilValue(MediaTotalSelector); + const [ page, setPage ] = React.useState(0); + + const totalPages = Math.ceil(totalMedia / LIMIT) - 1; + + const getTotalPage = () => { + const mediaItems = ((page + 1) * LIMIT); + if (totalMedia < mediaItems) { + return totalMedia; + } + return mediaItems; + }; + + // Write me function to retrieve buttons before and after current page + const getButtons = (): number[] => { + const maxButtons = 5; + const buttons: number[] = []; + const start = page - maxButtons; + const end = page + maxButtons; + + for (let i = start; i <= end; i++) { + if (i >= 0 && i <= totalPages) { + buttons.push(i); + } + } + return buttons; + }; + + const buttons = getButtons(); + + React.useEffect(() => { + Messenger.send(DashboardMessage.getMedia, { + page, + folder: selectedFolder || '' + }); + }, [page]); + + React.useEffect(() => { + Messenger.send(DashboardMessage.getMedia, { + page: 0, + folder: selectedFolder || '' + }); + setPage(0); + }, [selectedFolder]); + + return ( + + ); +}; \ No newline at end of file diff --git a/src/pagesView/components/Media/PaginationButton.tsx b/src/pagesView/components/Media/PaginationButton.tsx new file mode 100644 index 00000000..a5abea22 --- /dev/null +++ b/src/pagesView/components/Media/PaginationButton.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; + +export interface IPaginationButtonProps { + title: string; + disabled?: boolean; + onClick: () => void; +} + +export const PaginationButton: React.FunctionComponent = ({title, disabled, onClick}: React.PropsWithChildren) => { + return ( + + ); +}; \ No newline at end of file diff --git a/src/pagesView/models/Settings.ts b/src/pagesView/models/Settings.ts index 06f80306..f6ef6b1d 100644 --- a/src/pagesView/models/Settings.ts +++ b/src/pagesView/models/Settings.ts @@ -3,6 +3,8 @@ import { ViewType } from '../state'; import { ContentFolder } from './../../models/ContentFolder'; export interface Settings { + wsFolder: string; + staticFolder: string; folders: ContentFolder[]; initialized: boolean tags: string[]; diff --git a/src/pagesView/state/atom/MediaFoldersAtom.ts b/src/pagesView/state/atom/MediaFoldersAtom.ts new file mode 100644 index 00000000..4028ecf7 --- /dev/null +++ b/src/pagesView/state/atom/MediaFoldersAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const MediaFoldersAtom = atom({ + key: 'MediaFoldersAtom', + default: [] +}); \ No newline at end of file diff --git a/src/pagesView/state/atom/MediaTotalAtom.ts b/src/pagesView/state/atom/MediaTotalAtom.ts new file mode 100644 index 00000000..a76c976b --- /dev/null +++ b/src/pagesView/state/atom/MediaTotalAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const MediaTotalAtom = atom({ + key: 'MediaTotalAtom', + default: 0 +}); \ No newline at end of file diff --git a/src/pagesView/state/atom/SelectedMediaFolderAtom.ts b/src/pagesView/state/atom/SelectedMediaFolderAtom.ts new file mode 100644 index 00000000..6e07c2f7 --- /dev/null +++ b/src/pagesView/state/atom/SelectedMediaFolderAtom.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil'; + +export const SelectedMediaFolderAtom = atom({ + key: 'SelectedMediaFolderAtom', + default: null +}); \ No newline at end of file diff --git a/src/pagesView/state/atom/index.ts b/src/pagesView/state/atom/index.ts index ee0a7477..6243caab 100644 --- a/src/pagesView/state/atom/index.ts +++ b/src/pagesView/state/atom/index.ts @@ -2,7 +2,10 @@ export * from './CategoryAtom'; export * from './DashboardViewAtom'; export * from './FolderAtom'; export * from './GroupingAtom'; +export * from './MediaFoldersAtom'; +export * from './MediaTotalAtom'; export * from './SearchAtom'; +export * from './SelectedMediaFolderAtom'; export * from './SettingsAtom'; export * from './SortingAtom'; export * from './TabAtom'; diff --git a/src/pagesView/state/selectors/MediaFoldersSelector.ts b/src/pagesView/state/selectors/MediaFoldersSelector.ts new file mode 100644 index 00000000..aec75bc9 --- /dev/null +++ b/src/pagesView/state/selectors/MediaFoldersSelector.ts @@ -0,0 +1,9 @@ +import { selector } from 'recoil'; +import { MediaFoldersAtom } from '..'; + +export const MediaFoldersSelector = selector({ + key: 'MediaFoldersSelector', + get: ({get}) => { + return get(MediaFoldersAtom); + } +}); \ No newline at end of file diff --git a/src/pagesView/state/selectors/MediaTotalSelector.ts b/src/pagesView/state/selectors/MediaTotalSelector.ts new file mode 100644 index 00000000..2a7452ab --- /dev/null +++ b/src/pagesView/state/selectors/MediaTotalSelector.ts @@ -0,0 +1,9 @@ +import { selector } from 'recoil'; +import { MediaTotalAtom } from '..'; + +export const MediaTotalSelector = selector({ + key: 'MediaTotalSelector', + get: ({get}) => { + return get(MediaTotalAtom); + } +}); \ No newline at end of file diff --git a/src/pagesView/state/selectors/SelectedMediaFolderSelector.ts b/src/pagesView/state/selectors/SelectedMediaFolderSelector.ts new file mode 100644 index 00000000..7683214d --- /dev/null +++ b/src/pagesView/state/selectors/SelectedMediaFolderSelector.ts @@ -0,0 +1,9 @@ +import { selector } from 'recoil'; +import { SelectedMediaFolderAtom } from '..'; + +export const SelectedMediaFolderSelector = selector({ + key: 'SelectedMediaFolderSelector', + get: ({get}) => { + return get(SelectedMediaFolderAtom); + } +}); \ No newline at end of file diff --git a/src/pagesView/state/selectors/index.ts b/src/pagesView/state/selectors/index.ts index 805935a0..21113f17 100644 --- a/src/pagesView/state/selectors/index.ts +++ b/src/pagesView/state/selectors/index.ts @@ -2,7 +2,10 @@ export * from './CategorySelector'; export * from './DashboardViewSelector'; export * from './FolderSelector'; export * from './GroupingSelector'; +export * from './MediaFoldersSelector'; +export * from './MediaTotalSelector'; export * from './SearchSelector'; +export * from './SelectedMediaFolderSelector'; export * from './SettingsSelector'; export * from './SortingSelector'; export * from './TabSelector';