178 lines
4.7 KiB
TypeScript
178 lines
4.7 KiB
TypeScript
import type { IconName } from './NamedIcon'
|
|
import type { MobileNote } from './mobileNoteProjection'
|
|
import { evaluateMobileView, mobileViewDefinitions } from './mobileViewFilters'
|
|
|
|
export type MobileSidebarSelection =
|
|
| { kind: 'library'; id: 'all' | 'archive' | 'favorites' | 'inbox' }
|
|
| { kind: 'type'; type: string }
|
|
| { kind: 'view'; id: string }
|
|
|
|
export type MobileSidebarItem = {
|
|
count: number
|
|
icon: IconName
|
|
label: string
|
|
selection: MobileSidebarSelection
|
|
}
|
|
|
|
export type MobileSidebarSection = {
|
|
items: MobileSidebarItem[]
|
|
title: string
|
|
}
|
|
|
|
export const defaultMobileSidebarSelection: MobileSidebarSelection = { kind: 'library', id: 'inbox' }
|
|
|
|
export function createMobileSidebarSections(notes: MobileNote[]): MobileSidebarSection[] {
|
|
return [
|
|
{
|
|
title: 'Library',
|
|
items: [
|
|
libraryItem({ count: inboxNotes(notes).length, icon: 'tray', id: 'inbox', label: 'Inbox' }),
|
|
libraryItem({ count: activeNotes(notes).length, icon: 'file-text', id: 'all', label: 'All Notes' }),
|
|
libraryItem({ count: archivedNotes(notes).length, icon: 'archive', id: 'archive', label: 'Archive' }),
|
|
libraryItem({ count: favoriteNotes(notes).length, icon: 'star', id: 'favorites', label: 'Favorites' }),
|
|
],
|
|
},
|
|
{
|
|
title: 'Views',
|
|
items: mobileViewDefinitions.map((view) => ({
|
|
count: evaluateMobileView({ notes: activeNotes(notes), view }).length,
|
|
icon: view.icon as IconName,
|
|
label: view.name,
|
|
selection: { kind: 'view', id: view.id },
|
|
})),
|
|
},
|
|
{
|
|
title: 'Types',
|
|
items: noteTypes(notes).map((type) => ({
|
|
count: activeNotes(notes).filter((note) => note.type === type).length,
|
|
icon: iconForType(type),
|
|
label: pluralTypeLabel(type),
|
|
selection: { kind: 'type', type },
|
|
})),
|
|
},
|
|
]
|
|
}
|
|
|
|
export function filterNotesForSidebarSelection({
|
|
notes,
|
|
selection,
|
|
}: {
|
|
notes: MobileNote[]
|
|
selection: MobileSidebarSelection
|
|
}) {
|
|
if (selection.kind === 'type') {
|
|
return activeNotes(notes).filter((note) => note.type === selection.type)
|
|
}
|
|
|
|
if (selection.kind === 'view') {
|
|
const view = mobileViewDefinitions.find((definition) => definition.id === selection.id)
|
|
return view ? evaluateMobileView({ notes: activeNotes(notes), view }) : []
|
|
}
|
|
|
|
switch (selection.id) {
|
|
case 'all':
|
|
return activeNotes(notes)
|
|
case 'archive':
|
|
return archivedNotes(notes)
|
|
case 'favorites':
|
|
return favoriteNotes(notes)
|
|
default:
|
|
return inboxNotes(notes)
|
|
}
|
|
}
|
|
|
|
export function mobileSidebarTitle(selection: MobileSidebarSelection) {
|
|
if (selection.kind === 'type') {
|
|
return pluralTypeLabel(selection.type)
|
|
}
|
|
|
|
if (selection.kind === 'view') {
|
|
return mobileViewDefinitions.find((definition) => definition.id === selection.id)?.name ?? 'View'
|
|
}
|
|
|
|
return libraryTitle(selection.id)
|
|
}
|
|
|
|
export function isMobileSidebarSelectionActive({
|
|
candidate,
|
|
current,
|
|
}: {
|
|
candidate: MobileSidebarSelection
|
|
current: MobileSidebarSelection
|
|
}) {
|
|
return candidate.kind === current.kind
|
|
&& (candidate.kind === 'type' ? candidate.type === (current as { type: string }).type : candidate.id === (current as { id: string }).id)
|
|
}
|
|
|
|
function libraryItem({
|
|
count,
|
|
icon,
|
|
id,
|
|
label,
|
|
}: {
|
|
count: number
|
|
icon: IconName
|
|
id: 'all' | 'archive' | 'favorites' | 'inbox'
|
|
label: string
|
|
}): MobileSidebarItem {
|
|
return {
|
|
count,
|
|
icon,
|
|
label,
|
|
selection: { kind: 'library', id },
|
|
}
|
|
}
|
|
|
|
function inboxNotes(notes: MobileNote[]) {
|
|
return activeNotes(notes).filter((note) => !note.status || note.status === 'Draft')
|
|
}
|
|
|
|
function activeNotes(notes: MobileNote[]) {
|
|
return notes.filter((note) => !note.archived)
|
|
}
|
|
|
|
function archivedNotes(notes: MobileNote[]) {
|
|
return notes.filter((note) => note.archived)
|
|
}
|
|
|
|
function favoriteNotes(notes: MobileNote[]) {
|
|
return activeNotes(notes)
|
|
.filter((note) => note.favorite)
|
|
.sort((left, right) => (left.favoriteIndex ?? Number.MAX_SAFE_INTEGER) - (right.favoriteIndex ?? Number.MAX_SAFE_INTEGER))
|
|
}
|
|
|
|
function noteTypes(notes: MobileNote[]) {
|
|
return [...new Set(activeNotes(notes).map((note) => note.type))].sort()
|
|
}
|
|
|
|
function libraryTitle(id: 'all' | 'archive' | 'favorites' | 'inbox') {
|
|
if (id === 'all') return 'All Notes'
|
|
if (id === 'archive') return 'Archive'
|
|
if (id === 'favorites') return 'Favorites'
|
|
return 'Inbox'
|
|
}
|
|
|
|
function pluralTypeLabel(type: string) {
|
|
return type.endsWith('s') ? type : `${type}s`
|
|
}
|
|
|
|
function iconForType(type: string): IconName {
|
|
if (type === 'Essay') {
|
|
return 'pen-nib'
|
|
}
|
|
|
|
if (type === 'Project') {
|
|
return 'wrench'
|
|
}
|
|
|
|
if (type === 'Resource') {
|
|
return 'books'
|
|
}
|
|
|
|
if (type === 'Release Note') {
|
|
return 'flag'
|
|
}
|
|
|
|
return 'file-text'
|
|
}
|