mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-03-28 17:42:40 +01:00
Added media refresh + spinner
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -9,4 +9,5 @@ export enum DashboardMessage {
|
||||
setPageViewType = 'setPageViewType',
|
||||
getMedia = 'getMedia',
|
||||
copyToClipboard = 'copyToClipboard',
|
||||
refreshMedia = 'refreshMedia',
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
6
src/pagesView/state/atom/LoadingAtom.ts
Normal file
6
src/pagesView/state/atom/LoadingAtom.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const LoadingAtom = atom<boolean>({
|
||||
key: 'LoadingAtom',
|
||||
default: false
|
||||
});
|
||||
@@ -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';
|
||||
|
||||
9
src/pagesView/state/selectors/LoadingSelector.ts
Normal file
9
src/pagesView/state/selectors/LoadingSelector.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { selector } from 'recoil';
|
||||
import { LoadingAtom } from '..';
|
||||
|
||||
export const LoadingSelector = selector({
|
||||
key: 'LoadingSelector',
|
||||
get: ({get}) => {
|
||||
return get(LoadingAtom);
|
||||
}
|
||||
});
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user