123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- import { Data } from 'types'
- import clipboard from './clipboard'
- import state from './state'
- import { isDraft, current } from 'immer'
- import tld from 'utils/tld'
- import inputs from './inputs'
-
- interface LogEntry {
- eventName: string
- payload: any
- time: number
- didCauseUpdate: boolean
- }
-
- class Logger {
- filters = new Set([
- // 'MOVED_OVER_SHAPE',
- // 'RESIZED_WINDOW',
- // 'HOVERED_SHAPE',
- // 'UNHOVERED_SHAPE',
- // 'PANNED_CAMERA',
- 'STARTED_LOGGING',
- 'STOPPED_LOGGING',
- ])
-
- snapshotStart: Data
- snapshotEnd: Data
-
- log: LogEntry[] = []
-
- isSimulating = false
-
- isRunning = false
-
- speed = 0
-
- startTime = 0
-
- /**
- * Start the logger.
- *
- * ### Example
- *
- *```ts
- * logger.start()
- *```
- */
- start = (data: Data): Logger => {
- if (this.isRunning) return
-
- this.isRunning = true
-
- this.snapshotStart = isDraft(data) ? current(data) : data
-
- this.log = []
-
- this.startTime = Date.now()
-
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- this.snapshotStart.pageStates[data.currentPageId].selectedIds = [
- ...tld.getSelectedIds(data),
- ]
-
- return this
- }
-
- /**
- * Stop the logger.
- *
- * ### Example
- *
- *```ts
- * logger.stop()
- *```
- */
- stop = (data: Data): Logger => {
- if (!this.isRunning) return
-
- this.isRunning = false
-
- this.snapshotEnd = isDraft(data) ? current(data) : data
-
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- this.snapshotEnd.pageStates[data.currentPageId].selectedIds = [
- ...tld.getSelectedIds(data),
- ]
-
- // if (window.confirm('Stopped logging. Copy to clipboard?')) {
- // this.copyToJson()
- // }
-
- return this
- }
-
- /**
- * Add an event and payload to the log.
- *
- * ### Example
- *
- *```ts
- * logger.addToLog(eventName, payload)
- *```
- */
- addToLog(event: string, payload: any, didCauseUpdate = false) {
- if (!this.isRunning) return
-
- if (this.filters.has(event)) return
-
- didCauseUpdate
- // if (!didCauseUpdate) return
-
- this.log.push({
- eventName: event,
- payload: payload,
- time: Date.now() - this.startTime,
- didCauseUpdate: true,
- })
- }
-
- /**
- * Play back a log entry.
- *
- * ### Example
- *
- *```ts
- * logger.playback(log)
- *```
- */
- playback = (data: Data, log: string): Logger => {
- const parsed: { start: Data; end: Data; events: LogEntry[] } =
- JSON.parse(log)
-
- const { start, events } = parsed
-
- this.isSimulating = true
-
- try {
- data.pageStates[data.currentPageId].selectedIds = [
- ...start.pageStates[start.currentPageId].selectedIds,
- ]
-
- state.send('RESET_DOCUMENT_STATE').forceData(start)
-
- const pointerDowns = [
- 'POINTED_CANVAS',
- 'POINTED_SHAPE',
- 'POINTED_BOUNDS',
- 'DOUBLE_POINTED_SHAPE',
- 'POINTED_HANDLE',
- 'RIGHT_POINTED',
- ]
-
- const pointerChanges = [
- ...pointerDowns,
- 'MOVED_POINTER',
- 'MOVED_OVER_SHAPE',
- 'STOPPED_POINTING',
- 'DOUBLE_POINTED_CANVAS',
- ]
-
- const pointerUps = ['STOPPED_POINTING']
-
- for (const event of events) {
- if (pointerDowns.includes(event.eventName)) {
- inputs.pointer.origin = event.payload.point
- }
-
- if (pointerChanges.includes(event.eventName)) {
- inputs.activePointerId = event.payload.pointerId
- inputs.pointer = { ...inputs.pointer, ...event.payload }
- inputs.points[event.payload.pointerId] = inputs.pointer
- }
-
- if (pointerUps.includes(event.eventName)) {
- delete inputs.points[event.payload.pointerId]
- delete inputs.activePointerId
-
- // TODO: Double pointing
- }
-
- state.send(event.eventName, event.payload)
- }
-
- setTimeout(
- () => (this.isSimulating = false),
- events[events.length - 1].time + 1
- )
- } catch (e) {
- console.warn('Could not play back that state.')
- }
-
- return this
- }
-
- /**
- * Export the log as JSON.
- *
- * ### Example
- *
- *```ts
- * logger.toJson()
- *```
- */
- copyToJson = () => {
- const logAsString = JSON.stringify({
- start: this.snapshotStart,
- end: this.snapshotEnd,
- events: this.log,
- })
-
- clipboard.copyStringToClipboard(logAsString)
-
- return logAsString
- }
-
- /**
- * Add a new event filter. Filtered events will not be logged.
- *
- * ### Example
- *
- *```ts
- * logger.addFilter("SOME_EVENT")
- *```
- */
- addFilter(eventName: string) {
- this.filters.add(eventName)
- }
-
- /**
- * Remove an event from the filters. Filtered events will not be logged.
- *
- * ### Example
- *
- *```ts
- * logger.removeFilter("SOME_EVENT")
- *```
- */
- removeFilter(eventName: string) {
- this.filters.delete(eventName)
- }
-
- /**
- * Replace all of the filtered events.
- *
- * ### Example
- *
- *```ts
- * logger.setFilters(["SOME_EVENT", "SOME_OTHER_EVENT"])
- *```
- */
- setFilters(eventNames: string[]) {
- this.filters = new Set(eventNames)
- }
-
- /**
- * Clear the current set of event filters.
- *
- * ### Example
- *
- *```ts
- * logger.clear()
- *```
- */
- clearFilters() {
- this.filters.clear()
- }
- }
-
- export default new Logger()
|