@@ -358,14 +388,17 @@ const HighlightTable = ({
{
- setSelected(prev => {
- if (prev.includes(highlight.id)) {
- return prev.filter(id => id !== highlight.id);
- } else {
- return [...prev, highlight.id];
- }
+ onChange={(_: ChangeEvent, checked: boolean) => {
+ readwiseTrack.selectIntegrationImport({
+ method: 'single',
+ option: checked ? 'on' : 'off',
+ control: 'Readwise import list',
});
+ setSelected(
+ checked
+ ? [...selected, highlight.id]
+ : selected.filter(id => id !== highlight.id)
+ );
}}
/>
diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/index.tsx
index 4a0c211047..f9042f5578 100644
--- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/index.tsx
+++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/index.tsx
@@ -16,6 +16,7 @@ import { ConnectButton } from './connect';
import { ConnectedActions } from './connected';
import { ImportDialog } from './import-dialog';
import { SettingDialog } from './setting-dialog';
+import { readwiseTrack } from './track';
export const ReadwiseIntegration = () => {
const t = useI18n();
@@ -42,6 +43,14 @@ export const ReadwiseIntegration = () => {
setOpenImportDialog(true);
}, []);
+ const onImportClick = useCallback(() => {
+ readwiseTrack.startIntegrationImport({
+ method: settings?.lastImportedAt ? 'withtimestamp' : 'new',
+ control: 'Readwise Card',
+ });
+ handleImport();
+ }, [handleImport, settings?.lastImportedAt]);
+
return (
{
{token ? (
<>
-
+
{openSetting && (
{
+ readwiseTrack.modifyIntegrationSettings({
+ item,
+ option,
+ method,
+ });
+};
+
const Divider = () => {
return ;
};
@@ -72,6 +85,7 @@ const NewHighlightSetting = () => {
const toggle = useCallback(
(value: boolean) => {
+ trackModifySetting('New', value ? 'on' : 'off');
readwise.updateSetting('syncNewHighlights', value);
},
[readwise]
@@ -98,6 +112,7 @@ const UpdateStrategySetting = () => {
const toggle = useCallback(
(value: boolean) => {
+ trackModifySetting('Update', value ? 'on' : 'off', 'append');
if (!value) readwise.updateSetting('updateStrategy', undefined);
else readwise.updateSetting('updateStrategy', 'append');
},
@@ -106,6 +121,7 @@ const UpdateStrategySetting = () => {
const handleUpdate = useCallback(
(value: ReadwiseConfig['updateStrategy']) => {
+ trackModifySetting('Update', 'on', value);
readwise.updateSetting('updateStrategy', value);
},
[readwise]
@@ -167,12 +183,23 @@ const UpdateStrategySetting = () => {
const StartImport = ({ onImport }: { onImport: () => void }) => {
const t = useI18n();
+ const readwise = useService(IntegrationService).readwise;
+
+ const handleImport = useCallback(() => {
+ const lastImportedAt = readwise.setting$('lastImportedAt').value;
+ readwiseTrack.startIntegrationImport({
+ method: lastImportedAt ? 'withtimestamp' : 'new',
+ control: 'Readwise settings',
+ });
+ onImport();
+ }, [onImport, readwise]);
+
return (
-
@@ -226,18 +253,23 @@ const TagsSetting = () => {
);
const onSelectTag = useCallback(
(tagId: string) => {
+ trackModifySetting('Tag', 'on');
updateReadwiseTags([...(tagIds ?? []), tagId]);
},
[tagIds, updateReadwiseTags]
);
const onDeselectTag = useCallback(
(tagId: string) => {
+ trackModifySetting('Tag', 'off');
updateReadwiseTags(tagIds?.filter(id => id !== tagId) ?? []);
},
[tagIds, updateReadwiseTags]
);
const onDeleteTag = useCallback(
(tagId: string) => {
+ if (tagIds?.includes(tagId)) {
+ trackModifySetting('Tag', 'off');
+ }
tagService.tagList.deleteTag(tagId);
updateReadwiseTags(tagIds ?? []);
},
diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/track.ts b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/track.ts
new file mode 100644
index 0000000000..fc430ddc58
--- /dev/null
+++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/integration/readwise/track.ts
@@ -0,0 +1,25 @@
+import track from '@affine/track';
+
+/**
+ * Wrap the track function to add default properties to the first argument
+ */
+export const readwiseTrack = new Proxy(track.$.settingsPanel.integrationList, {
+ get(target, key, receiver) {
+ const original = Reflect.get(target, key, receiver);
+
+ if (typeof original !== 'function') {
+ return original;
+ }
+
+ return function (this: unknown, ...args: unknown[]) {
+ if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
+ args[0] = {
+ type: 'readwise',
+ control: 'Readwise Card',
+ ...args[0],
+ };
+ }
+ return original.apply(this, args);
+ };
+ },
+});
diff --git a/packages/frontend/track/src/events.ts b/packages/frontend/track/src/events.ts
index 4a2ba279e7..1f383f8450 100644
--- a/packages/frontend/track/src/events.ts
+++ b/packages/frontend/track/src/events.ts
@@ -149,6 +149,18 @@ type TemplateEvents = 'openTemplateListMenu';
type NotificationEvents = 'openInbox' | 'clickNotification';
// END SECTION
+// SECTION: Integration
+type IntegrationEvents =
+ | 'connectIntegration'
+ | 'disconnectIntegration'
+ | 'modifyIntegrationSettings'
+ | 'startIntegrationImport'
+ | 'selectIntegrationImport'
+ | 'confirmIntegrationImport'
+ | 'abortIntegrationImport'
+ | 'completeIntegrationImport';
+// END SECTION
+
type UserEvents =
| GeneralEvents
| AppEvents
@@ -167,8 +179,8 @@ type UserEvents =
| DNDEvents
| AttachmentEvents
| TemplateEvents
- | NotificationEvents;
-
+ | NotificationEvents
+ | IntegrationEvents;
interface PageDivision {
[page: string]: {
[segment: string]: {
@@ -235,6 +247,16 @@ const PageEvents = {
],
billing: ['viewPlans', 'bookDemo'],
about: ['checkUpdates', 'downloadUpdate', 'changeAppSetting'],
+ integrationList: [
+ 'connectIntegration',
+ 'disconnectIntegration',
+ 'modifyIntegrationSettings',
+ 'startIntegrationImport',
+ 'selectIntegrationImport',
+ 'confirmIntegrationImport',
+ 'abortIntegrationImport',
+ 'completeIntegrationImport',
+ ],
},
cmdk: {
recent: ['recentDocs'],
@@ -485,6 +507,10 @@ type ImportArgs = {
docCount: number;
};
};
+type IntegrationArgs> = {
+ type: string;
+ control: 'Readwise Card' | 'Readwise settings' | 'Readwise import list';
+} & T;
export type EventArgs = {
createWorkspace: { flavour: string };
@@ -556,6 +582,33 @@ export type EventArgs = {
item: 'read' | 'button' | 'dismiss';
button?: string;
};
+ connectIntegration: IntegrationArgs<{ result: 'success' | 'failed' }>;
+ disconnectIntegration: IntegrationArgs<{ method: 'keep' | 'delete' }>;
+ modifyIntegrationSettings: IntegrationArgs<{
+ item: string;
+ option: any;
+ method: any;
+ }>;
+ startIntegrationImport: IntegrationArgs<{
+ method: 'new' | 'withtimestamp' | 'cleartimestamp';
+ }>;
+ selectIntegrationImport: IntegrationArgs<{
+ method: 'single' | 'all';
+ option: 'on' | 'off';
+ }>;
+ confirmIntegrationImport: IntegrationArgs<{
+ method: 'new' | 'withtimestamp';
+ }>;
+ abortIntegrationImport: IntegrationArgs<{
+ time: number;
+ done: number;
+ total: number;
+ }>;
+ completeIntegrationImport: IntegrationArgs<{
+ time: number;
+ done: number;
+ total: number;
+ }>;
};
// for type checking