mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 11:06:25 +08:00
Merge branch 'develop' into feature/remove-react-fc
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
/* eslint-disable filename-rules/match */
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { IconButton, MuiSnackbar, styled } from '@toeverything/components/ui';
|
||||
import { services } from '@toeverything/datasource/db-service';
|
||||
import { useLocalTrigger } from '@toeverything/datasource/state';
|
||||
import { CloseIcon } from '@toeverything/components/common';
|
||||
|
||||
const cleanupWorkspace = (workspace: string) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const req = indexedDB.deleteDatabase(workspace);
|
||||
req.addEventListener('error', e => reject(e));
|
||||
req.addEventListener('blocked', e => reject(e));
|
||||
req.addEventListener('upgradeneeded', e => reject(e));
|
||||
req.addEventListener('success', e => resolve(e));
|
||||
});
|
||||
|
||||
const requestPermission = async (workspace: string) => {
|
||||
await cleanupWorkspace(workspace);
|
||||
// @ts-ignore
|
||||
const dirHandler = await window.showDirectoryPicker({
|
||||
id: 'AFFiNE_' + workspace,
|
||||
mode: 'readwrite',
|
||||
startIn: 'documents',
|
||||
});
|
||||
|
||||
const fileHandle = await dirHandler.getFileHandle('affine.db', {
|
||||
create: true,
|
||||
});
|
||||
const file = await fileHandle.getFile();
|
||||
const initialData = new Uint8Array(await file.arrayBuffer());
|
||||
|
||||
const exporter = async (contents: Uint8Array) => {
|
||||
try {
|
||||
const writable = await fileHandle.createWritable();
|
||||
await writable.write(contents);
|
||||
await writable.close();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
await services.api.editorBlock.setupDataExporter(
|
||||
workspace,
|
||||
new Uint8Array(initialData),
|
||||
exporter
|
||||
);
|
||||
};
|
||||
|
||||
const StyledFileSystem = styled('div')<{ disabled?: boolean }>({
|
||||
padding: '10px 12px',
|
||||
fontWeight: 600,
|
||||
fontSize: '14px',
|
||||
color: '#3E6FDB',
|
||||
textTransform: 'uppercase',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
background: '#F5F7F8',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
});
|
||||
|
||||
export const fsApiSupported = () => {
|
||||
try {
|
||||
return 'showOpenFilePicker' in window;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const FileSystem = () => {
|
||||
const [selected, onSelected] = useLocalTrigger();
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
const onError = useCallback(() => {
|
||||
setError(true);
|
||||
setTimeout(() => setError(false), 3000);
|
||||
}, []);
|
||||
|
||||
const apiSupported = useMemo(() => fsApiSupported(), []);
|
||||
|
||||
if (apiSupported && !selected) {
|
||||
return (
|
||||
<>
|
||||
<MuiSnackbar
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||
open={error}
|
||||
message="Request File Permission failed, please check if you have permission"
|
||||
sx={{ marginTop: '3em' }}
|
||||
action={
|
||||
<IconButton
|
||||
aria-label="close"
|
||||
onClick={() => setError(false)}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
}
|
||||
/>
|
||||
<StyledFileSystem
|
||||
onClick={async () => {
|
||||
try {
|
||||
await requestPermission('AFFiNE');
|
||||
onSelected();
|
||||
} catch (e) {
|
||||
onError();
|
||||
}
|
||||
}}
|
||||
>
|
||||
Sync to Disk
|
||||
</StyledFileSystem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -1,19 +1,36 @@
|
||||
import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { IconButton, styled } from '@toeverything/components/ui';
|
||||
import {
|
||||
LogoIcon,
|
||||
SideBarViewIcon,
|
||||
SearchIcon,
|
||||
SideBarViewCloseIcon,
|
||||
} from '@toeverything/components/icons';
|
||||
import { useShowSettingsSidebar } from '@toeverything/datasource/state';
|
||||
import {
|
||||
useShowSettingsSidebar,
|
||||
useLocalTrigger,
|
||||
} from '@toeverything/datasource/state';
|
||||
|
||||
import { CurrentPageTitle } from './Title';
|
||||
import { EditorBoardSwitcher } from './EditorBoardSwitcher';
|
||||
import { fsApiSupported, FileSystem } from './FileSystem';
|
||||
import { CurrentPageTitle } from './Title';
|
||||
|
||||
export const LayoutHeader = () => {
|
||||
const [isLocalWorkspace] = useLocalTrigger();
|
||||
const { toggleSettingsSidebar: toggleInfoSidebar, showSettingsSidebar } =
|
||||
useShowSettingsSidebar();
|
||||
|
||||
const warningTips = useMemo(() => {
|
||||
if (!fsApiSupported()) {
|
||||
return 'Your browser does not support the local storage feature, please upgrade to the latest version of Chrome or Edge browser';
|
||||
} else if (!isLocalWorkspace) {
|
||||
return 'You are in DEMO mode. Changes will NOT be saved unless you SYNC TO DISK';
|
||||
} else {
|
||||
return 'AFFiNE is under active development and the current version is UNSTABLE. Please DO NOT store information or data';
|
||||
}
|
||||
}, [isLocalWorkspace]);
|
||||
|
||||
return (
|
||||
<StyledContainerForHeaderRoot>
|
||||
<StyledHeaderRoot>
|
||||
@@ -25,6 +42,7 @@ export const LayoutHeader = () => {
|
||||
</FlexContainer>
|
||||
<FlexContainer>
|
||||
<StyledHelper>
|
||||
<FileSystem />
|
||||
<StyledShare disabled={true}>Share</StyledShare>
|
||||
<div style={{ margin: '0px 12px' }}>
|
||||
<IconButton
|
||||
@@ -51,10 +69,7 @@ export const LayoutHeader = () => {
|
||||
</StyledContainerForEditorBoardSwitcher>
|
||||
</StyledHeaderRoot>
|
||||
<StyledUnstableTips>
|
||||
<StyledUnstableTipsText>
|
||||
AFFiNE now under active development, the version is
|
||||
UNSTABLE, please DO NOT store important data in this version
|
||||
</StyledUnstableTipsText>
|
||||
<StyledUnstableTipsText>{warningTips}</StyledUnstableTipsText>
|
||||
</StyledUnstableTips>
|
||||
</StyledContainerForHeaderRoot>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user