Added media refresh + spinner

This commit is contained in:
Elio Struyf
2021-09-08 16:18:26 +02:00
parent 2769eb9b71
commit 40646fd1b3
14 changed files with 84 additions and 26 deletions

View File

@@ -3,6 +3,7 @@
## [3.1.0] - (Upcoming release)
- BETA version available at: [beta.frontmatter.codes](https://beta.frontmatter.codes)
- [#72](https://github.com/estruyf/vscode-front-matter/issues/72): Media view on the dashboard
- [#73](https://github.com/estruyf/vscode-front-matter/issues/73): List view option for the dashboard
- [#77](https://github.com/estruyf/vscode-front-matter/issues/77): Dashboard grouping pages functionality integrated
- [#81](https://github.com/estruyf/vscode-front-matter/issues/81): Optimizing the content folders to use a new setting to simplify configuration
@@ -10,6 +11,7 @@
- [#88](https://github.com/estruyf/vscode-front-matter/issues/88): Fix issue with search sorting
- [#89](https://github.com/estruyf/vscode-front-matter/issues/89): Clear filter, sorting, and grouping button added
- [#90](https://github.com/estruyf/vscode-front-matter/issues/90): Refactoring to use Recoil state management
- [#91](https://github.com/estruyf/vscode-front-matter/issues/91): Support image previews from content folders
## [3.0.2] - 2021-08-31

View File

@@ -138,6 +138,10 @@ export class Dashboard {
case DashboardMessage.copyToClipboard:
env.clipboard.writeText(msg.data);
break;
case DashboardMessage.refreshMedia:
Dashboard.media = [];
Dashboard.getMedia(0, msg?.data?.folder);
break;
}
});
}
@@ -153,6 +157,7 @@ export class Dashboard {
Dashboard.postWebviewMessage({
command: DashboardCommand.settings,
data: {
beta: ext.isBetaVersion(),
wsFolder: wsFolder ? wsFolder.fsPath : '',
staticFolder: config.get<string>(SETTINGS_CONTENT_STATIC_FOLDERS),
folders: Folders.get(),

View File

@@ -9,4 +9,5 @@ export enum DashboardMessage {
setPageViewType = 'setPageViewType',
getMedia = 'getMedia',
copyToClipboard = 'copyToClipboard',
refreshMedia = 'refreshMedia',
}

View File

@@ -29,7 +29,7 @@ export const Contents: React.FunctionComponent<IContentsProps> = ({pages, loadin
{ loading ? <Spinner /> : <Overview pages={pages} settings={settings} /> }
</div>
<SponsorMsg version={settings?.versionInfo} />
<SponsorMsg beta={settings?.beta} version={settings?.versionInfo} />
</div>
</main>
);

View File

@@ -1,5 +1,5 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { ClipboardCopyIcon, FolderIcon, PhotographIcon } from '@heroicons/react/outline';
import { ClipboardCopyIcon } from '@heroicons/react/outline';
import { basename, dirname } from 'path';
import * as React from 'react';
import { useRecoilValue } from 'recoil';
@@ -69,12 +69,12 @@ export const Item: React.FunctionComponent<IItemProps> = ({media}: React.PropsWi
{basename(media.fsPath)}
</p>
<p className="mt-2 text-sm dark:text-whisper-900 font-medium pointer-events-none flex items-center">
<FolderIcon className={`w-5 h-5 mr-1`} /> {getFolder()}
<b className={`mr-2`}>Folder:</b> {getFolder()}
</p>
{
media?.stats?.size && (
<p className="mt-2 text-sm dark:text-whisper-900 font-medium pointer-events-none flex items-center">
{calculateSize()}
<b className={`mr-1`}>Size:</b> {calculateSize()}
</p>
)
}

View File

@@ -1,10 +1,13 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { EventData } from '@estruyf/vscode/dist/models';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { MediaInfo, MediaPaths } from '../../../models/MediaPaths';
import { DashboardCommand } from '../../DashboardCommand';
import { MediaFoldersAtom, MediaTotalAtom, SettingsSelector } from '../../state';
import { LoadingAtom, MediaFoldersAtom, MediaTotalAtom, SettingsSelector } from '../../state';
import { Header } from '../Header';
import { Spinner } from '../Spinner';
import { SponsorMsg } from '../SponsorMsg';
import { Item } from './Item';
import { List } from './List';
@@ -17,15 +20,23 @@ export const Media: React.FunctionComponent<IMediaProps> = (props: React.PropsWi
const [ media, setMedia ] = React.useState<MediaInfo[]>([]);
const [ , setTotal ] = useRecoilState(MediaTotalAtom);
const [ , setFolders ] = useRecoilState(MediaFoldersAtom);
const [ loading, setLoading ] = useRecoilState(LoadingAtom);
const messageListener = (message: MessageEvent<EventData<MediaPaths>>) => {
if (message.data.command === DashboardCommand.media) {
setLoading(false);
setMedia(message.data.data.media);
setTotal(message.data.data.total);
setFolders(message.data.data.folders);
}
}
React.useEffect(() => {
Messenger.listen<MediaPaths>((message) => {
if (message.command === DashboardCommand.media) {
setMedia(message.data.media);
setTotal(message.data.total);
setFolders(message.data.folders);
}
});
Messenger.listen<MediaPaths>(messageListener);
return () => {
Messenger.unlisten(messageListener);
}
}, ['']);
return (
@@ -33,7 +44,7 @@ export const Media: React.FunctionComponent<IMediaProps> = (props: React.PropsWi
<div className="flex flex-col h-full overflow-auto">
<Header settings={settings} />
<div className="w-full max-w-7xl mx-auto py-6 px-4">
<div className="w-full flex-grow max-w-7xl mx-auto py-6 px-4">
<List>
{
media.map((file) => (
@@ -42,6 +53,12 @@ export const Media: React.FunctionComponent<IMediaProps> = (props: React.PropsWi
}
</List>
</div>
{
loading && ( <Spinner /> )
}
<SponsorMsg beta={settings?.beta} version={settings?.versionInfo} />
</div>
</main>
);

View File

@@ -1,8 +1,9 @@
import { Messenger } from '@estruyf/vscode/dist/client';
import { RefreshIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { DashboardMessage } from '../../DashboardMessage';
import { MediaTotalSelector, SelectedMediaFolderSelector } from '../../state';
import { LoadingAtom, MediaTotalSelector, SelectedMediaFolderSelector } from '../../state';
import { FolderSelection } from './FolderSelection';
import { LIMIT } from './Media';
import { PaginationButton } from './PaginationButton';
@@ -12,6 +13,7 @@ export interface IPaginationProps {}
export const Pagination: React.FunctionComponent<IPaginationProps> = ({}: React.PropsWithChildren<IPaginationProps>) => {
const selectedFolder = useRecoilValue(SelectedMediaFolderSelector);
const totalMedia = useRecoilValue(MediaTotalSelector);
const [ , setLoading ] = useRecoilState(LoadingAtom);
const [ page, setPage ] = React.useState<number>(0);
const totalPages = Math.ceil(totalMedia / LIMIT) - 1;
@@ -39,9 +41,13 @@ export const Pagination: React.FunctionComponent<IPaginationProps> = ({}: React.
return buttons;
};
const buttons = getButtons();
const refresh = () => {
setPage(0);
Messenger.send(DashboardMessage.refreshMedia, { folder: selectedFolder });
}
React.useEffect(() => {
setLoading(true);
Messenger.send(DashboardMessage.getMedia, {
page,
folder: selectedFolder || ''
@@ -49,6 +55,7 @@ export const Pagination: React.FunctionComponent<IPaginationProps> = ({}: React.
}, [page]);
React.useEffect(() => {
setLoading(true);
Messenger.send(DashboardMessage.getMedia, {
page: 0,
folder: selectedFolder || ''
@@ -61,7 +68,14 @@ export const Pagination: React.FunctionComponent<IPaginationProps> = ({}: React.
className="py-4 px-5 flex items-center justify-between bg-gray-200 border-b border-gray-300 dark:bg-vulcan-400 dark:border-vulcan-100"
aria-label="Pagination"
>
<div className="hidden sm:block">
<div className="hidden sm:flex">
<button className={`mr-2 text-gray-500 hover:text-gray-600 dark:text-whisper-900 dark:hover:text-whisper-500`}
title="Refresh media"
onClick={refresh}>
<RefreshIcon className={`h-5 w-5`} />
<span className="sr-only">Refresh media</span>
</button>
<p className="text-sm text-gray-500 dark:text-whisper-900">
Showing <span className="font-medium">{(page * LIMIT) + 1}</span> to <span className="font-medium">{getTotalPage()}</span> of{' '}
<span className="font-medium">{totalMedia}</span> results
@@ -89,7 +103,7 @@ export const Pagination: React.FunctionComponent<IPaginationProps> = ({}: React.
}
}} />
{buttons.map((button) => (
{getButtons().map((button) => (
<button
key={button}
disabled={button === page}

View File

@@ -4,16 +4,17 @@ import { REVIEW_LINK, SPONSOR_LINK } from '../../constants/Links';
import { VersionInfo } from '../../models';
export interface ISponsorMsgProps {
beta: boolean | undefined;
version: VersionInfo | undefined;
}
export const SponsorMsg: React.FunctionComponent<ISponsorMsgProps> = ({version}: React.PropsWithChildren<ISponsorMsgProps>) => {
export const SponsorMsg: React.FunctionComponent<ISponsorMsgProps> = ({beta, version}: React.PropsWithChildren<ISponsorMsgProps>) => {
return (
<p className={`w-full max-w-7xl mx-auto px-4 text-vulcan-50 dark:text-whisper-900 py-2 text-center space-x-8 flex items-center justify-between`}>
<a className={`group inline-flex justify-center items-center space-x-2 text-vulcan-500 dark:text-whisper-500 hover:text-vulcan-600 dark:hover:text-whisper-300 opacity-50 hover:opacity-100`} href={SPONSOR_LINK} title="Sponsor Front Matter">
<span>Sponsor</span> <HeartIcon className={`h-5 w-5 group-hover:fill-current`} />
</a>
<span>FrontMatter{version ? ` (v${version.installedVersion})` : ''}</span>
<span>Front Matter{version ? ` (v${version.installedVersion}${!!beta ? ` BETA` : ''})` : ''}</span>
<a className={`group inline-flex justify-center items-center space-x-2 text-vulcan-500 dark:text-whisper-500 hover:text-vulcan-600 dark:hover:text-whisper-300 opacity-50 hover:opacity-100`} href={REVIEW_LINK} title="Review Front Matter">
<StarIcon className={`h-5 w-5 group-hover:fill-current`} /> <span>Review</span>
</a>

View File

@@ -12,16 +12,16 @@ export default function useMessages() {
const [pages, setPages] = useState<Page[]>([]);
const [settings, setSettings] = useRecoilState(SettingsAtom);
Messenger.listen((message: EventData<any>) => {
switch (message.command) {
Messenger.listen((message: MessageEvent<EventData<any>>) => {
switch (message.data.command) {
case DashboardCommand.loading:
setLoading(message.data);
setLoading(message.data.data);
break;
case DashboardCommand.settings:
setSettings(message.data);
setSettings(message.data.data);
break;
case DashboardCommand.pages:
setPages(message.data);
setPages(message.data.data);
setLoading(false);
break;
}

View File

@@ -3,10 +3,11 @@ import { ViewType } from '../state';
import { ContentFolder } from './../../models/ContentFolder';
export interface Settings {
beta: boolean;
initialized: boolean;
wsFolder: string;
staticFolder: string;
folders: ContentFolder[];
initialized: boolean
tags: string[];
categories: string[];
openOnStart: boolean | null;

View File

@@ -0,0 +1,6 @@
import { atom } from 'recoil';
export const LoadingAtom = atom<boolean>({
key: 'LoadingAtom',
default: false
});

View File

@@ -2,6 +2,7 @@ export * from './CategoryAtom';
export * from './DashboardViewAtom';
export * from './FolderAtom';
export * from './GroupingAtom';
export * from './LoadingAtom';
export * from './MediaFoldersAtom';
export * from './MediaTotalAtom';
export * from './SearchAtom';

View File

@@ -0,0 +1,9 @@
import { selector } from 'recoil';
import { LoadingAtom } from '..';
export const LoadingSelector = selector({
key: 'LoadingSelector',
get: ({get}) => {
return get(LoadingAtom);
}
});

View File

@@ -2,6 +2,7 @@ export * from './CategorySelector';
export * from './DashboardViewSelector';
export * from './FolderSelector';
export * from './GroupingSelector';
export * from './LoadingSelector';
export * from './MediaFoldersSelector';
export * from './MediaTotalSelector';
export * from './SearchSelector';