mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 16:44:56 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6a26b8093 | ||
|
|
5e05952f6e | ||
|
|
c1930c5937 | ||
|
|
b7ebd33389 | ||
|
|
de9a3e1428 | ||
|
|
374eee9196 | ||
|
|
1bdccdbd57 | ||
|
|
053efb61f0 | ||
|
|
c7aebd0412 | ||
|
|
01aa6979eb | ||
|
|
c32f7c7964 |
@@ -886,8 +886,8 @@
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Enable indexer plugin\n@default true\n@environment `AFFINE_INDEXER_ENABLED`",
|
||||
"default": true
|
||||
"description": "Enable indexer plugin\n@default false\n@environment `AFFINE_INDEXER_ENABLED`",
|
||||
"default": false
|
||||
},
|
||||
"provider.type": {
|
||||
"type": "string",
|
||||
|
||||
1
.github/workflows/build-images.yml
vendored
1
.github/workflows/build-images.yml
vendored
@@ -113,6 +113,7 @@ jobs:
|
||||
build-server-native:
|
||||
name: Build Server native - ${{ matrix.targets.name }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ github.event.inputs.flavor }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
1
.github/workflows/build-test.yml
vendored
1
.github/workflows/build-test.yml
vendored
@@ -20,6 +20,7 @@ env:
|
||||
COVERAGE: true
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.13'
|
||||
DEPLOYMENT_TYPE: affine
|
||||
AFFINE_INDEXER_ENABLED: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
AttachmentBlockStyles,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
CitationProvider,
|
||||
DocModeProvider,
|
||||
FileSizeLimitProvider,
|
||||
TelemetryProvider,
|
||||
@@ -37,6 +38,7 @@ import { type ClassInfo, classMap } from 'lit/directives/class-map.js';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { when } from 'lit/directives/when.js';
|
||||
import { filter } from 'rxjs/operators';
|
||||
|
||||
import { AttachmentEmbedProvider } from './embed';
|
||||
import { styles } from './styles';
|
||||
@@ -79,8 +81,12 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
|
||||
return this.std.get(FileSizeLimitProvider).maxFileSize;
|
||||
}
|
||||
|
||||
get citationService() {
|
||||
return this.std.get(CitationProvider);
|
||||
}
|
||||
|
||||
get isCitation() {
|
||||
return !!this.model.props.footnoteIdentifier;
|
||||
return this.citationService.isCitationModel(this.model);
|
||||
}
|
||||
|
||||
convertTo = () => {
|
||||
@@ -139,6 +145,34 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
|
||||
selectionManager.setGroup('note', [blockSelection]);
|
||||
}
|
||||
|
||||
private readonly _trackCitationDeleteEvent = () => {
|
||||
// Check citation delete event
|
||||
this._disposables.add(
|
||||
this.std.store.slots.blockUpdated
|
||||
.pipe(
|
||||
filter(payload => {
|
||||
if (!payload.isLocal) return false;
|
||||
|
||||
const { flavour, id, type } = payload;
|
||||
if (
|
||||
type !== 'delete' ||
|
||||
flavour !== this.model.flavour ||
|
||||
id !== this.model.id
|
||||
)
|
||||
return false;
|
||||
|
||||
const { model } = payload;
|
||||
if (!this.citationService.isCitationModel(model)) return false;
|
||||
|
||||
return true;
|
||||
})
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.citationService.trackEvent('Delete');
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -162,6 +196,8 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<Attachment
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this._trackCitationDeleteEvent();
|
||||
}
|
||||
|
||||
override firstUpdated() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ConfirmIcon } from '@blocksuite/affine-components/icons';
|
||||
import { toast } from '@blocksuite/affine-components/toast';
|
||||
import type { AttachmentBlockModel } from '@blocksuite/affine-model';
|
||||
import { CitationProvider } from '@blocksuite/affine-shared/services';
|
||||
import type { EditorHost } from '@blocksuite/std';
|
||||
import { html } from 'lit';
|
||||
import { createRef, ref } from 'lit/directives/ref.js';
|
||||
@@ -33,6 +34,7 @@ export const RenameModal = ({
|
||||
|
||||
let fileName = includeExtension ? nameWithoutExtension : originalName;
|
||||
const extension = includeExtension ? originalExtension : '';
|
||||
const citationService = editorHost.std.get(CitationProvider);
|
||||
|
||||
const abort = () => abortController.abort();
|
||||
const onConfirm = () => {
|
||||
@@ -44,6 +46,9 @@ export const RenameModal = ({
|
||||
model.store.updateBlock(model, {
|
||||
name: newFileName,
|
||||
});
|
||||
if (citationService.isCitationModel(model)) {
|
||||
citationService.trackEvent('Edit');
|
||||
}
|
||||
abort();
|
||||
};
|
||||
const onInput = (e: InputEvent) => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
} from '@blocksuite/affine-model';
|
||||
import { ImageProxyService } from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
CitationProvider,
|
||||
DocModeProvider,
|
||||
LinkPreviewServiceIdentifier,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
@@ -18,6 +19,7 @@ import { html } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
import { type ClassInfo, classMap } from 'lit/directives/class-map.js';
|
||||
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
import { filter } from 'rxjs/operators';
|
||||
|
||||
import { refreshBookmarkUrlData } from './utils.js';
|
||||
|
||||
@@ -114,11 +116,12 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
|
||||
);
|
||||
};
|
||||
|
||||
get citationService() {
|
||||
return this.std.get(CitationProvider);
|
||||
}
|
||||
|
||||
get isCitation() {
|
||||
return (
|
||||
!!this.model.props.footnoteIdentifier &&
|
||||
this.model.props.style === 'citation'
|
||||
);
|
||||
return this.citationService.isCitationModel(this.model);
|
||||
}
|
||||
|
||||
get imageProxyService() {
|
||||
@@ -166,6 +169,31 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
|
||||
></bookmark-card>`;
|
||||
};
|
||||
|
||||
private readonly _trackCitationDeleteEvent = () => {
|
||||
// Check citation delete event
|
||||
this._disposables.add(
|
||||
this.std.store.slots.blockUpdated
|
||||
.pipe(
|
||||
filter(payload => {
|
||||
if (!payload.isLocal) return false;
|
||||
const { flavour, id, type } = payload;
|
||||
if (
|
||||
type !== 'delete' ||
|
||||
flavour !== this.model.flavour ||
|
||||
id !== this.model.id
|
||||
)
|
||||
return false;
|
||||
const { model } = payload;
|
||||
if (!this.citationService.isCitationModel(model)) return false;
|
||||
return true;
|
||||
})
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.citationService.trackEvent('Delete');
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -203,6 +231,8 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this._trackCitationDeleteEvent();
|
||||
}
|
||||
|
||||
override disconnectedCallback(): void {
|
||||
|
||||
@@ -40,6 +40,16 @@ export class CodeBlockComponent extends CaptionedBlockComponent<CodeBlockModel>
|
||||
|
||||
private _inlineRangeProvider: InlineRangeProvider | null = null;
|
||||
|
||||
private readonly _localPreview$ = signal<boolean | null>(null);
|
||||
|
||||
preview$: Signal<boolean> = computed(() => {
|
||||
const modelPreview = !!this.model.props.preview$.value;
|
||||
if (this.store.readonly) {
|
||||
return this._localPreview$.value ?? modelPreview;
|
||||
}
|
||||
return modelPreview;
|
||||
});
|
||||
|
||||
highlightTokens$: Signal<ThemedToken[][]> = signal([]);
|
||||
|
||||
languageName$: Signal<string> = computed(() => {
|
||||
@@ -393,7 +403,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<CodeBlockModel>
|
||||
true) &&
|
||||
(this.model.props.lineNumber ?? true);
|
||||
|
||||
const preview = !!this.model.props.preview;
|
||||
const preview = this.preview$.value;
|
||||
const previewContext = this.std.getOptional(
|
||||
CodeBlockPreviewIdentifier(this.model.props.language ?? '')
|
||||
);
|
||||
@@ -461,6 +471,14 @@ export class CodeBlockComponent extends CaptionedBlockComponent<CodeBlockModel>
|
||||
override accessor useCaptionEditor = true;
|
||||
|
||||
override accessor useZeroWidth = true;
|
||||
|
||||
setPreviewState(preview: boolean) {
|
||||
if (this.store.readonly) {
|
||||
this._localPreview$.value = preview;
|
||||
} else {
|
||||
this.store.updateBlock(this.model, { preview });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -58,11 +58,7 @@ export class PreviewButton extends WithDisposable(SignalWatcher(LitElement)) {
|
||||
`;
|
||||
|
||||
private readonly _toggle = (value: boolean) => {
|
||||
if (this.blockComponent.store.readonly) return;
|
||||
|
||||
this.blockComponent.store.updateBlock(this.blockComponent.model, {
|
||||
preview: value,
|
||||
});
|
||||
this.blockComponent.setPreviewState(value);
|
||||
|
||||
const std = this.blockComponent.std;
|
||||
const mode = std.getOptional(DocModeProvider)?.getEditorMode() ?? 'page';
|
||||
@@ -77,7 +73,7 @@ export class PreviewButton extends WithDisposable(SignalWatcher(LitElement)) {
|
||||
};
|
||||
|
||||
get preview() {
|
||||
return !!this.blockComponent.model.props.preview$.value;
|
||||
return this.blockComponent.preview$.value;
|
||||
}
|
||||
|
||||
override render() {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
REFERENCE_NODE,
|
||||
} from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
CitationProvider,
|
||||
DocDisplayMetaProvider,
|
||||
DocModeProvider,
|
||||
OpenDocExtensionIdentifier,
|
||||
@@ -43,6 +44,7 @@ import { repeat } from 'lit/directives/repeat.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { when } from 'lit/directives/when.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { renderLinkedDocInCard } from '../common/render-linked-doc';
|
||||
@@ -254,11 +256,12 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
|
||||
return this.store.readonly;
|
||||
}
|
||||
|
||||
get citationService() {
|
||||
return this.std.get(CitationProvider);
|
||||
}
|
||||
|
||||
get isCitation() {
|
||||
return (
|
||||
!!this.model.props.footnoteIdentifier &&
|
||||
this.model.props.style === 'citation'
|
||||
);
|
||||
return this.citationService.isCitationModel(this.model);
|
||||
}
|
||||
|
||||
private readonly _handleDoubleClick = (event: MouseEvent) => {
|
||||
@@ -454,6 +457,31 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
|
||||
);
|
||||
};
|
||||
|
||||
private readonly _trackCitationDeleteEvent = () => {
|
||||
// Check citation delete event
|
||||
this._disposables.add(
|
||||
this.std.store.slots.blockUpdated
|
||||
.pipe(
|
||||
filter(payload => {
|
||||
if (!payload.isLocal) return false;
|
||||
const { flavour, id, type } = payload;
|
||||
if (
|
||||
type !== 'delete' ||
|
||||
flavour !== this.model.flavour ||
|
||||
id !== this.model.id
|
||||
)
|
||||
return false;
|
||||
const { model } = payload;
|
||||
if (!this.citationService.isCitationModel(model)) return false;
|
||||
return true;
|
||||
})
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.citationService.trackEvent('Delete');
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -532,6 +560,8 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this._trackCitationDeleteEvent();
|
||||
}
|
||||
|
||||
getInitialState(): {
|
||||
|
||||
@@ -7,7 +7,10 @@ import {
|
||||
BLOCK_CHILDREN_CONTAINER_PADDING_LEFT,
|
||||
EDGELESS_TOP_CONTENTEDITABLE_SELECTOR,
|
||||
} from '@blocksuite/affine-shared/consts';
|
||||
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
CitationProvider,
|
||||
DocModeProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
calculateCollapsedSiblings,
|
||||
getNearestHeadingBefore,
|
||||
@@ -63,6 +66,10 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<ParagraphBl
|
||||
?.getPlaceholder(this.model);
|
||||
}
|
||||
|
||||
get citationService() {
|
||||
return this.std.get(CitationProvider);
|
||||
}
|
||||
|
||||
get attributeRenderer() {
|
||||
return this.inlineManager.getRenderer();
|
||||
}
|
||||
@@ -94,6 +101,12 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<ParagraphBl
|
||||
return this.std.get(DefaultInlineManagerExtension.identifier);
|
||||
}
|
||||
|
||||
get hasCitationSiblings() {
|
||||
return this.collapsedSiblings.some(sibling =>
|
||||
this.citationService.isCitationModel(sibling)
|
||||
);
|
||||
}
|
||||
|
||||
override get topContenteditableElement() {
|
||||
if (this.std.get(DocModeProvider).getEditorMode() === 'edgeless') {
|
||||
return this.closest<BlockComponent>(
|
||||
@@ -286,6 +299,13 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<ParagraphBl
|
||||
collapsed: value,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.hasCitationSiblings) {
|
||||
this.citationService.trackEvent('Expand', {
|
||||
control: 'Source Button',
|
||||
type: value ? 'Hide' : 'Show',
|
||||
});
|
||||
}
|
||||
}}
|
||||
></blocksuite-toggle-button>
|
||||
`
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '@blocksuite/affine-ext-loader';
|
||||
import {
|
||||
AutoClearSelectionService,
|
||||
CitationService,
|
||||
DefaultOpenDocExtension,
|
||||
DNDAPIExtension,
|
||||
DocDisplayMetaService,
|
||||
@@ -76,6 +77,7 @@ export class FoundationViewExtension extends ViewExtensionProvider<FoundationVie
|
||||
FileSizeLimitService,
|
||||
LinkPreviewCache,
|
||||
LinkPreviewService,
|
||||
CitationService,
|
||||
]);
|
||||
context.register(clipboardConfigs);
|
||||
if (this.isEdgeless(context.scope)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { HoverController } from '@blocksuite/affine-components/hover';
|
||||
import { PeekViewProvider } from '@blocksuite/affine-components/peek';
|
||||
import type { FootNote } from '@blocksuite/affine-model';
|
||||
import { CitationProvider } from '@blocksuite/affine-shared/services';
|
||||
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
@@ -117,6 +118,10 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) {
|
||||
return this.std.store.readonly;
|
||||
}
|
||||
|
||||
get citationService() {
|
||||
return this.std.get(CitationProvider);
|
||||
}
|
||||
|
||||
onFootnoteClick = () => {
|
||||
if (!this.footnote) {
|
||||
return;
|
||||
@@ -215,6 +220,10 @@ export class AffineFootnoteNode extends WithDisposable(ShadowlessElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.citationService.trackEvent('Hover', {
|
||||
control: 'Source Footnote',
|
||||
});
|
||||
|
||||
return {
|
||||
template: this._FootNotePopup(footnote, abortController),
|
||||
container: this.std.host,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { type Container, createIdentifier } from '@blocksuite/global/di';
|
||||
import { type BlockStdScope, StdIdentifier } from '@blocksuite/std';
|
||||
import { type BlockModel, Extension } from '@blocksuite/store';
|
||||
|
||||
import { DocModeProvider } from '../doc-mode-service';
|
||||
import type {
|
||||
CitationEvents,
|
||||
CitationEventType,
|
||||
} from '../telemetry-service/citation';
|
||||
import { TelemetryProvider } from '../telemetry-service/telemetry-service';
|
||||
|
||||
const CitationEventTypeMap = {
|
||||
Hover: 'AICitationHoverSource',
|
||||
Expand: 'AICitationExpandSource',
|
||||
Delete: 'AICitationDelete',
|
||||
Edit: 'AICitationEdit',
|
||||
} as const;
|
||||
|
||||
type EventType = keyof typeof CitationEventTypeMap;
|
||||
|
||||
type EventTypeMapping = {
|
||||
[K in EventType]: CitationEventType;
|
||||
};
|
||||
|
||||
export interface CitationViewService {
|
||||
/**
|
||||
* Tracks citation-related events
|
||||
* @param type - The type of citation event to track
|
||||
* @param properties - The properties of the event
|
||||
*/
|
||||
trackEvent<T extends EventType>(
|
||||
type: T,
|
||||
properties?: CitationEvents[EventTypeMapping[T]]
|
||||
): void;
|
||||
/**
|
||||
* Checks if the model is a citation model
|
||||
* @param model - The model to check
|
||||
* @returns True if the model is a citation model, false otherwise
|
||||
*/
|
||||
isCitationModel(model: BlockModel): boolean;
|
||||
}
|
||||
|
||||
export const CitationProvider =
|
||||
createIdentifier<CitationViewService>('CitationService');
|
||||
|
||||
export class CitationService extends Extension implements CitationViewService {
|
||||
constructor(private readonly std: BlockStdScope) {
|
||||
super();
|
||||
}
|
||||
|
||||
static override setup(di: Container) {
|
||||
di.addImpl(CitationProvider, CitationService, [StdIdentifier]);
|
||||
}
|
||||
|
||||
get docModeService() {
|
||||
return this.std.getOptional(DocModeProvider);
|
||||
}
|
||||
|
||||
get telemetryService() {
|
||||
return this.std.getOptional(TelemetryProvider);
|
||||
}
|
||||
|
||||
isCitationModel = (model: BlockModel) => {
|
||||
return (
|
||||
'footnoteIdentifier' in model.props &&
|
||||
!!model.props.footnoteIdentifier &&
|
||||
'style' in model.props &&
|
||||
model.props.style === 'citation'
|
||||
);
|
||||
};
|
||||
|
||||
trackEvent<T extends EventType>(
|
||||
type: T,
|
||||
properties?: CitationEvents[EventTypeMapping[T]]
|
||||
) {
|
||||
const editorMode = this.docModeService?.getEditorMode() ?? 'page';
|
||||
this.telemetryService?.track(CitationEventTypeMap[type], {
|
||||
page: editorMode === 'page' ? 'doc editor' : 'whiteboard editor',
|
||||
module: 'AI Result',
|
||||
control: 'Source',
|
||||
...properties,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './citation-service';
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './auto-clear-selection-service';
|
||||
export * from './block-meta-service';
|
||||
export * from './citation-service';
|
||||
export * from './doc-display-meta-service';
|
||||
export * from './doc-mode-service';
|
||||
export * from './drag-handle-config';
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { TelemetryEvent } from './types';
|
||||
export type CitationEventType =
|
||||
| 'AICitationHoverSource'
|
||||
| 'AICitationExpandSource'
|
||||
| 'AICitationDelete'
|
||||
| 'AICitationEdit';
|
||||
|
||||
export type CitationEvents = Record<CitationEventType, TelemetryEvent>;
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './citation.js';
|
||||
export * from './database.js';
|
||||
export * from './link.js';
|
||||
export * from './telemetry-service.js';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createIdentifier } from '@blocksuite/global/di';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import type { CitationEvents } from './citation.js';
|
||||
import type { CodeBlockEvents } from './code-block.js';
|
||||
import type { OutDatabaseAllEvents } from './database.js';
|
||||
import type { LinkToolbarEvents } from './link.js';
|
||||
@@ -28,7 +29,8 @@ export type TelemetryEventMap = OutDatabaseAllEvents &
|
||||
LinkToolbarEvents &
|
||||
SlashMenuEvents &
|
||||
CodeBlockEvents &
|
||||
NoteEvents & {
|
||||
NoteEvents &
|
||||
CitationEvents & {
|
||||
DocCreated: DocCreatedEvent;
|
||||
Link: TelemetryEvent;
|
||||
LinkedDocCreated: LinkedDocCreatedEvent;
|
||||
|
||||
@@ -220,6 +220,12 @@ export class UIEventDispatcher extends LifeCycleWatcher {
|
||||
|
||||
this._setActive(false);
|
||||
});
|
||||
// When the document is hidden, the event dispatcher should be inactive
|
||||
this.disposables.addFromEvent(document, 'visibilitychange', () => {
|
||||
if (document.visibilityState === 'hidden') {
|
||||
this._setActive(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _buildEventScopeBySelection(name: EventName) {
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"@vitest/coverage-istanbul": "3.1.3",
|
||||
"@vitest/ui": "3.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^36.0.0",
|
||||
"electron": "^35.0.0",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-import-resolver-typescript": "^4.0.0",
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
# MAILER_SENDER="noreply@toeverything.info"
|
||||
# MAILER_USER="noreply@toeverything.info"
|
||||
# MAILER_PASSWORD="affine"
|
||||
# MAILER_SECURE=false
|
||||
# MAILER_SECURE=false
|
||||
|
||||
# AFFINE_INDEXER_ENABLED=true
|
||||
|
||||
@@ -67,12 +67,18 @@ function fixFailedMigrations() {
|
||||
) ||
|
||||
err.message.includes(
|
||||
'cannot be rolled back because it was never applied'
|
||||
) ||
|
||||
err.message.includes(
|
||||
'called markMigrationRolledBack on a database without migrations table'
|
||||
)
|
||||
) {
|
||||
// migration has been rolled back, skip it
|
||||
continue;
|
||||
}
|
||||
throw err;
|
||||
// ignore other errors
|
||||
console.log(
|
||||
`migration [${migration}] rolled back failed. ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,19 @@ import Sinon from 'sinon';
|
||||
|
||||
import { createModule } from '../../../__tests__/create-module';
|
||||
import { Config } from '../../../base';
|
||||
import { ConfigModule } from '../../../base/config';
|
||||
import { IndexerModule } from '..';
|
||||
import { IndexerEvent } from '../event';
|
||||
|
||||
const module = await createModule({
|
||||
imports: [IndexerModule],
|
||||
imports: [
|
||||
IndexerModule,
|
||||
ConfigModule.override({
|
||||
indexer: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
const indexerEvent = module.get(IndexerEvent);
|
||||
const config = module.get(Config);
|
||||
|
||||
@@ -7,6 +7,7 @@ import Sinon from 'sinon';
|
||||
import { createModule } from '../../../__tests__/create-module';
|
||||
import { Mockers } from '../../../__tests__/mocks';
|
||||
import { JOB_SIGNAL } from '../../../base';
|
||||
import { ConfigModule } from '../../../base/config';
|
||||
import { ServerConfigModule } from '../../../core/config';
|
||||
import { Models } from '../../../models';
|
||||
import { IndexerModule, IndexerService } from '..';
|
||||
@@ -15,7 +16,15 @@ import { IndexerJob } from '../job';
|
||||
import { ManticoresearchProvider } from '../providers';
|
||||
|
||||
const module = await createModule({
|
||||
imports: [IndexerModule, ServerConfigModule],
|
||||
imports: [
|
||||
IndexerModule,
|
||||
ServerConfigModule,
|
||||
ConfigModule.override({
|
||||
indexer: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [IndexerService],
|
||||
});
|
||||
const indexerService = module.get(IndexerService);
|
||||
|
||||
@@ -33,6 +33,7 @@ _test.before(async () => {
|
||||
IndexerModule,
|
||||
ConfigModule.override({
|
||||
indexer: {
|
||||
enabled: true,
|
||||
provider: {
|
||||
type: SearchProviderType.Elasticsearch,
|
||||
endpoint: 'http://localhost:9200',
|
||||
|
||||
@@ -18,6 +18,7 @@ const module = await createModule({
|
||||
IndexerModule,
|
||||
ConfigModule.override({
|
||||
indexer: {
|
||||
enabled: true,
|
||||
provider: {
|
||||
type: SearchProviderType.Manticoresearch,
|
||||
endpoint: 'http://localhost:9308',
|
||||
|
||||
@@ -6,6 +6,7 @@ import { omit, pick } from 'lodash-es';
|
||||
|
||||
import { createModule } from '../../../__tests__/create-module';
|
||||
import { Mockers } from '../../../__tests__/mocks';
|
||||
import { ConfigModule } from '../../../base/config';
|
||||
import { ServerConfigModule } from '../../../core/config';
|
||||
import { IndexerModule, IndexerService } from '..';
|
||||
import { SearchProviderFactory } from '../factory';
|
||||
@@ -20,7 +21,15 @@ import {
|
||||
} from '../types';
|
||||
|
||||
const module = await createModule({
|
||||
imports: [IndexerModule, ServerConfigModule],
|
||||
imports: [
|
||||
IndexerModule,
|
||||
ServerConfigModule,
|
||||
ConfigModule.override({
|
||||
indexer: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [IndexerService],
|
||||
});
|
||||
const indexerService = module.get(IndexerService);
|
||||
|
||||
@@ -30,7 +30,7 @@ declare global {
|
||||
defineModuleConfig('indexer', {
|
||||
enabled: {
|
||||
desc: 'Enable indexer plugin',
|
||||
default: true,
|
||||
default: false,
|
||||
env: ['AFFINE_INDEXER_ENABLED', 'boolean'],
|
||||
},
|
||||
'provider.type': {
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"builder-util-runtime": "^9.2.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"debug": "^4.4.0",
|
||||
"electron": "^36.0.0",
|
||||
"electron": "^35.0.0",
|
||||
"electron-log": "^5.2.4",
|
||||
"electron-squirrel-startup": "1.0.1",
|
||||
"electron-window-state": "^5.0.3",
|
||||
|
||||
@@ -51,6 +51,7 @@ import { getSelectedModelsCommand } from '@blocksuite/affine/shared/commands';
|
||||
import { ImageSelection } from '@blocksuite/affine/shared/selection';
|
||||
import {
|
||||
ActionPlacement,
|
||||
CitationProvider,
|
||||
GenerateDocUrlProvider,
|
||||
isRemovedUserInfo,
|
||||
OpenDocExtensionIdentifier,
|
||||
@@ -462,6 +463,10 @@ function createExternalLinkableToolbarConfig(
|
||||
(_std, _component, props) => {
|
||||
ctx.store.updateBlock(model, props);
|
||||
block.requestUpdate();
|
||||
const citationService = ctx.std.get(CitationProvider);
|
||||
if (citationService.isCitationModel(model)) {
|
||||
citationService.trackEvent('Edit');
|
||||
}
|
||||
},
|
||||
abortController
|
||||
);
|
||||
@@ -805,6 +810,10 @@ const embedLinkedDocToolbarConfig = {
|
||||
(_std, _component, props) => {
|
||||
ctx.store.updateBlock(model, props);
|
||||
block.requestUpdate();
|
||||
const citationService = ctx.std.get(CitationProvider);
|
||||
if (citationService.isCitationModel(model)) {
|
||||
citationService.trackEvent('Edit');
|
||||
}
|
||||
},
|
||||
abortController
|
||||
);
|
||||
|
||||
@@ -21,6 +21,9 @@ export const menuTriggerStyle = style({
|
||||
});
|
||||
export const menuTriggerText = style({
|
||||
margin: '0px 4px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
});
|
||||
export const suffixClassName = style({
|
||||
width: '20px',
|
||||
|
||||
@@ -3,10 +3,11 @@ import {
|
||||
LiveData,
|
||||
Store,
|
||||
yjsGetPath,
|
||||
yjsObserveDeep,
|
||||
yjsObservePath,
|
||||
} from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { map, Observable, switchMap } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs';
|
||||
import { Array as YArray } from 'yjs';
|
||||
|
||||
import type { WorkspaceService } from '../../workspace';
|
||||
@@ -24,15 +25,22 @@ export class TagStore extends Store {
|
||||
get properties() {
|
||||
return this.workspaceService.workspace.docCollection.meta.properties;
|
||||
}
|
||||
get tagOptions() {
|
||||
return this.properties.tags?.options ?? [];
|
||||
}
|
||||
|
||||
tagOptions$ = LiveData.from(
|
||||
new Observable<Tag[]>(sub => {
|
||||
return this.subscribe(() => sub.next(this.tagOptions));
|
||||
}),
|
||||
this.tagOptions
|
||||
yjsGetPath(
|
||||
this.workspaceService.workspace.rootYDoc.getMap('meta'),
|
||||
'properties.tags.options'
|
||||
).pipe(
|
||||
switchMap(yjsObserveDeep),
|
||||
map(tagOptions => {
|
||||
if (tagOptions instanceof YArray) {
|
||||
return tagOptions.toJSON();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
subscribe(cb: () => void) {
|
||||
@@ -82,12 +90,14 @@ export class TagStore extends Store {
|
||||
};
|
||||
|
||||
updateTagOption = (id: string, option: Tag) => {
|
||||
this.updateTagOptions(this.tagOptions.map(o => (o.id === id ? option : o)));
|
||||
this.updateTagOptions(
|
||||
this.tagOptions$.value.map(o => (o.id === id ? option : o))
|
||||
);
|
||||
};
|
||||
|
||||
removeTagOption = (id: string) => {
|
||||
this.workspaceService.workspace.docCollection.doc.transact(() => {
|
||||
this.updateTagOptions(this.tagOptions.filter(o => o.id !== id));
|
||||
this.updateTagOptions(this.tagOptions$.value.filter(o => o.id !== id));
|
||||
// need to remove tag from all pages
|
||||
this.workspaceService.workspace.docCollection.docs.forEach(doc => {
|
||||
const tags = doc.meta?.tags ?? [];
|
||||
|
||||
59
yarn.lock
59
yarn.lock
@@ -573,7 +573,7 @@ __metadata:
|
||||
builder-util-runtime: "npm:^9.2.10"
|
||||
cross-env: "npm:^7.0.3"
|
||||
debug: "npm:^4.4.0"
|
||||
electron: "npm:^36.0.0"
|
||||
electron: "npm:^35.0.0"
|
||||
electron-log: "npm:^5.2.4"
|
||||
electron-squirrel-startup: "npm:1.0.1"
|
||||
electron-updater: "npm:^6.3.9"
|
||||
@@ -776,7 +776,7 @@ __metadata:
|
||||
"@vitest/coverage-istanbul": "npm:3.1.3"
|
||||
"@vitest/ui": "npm:3.1.3"
|
||||
cross-env: "npm:^7.0.3"
|
||||
electron: "npm:^36.0.0"
|
||||
electron: "npm:^35.0.0"
|
||||
eslint: "npm:^9.16.0"
|
||||
eslint-config-prettier: "npm:^10.0.0"
|
||||
eslint-import-resolver-typescript: "npm:^4.0.0"
|
||||
@@ -8968,14 +8968,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@nestjs-cls/transactional-adapter-prisma@npm:^1.2.19":
|
||||
version: 1.2.21
|
||||
resolution: "@nestjs-cls/transactional-adapter-prisma@npm:1.2.21"
|
||||
version: 1.2.23
|
||||
resolution: "@nestjs-cls/transactional-adapter-prisma@npm:1.2.23"
|
||||
peerDependencies:
|
||||
"@nestjs-cls/transactional": ^3.0.0
|
||||
"@nestjs-cls/transactional": ^3.0.2
|
||||
"@prisma/client": "> 4 < 7"
|
||||
nestjs-cls: ^6.0.0
|
||||
nestjs-cls: ^6.0.1
|
||||
prisma: "> 4 < 7"
|
||||
checksum: 10/3a0e6ed43ab97b6f94a859bcb9c71d79034f5c1ded1038204e374f170f81ea198ec93793c05b70d556342e4cec3d9fbd4e792f544f229572474bc10231b6a0ae
|
||||
checksum: 10/98228a8fe132951095082b1657d73889ecbf564c4426bfc1b1daf6b0cdcfd29a9f243a77f1c9021edff5484e44664bc224b4337b6db3da188a6a969640a65a15
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19148,6 +19148,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"concat-stream@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "concat-stream@npm:2.0.0"
|
||||
dependencies:
|
||||
buffer-from: "npm:^1.0.0"
|
||||
inherits: "npm:^2.0.3"
|
||||
readable-stream: "npm:^3.0.2"
|
||||
typedarray: "npm:^0.0.6"
|
||||
checksum: 10/250e576d0617e7c58e1c4b2dd6fe69560f316d2c962a409f9f3aac794018499ddb31948b1e4296f217008e124cd5d526432097745157fe504b5d9f3dc469eadb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"concordance@npm:^5.0.4":
|
||||
version: 5.0.4
|
||||
resolution: "concordance@npm:5.0.4"
|
||||
@@ -20595,16 +20607,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron@npm:^36.0.0":
|
||||
version: 36.2.1
|
||||
resolution: "electron@npm:36.2.1"
|
||||
"electron@npm:^35.0.0":
|
||||
version: 35.5.1
|
||||
resolution: "electron@npm:35.5.1"
|
||||
dependencies:
|
||||
"@electron/get": "npm:^2.0.0"
|
||||
"@types/node": "npm:^22.7.7"
|
||||
extract-zip: "npm:^2.0.1"
|
||||
bin:
|
||||
electron: cli.js
|
||||
checksum: 10/2dbcac9208c6a513b75ef92a969441407e44fb11377a3d831d3e043d3c5e1bf927badc475a490b554e6007995f1a28db9d833044202d21d629bb84587745dbf7
|
||||
checksum: 10/765752c94c3bea799f62fb0a75049a10452ff97e791a96111f36b97293ffed9240b27dbc083c01f7a2c7172e84b6b394b07c9aaf91d57783958b2adb4e570579
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27077,7 +27089,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.4":
|
||||
"mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.6":
|
||||
version: 0.5.6
|
||||
resolution: "mkdirp@npm:0.5.6"
|
||||
dependencies:
|
||||
@@ -27253,7 +27265,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multer@npm:2.0.0, multer@npm:^2.0.0":
|
||||
"multer@npm:2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "multer@npm:2.0.0"
|
||||
dependencies:
|
||||
@@ -27268,6 +27280,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multer@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "multer@npm:2.0.1"
|
||||
dependencies:
|
||||
append-field: "npm:^1.0.0"
|
||||
busboy: "npm:^1.6.0"
|
||||
concat-stream: "npm:^2.0.0"
|
||||
mkdirp: "npm:^0.5.6"
|
||||
object-assign: "npm:^4.1.1"
|
||||
type-is: "npm:^1.6.18"
|
||||
xtend: "npm:^4.0.2"
|
||||
checksum: 10/cb0dda65ae37be40968fc1f9ea492bdb4c20bd189ce427e11e95d333837193544606b82ef6431f2acd3cd11156164f215bdeb46f47847d29b6bf3a36ac736a8f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multicast-dns@npm:^7.2.5":
|
||||
version: 7.2.5
|
||||
resolution: "multicast-dns@npm:7.2.5"
|
||||
@@ -30208,7 +30235,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"readable-stream@npm:3, readable-stream@npm:^3.0.6, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.2":
|
||||
"readable-stream@npm:3, readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.2":
|
||||
version: 3.6.2
|
||||
resolution: "readable-stream@npm:3.6.2"
|
||||
dependencies:
|
||||
@@ -33358,7 +33385,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"type-is@npm:^1.6.4, type-is@npm:~1.6.18":
|
||||
"type-is@npm:^1.6.18, type-is@npm:^1.6.4, type-is@npm:~1.6.18":
|
||||
version: 1.6.18
|
||||
resolution: "type-is@npm:1.6.18"
|
||||
dependencies:
|
||||
@@ -34902,7 +34929,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"xtend@npm:^4.0.0":
|
||||
"xtend@npm:^4.0.0, xtend@npm:^4.0.2":
|
||||
version: 4.0.2
|
||||
resolution: "xtend@npm:4.0.2"
|
||||
checksum: 10/ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a
|
||||
|
||||
Reference in New Issue
Block a user