Skip to content

Commit 86729fb

Browse files
authored
feat(core): adjust web clipper page (#10779)
1 parent 5ed8541 commit 86729fb

File tree

5 files changed

+92
-13
lines changed

5 files changed

+92
-13
lines changed

packages/frontend/component/src/components/auth-components/auth-header.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { Logo1Icon } from '@blocksuite/icons/rc';
2+
import clsx from 'clsx';
23
import type { FC } from 'react';
34

45
import { authHeaderWrapper } from './share.css';
6+
57
export const AuthHeader: FC<{
68
title: string;
79
subTitle?: string;
8-
}> = ({ title, subTitle }) => {
10+
className?: string;
11+
}> = ({ title, subTitle, className }) => {
912
return (
10-
<div className={authHeaderWrapper}>
13+
<div className={clsx(authHeaderWrapper, className)}>
1114
<p>
1215
<Logo1Icon className="logo" />
1316
{title}

packages/frontend/core/src/desktop/pages/auth/sign-in.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export const SignIn = ({
4646
(status: AuthSessionStatus) => {
4747
if (status === 'authenticated') {
4848
if (redirectUrl) {
49+
if (redirectUrl.toUpperCase() === 'CLOSE_POPUP') {
50+
window.close();
51+
}
4952
navigate(redirectUrl, {
5053
replace: true,
5154
});

packages/frontend/core/src/desktop/pages/import-clipper/index.tsx

+78-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Button } from '@affine/component';
2+
import { AuthHeader } from '@affine/component/auth-components';
23
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
3-
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
44
import { useWorkspaceName } from '@affine/core/components/hooks/use-workspace-info';
55
import { WorkspaceSelector } from '@affine/core/components/workspace-selector';
6-
import { AuthService } from '@affine/core/modules/cloud';
6+
import { AuthService, ServerService } from '@affine/core/modules/cloud';
77
import {
88
type ClipperInput,
99
ImportClipperService,
@@ -16,7 +16,7 @@ import { useI18n } from '@affine/i18n';
1616
import { AllDocsIcon } from '@blocksuite/icons/rc';
1717
import { LiveData, useLiveData, useService } from '@toeverything/infra';
1818
import { cssVar } from '@toeverything/theme';
19-
import { useCallback, useEffect, useState } from 'react';
19+
import { useCallback, useEffect, useRef, useState } from 'react';
2020

2121
import * as styles from './style.css';
2222

@@ -36,24 +36,29 @@ export const Component = () => {
3636
const t = useI18n();
3737
const session = useService(AuthService).session;
3838
const notLogin = useLiveData(session.status$) === 'unauthenticated';
39-
const isSessionRevalidating = useLiveData(session.isRevalidating$);
4039

4140
const [importing, setImporting] = useState(false);
4241
const [importingError, setImportingError] = useState<any>(null);
4342
const clipperInput = useLiveData(clipperInput$);
4443
const [clipperInputSnapshot, setClipperInputSnapshot] =
4544
useState<ClipperInput | null>(null);
4645
const isMissingInput = !clipperInputSnapshot;
46+
const workspaceStrategy = clipperInputSnapshot?.workspace ?? 'select-by-user';
47+
const serverService = useService(ServerService);
4748
const workspacesService = useService(WorkspacesService);
49+
const serverConfig = useLiveData(serverService.server.config$);
4850
const workspaces = useLiveData(workspacesService.list.workspaces$);
4951
const [rawSelectedWorkspace, setSelectedWorkspace] =
5052
useState<WorkspaceMetadata | null>(null);
53+
const [lastOpenedWorkspaceId] = useState(() =>
54+
localStorage.getItem('last_workspace_id')
55+
);
5156
const selectedWorkspace =
5257
rawSelectedWorkspace ??
58+
workspaces.find(w => w.id === lastOpenedWorkspaceId) ??
5359
workspaces.find(w => w.flavour !== 'local') ??
5460
workspaces.at(0);
5561
const selectedWorkspaceName = useWorkspaceName(selectedWorkspace);
56-
const { jumpToSignIn } = useNavigateHelper();
5762

5863
const noWorkspace = workspaces.length === 0;
5964

@@ -65,12 +70,6 @@ export const Component = () => {
6570
session.revalidate();
6671
}, [session]);
6772

68-
useEffect(() => {
69-
if (!isSessionRevalidating && notLogin) {
70-
jumpToSignIn('/clipper/import');
71-
}
72-
}, [isSessionRevalidating, jumpToSignIn, notLogin]);
73-
7473
useEffect(() => {
7574
if (!clipperInputSnapshot) {
7675
setClipperInputSnapshot(clipperInput);
@@ -99,6 +98,9 @@ export const Component = () => {
9998
selectedWorkspace,
10099
clipperInputSnapshot
101100
);
101+
window.postMessage({
102+
type: 'affine-clipper:import:success',
103+
});
102104
window.close();
103105
} catch (err) {
104106
setImportingError(err);
@@ -119,6 +121,9 @@ export const Component = () => {
119121
'Workspace',
120122
clipperInputSnapshot
121123
);
124+
window.postMessage({
125+
type: 'affine-clipper:import:success',
126+
});
122127
window.close();
123128
} catch (err) {
124129
setImportingError(err);
@@ -127,8 +132,70 @@ export const Component = () => {
127132
}
128133
}, [clipperInputSnapshot, importClipperService]);
129134

135+
const handleClickSignIn = useCallback(() => {
136+
window.open(
137+
`/sign-in?redirect_uri=${encodeURIComponent('CLOSE_POPUP')}`,
138+
'_blank',
139+
'popup'
140+
);
141+
}, []);
142+
143+
const autoImportTriggered = useRef(false);
144+
145+
useEffect(() => {
146+
if (isMissingInput) {
147+
return;
148+
}
149+
// use ref to avoid multiple auto import
150+
// and make sure the following code only runs once
151+
if (autoImportTriggered.current) {
152+
return;
153+
}
154+
autoImportTriggered.current = true;
155+
156+
// if not login, we don't auto import
157+
if (notLogin) {
158+
return;
159+
}
160+
161+
// if the workspace strategy is last-open-workspace, we automatically click the import button
162+
if (
163+
workspaceStrategy === 'last-open-workspace' &&
164+
selectedWorkspace?.id === lastOpenedWorkspaceId
165+
) {
166+
handleImportToSelectedWorkspace();
167+
}
168+
}, [
169+
workspaceStrategy,
170+
selectedWorkspace,
171+
handleImportToSelectedWorkspace,
172+
lastOpenedWorkspaceId,
173+
isMissingInput,
174+
notLogin,
175+
]);
176+
130177
const disabled = isMissingInput || importing || notLogin;
131178

179+
if (notLogin) {
180+
// not login
181+
return (
182+
<div className={styles.container}>
183+
<AuthHeader
184+
className={styles.authHeader}
185+
title={t['com.affine.auth.sign.in']()}
186+
subTitle={serverConfig.serverName}
187+
/>
188+
<Button
189+
className={styles.mainButton}
190+
variant="primary"
191+
onClick={handleClickSignIn}
192+
>
193+
{t['com.affine.auth.sign.in']()}
194+
</Button>
195+
</div>
196+
);
197+
}
198+
132199
return (
133200
<div className={styles.container}>
134201
<AllDocsIcon className={styles.mainIcon} />

packages/frontend/core/src/desktop/pages/import-clipper/style.css.ts

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export const container = style({
1212
padding: '16px',
1313
});
1414

15+
export const authHeader = style({
16+
width: '100%',
17+
});
18+
1519
export const buttonContainer = style({
1620
paddingTop: '16px',
1721
});

packages/frontend/core/src/modules/import-clipper/services/import.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface ClipperInput {
1313
contentMarkdown: string;
1414
contentHtml: string;
1515
attachments: Record<string, Blob>;
16+
workspace?: 'select-by-user' | 'last-open-workspace';
1617
}
1718

1819
export class ImportClipperService extends Service {
@@ -37,6 +38,7 @@ export class ImportClipperService extends Service {
3738
const docsService = workspace.scope.get(DocsService);
3839
if (docId) {
3940
// only support page mode for now
41+
await docsService.changeDocTitle(docId, clipperInput.title);
4042
docsService.list.setPrimaryMode(docId, 'page');
4143
workspace.engine.doc.addPriority(workspace.id, 100);
4244
workspace.engine.doc.addPriority(docId, 100);

0 commit comments

Comments
 (0)