mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
@@ -131,11 +131,13 @@ export const DocPropertyRow = ({
|
||||
typeInfo && 'value' in typeInfo ? typeInfo.value : undefined;
|
||||
|
||||
const handleChange = useCallback(
|
||||
(value: any) => {
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error('only allow string value');
|
||||
(value: any, skipCommit?: boolean) => {
|
||||
if (!skipCommit) {
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error('only allow string value');
|
||||
}
|
||||
docService.doc.record.setCustomProperty(propertyInfo.id, value);
|
||||
}
|
||||
docService.doc.record.setCustomProperty(propertyInfo.id, value);
|
||||
onChange?.(value);
|
||||
},
|
||||
[docService, onChange, propertyInfo]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { TagService, useDeleteTagConfirmModal } from '@affine/core/modules/tag';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import track from '@affine/track';
|
||||
import { TagsIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
LiveData,
|
||||
@@ -26,6 +25,7 @@ interface TagsEditorProps {
|
||||
interface TagsInlineEditorProps extends TagsEditorProps {
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
onChange?: (value: unknown) => void;
|
||||
}
|
||||
|
||||
export const TagsInlineEditor = ({
|
||||
@@ -33,19 +33,18 @@ export const TagsInlineEditor = ({
|
||||
readonly,
|
||||
placeholder,
|
||||
className,
|
||||
onChange,
|
||||
}: TagsInlineEditorProps) => {
|
||||
const workspace = useService(WorkspaceService);
|
||||
const tagService = useService(TagService);
|
||||
const tagIds = useLiveData(tagService.tagList.tagIdsByPageId$(pageId));
|
||||
const tagIds$ = tagService.tagList.tagIdsByPageId$(pageId);
|
||||
const tagIds = useLiveData(tagIds$);
|
||||
const tags = useLiveData(tagService.tagList.tags$);
|
||||
const tagColors = tagService.tagColors;
|
||||
|
||||
const onCreateTag = useCallback(
|
||||
(name: string, color: string) => {
|
||||
const newTag = tagService.tagList.createTag(name, color);
|
||||
track.doc.inlineDocInfo.property.editProperty({
|
||||
type: 'tags',
|
||||
});
|
||||
return {
|
||||
id: newTag.id,
|
||||
value: newTag.value$.value,
|
||||
@@ -58,21 +57,17 @@ export const TagsInlineEditor = ({
|
||||
const onSelectTag = useCallback(
|
||||
(tagId: string) => {
|
||||
tagService.tagList.tagByTagId$(tagId).value?.tag(pageId);
|
||||
track.doc.inlineDocInfo.property.editProperty({
|
||||
type: 'tags',
|
||||
});
|
||||
onChange?.(tagIds$.value);
|
||||
},
|
||||
[pageId, tagService.tagList]
|
||||
[onChange, pageId, tagIds$, tagService.tagList]
|
||||
);
|
||||
|
||||
const onDeselectTag = useCallback(
|
||||
(tagId: string) => {
|
||||
tagService.tagList.tagByTagId$(tagId).value?.untag(pageId);
|
||||
track.doc.inlineDocInfo.property.editProperty({
|
||||
type: 'tags',
|
||||
});
|
||||
onChange?.(tagIds$.value);
|
||||
},
|
||||
[pageId, tagService.tagList]
|
||||
[onChange, pageId, tagIds$, tagService.tagList]
|
||||
);
|
||||
|
||||
const onTagChange = useCallback(
|
||||
@@ -82,11 +77,9 @@ export const TagsInlineEditor = ({
|
||||
} else if (property === 'color') {
|
||||
tagService.tagList.tagByTagId$(id).value?.changeColor(value);
|
||||
}
|
||||
track.doc.inlineDocInfo.property.editProperty({
|
||||
type: 'tags',
|
||||
});
|
||||
onChange?.(tagIds$.value);
|
||||
},
|
||||
[tagService.tagList]
|
||||
[onChange, tagIds$, tagService.tagList]
|
||||
);
|
||||
|
||||
const deleteTags = useDeleteTagConfirmModal();
|
||||
@@ -94,11 +87,9 @@ export const TagsInlineEditor = ({
|
||||
const onTagDelete = useAsyncCallback(
|
||||
async (id: string) => {
|
||||
await deleteTags([id]);
|
||||
track.doc.inlineDocInfo.property.editProperty({
|
||||
type: 'tags',
|
||||
});
|
||||
onChange?.(tagIds$.value);
|
||||
},
|
||||
[deleteTags]
|
||||
[onChange, tagIds$, deleteTags]
|
||||
);
|
||||
|
||||
const adaptedTags = useLiveData(
|
||||
|
||||
@@ -10,8 +10,9 @@ import { DocService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import * as styles from './doc-primary-mode.css';
|
||||
import type { PropertyValueProps } from './types';
|
||||
|
||||
export const DocPrimaryModeValue = () => {
|
||||
export const DocPrimaryModeValue = ({ onChange }: PropertyValueProps) => {
|
||||
const t = useI18n();
|
||||
const doc = useService(DocService).doc;
|
||||
|
||||
@@ -44,8 +45,9 @@ export const DocPrimaryModeValue = () => {
|
||||
? t['com.affine.toastMessage.defaultMode.page.message']()
|
||||
: t['com.affine.toastMessage.defaultMode.edgeless.message'](),
|
||||
});
|
||||
onChange?.(mode, true);
|
||||
},
|
||||
[doc, t]
|
||||
[doc, t, onChange]
|
||||
);
|
||||
return (
|
||||
<PropertyValue className={styles.container} hoverable={false}>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DocService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import * as styles from './edgeless-theme.css';
|
||||
import type { PropertyValueProps } from './types';
|
||||
|
||||
const getThemeOptions = (t: ReturnType<typeof useI18n>) =>
|
||||
[
|
||||
@@ -21,7 +22,7 @@ const getThemeOptions = (t: ReturnType<typeof useI18n>) =>
|
||||
},
|
||||
] satisfies RadioItem[];
|
||||
|
||||
export const EdgelessThemeValue = () => {
|
||||
export const EdgelessThemeValue = ({ onChange }: PropertyValueProps) => {
|
||||
const t = useI18n();
|
||||
const doc = useService(DocService).doc;
|
||||
const edgelessTheme = useLiveData(doc.properties$).edgelessColorTheme;
|
||||
@@ -29,8 +30,9 @@ export const EdgelessThemeValue = () => {
|
||||
const handleChange = useCallback(
|
||||
(theme: string) => {
|
||||
doc.record.setProperty('edgelessColorTheme', theme);
|
||||
onChange?.(theme, true);
|
||||
},
|
||||
[doc]
|
||||
[doc, onChange]
|
||||
);
|
||||
const themeItems = useMemo<RadioItem[]>(() => getThemeOptions(t), [t]);
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@ import dayjs from 'dayjs';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import * as styles from './journal.css';
|
||||
import type { PropertyValueProps } from './types';
|
||||
|
||||
export const JournalValue = () => {
|
||||
export const JournalValue = ({ onChange }: PropertyValueProps) => {
|
||||
const t = useI18n();
|
||||
|
||||
const journalService = useService(JournalService);
|
||||
@@ -50,8 +51,9 @@ export const JournalValue = () => {
|
||||
const date = dayjs(day).format('YYYY-MM-DD');
|
||||
setSelectedDate(date);
|
||||
journalService.setJournalDate(doc.id, date);
|
||||
onChange?.(date, true);
|
||||
},
|
||||
[journalService, doc.id]
|
||||
[journalService, doc.id, onChange]
|
||||
);
|
||||
|
||||
const handleCheck = useCallback(
|
||||
@@ -59,11 +61,12 @@ export const JournalValue = () => {
|
||||
if (!v) {
|
||||
journalService.removeJournalDate(doc.id);
|
||||
setShowDatePicker(false);
|
||||
onChange?.(null, true);
|
||||
} else {
|
||||
handleDateSelect(selectedDate);
|
||||
}
|
||||
},
|
||||
[handleDateSelect, journalService, doc.id, selectedDate]
|
||||
[onChange, journalService, doc.id, handleDateSelect, selectedDate]
|
||||
);
|
||||
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
@@ -101,11 +104,7 @@ export const JournalValue = () => {
|
||||
onClick={toggle}
|
||||
>
|
||||
<div className={styles.root}>
|
||||
<Checkbox
|
||||
className={styles.checkbox}
|
||||
checked={checked}
|
||||
onChange={handleCheck}
|
||||
/>
|
||||
<Checkbox className={styles.checkbox} checked={checked} />
|
||||
{checked ? (
|
||||
<Menu
|
||||
contentOptions={{
|
||||
|
||||
@@ -5,9 +5,9 @@ import { DocService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { container } from './page-width.css';
|
||||
import type { PageLayoutMode } from './types';
|
||||
import type { PageLayoutMode, PropertyValueProps } from './types';
|
||||
|
||||
export const PageWidthValue = () => {
|
||||
export const PageWidthValue = ({ onChange }: PropertyValueProps) => {
|
||||
const t = useI18n();
|
||||
const editorSetting = useService(EditorSettingService).editorSetting;
|
||||
const defaultPageWidth = useLiveData(editorSetting.settings$).fullWidthLayout;
|
||||
@@ -44,8 +44,9 @@ export const PageWidthValue = () => {
|
||||
const handleChange = useCallback(
|
||||
(value: PageLayoutMode) => {
|
||||
doc.record.setProperty('pageWidth', value);
|
||||
onChange?.(value, true);
|
||||
},
|
||||
[doc]
|
||||
[doc, onChange]
|
||||
);
|
||||
return (
|
||||
<PropertyValue className={container} hoverable={false}>
|
||||
|
||||
@@ -5,8 +5,9 @@ import { DocService, useLiveData, useService } from '@toeverything/infra';
|
||||
|
||||
import { TagsInlineEditor } from '../tags-inline-editor';
|
||||
import * as styles from './tags.css';
|
||||
import type { PropertyValueProps } from './types';
|
||||
|
||||
export const TagsValue = () => {
|
||||
export const TagsValue = ({ onChange }: PropertyValueProps) => {
|
||||
const t = useI18n();
|
||||
|
||||
const doc = useService(DocService).doc;
|
||||
@@ -27,6 +28,7 @@ export const TagsValue = () => {
|
||||
'com.affine.page-properties.property-value-placeholder'
|
||||
]()}
|
||||
pageId={doc.id}
|
||||
onChange={value => onChange(value, true)}
|
||||
/>
|
||||
</PropertyValue>
|
||||
);
|
||||
|
||||
@@ -69,7 +69,6 @@ export const textInvisible = style({
|
||||
visibility: 'hidden',
|
||||
fontSize: cssVar('fontSm'),
|
||||
lineHeight: '22px',
|
||||
padding: `6px`,
|
||||
});
|
||||
|
||||
export const mobileTextInvisible = style([textInvisible, mobileTextareaBase]);
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { DocCustomPropertyInfo } from '@toeverything/infra';
|
||||
export interface PropertyValueProps {
|
||||
propertyInfo?: DocCustomPropertyInfo;
|
||||
value: any;
|
||||
onChange: (value: any) => void;
|
||||
onChange: (value: any, skipCommit?: boolean) => void; // if skipCommit is true, the change will be handled in the component itself
|
||||
}
|
||||
|
||||
export type PageLayoutMode = 'standard' | 'fullWidth';
|
||||
|
||||
@@ -72,6 +72,15 @@ export const InfoTable = ({
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onPropertyChange = useCallback(
|
||||
(property: DocCustomPropertyInfo, _value: unknown) => {
|
||||
track.$.docInfoPanel.property.editProperty({
|
||||
type: property.type,
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{backlinks && backlinks.length > 0 ? (
|
||||
@@ -122,6 +131,7 @@ export const InfoTable = ({
|
||||
key={property.id}
|
||||
propertyInfo={property}
|
||||
defaultOpenEditMenu={newPropertyId === property.id}
|
||||
onChange={value => onPropertyChange(property, value)}
|
||||
/>
|
||||
))}
|
||||
<Menu
|
||||
|
||||
Reference in New Issue
Block a user