mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-24 22:09:08 +08:00
feat(editor): replace slot with rxjs subject (#10768)
This commit is contained in:
@@ -441,7 +441,7 @@ const CREATE_AS_DOC = {
|
||||
newDoc.addBlock('affine:surface', {}, rootId);
|
||||
const noteId = newDoc.addBlock('affine:note', {}, rootId);
|
||||
|
||||
host.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.emit({
|
||||
host.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({
|
||||
pageId: newDoc.id,
|
||||
host,
|
||||
});
|
||||
|
||||
@@ -341,7 +341,7 @@ const OthersAIGroup: AIItemGroupConfig = {
|
||||
icon: CommentIcon(),
|
||||
handler: host => {
|
||||
const panel = getAIPanelWidget(host);
|
||||
AIProvider.slots.requestOpenWithChat.emit({
|
||||
AIProvider.slots.requestOpenWithChat.next({
|
||||
host,
|
||||
autoSelect: true,
|
||||
});
|
||||
|
||||
@@ -565,7 +565,7 @@ export function actionToResponse<T extends keyof BlockSuitePresets.AIActions>(
|
||||
handler: () => {
|
||||
reportResponse('result:continue-in-chat');
|
||||
const panel = getAIPanelWidget(host);
|
||||
AIProvider.slots.requestOpenWithChat.emit({ host });
|
||||
AIProvider.slots.requestOpenWithChat.next({ host });
|
||||
panel.hide();
|
||||
},
|
||||
},
|
||||
@@ -604,11 +604,11 @@ export function actionToErrorResponse<
|
||||
): ErrorConfig {
|
||||
return {
|
||||
upgrade: () => {
|
||||
AIProvider.slots.requestUpgradePlan.emit({ host: panel.host });
|
||||
AIProvider.slots.requestUpgradePlan.next({ host: panel.host });
|
||||
panel.hide();
|
||||
},
|
||||
login: () => {
|
||||
AIProvider.slots.requestLogin.emit({ host: panel.host });
|
||||
AIProvider.slots.requestLogin.next({ host: panel.host });
|
||||
panel.hide();
|
||||
},
|
||||
cancel: () => {
|
||||
|
||||
@@ -193,7 +193,7 @@ function buildPageResponseConfig<T extends keyof BlockSuitePresets.AIActions>(
|
||||
icon: ChatWithAiIcon(),
|
||||
handler: () => {
|
||||
reportResponse('result:continue-in-chat');
|
||||
AIProvider.slots.requestOpenWithChat.emit({ host });
|
||||
AIProvider.slots.requestOpenWithChat.next({ host });
|
||||
panel.hide();
|
||||
},
|
||||
},
|
||||
@@ -258,11 +258,11 @@ export function buildFinishConfig<T extends keyof BlockSuitePresets.AIActions>(
|
||||
export function buildErrorConfig(panel: AffineAIPanelWidget) {
|
||||
return {
|
||||
upgrade: () => {
|
||||
AIProvider.slots.requestUpgradePlan.emit({ host: panel.host });
|
||||
AIProvider.slots.requestUpgradePlan.next({ host: panel.host });
|
||||
panel.hide();
|
||||
},
|
||||
login: () => {
|
||||
AIProvider.slots.requestLogin.emit({ host: panel.host });
|
||||
AIProvider.slots.requestLogin.next({ host: panel.host });
|
||||
panel.hide();
|
||||
},
|
||||
cancel: () => {
|
||||
|
||||
@@ -273,12 +273,16 @@ export class ChatPanelInput extends SignalWatcher(WithDisposable(LitElement)) {
|
||||
super.connectedCallback();
|
||||
|
||||
this._disposables.add(
|
||||
AIProvider.slots.requestSendWithChat.on(
|
||||
async ({ input, context, host }) => {
|
||||
AIProvider.slots.requestSendWithChat.subscribe(
|
||||
({ input, context, host }) => {
|
||||
if (this.host === host) {
|
||||
context && this.updateContext(context);
|
||||
await this.updateComplete;
|
||||
await this.send(input);
|
||||
const { updateComplete, send } = this;
|
||||
updateComplete
|
||||
.then(() => {
|
||||
return send(input);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -316,7 +316,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
|
||||
.catch(console.error);
|
||||
|
||||
disposables.add(
|
||||
AIProvider.slots.userInfo.on(userInfo => {
|
||||
AIProvider.slots.userInfo.subscribe(userInfo => {
|
||||
const { status, error } = this.chatContextValue;
|
||||
this.avatarUrl = userInfo?.avatarUrl ?? '';
|
||||
if (
|
||||
@@ -329,7 +329,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
|
||||
})
|
||||
);
|
||||
disposables.add(
|
||||
this.host.selection.slots.changed.on(() => {
|
||||
this.host.selection.slots.changed.subscribe(() => {
|
||||
this._selectionValue = this.host.selection.value;
|
||||
})
|
||||
);
|
||||
|
||||
@@ -54,7 +54,7 @@ export class ChatPanelDocChip extends SignalWatcher(
|
||||
const doc = this.docDisplayConfig.getDoc(this.chip.docId);
|
||||
if (doc) {
|
||||
this.disposables.add(
|
||||
doc.slots.blockUpdated.on(
|
||||
doc.slots.blockUpdated.subscribe(
|
||||
throttle(this.autoUpdateChip, EXTRACT_DOC_THROTTLE)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -392,7 +392,7 @@ export class ChatPanel extends SignalWatcher(
|
||||
if (!this.doc) throw new Error('doc is required');
|
||||
|
||||
this._disposables.add(
|
||||
AIProvider.slots.actions.on(({ event }) => {
|
||||
AIProvider.slots.actions.subscribe(({ event }) => {
|
||||
const { status } = this.chatContextValue;
|
||||
if (
|
||||
event === 'finished' &&
|
||||
@@ -403,16 +403,19 @@ export class ChatPanel extends SignalWatcher(
|
||||
})
|
||||
);
|
||||
this._disposables.add(
|
||||
AIProvider.slots.userInfo.on(async () => {
|
||||
await this._initPanel();
|
||||
AIProvider.slots.userInfo.subscribe(() => {
|
||||
this._initPanel().catch(console.error);
|
||||
})
|
||||
);
|
||||
this._disposables.add(
|
||||
AIProvider.slots.requestOpenWithChat.on(async ({ host }) => {
|
||||
AIProvider.slots.requestOpenWithChat.subscribe(({ host }) => {
|
||||
if (this.host === host) {
|
||||
const context = await extractSelectedContent(host);
|
||||
if (!context) return;
|
||||
this.updateContext(context);
|
||||
extractSelectedContent(host)
|
||||
.then(context => {
|
||||
if (!context) return;
|
||||
this.updateContext(context);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ export const AIPreloadConfig = [
|
||||
icon: LanguageIcon(),
|
||||
text: 'Read a foreign language article with AI',
|
||||
handler: () => {
|
||||
AIProvider.slots.requestInsertTemplate.emit({
|
||||
AIProvider.slots.requestInsertTemplate.next({
|
||||
template: readAforeign,
|
||||
mode: 'edgeless',
|
||||
});
|
||||
@@ -28,7 +28,7 @@ export const AIPreloadConfig = [
|
||||
icon: MindmapIcon(),
|
||||
text: 'Tidy an article with AI MindMap Action',
|
||||
handler: () => {
|
||||
AIProvider.slots.requestInsertTemplate.emit({
|
||||
AIProvider.slots.requestInsertTemplate.next({
|
||||
template: TidyMindMapV3,
|
||||
mode: 'edgeless',
|
||||
});
|
||||
@@ -38,7 +38,7 @@ export const AIPreloadConfig = [
|
||||
icon: ImageIcon(),
|
||||
text: 'Add illustrations to the article',
|
||||
handler: () => {
|
||||
AIProvider.slots.requestInsertTemplate.emit({
|
||||
AIProvider.slots.requestInsertTemplate.next({
|
||||
template: redHat,
|
||||
mode: 'edgeless',
|
||||
});
|
||||
@@ -48,7 +48,7 @@ export const AIPreloadConfig = [
|
||||
icon: PenIcon(),
|
||||
text: 'Complete writing with AI',
|
||||
handler: () => {
|
||||
AIProvider.slots.requestInsertTemplate.emit({
|
||||
AIProvider.slots.requestInsertTemplate.next({
|
||||
template: completeWritingWithAI,
|
||||
mode: 'edgeless',
|
||||
});
|
||||
@@ -58,7 +58,7 @@ export const AIPreloadConfig = [
|
||||
icon: SendIcon(),
|
||||
text: 'Freely communicate with AI',
|
||||
handler: () => {
|
||||
AIProvider.slots.requestInsertTemplate.emit({
|
||||
AIProvider.slots.requestInsertTemplate.next({
|
||||
template: freelyCommunicateWithAI,
|
||||
mode: 'edgeless',
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ export class AskAIToolbarButton extends WithDisposable(LitElement) {
|
||||
aiPanel.hide();
|
||||
extractSelectedContent(this.host)
|
||||
.then(context => {
|
||||
AIProvider.slots.requestSendWithChat.emit({
|
||||
AIProvider.slots.requestSendWithChat.next({
|
||||
input,
|
||||
context,
|
||||
host: this.host,
|
||||
|
||||
@@ -107,7 +107,7 @@ const othersGroup: AIItemGroupConfig = {
|
||||
showWhen: () => true,
|
||||
handler: host => {
|
||||
const panel = getAIPanelWidget(host);
|
||||
AIProvider.slots.requestOpenWithChat.emit({
|
||||
AIProvider.slots.requestOpenWithChat.next({
|
||||
host,
|
||||
mode: 'edgeless',
|
||||
autoSelect: true,
|
||||
|
||||
@@ -50,7 +50,7 @@ export function setupEdgelessElementToolbarAIEntry(
|
||||
aiPanel.hide();
|
||||
extractSelectedContent(edgeless.host)
|
||||
.then(context => {
|
||||
AIProvider.slots.requestSendWithChat.emit({
|
||||
AIProvider.slots.requestSendWithChat.next({
|
||||
input,
|
||||
context,
|
||||
host: edgeless.host,
|
||||
|
||||
@@ -13,7 +13,7 @@ class AICodeBlockWatcher extends LifeCycleWatcher {
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
view.viewUpdated.subscribe(payload => {
|
||||
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ function getAIEdgelessRootWatcher(framework: FrameworkProvider) {
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
view.viewUpdated.subscribe(payload => {
|
||||
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class AIImageBlockWatcher extends LifeCycleWatcher {
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
view.viewUpdated.subscribe(payload => {
|
||||
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ function getAIPageRootWatcher(framework: FrameworkProvider) {
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
view.viewUpdated.subscribe(payload => {
|
||||
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ const PaymentRequiredErrorRenderer = (host: EditorHost) => html`
|
||||
<ai-error-wrapper
|
||||
.text=${"You've reached the current usage cap for AFFiNE AI. You can subscribe to AFFiNE AI(with free 7-day-trial) to continue the AI experience!"}
|
||||
.actionText=${'Upgrade'}
|
||||
.onClick=${() => AIProvider.slots.requestUpgradePlan.emit({ host })}
|
||||
.onClick=${() => AIProvider.slots.requestUpgradePlan.next({ host })}
|
||||
></ai-error-wrapper>
|
||||
`;
|
||||
|
||||
@@ -196,7 +196,7 @@ const LoginRequiredErrorRenderer = (host: EditorHost) => html`
|
||||
<ai-error-wrapper
|
||||
.text=${'You need to login to AFFiNE Cloud to continue using AFFiNE AI.'}
|
||||
.actionText=${'Login'}
|
||||
.onClick=${() => AIProvider.slots.requestLogin.emit({ host })}
|
||||
.onClick=${() => AIProvider.slots.requestLogin.next({ host })}
|
||||
></ai-error-wrapper>
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { BlockService } from '@blocksuite/affine/block-std';
|
||||
import { Slot } from '@blocksuite/affine/global/slot';
|
||||
import { RootBlockSchema } from '@blocksuite/affine/model';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export class MindmapService extends BlockService {
|
||||
static override readonly flavour = RootBlockSchema.model.flavour;
|
||||
|
||||
requestCenter = new Slot();
|
||||
// eslint-disable-next-line rxjs/finnish
|
||||
requestCenter = new Subject<void>();
|
||||
|
||||
center() {
|
||||
this.requestCenter.emit();
|
||||
this.requestCenter.next();
|
||||
}
|
||||
|
||||
override mounted(): void {}
|
||||
|
||||
@@ -65,7 +65,7 @@ export class MindmapSurfaceBlock extends BlockComponent<SurfaceBlockModel> {
|
||||
|
||||
private _setupCenterEffect() {
|
||||
this._disposables.add(
|
||||
this.mindmapService.requestCenter.on(() => {
|
||||
this.mindmapService.requestCenter.subscribe(() => {
|
||||
let bound: Bound;
|
||||
|
||||
this.model.elementModels.forEach(el => {
|
||||
@@ -85,7 +85,7 @@ export class MindmapSurfaceBlock extends BlockComponent<SurfaceBlockModel> {
|
||||
|
||||
private _setupRenderer() {
|
||||
this._disposables.add(
|
||||
this.model.elementUpdated.on(() => {
|
||||
this.model.elementUpdated.subscribe(() => {
|
||||
this.mindmapService.center();
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import { Slot } from '@blocksuite/affine/global/slot';
|
||||
import { captureException } from '@sentry/react';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import type { ChatContextValue } from '../chat-panel/chat-context';
|
||||
import {
|
||||
@@ -123,22 +123,24 @@ export class AIProvider {
|
||||
private readonly slots = {
|
||||
// use case: when user selects "continue in chat" in an ask ai result panel
|
||||
// do we need to pass the context to the chat panel?
|
||||
requestOpenWithChat: new Slot<AIChatParams>(),
|
||||
requestSendWithChat: new Slot<AISendParams>(),
|
||||
requestInsertTemplate: new Slot<{
|
||||
/* eslint-disable rxjs/finnish */
|
||||
requestOpenWithChat: new Subject<AIChatParams>(),
|
||||
requestSendWithChat: new Subject<AISendParams>(),
|
||||
requestInsertTemplate: new Subject<{
|
||||
template: string;
|
||||
mode: 'page' | 'edgeless';
|
||||
}>(),
|
||||
requestLogin: new Slot<{ host: EditorHost }>(),
|
||||
requestUpgradePlan: new Slot<{ host: EditorHost }>(),
|
||||
requestLogin: new Subject<{ host: EditorHost }>(),
|
||||
requestUpgradePlan: new Subject<{ host: EditorHost }>(),
|
||||
// stream of AI actions triggered by users
|
||||
actions: new Slot<{
|
||||
actions: new Subject<{
|
||||
action: keyof BlockSuitePresets.AIActions;
|
||||
options: BlockSuitePresets.AITextActionOptions;
|
||||
event: ActionEventType;
|
||||
}>(),
|
||||
// downstream can emit this slot to notify ai presets that user info has been updated
|
||||
userInfo: new Slot<AIUserInfo | null>(),
|
||||
userInfo: new Subject<AIUserInfo | null>(),
|
||||
/* eslint-enable rxjs/finnish */
|
||||
};
|
||||
|
||||
// track the history of triggered actions (in memory only)
|
||||
@@ -162,7 +164,7 @@ export class AIProvider {
|
||||
) => {
|
||||
const options = args[0];
|
||||
const slots = this.slots;
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'started',
|
||||
@@ -186,31 +188,31 @@ export class AIProvider {
|
||||
try {
|
||||
user = await AIProvider.userInfo;
|
||||
yield* result;
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'finished',
|
||||
});
|
||||
} catch (err) {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'error',
|
||||
});
|
||||
if (err instanceof PaymentRequiredError) {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'aborted:paywall',
|
||||
});
|
||||
} else if (err instanceof UnauthorizedError) {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'aborted:login-required',
|
||||
});
|
||||
} else {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'aborted:server-error',
|
||||
@@ -232,7 +234,7 @@ export class AIProvider {
|
||||
return result
|
||||
.then(async result => {
|
||||
user = await AIProvider.userInfo;
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'finished',
|
||||
@@ -240,13 +242,13 @@ export class AIProvider {
|
||||
return result;
|
||||
})
|
||||
.catch(err => {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'error',
|
||||
});
|
||||
if (err instanceof PaymentRequiredError) {
|
||||
slots.actions.emit({
|
||||
slots.actions.next({
|
||||
action: id,
|
||||
options,
|
||||
event: 'aborted:paywall',
|
||||
|
||||
@@ -527,13 +527,15 @@ Could you make a new website based on these notes and send back just the html fi
|
||||
return client.forkSession(options);
|
||||
});
|
||||
|
||||
const disposeRequestLoginHandler = AIProvider.slots.requestLogin.on(() => {
|
||||
globalDialogService.open('sign-in', {});
|
||||
});
|
||||
const disposeRequestLoginHandler = AIProvider.slots.requestLogin.subscribe(
|
||||
() => {
|
||||
globalDialogService.open('sign-in', {});
|
||||
}
|
||||
);
|
||||
|
||||
setupTracker();
|
||||
|
||||
return () => {
|
||||
disposeRequestLoginHandler.dispose();
|
||||
disposeRequestLoginHandler.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import type { GfxPrimitiveElementModel } from '@blocksuite/affine/block-std/gfx';
|
||||
import type { BlockModel } from '@blocksuite/affine/store';
|
||||
import { lowerCase, omit } from 'lodash-es';
|
||||
import type { Subject } from 'rxjs';
|
||||
|
||||
import { AIProvider } from './ai-provider';
|
||||
|
||||
@@ -60,9 +61,9 @@ type AIActionEventProperties = {
|
||||
workspaceId: string;
|
||||
};
|
||||
|
||||
type BlocksuiteActionEvent = Parameters<
|
||||
Parameters<typeof AIProvider.slots.actions.on>[0]
|
||||
>[0];
|
||||
type SubjectValue<T> = T extends Subject<infer U> ? U : never;
|
||||
|
||||
type BlocksuiteActionEvent = SubjectValue<typeof AIProvider.slots.actions>;
|
||||
|
||||
const trackAction = ({
|
||||
eventName,
|
||||
@@ -252,15 +253,15 @@ const toTrackedOptions = (
|
||||
};
|
||||
|
||||
export function setupTracker() {
|
||||
AIProvider.slots.requestUpgradePlan.on(() => {
|
||||
AIProvider.slots.requestUpgradePlan.subscribe(() => {
|
||||
track.$.paywall.aiAction.viewPlans();
|
||||
});
|
||||
|
||||
AIProvider.slots.requestLogin.on(() => {
|
||||
AIProvider.slots.requestLogin.subscribe(() => {
|
||||
track.doc.editor.aiActions.requestSignIn();
|
||||
});
|
||||
|
||||
AIProvider.slots.actions.on(event => {
|
||||
AIProvider.slots.actions.subscribe(event => {
|
||||
const properties = toTrackedOptions(event);
|
||||
if (properties) {
|
||||
trackAction(properties);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
Bound,
|
||||
getCommonBoundWithRotation,
|
||||
} from '@blocksuite/affine/global/gfx';
|
||||
import { Slot } from '@blocksuite/affine/global/slot';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import {
|
||||
AFFINE_AI_PANEL_WIDGET,
|
||||
@@ -22,7 +22,8 @@ export class CopilotTool extends BaseTool {
|
||||
|
||||
private _dragging = false;
|
||||
|
||||
draggingAreaUpdated = new Slot<boolean | void>();
|
||||
// eslint-disable-next-line rxjs/finnish
|
||||
draggingAreaUpdated = new Subject<boolean | void>();
|
||||
|
||||
dragLastPoint: [number, number] = [0, 0];
|
||||
|
||||
@@ -85,7 +86,7 @@ export class CopilotTool extends BaseTool {
|
||||
if (!this._dragging) return;
|
||||
|
||||
this._dragging = false;
|
||||
this.draggingAreaUpdated.emit(true);
|
||||
this.draggingAreaUpdated.next(true);
|
||||
}
|
||||
|
||||
override dragMove(e: PointerEventState): void {
|
||||
@@ -108,7 +109,7 @@ export class CopilotTool extends BaseTool {
|
||||
});
|
||||
}
|
||||
|
||||
this.draggingAreaUpdated.emit();
|
||||
this.draggingAreaUpdated.next();
|
||||
}
|
||||
|
||||
override dragStart(e: PointerEventState): void {
|
||||
@@ -116,7 +117,7 @@ export class CopilotTool extends BaseTool {
|
||||
|
||||
this._initDragState(e);
|
||||
this._dragging = true;
|
||||
this.draggingAreaUpdated.emit();
|
||||
this.draggingAreaUpdated.next();
|
||||
}
|
||||
|
||||
override mounted(): void {
|
||||
@@ -167,7 +168,7 @@ export class CopilotTool extends BaseTool {
|
||||
inoperable: true,
|
||||
});
|
||||
|
||||
this.draggingAreaUpdated.emit(true);
|
||||
this.draggingAreaUpdated.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ export function reportResponse(event: ActionEventType) {
|
||||
const lastAction = AIProvider.actionHistory.at(-1);
|
||||
if (!lastAction) return;
|
||||
|
||||
AIProvider.slots.actions.emit({
|
||||
AIProvider.slots.actions.next({
|
||||
action: lastAction.action,
|
||||
options: lastAction.options,
|
||||
event,
|
||||
|
||||
@@ -200,7 +200,7 @@ export class EdgelessCopilotWidget extends WidgetComponent<RootBlockModel> {
|
||||
const CopilotSelectionTool = this.gfx.tool.get('copilot');
|
||||
|
||||
this._disposables.add(
|
||||
CopilotSelectionTool.draggingAreaUpdated.on(shouldShowPanel => {
|
||||
CopilotSelectionTool.draggingAreaUpdated.subscribe(shouldShowPanel => {
|
||||
this._visible = true;
|
||||
this._updateSelection(CopilotSelectionTool.area);
|
||||
if (shouldShowPanel) {
|
||||
@@ -213,7 +213,7 @@ export class EdgelessCopilotWidget extends WidgetComponent<RootBlockModel> {
|
||||
);
|
||||
|
||||
this._disposables.add(
|
||||
this.gfx.viewport.viewportUpdated.on(() => {
|
||||
this.gfx.viewport.viewportUpdated.subscribe(() => {
|
||||
if (!this._visible) return;
|
||||
|
||||
this._updateSelection(CopilotSelectionTool.area);
|
||||
@@ -258,7 +258,7 @@ export class EdgelessCopilotWidget extends WidgetComponent<RootBlockModel> {
|
||||
|
||||
lockToolbar(disabled: boolean) {
|
||||
const legacySlot = this.std.get(EdgelessLegacySlotIdentifier);
|
||||
legacySlot.toolbarLocked.emit(disabled);
|
||||
legacySlot.toolbarLocked.next(disabled);
|
||||
}
|
||||
|
||||
override render() {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
customImageProxyMiddleware,
|
||||
ImageProxyService,
|
||||
} from '@blocksuite/affine/blocks/image';
|
||||
import { DisposableGroup } from '@blocksuite/affine/global/slot';
|
||||
import { DisposableGroup } from '@blocksuite/affine/global/disposable';
|
||||
import type { DocMode } from '@blocksuite/affine/model';
|
||||
import { LinkPreviewerService } from '@blocksuite/affine/shared/services';
|
||||
import type { Store } from '@blocksuite/affine/store';
|
||||
@@ -49,13 +49,14 @@ const BlockSuiteEditorImpl = ({
|
||||
defaultOpenProperty,
|
||||
}: EditorProps) => {
|
||||
useEffect(() => {
|
||||
const disposable = page.slots.blockUpdated.once(() => {
|
||||
const disposable = page.slots.blockUpdated.subscribe(() => {
|
||||
disposable.unsubscribe();
|
||||
page.workspace.meta.setDocMeta(page.id, {
|
||||
updatedDate: Date.now(),
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
disposable.unsubscribe();
|
||||
};
|
||||
}, [page]);
|
||||
|
||||
@@ -154,15 +155,16 @@ export const BlockSuiteEditor = (props: EditorProps) => {
|
||||
return;
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
disposable.dispose();
|
||||
disposable.unsubscribe();
|
||||
setError(new NoPageRootError(props.page));
|
||||
}, 20 * 1000);
|
||||
const disposable = props.page.slots.rootAdded.once(() => {
|
||||
const disposable = props.page.slots.rootAdded.subscribe(() => {
|
||||
disposable.unsubscribe();
|
||||
setIsLoading(false);
|
||||
clearTimeout(timer);
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
disposable.unsubscribe();
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [props.page]);
|
||||
|
||||
@@ -104,8 +104,11 @@ const StarterBarNotEmpty = ({ doc }: { doc: Store }) => {
|
||||
|
||||
const { id, created } = rootComponent.focusFirstParagraph();
|
||||
if (created) {
|
||||
std.view.viewUpdated.once(v => {
|
||||
if (v.id === id) handleInlineAskAIAction(std.host, pageAIGroups);
|
||||
const subscription = std.view.viewUpdated.subscribe(v => {
|
||||
if (v.id === id) {
|
||||
subscription.unsubscribe();
|
||||
handleInlineAskAIAction(std.host, pageAIGroups);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
handleInlineAskAIAction(std.host, pageAIGroups);
|
||||
|
||||
@@ -47,7 +47,7 @@ export class EdgelessEditor extends SignalWatcher(
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._disposables.add(
|
||||
this.doc.slots.rootAdded.on(() => this.requestUpdate())
|
||||
this.doc.slots.rootAdded.subscribe(() => this.requestUpdate())
|
||||
);
|
||||
this.std = new BlockStdScope({
|
||||
store: this.doc,
|
||||
|
||||
@@ -59,7 +59,7 @@ export class PageEditor extends SignalWatcher(
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._disposables.add(
|
||||
this.doc.slots.rootAdded.on(() => this.requestUpdate())
|
||||
this.doc.slots.rootAdded.subscribe(() => this.requestUpdate())
|
||||
);
|
||||
this.std = new BlockStdScope({
|
||||
store: this.doc,
|
||||
|
||||
@@ -44,9 +44,7 @@ export function patchDocModeService(
|
||||
? docsService.list.primaryMode$(id)
|
||||
: docService.doc.primaryMode$;
|
||||
const sub = mode$.subscribe(m => handler((m || DEFAULT_MODE) as DocMode));
|
||||
return {
|
||||
dispose: sub.unsubscribe,
|
||||
};
|
||||
return sub;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export class EdgelessClipboardWatcher extends LifeCycleWatcher {
|
||||
override mounted() {
|
||||
super.mounted();
|
||||
const { view } = this.std;
|
||||
view.viewUpdated.on(payload => {
|
||||
view.viewUpdated.subscribe(payload => {
|
||||
if (payload.type !== 'block' || payload.method !== 'add') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
Container,
|
||||
ServiceIdentifier,
|
||||
} from '@blocksuite/affine/global/di';
|
||||
import { DisposableGroup } from '@blocksuite/affine/global/slot';
|
||||
import { DisposableGroup } from '@blocksuite/affine/global/disposable';
|
||||
import {
|
||||
type ReferenceNodeConfig,
|
||||
ReferenceNodeConfigIdentifier,
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ const EdgelessNoteToggleButton = ({ note }: { note: NoteBlockModel }) => {
|
||||
|
||||
const { selection } = gfx;
|
||||
|
||||
const dispose = selection.slots.updated.on(() => {
|
||||
const dispose = selection.slots.updated.subscribe(() => {
|
||||
if (selection.has(note.id) && selection.editing) {
|
||||
note.doc.transact(() => {
|
||||
note.edgeless.collapse = false;
|
||||
@@ -65,7 +65,7 @@ const EdgelessNoteToggleButton = ({ note }: { note: NoteBlockModel }) => {
|
||||
}
|
||||
});
|
||||
|
||||
return () => dispose.dispose();
|
||||
return () => dispose.unsubscribe();
|
||||
}, [gfx, note]);
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user