fix: add @typescript-eslint/no-floating-promises rule (#2764)

Co-authored-by: himself65 <himself65@outlook.com>
This commit is contained in:
LongYinan 2023-06-13 14:55:23 +08:00 committed by GitHub
parent bbac03107e
commit 1c8f1a05d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 342 additions and 239 deletions

View File

@ -152,6 +152,27 @@ const config = {
'@typescript-eslint/no-var-requires': 0,
},
},
...allPackages.map(pkg => ({
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
parserOptions: {
project: resolve(__dirname, './tsconfig.eslint.json'),
},
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
patterns: createPattern(pkg),
},
],
'@typescript-eslint/no-floating-promises': [
'error',
{
ignoreVoid: false,
ignoreIIFE: false,
},
],
},
})),
{
files: [
'**/__tests__/**/*',
@ -173,19 +194,9 @@ const config = {
'ts-check': false,
},
],
'@typescript-eslint/no-floating-promises': 0,
},
},
...allPackages.map(pkg => ({
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
patterns: createPattern(pkg),
},
],
},
})),
],
};

View File

@ -110,7 +110,9 @@ export async function saveDBFileAs(
await fs.copyFile(db.path, filePath);
logger.log('saved', filePath);
mainRPC.showItemInFolder(filePath);
mainRPC.showItemInFolder(filePath).catch(err => {
console.error(err);
});
return { filePath };
} catch (err) {
logger.error('saveDBFileAs', err);

View File

@ -64,7 +64,9 @@ function setupRendererConnection(rendererPort: Electron.MessagePortMain) {
for (const [key, eventRegister] of Object.entries(namespaceEvents)) {
const subscription = eventRegister((...args: any[]) => {
const chan = `${namespace}:${key}`;
rpc.postEvent(chan, ...args);
rpc.postEvent(chan, ...args).catch(err => {
console.error(err);
});
});
process.on('exit', () => {
subscription();

View File

@ -15,8 +15,8 @@ AsyncCall(commandProxy, {
channel: new MessageEventChannel(parentPort),
});
import('@toeverything/plugin-infra/manager').then(
({ rootStore, affinePluginsAtom }) => {
import('@toeverything/plugin-infra/manager')
.then(({ rootStore, affinePluginsAtom }) => {
const bookmarkPluginPath = join(
process.env.PLUGIN_DIR ?? resolve(__dirname, '../plugins'),
'./bookmark-block/index.mjs'
@ -39,5 +39,7 @@ import('@toeverything/plugin-infra/manager').then(
}
});
});
}
);
})
.catch(err => {
console.error(err);
});

View File

@ -50,4 +50,6 @@ import { contextBridge, ipcRenderer } from 'electron';
} catch (error) {
console.error('Failed to expose affine APIs to window object!', error);
}
})();
})().catch(err => {
console.error('Failed to bootstrap preload script!', err);
});

View File

