• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {
16  AddNoteArgs,
17  AddSpanNoteArgs,
18  Note,
19  NoteManager,
20  SpanNote,
21} from '../public/note';
22import {randomColor} from '../components/colorizer';
23
24export class NoteManagerImpl implements NoteManager {
25  private _lastNodeId = 0;
26  private _notes = new Map<string, Note | SpanNote>();
27
28  // This function is wired up to clear the SelectionManager state if the
29  // current selection is a note.
30  // TODO(primiano): figure out some better (de-)coupling here.
31  // We cannot pass SelectionManager in our constructor because doing so would
32  // create a cyclic ctor dependency (SelectionManager requires NoteManager in
33  // its ctor). There is a 2way logical dependency between NoteManager and
34  // SelectionManager:
35  // 1. SM needs NM to handle SM.findTimeRangeOfSelection(), for [M]ark.
36  // 2. NM needs SM to tell it that a note has been delete and should be
37  //   deselected if it was currently selected.
38  onNoteDeleted?: (nodeId: string) => void;
39
40  get notes(): ReadonlyMap<string, Note | SpanNote> {
41    return this._notes;
42  }
43
44  getNote(id: string): Note | SpanNote | undefined {
45    return this._notes.get(id);
46  }
47
48  addNote(args: AddNoteArgs): string {
49    const id = args.id ?? `note_${++this._lastNodeId}`;
50    this._notes.set(id, {
51      ...args,
52      noteType: 'DEFAULT',
53      id,
54      color: args.color ?? randomColor(),
55      text: args.text ?? '',
56    });
57    return id;
58  }
59
60  addSpanNote(args: AddSpanNoteArgs): string {
61    const id = args.id ?? `note_${++this._lastNodeId}`;
62    this._notes.set(id, {
63      ...args,
64      noteType: 'SPAN',
65      id,
66      color: args.color ?? randomColor(),
67      text: args.text ?? '',
68    });
69    return id;
70  }
71
72  changeNote(id: string, args: {color?: string; text?: string}) {
73    const note = this._notes.get(id);
74    if (note === undefined) return;
75
76    this._notes.set(id, {
77      ...note,
78      color: args.color ?? note.color,
79      text: args.text ?? note.text,
80    });
81  }
82
83  removeNote(id: string) {
84    this._notes.delete(id);
85    this.onNoteDeleted?.(id);
86  }
87}
88