forked from WorldBrain/Memex
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathannotations-manager.ts
185 lines (165 loc) · 5.36 KB
/
annotations-manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import { remoteFunction } from 'src/util/webextensionRPC'
import { Anchor } from 'src/direct-linking/content_script/interactions'
import { Omit } from './types'
import { Annotation } from 'src/sidebar-overlay/sidebar/types'
import { EVENT_NAMES } from 'src/analytics/internal/constants'
import analytics from 'src/analytics'
import { AnnotSearchParams } from 'src/search/background/types'
export default class AnnotationsManager {
private readonly _processEventRPC = remoteFunction('processEvent')
private readonly _createAnnotationRPC = remoteFunction('createAnnotation')
private readonly _addAnnotationTagRPC = remoteFunction('addAnnotationTag')
private readonly _getAllAnnotationsByUrlRPC = remoteFunction(
'getAllAnnotationsByUrl',
)
private readonly _getTagsByAnnotationUrlRPC = remoteFunction(
'getAnnotationTags',
)
private readonly _editAnnotationRPC = remoteFunction('editAnnotation')
private readonly _editAnnotationTagsRPC = remoteFunction(
'editAnnotationTags',
)
private readonly _deleteAnnotationRPC = remoteFunction('deleteAnnotation')
private readonly bookmarkAnnotationRPC = remoteFunction(
'toggleAnnotBookmark',
)
private readonly searchAnnotationsRPC = remoteFunction('searchAnnotations')
public createAnnotation = async ({
url,
title,
body,
comment,
anchor,
tags,
bookmarked,
}: {
url: string
title: string
body: string
comment: string
anchor: Anchor
tags: string[]
bookmarked?: boolean
}) => {
this._processEventRPC({ type: EVENT_NAMES.CREATE_ANNOTATION })
if (tags && tags.length) {
analytics.trackEvent({
category: 'Annotations',
action: 'createWithTags',
})
} else {
analytics.trackEvent({
category: 'Annotations',
action: 'createWithoutTags',
})
}
// Write annotation to database.
const uniqueUrl = await this._createAnnotationRPC({
url,
title,
body,
comment,
selector: anchor,
bookmarked,
})
// Write tags to database.
tags.forEach(async tag => {
await this._addAnnotationTagRPC({ tag, url: uniqueUrl })
})
}
public fetchAnnotationsWithTags = async (
url: string,
limit = 10,
skip = 0,
) => {
const annotationsWithoutTags: Omit<
Annotation,
'tags'
>[] = await this._getAllAnnotationsByUrlRPC({
url,
// limit,
// skip,
})
return Promise.all(
annotationsWithoutTags.map(async annotation => {
const annotationTags: {
name: string
url: string
}[] = await this._getTagsByAnnotationUrlRPC(annotation.url)
const tags = annotationTags.map(tag => tag.name)
return {
...annotation,
tags,
}
}),
)
}
public editAnnotation = async ({
url,
comment,
tags,
}: {
url: string
comment: string
tags: string[]
}) => {
// Get the previously tags for the annotation.
const prevTags = await this._getTagsByAnnotationUrlRPC(url)
// Calculate which tags are to be added and which are to be deleted.
const { tagsToBeAdded, tagsToBeDeleted } = this._getTagArrays(
prevTags,
tags,
)
// Save the edited annotation to the storage.
await this._editAnnotationRPC(url, comment)
// Save the edited tags to the storage.
await this._editAnnotationTagsRPC({
tagsToBeAdded,
tagsToBeDeleted,
url,
})
if (tagsToBeAdded) {
analytics.trackEvent({
category: 'Tag',
action: 'addToExistingAnnotation',
})
}
}
public deleteAnnotation = async (url: string) => {
await this._processEventRPC({ type: EVENT_NAMES.DELETE_ANNOTATION })
await this._deleteAnnotationRPC(url)
}
public toggleBookmark = async (url: string) => {
return this.bookmarkAnnotationRPC({ url })
}
private _getTagArrays: (
oldTags: string[],
newTags: string[],
) => { tagsToBeAdded: string[]; tagsToBeDeleted: string[] } = (
oldTags,
newTags,
) => {
const oldSet = new Set(oldTags)
const tagsToBeAdded = newTags.reduce((accumulator, currentTag) => {
if (!oldSet.has(currentTag)) {
accumulator.push(currentTag)
}
return accumulator
}, [])
const newSet = new Set(newTags)
const tagsToBeDeleted = oldTags.reduce((accumulator, currentTag) => {
if (!newSet.has(currentTag)) {
accumulator.push(currentTag)
}
return accumulator
}, [])
return {
tagsToBeAdded,
tagsToBeDeleted,
}
}
public searchAnnotations = async (searchParams: AnnotSearchParams) => {
const annotations = await this.searchAnnotationsRPC(searchParams)
return annotations
}
}