feat: export page as file (#2923)

This commit is contained in:
xiaodong zuo
2023-06-30 05:58:02 +08:00
committed by GitHub
parent 8a7908c692
commit bc3ce7395e
4 changed files with 121 additions and 63 deletions
+1 -3
View File
@@ -1,4 +1,4 @@
import { BrowserWindow, dialog, shell } from 'electron'; import { BrowserWindow, dialog } from 'electron';
import fs from 'fs-extra'; import fs from 'fs-extra';
import { logger } from '../logger'; import { logger } from '../logger';
@@ -49,8 +49,6 @@ export async function savePDFFileAs(
logger.log(`Wrote PDF successfully to ${filePath}`); logger.log(`Wrote PDF successfully to ${filePath}`);
}); });
}); });
await shell.openPath(filePath);
return { filePath }; return { filePath };
} catch (err) { } catch (err) {
logger.error('savePDFFileAs', err); logger.error('savePDFFileAs', err);
@@ -1,6 +1,7 @@
import { Content, displayFlex } from '@affine/component'; import { Content, displayFlex } from '@affine/component';
import { AffineWatermark } from '@affine/component/affine-watermark'; import { AffineWatermark } from '@affine/component/affine-watermark';
import { appSidebarResizingAtom } from '@affine/component/app-sidebar'; import { appSidebarResizingAtom } from '@affine/component/app-sidebar';
import { NotificationCenter } from '@affine/component/notification-center';
import type { DraggableTitleCellData } from '@affine/component/page-list'; import type { DraggableTitleCellData } from '@affine/component/page-list';
import { StyledTitleLink } from '@affine/component/page-list'; import { StyledTitleLink } from '@affine/component/page-list';
import { import {
@@ -444,6 +445,7 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
<PageListTitleCellDragOverlay /> <PageListTitleCellDragOverlay />
</DndContext> </DndContext>
<QuickSearch /> <QuickSearch />
<NotificationCenter />
<Setting /> <Setting />
</> </>
); );
@@ -1,3 +1,4 @@
import { pushNotificationAtom } from '@affine/component/notification-center';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { PageBlockModel } from '@blocksuite/blocks'; import type { PageBlockModel } from '@blocksuite/blocks';
import { ContentParser } from '@blocksuite/blocks/content-parser'; import { ContentParser } from '@blocksuite/blocks/content-parser';
@@ -7,7 +8,9 @@ import {
ExportToHtmlIcon, ExportToHtmlIcon,
ExportToMarkdownIcon, ExportToMarkdownIcon,
ExportToPdfIcon, ExportToPdfIcon,
ExportToPngIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import { useSetAtom } from 'jotai';
import { useCallback, useRef } from 'react'; import { useCallback, useRef } from 'react';
import { Menu, MenuItem } from '../../..'; import { Menu, MenuItem } from '../../..';
@@ -19,43 +22,73 @@ const ExportToPdfMenuItem = ({
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const contentParserRef = useRef<ContentParser>(); const contentParserRef = useRef<ContentParser>();
const { currentEditor } = globalThis; const { currentEditor } = globalThis;
const setPushNotification = useSetAtom(pushNotificationAtom);
const onClickDownloadPDF = useCallback(() => { const onClickDownloadPDF = useCallback(() => {
if (!currentEditor) { if (!currentEditor) {
return; return;
} }
const contentParser =
contentParserRef.current ??
(contentParserRef.current = new ContentParser(currentEditor.page));
window.apis?.export if (environment.isDesktop && currentEditor.mode === 'page') {
.savePDFFileAs( window.apis?.export
(currentEditor.page.root as PageBlockModel).title.toString() .savePDFFileAs(
) (currentEditor.page.root as PageBlockModel).title.toString()
.then(result => { )
if (result !== undefined) { .then(() => {
return; onSelect?.({ type: 'pdf' });
} setPushNotification({
return contentParser.exportPdf(); key: 'export-to-pdf',
}) title: 'export',
.then(() => { message: 'Export success',
onSelect?.({ type: 'pdf' }); type: 'success',
}) });
.catch(err => { })
console.error(err); .catch(err => {
}); console.error(err);
}, [currentEditor, onSelect]); setPushNotification({
if (currentEditor && currentEditor.mode === 'page') { key: 'export-to-pdf',
return ( title: 'export',
<MenuItem message: 'Export error',
data-testid="export-to-pdf" type: 'error',
onClick={onClickDownloadPDF} });
icon={<ExportToPdfIcon />} });
> } else {
{t['Export to PDF']()} const contentParser =
</MenuItem> contentParserRef.current ??
); (contentParserRef.current = new ContentParser(currentEditor.page));
}
return null; contentParser
.exportPdf()
.then(() => {
onSelect?.({ type: 'pdf' });
setPushNotification({
key: 'export-to-pdf',
title: 'export',
message: 'Export success',
type: 'success',
});
})
.catch(err => {
console.error(err);
setPushNotification({
key: 'export-to-pdf',
title: 'export',
message: 'Export error',
type: 'error',
});
});
}
}, [currentEditor, onSelect, setPushNotification]);
return (
<MenuItem
data-testid="export-to-pdf"
onClick={onClickDownloadPDF}
icon={<ExportToPdfIcon />}
>
{t['Export to PDF']()}
</MenuItem>
);
}; };
const ExportToHtmlMenuItem = ({ const ExportToHtmlMenuItem = ({
@@ -89,33 +122,56 @@ const ExportToHtmlMenuItem = ({
); );
}; };
// const ExportToPngMenuItem = ({ const ExportToPngMenuItem = ({
// onSelect, onSelect,
// }: CommonMenuItemProps<{ type: 'png' }>) => { }: CommonMenuItemProps<{ type: 'png' }>) => {
// const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
// const contentParserRef = useRef<ContentParser>(); const contentParserRef = useRef<ContentParser>();
// return ( const { currentEditor } = globalThis;
// <> const setPushNotification = useSetAtom(pushNotificationAtom);
// {globalThis.currentEditor!.mode === 'page' && (
// <MenuItem const onClickDownloadPNG = useCallback(() => {
// data-testid="export-to-png" if (!currentEditor) {
// onClick={() => { return;
// if (!contentParserRef.current) { }
// contentParserRef.current = new ContentParser( const contentParser =
// globalThis.currentEditor!.page contentParserRef.current ??
// ); (contentParserRef.current = new ContentParser(currentEditor.page));
// }
// contentParserRef.current.exportPng(); contentParser
// onSelect?.({ type: 'png' }); .exportPng()
// }} .then(() => {
// icon={<ExportToPngIcon />} onSelect?.({ type: 'png' });
// > setPushNotification({
// {t['Export to PNG']()} key: 'export-to-pdf',
// </MenuItem> title: 'export',
// )} message: 'Export success',
// </> type: 'success',
// ); });
// }; })
.catch(err => {
console.error(err);
setPushNotification({
key: 'export-to-pdf',
title: 'export',
message: 'Export error',
type: 'error',
});
});
}, [currentEditor, onSelect, setPushNotification]);
return (
<>
<MenuItem
data-testid="export-to-png"
onClick={onClickDownloadPNG}
icon={<ExportToPngIcon />}
>
{t['Export to PNG']()}
</MenuItem>
</>
);
};
const ExportToMarkdownMenuItem = ({ const ExportToMarkdownMenuItem = ({
onSelect, onSelect,
@@ -161,7 +217,7 @@ export const Export = ({
<> <>
<ExportToPdfMenuItem></ExportToPdfMenuItem> <ExportToPdfMenuItem></ExportToPdfMenuItem>
<ExportToHtmlMenuItem></ExportToHtmlMenuItem> <ExportToHtmlMenuItem></ExportToHtmlMenuItem>
{/* <ExportToPngMenuItem></ExportToPngMenuItem> */} <ExportToPngMenuItem></ExportToPngMenuItem>
<ExportToMarkdownMenuItem></ExportToMarkdownMenuItem> <ExportToMarkdownMenuItem></ExportToMarkdownMenuItem>
</> </>
} }
@@ -65,6 +65,8 @@ export const mainContainerStyle = style({
'@media': { '@media': {
print: { print: {
overflow: 'visible', overflow: 'visible',
margin: '0px',
borderRadius: '0px',
}, },
}, },
}, },