* feat: add tag folders support basics * feat: add draggability to tags * feat: add drag & drop draft * feat: fold folders * fix: do not select on fold / unfold tags * style: clean the isValidTag call * feat: add native folder toggle * feat: add touch mobile support * ui: add nicer design & icons * style: render full-width tag items * feat: nicer looking dropzone * style: fix arguments * fix: tag template rendering in list items * feat: tag can be dragged over the whole item * fix: cancel / reset title after save * fix: disable drag completely when needed * fix: invalid tag parents * feat: add paying feature * feat: with paid feature tooltip * feat: tag has a plus feature * feat: add premium modal * style: simplif code * refactor: extract feature_state & simplif code * fix: icons and icons svg * style: remove comment * feat: tag folders naming * feat: use the feature notification * fix: tag folders copy * style: variable names * style: remove & clean comments * refactor: remove is-mobile library * feat: tags folder experimental (#10) * feat: hide native folders behind experimental flag * fix: better tags resizing * fix: merge global window * style: rename params * refactor: remove level of indirection in feature toggle * feat: recursively add tags to note on create (#9) * fix: use add tags folder hierarchy & isTemplateItem (#13) * fix: use new snjs add tag hierarchy * fix: use new snjs isTemplateItem * feat: tags folder premium (#774) * feat: upgrade premium in tags section refactor: move TagsSection to react feat: show premium on Tag section feat: keep drag and drop features always active fix: drag & drop tweak with premium feat: premium messages fix: remove fill in svg icons fix: change tag list color (temporary) style: remove dead code refactor: clarify names and modules fix: draggable behind feature toggle feat: add button in TagSection & design * feat: fix features loading with app state (#775) * fix: distinguish between app launch and start * fix: update state for footer too * fix: wait for application launch event Co-authored-by: Laurent Senta <laurent@singulargarden.com> * feat: tags folder with folder text design (#776) * feat: add folder text * fix: sn stylekit colors * fix: root drop zone * chore: upgrade stylekit * fix: hide dropzone when feature is disabled * chore: bump versions now that they are released Co-authored-by: Mo <me@bitar.io> * feat: tags folder design review (#785) * fix: upgrade design after review * fix: tweak dropzone * fix: sync after assign parent * fix: tsc error on build * fix: vertical center the fold arrows * fix: define our own hoist for react-dnd * feat: hide fold when there are no folders * fix: show children usability + resize UI * fix: use old colors for now, theme compat * fix: tweak alignment and add title * fix: meta offset with folders * fix: tweak tag size * fix: observable setup * fix: use link-off icon on dropzone * fix: more tweak on text sizes Co-authored-by: Mo <me@bitar.io>
126 lines
3.3 KiB
TypeScript
126 lines
3.3 KiB
TypeScript
import {
|
|
SNNote,
|
|
ContentType,
|
|
PayloadSource,
|
|
UuidString,
|
|
TagMutator,
|
|
SNTag,
|
|
} from '@standardnotes/snjs';
|
|
import { WebApplication } from './application';
|
|
import { NoteTagsState } from './app_state/note_tags_state';
|
|
|
|
export class Editor {
|
|
public note!: SNNote;
|
|
private application: WebApplication;
|
|
private _onNoteChange?: () => void;
|
|
private _onNoteValueChange?: (note: SNNote, source?: PayloadSource) => void;
|
|
private removeStreamObserver?: () => void;
|
|
public isTemplateNote = false;
|
|
|
|
constructor(
|
|
application: WebApplication,
|
|
noteUuid: string | undefined,
|
|
noteTitle: string | undefined,
|
|
noteTag: UuidString | undefined
|
|
) {
|
|
this.application = application;
|
|
if (noteUuid) {
|
|
this.note = application.findItem(noteUuid) as SNNote;
|
|
this.streamItems();
|
|
} else {
|
|
this.reset(noteTitle, noteTag)
|
|
.then(() => this.streamItems())
|
|
.catch(console.error);
|
|
}
|
|
}
|
|
|
|
private streamItems() {
|
|
this.removeStreamObserver = this.application.streamItems(
|
|
ContentType.Note,
|
|
(items, source) => {
|
|
this.handleNoteStream(items as SNNote[], source);
|
|
}
|
|
);
|
|
}
|
|
|
|
deinit() {
|
|
this.removeStreamObserver?.();
|
|
(this.removeStreamObserver as any) = undefined;
|
|
this._onNoteChange = undefined;
|
|
(this.application as any) = undefined;
|
|
this._onNoteChange = undefined;
|
|
this._onNoteValueChange = undefined;
|
|
}
|
|
|
|
private handleNoteStream(notes: SNNote[], source?: PayloadSource) {
|
|
/** Update our note object reference whenever it changes */
|
|
const matchingNote = notes.find((item) => {
|
|
return item.uuid === this.note.uuid;
|
|
}) as SNNote;
|
|
if (matchingNote) {
|
|
this.isTemplateNote = false;
|
|
this.note = matchingNote;
|
|
this._onNoteValueChange && this._onNoteValueChange!(matchingNote, source);
|
|
}
|
|
}
|
|
|
|
insertTemplatedNote() {
|
|
this.isTemplateNote = false;
|
|
return this.application.insertItem(this.note);
|
|
}
|
|
|
|
/**
|
|
* Reverts the editor to a blank state, removing any existing note from view,
|
|
* and creating a placeholder note.
|
|
*/
|
|
async reset(noteTitle = '', noteTag?: UuidString) {
|
|
const note = (await this.application.createTemplateItem(ContentType.Note, {
|
|
text: '',
|
|
title: noteTitle,
|
|
references: [],
|
|
})) as SNNote;
|
|
if (noteTag) {
|
|
const tag = this.application.findItem(noteTag) as SNTag;
|
|
await this.application.addTagHierarchyToNote(note, tag);
|
|
}
|
|
if (!this.isTemplateNote || this.note.title !== note.title) {
|
|
this.setNote(note as SNNote, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register to be notified when the editor's note changes.
|
|
*/
|
|
public onNoteChange(callback: () => void) {
|
|
this._onNoteChange = callback;
|
|
if (this.note) {
|
|
callback();
|
|
}
|
|
}
|
|
|
|
public clearNoteChangeListener() {
|
|
this._onNoteChange = undefined;
|
|
}
|
|
|
|
/**
|
|
* Register to be notified when the editor's note's values change
|
|
* (and thus a new object reference is created)
|
|
*/
|
|
public onNoteValueChange(
|
|
callback: (note: SNNote, source?: PayloadSource) => void
|
|
) {
|
|
this._onNoteValueChange = callback;
|
|
}
|
|
|
|
/**
|
|
* Sets the editor contents by setting its note.
|
|
*/
|
|
public setNote(note: SNNote, isTemplate = false) {
|
|
this.note = note;
|
|
this.isTemplateNote = isTemplate;
|
|
if (this._onNoteChange) {
|
|
this._onNoteChange();
|
|
}
|
|
}
|
|
}
|