|
|
@@ -29,6 +29,7 @@ import {
|
|
|
} from './completions/apply'
|
|
|
import { snippet } from './completions/data/environments'
|
|
|
import { syntaxTree } from '@codemirror/language'
|
|
|
+import { sendMBSampled } from '@/infrastructure/event-tracking'
|
|
|
|
|
|
function blankCompletions(): Completions {
|
|
|
return {
|
|
|
@@ -206,6 +207,90 @@ export const bibKeyArgumentCompletionSource: CompletionSource =
|
|
|
}
|
|
|
)
|
|
|
|
|
|
+const debouncedCounter = (
|
|
|
+ debounceTime: number
|
|
|
+): {
|
|
|
+ debounceTime: number
|
|
|
+ counter: number
|
|
|
+ increment: () => void
|
|
|
+ reset: () => void
|
|
|
+} => {
|
|
|
+ let timeoutId = 0
|
|
|
+ let _counter = 0
|
|
|
+ return {
|
|
|
+ debounceTime,
|
|
|
+ get counter() {
|
|
|
+ return _counter
|
|
|
+ },
|
|
|
+ increment() {
|
|
|
+ if (timeoutId !== 0) {
|
|
|
+ clearTimeout(timeoutId)
|
|
|
+ }
|
|
|
+ timeoutId = window.setTimeout(() => {
|
|
|
+ _counter += 1
|
|
|
+ timeoutId = 0
|
|
|
+ }, debounceTime)
|
|
|
+ },
|
|
|
+ reset() {
|
|
|
+ clearTimeout(timeoutId)
|
|
|
+ _counter = 0
|
|
|
+ timeoutId = 0
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const CITE_ANALYTICS_REPORT_TIMEOUT = 4000
|
|
|
+
|
|
|
+const analyticsSourceBuilder = (debounceTimes: number[]) => {
|
|
|
+ let timeoutId = 0
|
|
|
+ const counters = debounceTimes.map(debounceTime => {
|
|
|
+ if (debounceTime >= CITE_ANALYTICS_REPORT_TIMEOUT) {
|
|
|
+ throw new Error(
|
|
|
+ `Debounce time ${debounceTime} is greater than the report timeout ${CITE_ANALYTICS_REPORT_TIMEOUT}`
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return debouncedCounter(debounceTime)
|
|
|
+ })
|
|
|
+
|
|
|
+ const incrementCounters = () => {
|
|
|
+ counters.forEach(counter => counter.increment())
|
|
|
+ }
|
|
|
+
|
|
|
+ const resetCounters = () => {
|
|
|
+ counters.forEach(counter => counter.reset())
|
|
|
+ }
|
|
|
+
|
|
|
+ const delayedReport = () => {
|
|
|
+ if (timeoutId !== 0) {
|
|
|
+ clearTimeout(timeoutId)
|
|
|
+ }
|
|
|
+ timeoutId = window.setTimeout(() => {
|
|
|
+ const result: Record<string, number> = {}
|
|
|
+ counters.forEach(debouncedCounter => {
|
|
|
+ result[`${debouncedCounter.debounceTime}ms`] = debouncedCounter.counter
|
|
|
+ })
|
|
|
+ sendMBSampled(
|
|
|
+ 'cite-key-search',
|
|
|
+ { searchesForDebouncedTime: result },
|
|
|
+ 0.01
|
|
|
+ )
|
|
|
+ timeoutId = 0
|
|
|
+ resetCounters()
|
|
|
+ }, CITE_ANALYTICS_REPORT_TIMEOUT)
|
|
|
+ }
|
|
|
+
|
|
|
+ return () => {
|
|
|
+ incrementCounters()
|
|
|
+ delayedReport()
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const citeKeyAnalyticsSource = makeMultipleArgumentCompletionSource(
|
|
|
+ ['BibKeyArgument'],
|
|
|
+ analyticsSourceBuilder([0, 100, 250, 500])
|
|
|
+)
|
|
|
+
|
|
|
export const refArgumentCompletionSource: CompletionSource =
|
|
|
makeMultipleArgumentCompletionSource(
|
|
|
['RefArgument'],
|
|
|
@@ -359,6 +444,7 @@ export const argumentCompletionSources: CompletionSource[] = [
|
|
|
documentClassArgumentCompletionSource,
|
|
|
bibliographyArgumentCompletionSource,
|
|
|
bibliographyStyleArgumentCompletionSource,
|
|
|
+ citeKeyAnalyticsSource,
|
|
|
]
|
|
|
|
|
|
const commandCompletionSource = (context: CompletionContext) => {
|