refactor: smart tags to views (#902)
* refactor: smart tags to views * chore: upgrade snjs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { SmartTagsSection } from '@/components/Tags/SmartTagsSection';
|
||||
import { SmartViewsSection } from '@/components/Tags/SmartViewsSection';
|
||||
import { TagsSection } from '@/components/Tags/TagsSection';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { PANEL_NAME_NAVIGATION } from '@/constants';
|
||||
@@ -65,7 +65,7 @@ export const Navigation: FunctionComponent<Props> = observer(
|
||||
</div>
|
||||
</div>
|
||||
<div className="scrollable">
|
||||
<SmartTagsSection appState={appState} />
|
||||
<SmartViewsSection appState={appState} />
|
||||
<TagsSection appState={appState} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { WebApplication } from '@/ui_models/application';
|
||||
import { KeyboardKey } from '@/services/ioService';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { DisplayOptions } from '@/ui_models/app_state/notes_view_state';
|
||||
import { SNNote } from '@standardnotes/snjs';
|
||||
import { SNNote, SNTag } from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { NotesListItem } from './NotesListItem';
|
||||
@@ -42,7 +42,7 @@ export const NotesList: FunctionComponent<Props> = observer(
|
||||
return [];
|
||||
}
|
||||
const tags = appState.getNoteTags(note);
|
||||
if (!selectedTag.isSmartTag && tags.length === 1) {
|
||||
if (selectedTag instanceof SNTag && tags.length === 1) {
|
||||
return [];
|
||||
}
|
||||
return tags.map((tag) => tag.title).sort();
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { SmartTagsListItem } from './SmartTagsListItem';
|
||||
import { SmartViewsListItem } from './SmartViewsListItem';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
};
|
||||
|
||||
export const SmartTagsList: FunctionComponent<Props> = observer(
|
||||
export const SmartViewsList: FunctionComponent<Props> = observer(
|
||||
({ appState }) => {
|
||||
const allTags = appState.tags.smartTags;
|
||||
const allViews = appState.tags.smartViews;
|
||||
|
||||
return (
|
||||
<>
|
||||
{allTags.map((tag) => {
|
||||
{allViews.map((view) => {
|
||||
return (
|
||||
<SmartTagsListItem
|
||||
key={tag.uuid}
|
||||
tag={tag}
|
||||
<SmartViewsListItem
|
||||
key={view.uuid}
|
||||
view={view}
|
||||
tagsState={appState.tags}
|
||||
features={appState.features}
|
||||
/>
|
||||
@@ -2,13 +2,18 @@ import { Icon } from '@/components/Icon';
|
||||
import { FeaturesState } from '@/ui_models/app_state/features_state';
|
||||
import { TagsState } from '@/ui_models/app_state/tags_state';
|
||||
import '@reach/tooltip/styles.css';
|
||||
import { SNSmartTag, IconType } from '@standardnotes/snjs';
|
||||
import {
|
||||
SmartView,
|
||||
SystemViewId,
|
||||
IconType,
|
||||
isSystemView,
|
||||
} from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
|
||||
|
||||
type Props = {
|
||||
tag: SNSmartTag;
|
||||
view: SmartView;
|
||||
tagsState: TagsState;
|
||||
features: FeaturesState;
|
||||
};
|
||||
@@ -16,40 +21,40 @@ type Props = {
|
||||
const PADDING_BASE_PX = 14;
|
||||
const PADDING_PER_LEVEL_PX = 21;
|
||||
|
||||
const smartTagIconType = (tag: SNSmartTag): IconType => {
|
||||
if (tag.isAllTag) {
|
||||
const smartViewIconType = (view: SmartView): IconType => {
|
||||
if (view.uuid === SystemViewId.AllNotes) {
|
||||
return 'notes';
|
||||
}
|
||||
if (tag.isArchiveTag) {
|
||||
if (view.uuid === SystemViewId.ArchivedNotes) {
|
||||
return 'archive';
|
||||
}
|
||||
if (tag.isTrashTag) {
|
||||
if (view.uuid === SystemViewId.TrashedNotes) {
|
||||
return 'trash';
|
||||
}
|
||||
return 'hashtag';
|
||||
};
|
||||
|
||||
export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
({ tag, tagsState, features }) => {
|
||||
const [title, setTitle] = useState(tag.title || '');
|
||||
export const SmartViewsListItem: FunctionComponent<Props> = observer(
|
||||
({ view, tagsState }) => {
|
||||
const [title, setTitle] = useState(view.title || '');
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const level = 0;
|
||||
const isSelected = tagsState.selected === tag;
|
||||
const isEditing = tagsState.editingTag === tag;
|
||||
const isSelected = tagsState.selected === view;
|
||||
const isEditing = tagsState.editingTag === view;
|
||||
|
||||
useEffect(() => {
|
||||
setTitle(tag.title || '');
|
||||
}, [setTitle, tag]);
|
||||
setTitle(view.title || '');
|
||||
}, [setTitle, view]);
|
||||
|
||||
const selectCurrentTag = useCallback(() => {
|
||||
tagsState.selected = tag;
|
||||
}, [tagsState, tag]);
|
||||
tagsState.selected = view;
|
||||
}, [tagsState, view]);
|
||||
|
||||
const onBlur = useCallback(() => {
|
||||
tagsState.save(tag, title);
|
||||
setTitle(tag.title);
|
||||
}, [tagsState, tag, title, setTitle]);
|
||||
tagsState.save(view, title);
|
||||
setTitle(view.title);
|
||||
}, [tagsState, view, title, setTitle]);
|
||||
|
||||
const onInput = useCallback(
|
||||
(e: Event) => {
|
||||
@@ -76,19 +81,19 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
}, [inputRef, isEditing]);
|
||||
|
||||
const onClickRename = useCallback(() => {
|
||||
tagsState.editingTag = tag;
|
||||
}, [tagsState, tag]);
|
||||
tagsState.editingTag = view;
|
||||
}, [tagsState, view]);
|
||||
|
||||
const onClickSave = useCallback(() => {
|
||||
inputRef.current?.blur();
|
||||
}, [inputRef]);
|
||||
|
||||
const onClickDelete = useCallback(() => {
|
||||
tagsState.remove(tag, true);
|
||||
}, [tagsState, tag]);
|
||||
tagsState.remove(view, true);
|
||||
}, [tagsState, view]);
|
||||
|
||||
const isFaded = !tag.isAllTag;
|
||||
const iconType = smartTagIconType(tag);
|
||||
const isFaded = false;
|
||||
const iconType = smartViewIconType(view);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -101,7 +106,7 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`,
|
||||
}}
|
||||
>
|
||||
{!tag.errorDecrypting ? (
|
||||
{!view.errorDecrypting ? (
|
||||
<div className="tag-info">
|
||||
<div className={`tag-icon mr-1`}>
|
||||
<Icon
|
||||
@@ -112,7 +117,7 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
<input
|
||||
className={`title ${isEditing ? 'editing' : ''}`}
|
||||
disabled={!isEditing}
|
||||
id={`react-tag-${tag.uuid}`}
|
||||
id={`react-tag-${view.uuid}`}
|
||||
onBlur={onBlur}
|
||||
onInput={onInput}
|
||||
value={title}
|
||||
@@ -121,21 +126,21 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
ref={inputRef}
|
||||
/>
|
||||
<div className="count">
|
||||
{tag.isAllTag && tagsState.allNotesCount}
|
||||
{view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{!tag.isSystemSmartTag && (
|
||||
{!isSystemView(view) && (
|
||||
<div className="meta">
|
||||
{tag.conflictOf && (
|
||||
{view.conflictOf && (
|
||||
<div className="danger small-text font-bold">
|
||||
Conflicted Copy {tag.conflictOf}
|
||||
Conflicted Copy {view.conflictOf}
|
||||
</div>
|
||||
)}
|
||||
{tag.errorDecrypting && !tag.waitingForKey && (
|
||||
{view.errorDecrypting && !view.waitingForKey && (
|
||||
<div className="danger small-text font-bold">Missing Keys</div>
|
||||
)}
|
||||
{tag.errorDecrypting && tag.waitingForKey && (
|
||||
{view.errorDecrypting && view.waitingForKey && (
|
||||
<div className="info small-text font-bold">
|
||||
Waiting For Keys
|
||||
</div>
|
||||
@@ -1,17 +1,17 @@
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { SmartTagsList } from './SmartTagsList';
|
||||
import { SmartViewsList } from './SmartViewsList';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
};
|
||||
|
||||
export const SmartTagsSection: FunctionComponent<Props> = observer(
|
||||
export const SmartViewsSection: FunctionComponent<Props> = observer(
|
||||
({ appState }) => {
|
||||
return (
|
||||
<section>
|
||||
<SmartTagsList appState={appState} />
|
||||
<SmartViewsList appState={appState} />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { Menu } from '../menu/Menu';
|
||||
import { MenuItem, MenuItemType } from '../menu/MenuItem';
|
||||
import { usePremiumModal } from '../Premium';
|
||||
import { useCloseOnBlur } from '../utils';
|
||||
import { SNTag } from '@standardnotes/snjs';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
@@ -17,7 +18,7 @@ export const TagsContextMenu: FunctionComponent<Props> = observer(
|
||||
const premiumModal = usePremiumModal();
|
||||
const selectedTag = appState.tags.selected;
|
||||
|
||||
if (!selectedTag) {
|
||||
if (!selectedTag || !(selectedTag instanceof SNTag)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ import {
|
||||
PayloadSource,
|
||||
PrefKey,
|
||||
SNNote,
|
||||
SNSmartTag,
|
||||
SmartView,
|
||||
SNTag,
|
||||
SystemViewId,
|
||||
} from '@standardnotes/snjs';
|
||||
import pull from 'lodash/pull';
|
||||
import {
|
||||
@@ -241,7 +242,9 @@ export class AppState {
|
||||
const selectedTag = this.selectedTag;
|
||||
|
||||
const activeRegularTagUuid =
|
||||
selectedTag && !selectedTag.isSmartTag ? selectedTag.uuid : undefined;
|
||||
selectedTag && selectedTag instanceof SNTag
|
||||
? selectedTag.uuid
|
||||
: undefined;
|
||||
|
||||
await this.application.noteControllerGroup.createNoteView(
|
||||
undefined,
|
||||
@@ -313,11 +316,11 @@ export class AppState {
|
||||
);
|
||||
}
|
||||
|
||||
public get selectedTag(): SNTag | SNSmartTag | undefined {
|
||||
public get selectedTag(): SNTag | SmartView | undefined {
|
||||
return this.tags.selected;
|
||||
}
|
||||
|
||||
public set selectedTag(tag: SNTag | SNSmartTag | undefined) {
|
||||
public set selectedTag(tag: SNTag | SmartView | undefined) {
|
||||
this.tags.selected = tag;
|
||||
}
|
||||
|
||||
@@ -341,13 +344,19 @@ export class AppState {
|
||||
this.closeNoteController(noteController);
|
||||
} else if (
|
||||
note.trashed &&
|
||||
!selectedTag?.isTrashTag &&
|
||||
!(
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid === SystemViewId.TrashedNotes
|
||||
) &&
|
||||
!this.searchOptions.includeTrashed
|
||||
) {
|
||||
this.closeNoteController(noteController);
|
||||
} else if (
|
||||
note.archived &&
|
||||
!selectedTag?.isArchiveTag &&
|
||||
!(
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid === SystemViewId.ArchivedNotes
|
||||
) &&
|
||||
!this.searchOptions.includeArchived &&
|
||||
!this.application.getPreference(PrefKey.NotesShowArchived, false)
|
||||
) {
|
||||
|
||||
@@ -28,19 +28,19 @@ export class FeaturesState {
|
||||
window?.enabledUnfinishedFeatures;
|
||||
|
||||
_hasFolders = false;
|
||||
_hasSmartTags = false;
|
||||
_hasSmartViews = false;
|
||||
_premiumAlertFeatureName: string | undefined;
|
||||
|
||||
private unsub: () => void;
|
||||
|
||||
constructor(private application: WebApplication) {
|
||||
this._hasFolders = this.hasNativeFolders();
|
||||
this._hasSmartTags = this.hasNativeSmartTags();
|
||||
this._hasSmartViews = this.hasNativeSmartViews();
|
||||
this._premiumAlertFeatureName = undefined;
|
||||
|
||||
makeObservable(this, {
|
||||
_hasFolders: observable,
|
||||
_hasSmartTags: observable,
|
||||
_hasSmartViews: observable,
|
||||
hasFolders: computed,
|
||||
_premiumAlertFeatureName: observable,
|
||||
showPremiumAlert: action,
|
||||
@@ -56,7 +56,7 @@ export class FeaturesState {
|
||||
case ApplicationEvent.Launched:
|
||||
runInAction(() => {
|
||||
this._hasFolders = this.hasNativeFolders();
|
||||
this._hasSmartTags = this.hasNativeSmartTags();
|
||||
this._hasSmartViews = this.hasNativeSmartViews();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -73,8 +73,8 @@ export class FeaturesState {
|
||||
return this._hasFolders;
|
||||
}
|
||||
|
||||
public get hasSmartTags(): boolean {
|
||||
return this._hasSmartTags;
|
||||
public get hasSmartViews(): boolean {
|
||||
return this._hasSmartViews;
|
||||
}
|
||||
|
||||
public async showPremiumAlert(featureName: string): Promise<void> {
|
||||
@@ -94,7 +94,7 @@ export class FeaturesState {
|
||||
return status === FeatureStatus.Entitled;
|
||||
}
|
||||
|
||||
private hasNativeSmartTags(): boolean {
|
||||
private hasNativeSmartViews(): boolean {
|
||||
const status = this.application.getFeatureStatus(
|
||||
FeatureIdentifier.SmartFilters
|
||||
);
|
||||
|
||||
@@ -5,8 +5,10 @@ import {
|
||||
findInArray,
|
||||
NotesDisplayCriteria,
|
||||
PrefKey,
|
||||
SmartView,
|
||||
SNNote,
|
||||
SNTag,
|
||||
SystemViewId,
|
||||
UuidString,
|
||||
} from '@standardnotes/snjs';
|
||||
import {
|
||||
@@ -79,7 +81,10 @@ export class NotesViewState {
|
||||
const discarded = activeNote.deleted || activeNote.trashed;
|
||||
if (
|
||||
discarded &&
|
||||
!this.appState?.selectedTag?.isTrashTag &&
|
||||
!(
|
||||
this.appState.selectedTag instanceof SmartView &&
|
||||
this.appState.selectedTag?.uuid === SystemViewId.TrashedNotes
|
||||
) &&
|
||||
!this.appState?.searchOptions.includeTrashed
|
||||
) {
|
||||
this.selectNextOrCreateNew();
|
||||
@@ -116,7 +121,8 @@ export class NotesViewState {
|
||||
this.reloadNotes();
|
||||
if (
|
||||
this.notes.length === 0 &&
|
||||
this.appState.selectedTag?.isAllTag &&
|
||||
this.appState.selectedTag instanceof SmartView &&
|
||||
this.appState.selectedTag.uuid === SystemViewId.AllNotes &&
|
||||
this.noteFilterText === '' &&
|
||||
!this.appState.notes.activeNoteController
|
||||
) {
|
||||
@@ -246,7 +252,8 @@ export class NotesViewState {
|
||||
const criteria = NotesDisplayCriteria.Create({
|
||||
sortProperty: this.displayOptions.sortBy as CollectionSort,
|
||||
sortDirection: this.displayOptions.sortReverse ? 'asc' : 'dsc',
|
||||
tags: tag ? [tag] : [],
|
||||
tags: tag instanceof SNTag ? [tag] : [],
|
||||
views: tag instanceof SmartView ? [tag] : [],
|
||||
includeArchived,
|
||||
includeTrashed,
|
||||
includePinned: !this.displayOptions.hidePinned,
|
||||
@@ -353,7 +360,11 @@ export class NotesViewState {
|
||||
|
||||
createPlaceholderNote = () => {
|
||||
const selectedTag = this.appState.selectedTag;
|
||||
if (selectedTag && selectedTag.isSmartTag && !selectedTag.isAllTag) {
|
||||
if (
|
||||
selectedTag &&
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid !== SystemViewId.AllNotes
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return this.createNewNote();
|
||||
|
||||
@@ -9,10 +9,11 @@ import {
|
||||
ContentType,
|
||||
MessageData,
|
||||
SNApplication,
|
||||
SNSmartTag,
|
||||
SmartView,
|
||||
SNTag,
|
||||
TagMutator,
|
||||
UuidString,
|
||||
isSystemView,
|
||||
} from '@standardnotes/snjs';
|
||||
import {
|
||||
action,
|
||||
@@ -25,7 +26,7 @@ import {
|
||||
import { WebApplication } from '../application';
|
||||
import { FeaturesState, SMART_TAGS_FEATURE_NAME } from './features_state';
|
||||
|
||||
type AnyTag = SNTag | SNSmartTag;
|
||||
type AnyTag = SNTag | SmartView;
|
||||
|
||||
const rootTags = (application: SNApplication): SNTag[] => {
|
||||
const hasNoParent = (tag: SNTag) => !application.getTagParent(tag);
|
||||
@@ -71,11 +72,11 @@ const isValidFutureSiblings = (
|
||||
|
||||
export class TagsState {
|
||||
tags: SNTag[] = [];
|
||||
smartTags: SNSmartTag[] = [];
|
||||
smartViews: SmartView[] = [];
|
||||
allNotesCount_ = 0;
|
||||
selected_: AnyTag | undefined;
|
||||
previouslySelected_: AnyTag | undefined;
|
||||
editing_: SNTag | undefined;
|
||||
editing_: SNTag | SmartView | undefined;
|
||||
addingSubtagTo: SNTag | undefined;
|
||||
|
||||
contextMenuOpen = false;
|
||||
@@ -100,12 +101,12 @@ export class TagsState {
|
||||
this.editing_ = undefined;
|
||||
this.addingSubtagTo = undefined;
|
||||
|
||||
this.smartTags = this.application.getSmartTags();
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.smartViews = this.application.getSmartViews();
|
||||
this.selected_ = this.smartViews[0];
|
||||
|
||||
makeObservable(this, {
|
||||
tags: observable.ref,
|
||||
smartTags: observable.ref,
|
||||
smartViews: observable.ref,
|
||||
hasAtLeastOneFolder: computed,
|
||||
allNotesCount_: observable,
|
||||
allNotesCount: computed,
|
||||
@@ -144,28 +145,28 @@ export class TagsState {
|
||||
|
||||
appEventListeners.push(
|
||||
this.application.streamItems(
|
||||
[ContentType.Tag, ContentType.SmartTag],
|
||||
[ContentType.Tag, ContentType.SmartView],
|
||||
(items) => {
|
||||
runInAction(() => {
|
||||
this.tags = this.application.getDisplayableItems(
|
||||
this.tags = this.application.getDisplayableItems<SNTag>(
|
||||
ContentType.Tag
|
||||
) as SNTag[];
|
||||
this.smartTags = this.application.getSmartTags();
|
||||
);
|
||||
this.smartViews = this.application.getSmartViews();
|
||||
|
||||
const selectedTag = this.selected_;
|
||||
if (selectedTag) {
|
||||
if (selectedTag && !isSystemView(selectedTag as SmartView)) {
|
||||
const matchingTag = items.find(
|
||||
(candidate) => candidate.uuid === selectedTag.uuid
|
||||
);
|
||||
) as AnyTag;
|
||||
if (matchingTag) {
|
||||
if (matchingTag.deleted) {
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.selected_ = this.smartViews[0];
|
||||
} else {
|
||||
this.selected_ = matchingTag as AnyTag;
|
||||
this.selected_ = matchingTag;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.selected_ = this.smartViews[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -193,7 +194,9 @@ export class TagsState {
|
||||
return;
|
||||
}
|
||||
|
||||
const createdTag = await this.application.createTagOrSmartTag(title);
|
||||
const createdTag = (await this.application.createTagOrSmartView(
|
||||
title
|
||||
)) as SNTag;
|
||||
|
||||
const futureSiblings = this.application.getTagChildren(parent);
|
||||
|
||||
@@ -294,7 +297,10 @@ export class TagsState {
|
||||
}
|
||||
|
||||
public get allLocalRootTags(): SNTag[] {
|
||||
if (this.editing_ && this.application.isTemplateItem(this.editing_)) {
|
||||
if (
|
||||
this.editing_ instanceof SNTag &&
|
||||
this.application.isTemplateItem(this.editing_)
|
||||
) {
|
||||
return [this.editing_, ...this.rootTags];
|
||||
}
|
||||
return this.rootTags;
|
||||
@@ -309,9 +315,7 @@ export class TagsState {
|
||||
return [];
|
||||
}
|
||||
|
||||
const children = this.application
|
||||
.getTagChildren(tag)
|
||||
.filter((tag) => !tag.isSmartTag);
|
||||
const children = this.application.getTagChildren(tag);
|
||||
|
||||
const childrenUuids = children.map((childTag) => childTag.uuid);
|
||||
const childrenTags = this.tags.filter((tag) =>
|
||||
@@ -414,11 +418,11 @@ export class TagsState {
|
||||
return this.selected_?.uuid;
|
||||
}
|
||||
|
||||
public get editingTag(): SNTag | undefined {
|
||||
public get editingTag(): SNTag | SmartView | undefined {
|
||||
return this.editing_;
|
||||
}
|
||||
|
||||
public set editingTag(editingTag: SNTag | undefined) {
|
||||
public set editingTag(editingTag: SNTag | SmartView | undefined) {
|
||||
this.editing_ = editingTag;
|
||||
this.selected = editingTag;
|
||||
}
|
||||
@@ -442,11 +446,11 @@ export class TagsState {
|
||||
|
||||
public undoCreateNewTag() {
|
||||
this.editing_ = undefined;
|
||||
const previousTag = this.previouslySelected_ || this.smartTags[0];
|
||||
const previousTag = this.previouslySelected_ || this.smartViews[0];
|
||||
this.selected = previousTag;
|
||||
}
|
||||
|
||||
public async remove(tag: SNTag, userTriggered: boolean) {
|
||||
public async remove(tag: SNTag | SmartView, userTriggered: boolean) {
|
||||
let shouldDelete = !userTriggered;
|
||||
if (userTriggered) {
|
||||
shouldDelete = await confirmDialog({
|
||||
@@ -456,16 +460,17 @@ export class TagsState {
|
||||
}
|
||||
if (shouldDelete) {
|
||||
this.application.deleteItem(tag);
|
||||
this.selected = this.smartTags[0];
|
||||
this.selected = this.smartViews[0];
|
||||
}
|
||||
}
|
||||
|
||||
public async save(tag: SNTag, newTitle: string) {
|
||||
public async save(tag: SNTag | SmartView, newTitle: string) {
|
||||
const hasEmptyTitle = newTitle.length === 0;
|
||||
const hasNotChangedTitle = newTitle === tag.title;
|
||||
const isTemplateChange = this.application.isTemplateItem(tag);
|
||||
|
||||
const siblings = tagSiblings(this.application, tag);
|
||||
const siblings =
|
||||
tag instanceof SNTag ? tagSiblings(this.application, tag) : [];
|
||||
const hasDuplicatedTitle = siblings.some(
|
||||
(other) => other.title.toLowerCase() === newTitle.toLowerCase()
|
||||
);
|
||||
@@ -492,16 +497,16 @@ export class TagsState {
|
||||
}
|
||||
|
||||
if (isTemplateChange) {
|
||||
const isSmartTagTitle = this.application.isSmartTagTitle(newTitle);
|
||||
const isSmartViewTitle = this.application.isSmartViewTitle(newTitle);
|
||||
|
||||
if (isSmartTagTitle) {
|
||||
if (!this.features.hasSmartTags) {
|
||||
if (isSmartViewTitle) {
|
||||
if (!this.features.hasSmartViews) {
|
||||
await this.features.showPremiumAlert(SMART_TAGS_FEATURE_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const insertedTag = await this.application.createTagOrSmartTag(newTitle);
|
||||
const insertedTag = await this.application.createTagOrSmartView(newTitle);
|
||||
this.application.sync();
|
||||
runInAction(() => {
|
||||
this.selected = insertedTag as SNTag;
|
||||
@@ -529,7 +534,7 @@ export class TagsState {
|
||||
|
||||
if (
|
||||
item.content_type === ContentType.Tag ||
|
||||
item.content_type === ContentType.SmartTag
|
||||
item.content_type === ContentType.SmartView
|
||||
) {
|
||||
const matchingTag = this.application.findItem(item.uuid);
|
||||
|
||||
@@ -539,7 +544,7 @@ export class TagsState {
|
||||
}
|
||||
}
|
||||
} else if (action === ComponentAction.ClearSelection) {
|
||||
this.selected = this.smartTags[0];
|
||||
this.selected = this.smartViews[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user