@ -75,7 +75,9 @@ export function useHistoryAtom() {
if (forward) {
const target = Math.min(prev.stack.length - 1, prev.current + 1);
const url = prev.stack[target];
void router.push(url);
router.push(url).catch(err => {
console.error(err);
});
return {
...prev,
current: target,
@ -84,7 +86,9 @@ export function useHistoryAtom() {
} else {
const target = Math.max(0, prev.current - 1);
const url = prev.stack[target];
void router.push(url);
router.push(url).catch(err => {
console.error(err);
});
return {
...prev,
current: target,

View File

@ -49,19 +49,24 @@ rootWorkspacesMetadataAtom.onMount = setAtom => {
}, 0);
if (environment.isDesktop) {
window.apis?.workspace.list().then(workspaceIDs => {
if (abortController.signal.aborted) return;
const newMetadata = workspaceIDs.map(w => ({
id: w[0],
flavour: WorkspaceFlavour.LOCAL,
}));
setAtom(metadata => {
return [
...metadata,
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
];
window.apis?.workspace
.list()
.then(workspaceIDs => {
if (abortController.signal.aborted) return;
const newMetadata = workspaceIDs.map(w => ({
id: w[0],
flavour: WorkspaceFlavour.LOCAL,
}));
setAtom(metadata => {
return [
...metadata,
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
];
});
})
.catch(err => {
console.error(err);
});
});
}
return () => {

View File

@ -116,9 +116,14 @@ const useDefaultDBLocation = () => {
const [defaultDBLocation, setDefaultDBLocation] = useState('');
useEffect(() => {
window.apis?.db.getDefaultStorageLocation().then(dir => {
setDefaultDBLocation(dir);
});
window.apis?.db
.getDefaultStorageLocation()
.then(dir => {
setDefaultDBLocation(dir);
})
.catch(err => {
console.error(err);
});
}, []);
return defaultDBLocation;
@ -281,7 +286,9 @@ export const CreateWorkspaceModal = ({
}
onClose();
}
})();
})().catch(err => {
console.error(err);
});
} else if (mode === 'new') {
setStep(environment.isDesktop ? 'set-db-location' : 'name-workspace');
} else {

View File

@ -12,7 +12,7 @@ import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-s
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import clsx from 'clsx';
import type React from 'react';
import { useEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useIsWorkspaceOwner } from '../../../../../hooks/affine/use-is-workspace-owner';
import { Upload } from '../../../../pure/file-upload';
@ -27,9 +27,14 @@ const useShowOpenDBFile = (workspaceId: string) => {
const [show, setShow] = useState(false);
useEffect(() => {
if (window.apis && window.events && environment.isDesktop) {
window.apis.workspace.getMeta(workspaceId).then(meta => {
setShow(!!meta.secondaryDBPath);
});
window.apis.workspace
.getMeta(workspaceId)
.then(meta => {
setShow(!!meta.secondaryDBPath);
})
.catch(err => {
console.error(err);
});
return window.events.workspace.onMetaChange((newMeta: any) => {
if (newMeta.workspaceId === workspaceId) {
const meta = newMeta.meta;
@ -54,35 +59,11 @@ export const GeneralPanel: React.FC<PanelProps> = ({
const isOwner = useIsWorkspaceOwner(workspace);
const t = useAFFiNEI18N();
const showOpenFolder = useShowOpenDBFile(workspace.id);
const handleUpdateWorkspaceName = (name: string) => {
setName(name);
toast(t['Update workspace name success']());
};
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
const handleMoveTo = async () => {
if (moveToInProgress) {
return;
}
try {
setMoveToInProgress(true);
const result = await window.apis?.dialog.moveDBFile(workspace.id);
if (!result?.error && !result?.canceled) {
toast(t['Move folder success']());
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
}
} catch (err) {
toast(t['UNKNOWN_ERROR']());
} finally {
setMoveToInProgress(false);
}
};
const [, update] = useBlockSuiteWorkspaceAvatarUrl(
workspace.blockSuiteWorkspace
);
@ -137,9 +118,7 @@ export const GeneralPanel: React.FC<PanelProps> = ({
placeholder={t['Workspace Name']()}
maxLength={64}
minLength={0}
onChange={newName => {
setInput(newName);
}}
onChange={setInput}
></StyledInput>
</div>
@ -158,63 +137,7 @@ export const GeneralPanel: React.FC<PanelProps> = ({
</Button>
</div>
</div>
{environment.isDesktop && (
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>
{t['Storage Folder']()}
</div>
<div className={style.settingItemLabelHint}>
{t['Storage Folder Hint']()}
</div>
</div>
<div className={style.col}>
{showOpenFolder && (
<div
className={style.storageTypeWrapper}
onClick={() => {
if (environment.isDesktop) {
window.apis?.dialog.revealDBFile(workspace.id);
}
}}
>
<FolderIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>
{t['Open folder']()}
</div>
<div className={style.storageTypeLabelHint}>
{t['Open folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
)}
<div
data-testid="move-folder"
data-disabled={moveToInProgress}
className={style.storageTypeWrapper}
onClick={handleMoveTo}
>
<MoveToIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>
{t['Move folder']()}
</div>
<div className={style.storageTypeLabelHint}>
{t['Move folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
</div>
<div className={style.col}></div>
</div>
)}
<DesktopClientOnly workspaceId={workspace.id} />
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>
@ -273,3 +196,81 @@ export const GeneralPanel: React.FC<PanelProps> = ({
</>
);
};
function DesktopClientOnly({ workspaceId }: { workspaceId: string }) {
const t = useAFFiNEI18N();
const showOpenFolder = useShowOpenDBFile(workspaceId);
const onRevealDBFile = useCallback(() => {
if (environment.isDesktop) {
window.apis?.dialog.revealDBFile(workspaceId).catch(err => {
console.error(err);
});
}
}, [workspaceId]);
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
const handleMoveTo = useCallback(() => {
if (moveToInProgress) {
return;
}
setMoveToInProgress(true);
window.apis?.dialog
.moveDBFile(workspaceId)
.then(result => {
if (!result?.error && !result?.canceled) {
toast(t['Move folder success']());
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
}
})
.catch(() => {
toast(t['UNKNOWN_ERROR']());
})
.finally(() => {
setMoveToInProgress(false);
});
}, [moveToInProgress, t, workspaceId]);
const openFolderNode = showOpenFolder ? (
<div className={style.storageTypeWrapper} onClick={onRevealDBFile}>
<FolderIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>{t['Open folder']()}</div>
<div className={style.storageTypeLabelHint}>
{t['Open folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
) : null;
return (
<div className={style.row}>
<div className={style.col}>
<div className={style.settingItemLabel}>{t['Storage Folder']()}</div>
<div className={style.settingItemLabelHint}>
{t['Storage Folder Hint']()}
</div>
</div>
<div className={style.col}>
{openFolderNode}
<div
data-testid="move-folder"
data-disabled={moveToInProgress}
className={style.storageTypeWrapper}
onClick={handleMoveTo}
>
<MoveToIcon color="var(--affine-primary-color)" />
<div className={style.storageTypeLabelWrapper}>
<div className={style.storageTypeLabel}>{t['Move folder']()}</div>
<div className={style.storageTypeLabelHint}>
{t['Move folder hint']()}
</div>
</div>
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
</div>
</div>
<div className={style.col}></div>
</div>
);
}

View File

@ -9,7 +9,9 @@ const LanguageMenuContent: FC = () => {
const i18n = useI18N();
const changeLanguage = useCallback(
(event: string) => {
void i18n.changeLanguage(event);
i18n.changeLanguage(event).catch(err => {
console.error(err);
});
},
[i18n]
);

View File

@ -12,6 +12,7 @@ import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
import { useAtom, useAtomValue } from 'jotai';
import type { FC, HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
import { forwardRef, memo, useEffect, useMemo, useState } from 'react';
import { noop } from 'rxjs';
import { guideDownloadClientTipAtom } from '../../../atoms/guide';
import { contentLayoutAtom } from '../../../atoms/layout';
@ -104,27 +105,21 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
<button
data-type="minimize"
className={styles.windowAppControl}
onClick={() => {
window.apis?.ui.handleMinimizeApp();
}}
onClick={window.apis?.ui.handleMinimizeApp ?? noop}
>
<MinusIcon />
</button>
<button
data-type="maximize"
className={styles.windowAppControl}
onClick={() => {
window.apis?.ui.handleMaximizeApp();
}}
onClick={window.apis?.ui.handleMaximizeApp ?? noop}
>
<RoundedRectangleIcon />
</button>
<button
data-type="close"
className={styles.windowAppControl}
onClick={() => {
window.apis?.ui.handleCloseApp();
}}
onClick={window.apis?.ui.handleCloseApp ?? noop}
>
<CloseIcon />
</button>

View File

@ -54,7 +54,9 @@ export const Footer: React.FC<FooterProps> = ({
title: query,
});
onClose();
void jumpToPage(blockSuiteWorkspace.id, page.id);
jumpToPage(blockSuiteWorkspace.id, page.id).catch(err => {
console.error(err);
});
}, [blockSuiteWorkspace, createPage, jumpToPage, onClose, query])}
>
<StyledModalFooterContent>

View File

@ -107,7 +107,9 @@ export const RootAppSidebar = ({
const [sidebarOpen, setSidebarOpen] = useAtom(appSidebarOpenAtom);
useEffect(() => {
if (environment.isDesktop && typeof sidebarOpen === 'boolean') {
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen);
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen).catch(err => {
console.error(err);
});
}
}, [sidebarOpen]);

View File

@ -174,7 +174,9 @@ export const CurrentWorkspaceContext = ({
useEffect(() => {
const id = setTimeout(() => {
if (!exist) {
void push('/');
push('/').catch(err => {
console.error(err);
});
globalThis.HALTING_PROBLEM_TIMEOUT <<= 1;
}
}, globalThis.HALTING_PROBLEM_TIMEOUT);
@ -319,7 +321,9 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
}
if (!router.query.pageId) {
setCurrentPageId(pageId);
void jumpToPage(currentWorkspace.id, pageId);
jumpToPage(currentWorkspace.id, pageId).catch(err => {
console.error(err);
});
}
}
//#endregion
@ -353,7 +357,9 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
}
);
setCurrentPageId(currentPageId);
void jumpToPage(currentWorkspace.id, page.id);
jumpToPage(currentWorkspace.id, page.id).catch(err => {
console.error(err);
});
}
}, [
currentPageId,

View File

@ -39,21 +39,31 @@ const IndexPageInner = () => {
nonTrashPages.at(0)?.id;
if (pageId) {
logger.debug('Found target workspace. Jump to page', pageId);
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
err => {
console.error(err);
}
);
} else {
const clearId = setTimeout(() => {
dispose.dispose();
logger.debug('Found target workspace. Jump to all pages');
void jumpToSubPath(
jumpToSubPath(
targetWorkspace.id,
WorkspaceSubPath.ALL,
RouteLogic.REPLACE
);
).catch(err => {
console.error(err);
});
}, 1000);
const dispose =
targetWorkspace.blockSuiteWorkspace.slots.pageAdded.once(pageId => {
clearTimeout(clearId);
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
err => {
console.error(err);
}
);
});
return () => {
clearTimeout(clearId);

View File

@ -11,7 +11,7 @@ import { atomWithStorage } from 'jotai/utils';
import Head from 'next/head';
import type { NextRouter } from 'next/router';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect } from 'react';
import React, { useCallback } from 'react';
import { getUIAdapter } from '../../../adapters/workspace';
import { PageLoading } from '../../../components/pure/loading';
@ -30,7 +30,7 @@ function useTabRouterSync(
router: NextRouter,
currentTab: SettingPanel,
setCurrentTab: (tab: SettingPanel) => void
) {
): void {
if (!router.isReady) {
return;
}
@ -43,33 +43,36 @@ function useTabRouterSync(
settingPanelValues.indexOf(queryCurrentTab as SettingPanel) === -1
) {
setCurrentTab(settingPanel.General);
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
});
return;
router
.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
})
.catch(console.error);
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
setCurrentTab(settingPanel.General);
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
});
return;
router
.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: settingPanel.General,
},
})
.catch(console.error);
} else if (queryCurrentTab !== currentTab) {
void router.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: currentTab,
},
});
return;
router
.replace({
pathname: router.pathname,
query: {
...router.query,
currentTab: currentTab,
},
})
.catch(console.error);
}
}
@ -78,20 +81,24 @@ const SettingPage: NextPageWithLayout = () => {
const [currentWorkspace] = useCurrentWorkspace();
const t = useAFFiNEI18N();
const [currentTab, setCurrentTab] = useAtom(settingPanelAtom);
useEffect(() => {});
const onChangeTab = useCallback(
(tab: SettingPanel) => {
setCurrentTab(tab as SettingPanel);
void router.push({
pathname: router.pathname,
query: {
...router.query,
currentTab: tab,
},
});
router
.push({
pathname: router.pathname,
query: {
...router.query,
currentTab: tab,
},
})
.catch(err => {
console.error(err);
});
},
[router, setCurrentTab]
);
useTabRouterSync(router, currentTab, setCurrentTab);
const helper = useAppHelper();

View File

@ -49,7 +49,9 @@ export const updateAvailableAtom = atomWithObservable(() => {
return rpcToObservable(null as any | null, {
event: window.events?.updater.onUpdateAvailable,
onSubscribe: () => {
window.apis?.updater.checkForUpdatesAndNotify();
window.apis?.updater.checkForUpdatesAndNotify().catch(err => {
console.error(err);
});
},
});
});

View File

@ -65,7 +65,10 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
}, [currentVersion, setChangelogCheckAtom]);
const onClickUpdate = useCallback(() => {
if (updateReady) {
window.apis?.updater.quitAndInstall();
window.apis?.updater.quitAndInstall().catch(err => {
// TODO: add error toast here
console.error(err);
});
} else if (updateAvailable) {
if (updateAvailable.allowAutoUpdate) {
// wait for download to finish

View File

@ -9,8 +9,15 @@ export const CopyLink = ({ onItemClick, onSelect }: CommonMenuItemProps) => {
const t = useAFFiNEI18N();
const copyUrl = useCallback(() => {
navigator.clipboard.writeText(window.location.href);
toast(t['Copied link to clipboard']());
navigator.clipboard
.writeText(window.location.href)
.then(() => {
toast(t['Copied link to clipboard']());
})
.catch(err => {
// TODO add error toast here
console.error(err);
});
}, [t]);
return (

View File

@ -35,8 +35,13 @@ const ExportToPdfMenuItem = ({
if (result !== undefined) {
return;
}
contentParser.exportPdf();
return contentParser.exportPdf();
})
.then(() => {
onSelect?.({ type: 'pdf' });
})
.catch(err => {
console.error(err);
});
}, [currentEditor, onSelect]);
if (currentEditor && currentEditor.mode === 'page') {
@ -66,7 +71,9 @@ const ExportToHtmlMenuItem = ({
if (!contentParserRef.current) {
contentParserRef.current = new ContentParser(currentEditor.page);
}
contentParserRef.current.exportHtml();
contentParserRef.current.exportHtml().catch(err => {
console.error(err);
});
onSelect?.({ type: 'html' });
}, [onSelect, currentEditor]);
return (
@ -123,7 +130,9 @@ const ExportToMarkdownMenuItem = ({
if (!contentParserRef.current) {
contentParserRef.current = new ContentParser(currentEditor.page);
}
contentParserRef.current.exportMarkdown();
contentParserRef.current.exportMarkdown().catch(err => {
console.error(err);
});
onSelect?.({ type: 'markdown' });
}, [onSelect, currentEditor]);
return (

View File

@ -10,7 +10,11 @@ const DesktopThemeSync = memo(function DesktopThemeSync() {
const onceRef = useRef(false);
if (lastThemeRef.current !== theme || !onceRef.current) {
if (environment.isDesktop && theme) {
window.apis?.ui.handleThemeChange(theme as 'dark' | 'light' | 'system');
window.apis?.ui
.handleThemeChange(theme as 'dark' | 'light' | 'system')
.catch(err => {
console.error(err);
});
}
lastThemeRef.current = theme;
onceRef.current = true;

View File

@ -32,15 +32,20 @@ export function definePlugin<ID extends string>(
if (isServer) {
if (serverAdapter) {
serverAdapter.load().then(({ default: adapter }) => {
rootStore.set(affinePluginsAtom, plugins => ({
...plugins,
[definition.id]: {
...basePlugin,
serverAdapter: adapter,
},
}));
});
serverAdapter
.load()
.then(({ default: adapter }) => {
rootStore.set(affinePluginsAtom, plugins => ({
...plugins,
[definition.id]: {
...basePlugin,
serverAdapter: adapter,
},
}));
})
.catch(err => {
console.error(err);
});
}
} else if (isClient) {
if (blockSuiteAdapter) {

View File

@ -171,7 +171,9 @@ const createSQLiteProvider = (
if (origin === sqliteOrigin) {
return;
}
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update);
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update).catch(err => {
console.error(err);
});
}
let unsubscribe = () => {};
@ -247,7 +249,7 @@ const createSQLiteDBDownloadProvider = (
const diff = Y.encodeStateAsUpdate(blockSuiteWorkspace.doc, updates);
// also apply updates to sqlite
apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
await apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
const bs = blockSuiteWorkspace.blobs;

View File

@ -12,47 +12,48 @@ import { openAIApiKeyAtom, useChatAtoms } from '../core/hooks';
import { detailContentActionsStyle, detailContentStyle } from './index.css';
if (typeof window === 'undefined') {
import('@blocksuite/blocks').then(({ FormatQuickBar }) => {
FormatQuickBar.customElements.push((_page, getSelection) => {
const div = document.createElement('div');
const root = createRoot(div);
import('@blocksuite/blocks')
.then(({ FormatQuickBar }) => {
FormatQuickBar.customElements.push((_page, getSelection) => {
const div = document.createElement('div');
const root = createRoot(div);
const AskAI = (): ReactElement => {
const { conversationAtom } = useChatAtoms();
const call = useSetAtom(conversationAtom);
const AskAI = (): ReactElement => {
const { conversationAtom } = useChatAtoms();
const call = useSetAtom(conversationAtom);
const onClickAskAI = useCallback(() => {
const selection = getSelection();
if (selection != null) {
const text = selection.models
.map(model => {
return model.text?.toString();
})
.filter((v): v is string => Boolean(v))
.join('\n');
console.log('selected text:', text);
call(
`I selected some text from the document: \n"${text}."`
).catch(err => {
console.error(err);
});
}
}, [call]);
return (
<div
onClick={() => {
const selection = getSelection();
if (selection != null) {
const text = selection.models
.map(model => {
return model.text?.toString();
})
.filter((v): v is string => Boolean(v))
.join('\n');
console.log('selected text:', text);
void call(
`I selected some text from the document: \n"${text}."`
);
}
}}
>
Ask AI
</div>
return <div onClick={onClickAskAI}>Ask AI</div>;
};
root.render(
<StrictMode>
<Provider store={rootStore}>
<AskAI />
</Provider>
</StrictMode>
);
};
root.render(
<StrictMode>
<Provider store={rootStore}>
<AskAI />
</Provider>
</StrictMode>
);
return div;
return div;
});
})
.catch(error => {
console.error(error);
});
});
}
const Actions = () => {

View File

@ -49,9 +49,14 @@ const getConversationAtom = (chat: ConversationChain) => {
throw new Error();
}
const memory = chat.memory as BufferMemory;
void memory.chatHistory.getMessages().then(messages => {
setAtom(messages);
});
memory.chatHistory
.getMessages()
.then(messages => {
setAtom(messages);
})
.catch(err => {
console.error(err);
});
const llmStart = (): void => {
setAtom(conversations => [...conversations, new AIChatMessage('')]);
};
@ -86,9 +91,14 @@ const getConversationAtom = (chat: ConversationChain) => {
});
// refresh messages
const memory = chat.memory as BufferMemory;
void memory.chatHistory.getMessages().then(messages => {
set(conversationBaseAtom, messages);
});
memory.chatHistory
.getMessages()
.then(messages => {
set(conversationBaseAtom, messages);
})
.catch(err => {
console.error(err);
});
}
);
conversationWeakMap.set(chat, conversationAtom);