mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-30 00:29:46 +08:00
feat(core): readwise integration tags setting (#10946)
close AF-2307, AF-2262
This commit is contained in:
+25
@@ -79,3 +79,28 @@ export const updateStrategyGroup = style({
|
||||
export const updateStrategyGroupContent = style({
|
||||
overflow: 'hidden',
|
||||
});
|
||||
|
||||
export const tagsLabel = style({
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
lineHeight: '22px',
|
||||
color: cssVarV2.text.primary,
|
||||
marginBottom: 2,
|
||||
});
|
||||
|
||||
export const tagsEditor = style({
|
||||
padding: '6px 8px',
|
||||
borderRadius: 4,
|
||||
border: `1px solid ${cssVarV2.layer.insideBorder.border}`,
|
||||
fontSize: 14,
|
||||
});
|
||||
export const tagsPlaceholder = style({
|
||||
fontSize: 14,
|
||||
lineHeight: '22px',
|
||||
color: cssVarV2.text.placeholder,
|
||||
});
|
||||
export const tagsMenu = style({
|
||||
left: -1,
|
||||
top: 'calc(-1px + var(--radix-popper-anchor-height) * -1)',
|
||||
width: 'calc(2px + var(--radix-popper-anchor-width))',
|
||||
});
|
||||
|
||||
+107
-1
@@ -1,11 +1,13 @@
|
||||
import { Button, Modal } from '@affine/component';
|
||||
import { type TagLike, TagsInlineEditor } from '@affine/core/components/tags';
|
||||
import {
|
||||
IntegrationService,
|
||||
IntegrationTypeIcon,
|
||||
} from '@affine/core/modules/integration';
|
||||
import type { ReadwiseConfig } from '@affine/core/modules/integration/type';
|
||||
import { TagService } from '@affine/core/modules/tag';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { LiveData, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { IntegrationCardIcon } from '../card';
|
||||
@@ -45,6 +47,8 @@ export const SettingDialog = ({
|
||||
</div>
|
||||
</header>
|
||||
<ul className={styles.settings}>
|
||||
<TagsSetting />
|
||||
<Divider />
|
||||
<NewHighlightSetting />
|
||||
<Divider />
|
||||
<UpdateStrategySetting />
|
||||
@@ -174,3 +178,105 @@ const StartImport = ({ onImport }: { onImport: () => void }) => {
|
||||
</IntegrationSettingItem>
|
||||
);
|
||||
};
|
||||
|
||||
const TagsSetting = () => {
|
||||
const t = useI18n();
|
||||
const tagService = useService(TagService);
|
||||
const readwise = useService(IntegrationService).readwise;
|
||||
const allTags = useLiveData(tagService.tagList.tags$);
|
||||
const tagColors = tagService.tagColors;
|
||||
const tagIds = useLiveData(
|
||||
useMemo(() => readwise.setting$('tags'), [readwise])
|
||||
);
|
||||
const adaptedTags = useLiveData(
|
||||
useMemo(() => {
|
||||
return LiveData.computed(get => {
|
||||
return allTags.map(tag => ({
|
||||
id: tag.id,
|
||||
value: get(tag.value$),
|
||||
color: get(tag.color$),
|
||||
}));
|
||||
});
|
||||
}, [allTags])
|
||||
);
|
||||
const adaptedTagColors = useMemo(() => {
|
||||
return tagColors.map(color => ({
|
||||
id: color[0],
|
||||
value: color[1],
|
||||
name: color[0],
|
||||
}));
|
||||
}, [tagColors]);
|
||||
|
||||
const updateReadwiseTags = useCallback(
|
||||
(tagIds: string[]) => {
|
||||
readwise.updateSetting(
|
||||
'tags',
|
||||
tagIds.filter(id => !!allTags.some(tag => tag.id === id))
|
||||
);
|
||||
},
|
||||
[allTags, readwise]
|
||||
);
|
||||
|
||||
const onCreateTag = useCallback(
|
||||
(name: string, color: string) => {
|
||||
const tag = tagService.tagList.createTag(name, color);
|
||||
return { id: tag.id, value: tag.value$.value, color: tag.color$.value };
|
||||
},
|
||||
[tagService.tagList]
|
||||
);
|
||||
const onSelectTag = useCallback(
|
||||
(tagId: string) => {
|
||||
updateReadwiseTags([...(tagIds ?? []), tagId]);
|
||||
},
|
||||
[tagIds, updateReadwiseTags]
|
||||
);
|
||||
const onDeselectTag = useCallback(
|
||||
(tagId: string) => {
|
||||
updateReadwiseTags(tagIds?.filter(id => id !== tagId) ?? []);
|
||||
},
|
||||
[tagIds, updateReadwiseTags]
|
||||
);
|
||||
const onDeleteTag = useCallback(
|
||||
(tagId: string) => {
|
||||
tagService.tagList.deleteTag(tagId);
|
||||
updateReadwiseTags(tagIds ?? []);
|
||||
},
|
||||
[tagIds, updateReadwiseTags, tagService.tagList]
|
||||
);
|
||||
const onTagChange = useCallback(
|
||||
(id: string, property: keyof TagLike, value: string) => {
|
||||
if (property === 'value') {
|
||||
tagService.tagList.tagByTagId$(id).value?.rename(value);
|
||||
} else if (property === 'color') {
|
||||
tagService.tagList.tagByTagId$(id).value?.changeColor(value);
|
||||
}
|
||||
},
|
||||
[tagService.tagList]
|
||||
);
|
||||
return (
|
||||
<li>
|
||||
<h6 className={styles.tagsLabel}>
|
||||
{t['com.affine.integration.readwise.setting.tags-label']()}
|
||||
</h6>
|
||||
<TagsInlineEditor
|
||||
placeholder={
|
||||
<span className={styles.tagsPlaceholder}>
|
||||
{t['com.affine.integration.readwise.setting.tags-placeholder']()}
|
||||
</span>
|
||||
}
|
||||
className={styles.tagsEditor}
|
||||
tagMode="inline-tag"
|
||||
tags={adaptedTags}
|
||||
selectedTags={tagIds ?? []}
|
||||
onCreateTag={onCreateTag}
|
||||
onSelectTag={onSelectTag}
|
||||
onDeselectTag={onDeselectTag}
|
||||
tagColors={adaptedTagColors}
|
||||
onTagChange={onTagChange}
|
||||
onDeleteTag={onDeleteTag}
|
||||
modalMenu={true}
|
||||
menuClassName={styles.tagsMenu}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user