feat: ability to favorite tags + customize icon (#1858)
This commit is contained in:
@@ -1,41 +1,33 @@
|
||||
import { DecryptedItem } from '../../Abstract/Item/Implementations/DecryptedItem'
|
||||
import { PredicateInterface, PredicateJsonForm } from '../../Runtime/Predicate/Interface'
|
||||
import { PredicateInterface } from '../../Runtime/Predicate/Interface'
|
||||
import { predicateFromJson } from '../../Runtime/Predicate/Generators'
|
||||
import { ItemContent } from '../../Abstract/Content/ItemContent'
|
||||
import { DecryptedPayloadInterface } from '../../Abstract/Payload/Interfaces/DecryptedPayload'
|
||||
import { SystemViewId } from './SystemViewId'
|
||||
import { EmojiString, IconType } from '../../Utilities/Icon/IconType'
|
||||
import { SmartViewDefaultIconName, systemViewIcon } from './SmartViewIcons'
|
||||
import { SmartViewContent } from './SmartViewContent'
|
||||
|
||||
export const SMART_TAG_DSL_PREFIX = '!['
|
||||
|
||||
export enum SystemViewId {
|
||||
AllNotes = 'all-notes',
|
||||
Files = 'files',
|
||||
ArchivedNotes = 'archived-notes',
|
||||
TrashedNotes = 'trashed-notes',
|
||||
UntaggedNotes = 'untagged-notes',
|
||||
StarredNotes = 'starred-notes',
|
||||
}
|
||||
|
||||
export interface SmartViewContent extends ItemContent {
|
||||
title: string
|
||||
predicate: PredicateJsonForm
|
||||
}
|
||||
|
||||
export function isSystemView(view: SmartView): boolean {
|
||||
return Object.values(SystemViewId).includes(view.uuid as SystemViewId)
|
||||
}
|
||||
|
||||
/**
|
||||
* A tag that defines a predicate that consumers can use
|
||||
* to retrieve a dynamic list of items.
|
||||
*/
|
||||
export class SmartView extends DecryptedItem<SmartViewContent> {
|
||||
public readonly predicate!: PredicateInterface<DecryptedItem>
|
||||
public readonly title: string
|
||||
public readonly iconString: IconType | EmojiString
|
||||
|
||||
constructor(payload: DecryptedPayloadInterface<SmartViewContent>) {
|
||||
super(payload)
|
||||
this.title = String(this.content.title || '')
|
||||
|
||||
if (isSystemView(this)) {
|
||||
this.iconString = systemViewIcon(this.uuid as SystemViewId)
|
||||
} else {
|
||||
this.iconString = this.payload.content.iconString || SmartViewDefaultIconName
|
||||
}
|
||||
|
||||
try {
|
||||
this.predicate = this.content.predicate && predicateFromJson(this.content.predicate)
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { DecryptedPayload } from './../../Abstract/Payload/Implementations/DecryptedPayload'
|
||||
import { SNNote } from '../Note/Note'
|
||||
import { SmartViewContent, SmartView, SystemViewId } from './SmartView'
|
||||
import { SmartView } from './SmartView'
|
||||
import { SmartViewContent } from './SmartViewContent'
|
||||
import { SystemViewId } from './SystemViewId'
|
||||
import { ItemWithTags } from '../../Runtime/Display/Search/ItemWithTags'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { FillItemContent } from '../../Abstract/Content/ItemContent'
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { TagContent } from './../Tag/TagContent'
|
||||
import { PredicateJsonForm } from '../../Runtime/Predicate/Interface'
|
||||
|
||||
export interface SmartViewContent extends TagContent {
|
||||
predicate: PredicateJsonForm
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { SystemViewId } from './SystemViewId'
|
||||
import { IconType } from '../../Utilities/Icon/IconType'
|
||||
|
||||
export const SmartViewIcons: Record<SystemViewId, IconType> = {
|
||||
[SystemViewId.AllNotes]: 'notes',
|
||||
[SystemViewId.Files]: 'folder',
|
||||
[SystemViewId.ArchivedNotes]: 'archive',
|
||||
[SystemViewId.TrashedNotes]: 'trash',
|
||||
[SystemViewId.UntaggedNotes]: 'hashtag-off',
|
||||
[SystemViewId.StarredNotes]: 'star-filled',
|
||||
}
|
||||
|
||||
export function systemViewIcon(id: SystemViewId): IconType {
|
||||
return SmartViewIcons[id]
|
||||
}
|
||||
|
||||
export const SmartViewDefaultIconName: IconType = 'restore'
|
||||
@@ -0,0 +1,8 @@
|
||||
export enum SystemViewId {
|
||||
AllNotes = 'all-notes',
|
||||
Files = 'files',
|
||||
ArchivedNotes = 'archived-notes',
|
||||
TrashedNotes = 'trashed-notes',
|
||||
UntaggedNotes = 'untagged-notes',
|
||||
StarredNotes = 'starred-notes',
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from './SmartView'
|
||||
export * from './SmartViewBuilder'
|
||||
export * from './SystemViewId'
|
||||
export * from './SmartViewContent'
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { PayloadSource } from './../../Abstract/Payload/Types/PayloadSource'
|
||||
import { DecryptedPayload } from './../../Abstract/Payload/Implementations/DecryptedPayload'
|
||||
import { SNTag, TagContent } from './Tag'
|
||||
import { SNTag } from './Tag'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { FillItemContent } from '../../Abstract/Content/ItemContent'
|
||||
import { ContentReference } from '../../Abstract/Reference/ContentReference'
|
||||
import { PayloadTimestampDefaults } from '../../Abstract/Payload'
|
||||
import { TagContent } from './TagContent'
|
||||
|
||||
const randUuid = () => String(Math.random())
|
||||
|
||||
|
||||
@@ -1,32 +1,28 @@
|
||||
import { VectorIconNameOrEmoji, IconType } from './../../Utilities/Icon/IconType'
|
||||
import { ContentType, Uuid } from '@standardnotes/common'
|
||||
import { DecryptedItem } from '../../Abstract/Item/Implementations/DecryptedItem'
|
||||
import { ItemInterface } from '../../Abstract/Item/Interfaces/ItemInterface'
|
||||
import { ItemContent } from '../../Abstract/Content/ItemContent'
|
||||
import { ContentReference } from '../../Abstract/Reference/ContentReference'
|
||||
import { isTagToParentTagReference } from '../../Abstract/Reference/Functions'
|
||||
import { DecryptedPayloadInterface } from '../../Abstract/Payload/Interfaces/DecryptedPayload'
|
||||
import { TagContent, TagContentSpecialized } from './TagContent'
|
||||
|
||||
export const TagFolderDelimitter = '.'
|
||||
|
||||
interface TagInterface {
|
||||
title: string
|
||||
expanded: boolean
|
||||
}
|
||||
|
||||
export type TagContent = TagInterface & ItemContent
|
||||
export const DefaultTagIconName: IconType = 'hashtag'
|
||||
|
||||
export const isTag = (x: ItemInterface): x is SNTag => x.content_type === ContentType.Tag
|
||||
|
||||
export class SNTag extends DecryptedItem<TagContent> implements TagInterface {
|
||||
export class SNTag extends DecryptedItem<TagContent> implements TagContentSpecialized {
|
||||
public readonly title: string
|
||||
|
||||
/** Whether to render child tags in view hierarchy. Opposite of collapsed. */
|
||||
public readonly iconString: VectorIconNameOrEmoji
|
||||
public readonly expanded: boolean
|
||||
|
||||
constructor(payload: DecryptedPayloadInterface<TagContent>) {
|
||||
super(payload)
|
||||
this.title = this.payload.content.title || ''
|
||||
this.expanded = this.payload.content.expanded != undefined ? this.payload.content.expanded : true
|
||||
this.iconString = this.payload.content.iconString || DefaultTagIconName
|
||||
}
|
||||
|
||||
get noteReferences(): ContentReference[] {
|
||||
|
||||
11
packages/models/src/Domain/Syncable/Tag/TagContent.ts
Normal file
11
packages/models/src/Domain/Syncable/Tag/TagContent.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { IconType } from './../../Utilities/Icon/IconType'
|
||||
import { ItemContent } from '../../Abstract/Content/ItemContent'
|
||||
import { EmojiString } from '../../Utilities/Icon/IconType'
|
||||
|
||||
export interface TagContentSpecialized {
|
||||
title: string
|
||||
expanded: boolean
|
||||
iconString: IconType | EmojiString
|
||||
}
|
||||
|
||||
export type TagContent = TagContentSpecialized & ItemContent
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { TagContent, SNTag } from './Tag'
|
||||
import { SNTag } from './Tag'
|
||||
import { TagContent } from './TagContent'
|
||||
import { FileItem } from '../File'
|
||||
import { SNNote } from '../Note'
|
||||
import { isTagToParentTagReference } from '../../Abstract/Reference/Functions'
|
||||
@@ -17,6 +18,10 @@ export class TagMutator extends DecryptedItemMutator<TagContent> {
|
||||
this.mutableContent.expanded = expanded
|
||||
}
|
||||
|
||||
set iconString(iconString: string) {
|
||||
this.mutableContent.iconString = iconString
|
||||
}
|
||||
|
||||
public makeChildOf(tag: SNTag): void {
|
||||
const references = this.immutableItem.references.filter((ref) => !isTagToParentTagReference(ref))
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './Tag'
|
||||
export * from './TagMutator'
|
||||
export * from './TagContent'
|
||||
|
||||
190
packages/models/src/Domain/Utilities/Icon/IconType.ts
Normal file
190
packages/models/src/Domain/Utilities/Icon/IconType.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
export type VectorIconNameOrEmoji = EmojiString | IconType
|
||||
|
||||
export type EmojiString = string
|
||||
|
||||
export type IconType =
|
||||
| 'accessibility'
|
||||
| 'account-card-details-outline'
|
||||
| 'account-circle'
|
||||
| 'add-bold'
|
||||
| 'add-text'
|
||||
| 'add'
|
||||
| 'archive'
|
||||
| 'arrow-down'
|
||||
| 'arrow-left'
|
||||
| 'arrow-right'
|
||||
| 'arrow-up'
|
||||
| 'arrows-horizontal'
|
||||
| 'arrows-sort-down'
|
||||
| 'arrows-sort-up'
|
||||
| 'asterisk'
|
||||
| 'attachment-file'
|
||||
| 'authenticator-variant'
|
||||
| 'authenticator'
|
||||
| 'back-ios'
|
||||
| 'bold'
|
||||
| 'box-filled'
|
||||
| 'box'
|
||||
| 'camera'
|
||||
| 'check-all'
|
||||
| 'check-bold'
|
||||
| 'check-circle-filled'
|
||||
| 'check-circle'
|
||||
| 'check'
|
||||
| 'chevron-down'
|
||||
| 'chevron-left'
|
||||
| 'chevron-right'
|
||||
| 'chevron-up'
|
||||
| 'clear-circle-filled'
|
||||
| 'close'
|
||||
| 'cloud-off'
|
||||
| 'code-2'
|
||||
| 'code-tags'
|
||||
| 'code'
|
||||
| 'color-fill'
|
||||
| 'copy'
|
||||
| 'dashboard'
|
||||
| 'diamond-filled'
|
||||
| 'diamond'
|
||||
| 'download'
|
||||
| 'drag'
|
||||
| 'draw'
|
||||
| 'editor-filled'
|
||||
| 'editor'
|
||||
| 'email-filled'
|
||||
| 'email'
|
||||
| 'enter'
|
||||
| 'eye-filled'
|
||||
| 'eye-off-filled'
|
||||
| 'eye-off'
|
||||
| 'eye'
|
||||
| 'feedback'
|
||||
| 'file-filled'
|
||||
| 'file'
|
||||
| 'file-other'
|
||||
| 'file-pdf'
|
||||
| 'file-doc'
|
||||
| 'file-ppt'
|
||||
| 'file-xls'
|
||||
| 'file-image'
|
||||
| 'file-mov'
|
||||
| 'file-music'
|
||||
| 'file-zip'
|
||||
| 'files-illustration'
|
||||
| 'folder-filled'
|
||||
| 'folder-key-filled'
|
||||
| 'folder'
|
||||
| 'format-align-center'
|
||||
| 'format-align-justify'
|
||||
| 'format-align-left'
|
||||
| 'format-align-right'
|
||||
| 'forward-ios'
|
||||
| 'fullscreen-exit'
|
||||
| 'fullscreen'
|
||||
| 'gift-outline'
|
||||
| 'hashtag-filled'
|
||||
| 'hashtag-off'
|
||||
| 'hashtag'
|
||||
| 'heart-filled'
|
||||
| 'help-filled'
|
||||
| 'help'
|
||||
| 'history'
|
||||
| 'image'
|
||||
| 'info'
|
||||
| 'italic'
|
||||
| 'keyboard-close'
|
||||
| 'keyboard-command'
|
||||
| 'keyboard-filled'
|
||||
| 'keyboard-option'
|
||||
| 'keyboard-shift'
|
||||
| 'keyboard-show'
|
||||
| 'keyboard'
|
||||
| 'lifebuoy'
|
||||
| 'line-width'
|
||||
| 'link-off'
|
||||
| 'link'
|
||||
| 'list-bulleted'
|
||||
| 'listed-filled'
|
||||
| 'listed'
|
||||
| 'lock-filled'
|
||||
| 'lock'
|
||||
| 'markdown'
|
||||
| 'menu-arrow-down-alt'
|
||||
| 'menu-arrow-down'
|
||||
| 'menu-arrow-right'
|
||||
| 'menu-close'
|
||||
| 'menu-open'
|
||||
| 'menu-variant'
|
||||
| 'merge'
|
||||
| 'more-vert'
|
||||
| 'more'
|
||||
| 'notes-filled'
|
||||
| 'notes-remove'
|
||||
| 'notes'
|
||||
| 'open-in'
|
||||
| 'password'
|
||||
| 'pencil-filled'
|
||||
| 'pencil-off'
|
||||
| 'pencil'
|
||||
| 'pin-filled'
|
||||
| 'pin-off'
|
||||
| 'pin'
|
||||
| 'plain-text'
|
||||
| 'plus-circle-filled'
|
||||
| 'plus-circle'
|
||||
| 'premium-feature'
|
||||
| 'print'
|
||||
| 'redo'
|
||||
| 'restore'
|
||||
| 'rich-text'
|
||||
| 'safe-square-filled'
|
||||
| 'safe-square'
|
||||
| 'safe'
|
||||
| 'save'
|
||||
| 'search-ios'
|
||||
| 'search'
|
||||
| 'security'
|
||||
| 'select-all'
|
||||
| 'send'
|
||||
| 'server'
|
||||
| 'settings-filled'
|
||||
| 'settings'
|
||||
| 'share'
|
||||
| 'signIn'
|
||||
| 'signOut'
|
||||
| 'sort-descending'
|
||||
| 'spellcheck'
|
||||
| 'spreadsheets'
|
||||
| 'standard-notes-2'
|
||||
| 'standard-notes'
|
||||
| 'star-circle-filled'
|
||||
| 'star-filled'
|
||||
| 'star-variant-filled'
|
||||
| 'star'
|
||||
| 'strikethrough'
|
||||
| 'sync'
|
||||
| 'tasks'
|
||||
| 'text-circle'
|
||||
| 'text-paragraph-long'
|
||||
| 'text'
|
||||
| 'textbox-password'
|
||||
| 'themes-filled'
|
||||
| 'themes'
|
||||
| 'timer'
|
||||
| 'trash-filled'
|
||||
| 'trash-sweep-filled'
|
||||
| 'trash-sweep'
|
||||
| 'trash'
|
||||
| 'tune'
|
||||
| 'unarchive'
|
||||
| 'underline'
|
||||
| 'undo'
|
||||
| 'unpin'
|
||||
| 'upload'
|
||||
| 'user-add'
|
||||
| 'user-filled'
|
||||
| 'user-switch'
|
||||
| 'user'
|
||||
| 'view'
|
||||
| 'warning'
|
||||
| 'window'
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TagContent } from './../../Syncable/Tag/Tag'
|
||||
import { TagContent } from './../../Syncable/Tag/TagContent'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { FillItemContent, ItemContent } from '../../Abstract/Content/ItemContent'
|
||||
import { DecryptedPayload, PayloadSource, PayloadTimestampDefaults } from '../../Abstract/Payload'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export * from './Abstract/Component/ActionObserver'
|
||||
export * from './Abstract/Component/ComponentViewerEvent'
|
||||
export * from './Abstract/Component/ComponentMessage'
|
||||
export * from './Abstract/Component/ComponentEventObserver'
|
||||
export * from './Abstract/Component/ComponentMessage'
|
||||
export * from './Abstract/Component/ComponentViewerEvent'
|
||||
export * from './Abstract/Component/IncomingComponentItemPayload'
|
||||
export * from './Abstract/Component/KeyboardModifier'
|
||||
export * from './Abstract/Component/MessageData'
|
||||
@@ -43,9 +43,9 @@ export * from './Runtime/Collection/Payload/ImmutablePayloadCollection'
|
||||
export * from './Runtime/Collection/Payload/PayloadCollection'
|
||||
export * from './Runtime/Deltas'
|
||||
export * from './Runtime/DirtyCounter/DirtyCounter'
|
||||
export * from './Runtime/Display'
|
||||
export * from './Runtime/Display/ItemDisplayController'
|
||||
export * from './Runtime/Display/Types'
|
||||
export * from './Runtime/Display'
|
||||
export * from './Runtime/History'
|
||||
export * from './Runtime/Index/ItemDelta'
|
||||
export * from './Runtime/Index/SNIndex'
|
||||
@@ -70,6 +70,7 @@ export * from './Syncable/SmartView'
|
||||
export * from './Syncable/Tag'
|
||||
export * from './Syncable/Theme'
|
||||
export * from './Syncable/UserPrefs'
|
||||
export * from './Utilities/Icon/IconType'
|
||||
export * from './Utilities/Item/FindItem'
|
||||
export * from './Utilities/Item/ItemContentsDiffer'
|
||||
export * from './Utilities/Item/ItemContentsEqual'
|
||||
|
||||
Reference in New Issue
Block a user