#74 - Integration with Bookmarks core plugin and support for indirect drag & drop arrangement
- advanced performance optimizations: bookmarks cache finetuning, switching to Obsidian sort code if the implicit bookmark-integration sorting spec is in effect for a folder and there are no bookmarked items in the folder - unit tests for some of newly introduced functions
This commit is contained in:
parent
a4a6c93412
commit
daf657721c
|
@ -0,0 +1,187 @@
|
|||
import {
|
||||
CustomSortGroupType,
|
||||
CustomSortOrder,
|
||||
CustomSortSpec
|
||||
} from "./custom-sort-types";
|
||||
import {
|
||||
collectSortingAndGroupingTypes,
|
||||
hasOnlyByBookmarkOrStandardObsidian,
|
||||
HasSortingOrGrouping,
|
||||
ImplicitSortspecForBookmarksIntegration
|
||||
} from "./custom-sort-utils";
|
||||
import {SortingSpecProcessor, SortSpecsCollection} from "./sorting-spec-processor";
|
||||
|
||||
type NM = number
|
||||
|
||||
const getHas = (gTotal?: NM, gBkmrk?: NM, gStar?: NM, gIcon?: NM, sTot?: NM, sBkmrk?: NM, sStd?: NM) => {
|
||||
const has: HasSortingOrGrouping = {
|
||||
grouping: {
|
||||
total: gTotal ||0,
|
||||
byBookmarks: gBkmrk ||0,
|
||||
byStarred: gStar ||0,
|
||||
byIcon: gIcon ||0
|
||||
},
|
||||
sorting: {
|
||||
total: sTot ||0,
|
||||
byBookmarks: sBkmrk ||0,
|
||||
standardObsidian: sStd ||0
|
||||
}
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
describe('hasOnlyByBookmarkOrStandardObsidian and collectSortingAndGroupingTypes', () => {
|
||||
it('should handle empty spec correctly', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined|null = undefined
|
||||
const expectedHas: HasSortingOrGrouping = getHas()
|
||||
const has = collectSortingAndGroupingTypes(spec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(has).toEqual(expectedHas)
|
||||
expect(hasOnly).toBeTruthy()
|
||||
})
|
||||
it('should handle empty spec correctly (null variant)', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined|null = null
|
||||
const expectedHas: HasSortingOrGrouping = getHas()
|
||||
const has = collectSortingAndGroupingTypes(spec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeTruthy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should handle spec with empty orders correctly', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
groups: [
|
||||
{type: CustomSortGroupType.Outsiders, filesOnly: true},
|
||||
{type: CustomSortGroupType.Outsiders}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas()
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeTruthy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should detect not matching default order', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
defaultOrder: CustomSortOrder.default,
|
||||
groups: [
|
||||
{
|
||||
type: CustomSortGroupType.ExactName,
|
||||
},
|
||||
{
|
||||
type: CustomSortGroupType.Outsiders,
|
||||
}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 0, 0, 0, 1, 0, 0)
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeFalsy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should detect not matching default secondary order', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
defaultOrder: CustomSortOrder.byBookmarkOrder,
|
||||
defaultSecondaryOrder: CustomSortOrder.default,
|
||||
groups: [
|
||||
{
|
||||
type: CustomSortGroupType.BookmarkedOnly,
|
||||
},
|
||||
{
|
||||
type: CustomSortGroupType.Outsiders,
|
||||
}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 1, 0, 0, 2, 1, 0)
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeFalsy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should detect not matching order in group', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
defaultOrder: CustomSortOrder.byBookmarkOrder,
|
||||
defaultSecondaryOrder: CustomSortOrder.standardObsidian,
|
||||
groups: [
|
||||
{
|
||||
type: CustomSortGroupType.ExactName,
|
||||
order: CustomSortOrder.byCreatedTimeReverse
|
||||
},
|
||||
{
|
||||
type: CustomSortGroupType.Outsiders,
|
||||
}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 0, 0, 0, 3, 1, 1)
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeFalsy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should detect not matching secondary order in group', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
defaultOrder: CustomSortOrder.byBookmarkOrder,
|
||||
defaultSecondaryOrder: CustomSortOrder.standardObsidian,
|
||||
groups: [
|
||||
{
|
||||
type: CustomSortGroupType.ExactName,
|
||||
order: CustomSortOrder.byBookmarkOrderReverse,
|
||||
secondaryOrder: CustomSortOrder.standardObsidian
|
||||
},
|
||||
{
|
||||
type: CustomSortGroupType.Outsiders,
|
||||
order: CustomSortOrder.byBookmarkOrder,
|
||||
secondaryOrder: CustomSortOrder.alphabetical
|
||||
}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 0, 0, 0, 6, 3, 2)
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeFalsy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
it('should detect matching orders at all levels', () => {
|
||||
const spec: Partial<CustomSortSpec>|undefined = {
|
||||
defaultOrder: CustomSortOrder.byBookmarkOrder,
|
||||
defaultSecondaryOrder: CustomSortOrder.standardObsidian,
|
||||
groups: [
|
||||
{
|
||||
type: CustomSortGroupType.BookmarkedOnly,
|
||||
order: CustomSortOrder.byBookmarkOrderReverse,
|
||||
secondaryOrder: CustomSortOrder.standardObsidian
|
||||
},
|
||||
{
|
||||
type: CustomSortGroupType.Outsiders,
|
||||
order: CustomSortOrder.byBookmarkOrder,
|
||||
secondaryOrder: CustomSortOrder.byBookmarkOrderReverse
|
||||
}
|
||||
]
|
||||
}
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 1, 0, 0, 6, 4, 2)
|
||||
const has = collectSortingAndGroupingTypes(spec as CustomSortSpec)
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeTruthy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ImplicitSortspecForBookmarksIntegration', () => {
|
||||
it('should correctly be recognized as only bookmark and obsidian standard', () => {
|
||||
const processor: SortingSpecProcessor = new SortingSpecProcessor();
|
||||
const inputTxtArr: Array<string> = ImplicitSortspecForBookmarksIntegration.replace(/\t/gi, '').split('\n')
|
||||
const spec: SortSpecsCollection|null|undefined = processor.parseSortSpecFromText(
|
||||
inputTxtArr,
|
||||
'mock-folder',
|
||||
'custom-name-note.md',
|
||||
null,
|
||||
true
|
||||
)
|
||||
const expectedHas: HasSortingOrGrouping = getHas(1, 1, 0, 0, 2, 1, 1)
|
||||
const has = collectSortingAndGroupingTypes(spec?.sortSpecByPath!['/'])
|
||||
const hasOnly = hasOnlyByBookmarkOrStandardObsidian(has)
|
||||
expect(hasOnly).toBeTruthy()
|
||||
expect(has).toEqual(expectedHas)
|
||||
})
|
||||
})
|
||||
|
||||
// TODO - czy tamto sprawdzanie dla itemów w rootowym filderze hasBookmarkInFolder dobrze zadziala
|
|
@ -0,0 +1,80 @@
|
|||
import {CustomSortGroupType, CustomSortOrder, CustomSortSpec} from "./custom-sort-types";
|
||||
|
||||
// Put here to allow unit tests coverage of this specific implicit sorting spec
|
||||
export const ImplicitSortspecForBookmarksIntegration: string = `
|
||||
target-folder: /*
|
||||
bookmarked:
|
||||
< by-bookmarks-order
|
||||
sorting: standard
|
||||
`
|
||||
|
||||
export interface HasSortingTypes {
|
||||
byBookmarks: number
|
||||
standardObsidian: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface HasGroupingTypes {
|
||||
byBookmarks: number
|
||||
byStarred: number
|
||||
byIcon: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface HasSortingOrGrouping {
|
||||
sorting: HasSortingTypes
|
||||
grouping: HasGroupingTypes
|
||||
}
|
||||
|
||||
export const checkByBookmark = (has: HasSortingOrGrouping, order?: CustomSortOrder, groupType?: CustomSortGroupType ) => {
|
||||
groupType === CustomSortGroupType.BookmarkedOnly && has.grouping.byBookmarks++;
|
||||
(order === CustomSortOrder.byBookmarkOrder || order === CustomSortOrder.byBookmarkOrderReverse) && has.sorting.byBookmarks++;
|
||||
}
|
||||
|
||||
export const checkByStarred = (has: HasSortingOrGrouping, order?: CustomSortOrder, groupType?: CustomSortGroupType ) => {
|
||||
groupType === CustomSortGroupType.StarredOnly && has.grouping.byStarred++;
|
||||
}
|
||||
|
||||
export const checkByIcon = (has: HasSortingOrGrouping, order?: CustomSortOrder, groupType?: CustomSortGroupType ) => {
|
||||
groupType === CustomSortGroupType.HasIcon && has.grouping.byIcon++;
|
||||
}
|
||||
|
||||
export const checkStandardObsidian = (has: HasSortingOrGrouping, order?: CustomSortOrder, groupType?: CustomSortGroupType ) => {
|
||||
order === CustomSortOrder.standardObsidian && has.sorting.standardObsidian++;
|
||||
}
|
||||
|
||||
export const doCheck = (has: HasSortingOrGrouping, order?: CustomSortOrder, groupType?: CustomSortGroupType) => {
|
||||
checkByBookmark(has, order, groupType)
|
||||
checkByStarred(has, order, groupType)
|
||||
checkByIcon(has, order, groupType)
|
||||
checkStandardObsidian(has, order, groupType)
|
||||
|
||||
order !== undefined && has.sorting.total++
|
||||
groupType !== undefined && groupType !== CustomSortGroupType.Outsiders && has.grouping.total++;
|
||||
}
|
||||
|
||||
export const collectSortingAndGroupingTypes = (sortSpec?: CustomSortSpec|null): HasSortingOrGrouping => {
|
||||
const has: HasSortingOrGrouping = {
|
||||
grouping: {
|
||||
byIcon: 0, byStarred: 0, byBookmarks: 0, total: 0
|
||||
},
|
||||
sorting: {
|
||||
byBookmarks: 0, standardObsidian: 0, total: 0
|
||||
}
|
||||
}
|
||||
if (!sortSpec) return has
|
||||
doCheck(has, sortSpec.defaultOrder)
|
||||
doCheck(has, sortSpec.defaultSecondaryOrder)
|
||||
if (sortSpec.groups) {
|
||||
for (let group of sortSpec.groups) {
|
||||
doCheck(has, group.order, group.type)
|
||||
doCheck(has, group.secondaryOrder)
|
||||
}
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
export const hasOnlyByBookmarkOrStandardObsidian = (has: HasSortingOrGrouping): boolean => {
|
||||
return has.sorting.total === has.sorting.standardObsidian + has.sorting.byBookmarks &&
|
||||
has.grouping.total === has.grouping.byBookmarks
|
||||
}
|
60
src/main.ts
60
src/main.ts
|
@ -30,7 +30,9 @@ import {
|
|||
SortingSpecProcessor,
|
||||
SortSpecsCollection
|
||||
} from './custom-sort/sorting-spec-processor';
|
||||
import {CustomSortSpec} from './custom-sort/custom-sort-types';
|
||||
import {
|
||||
CustomSortSpec
|
||||
} from './custom-sort/custom-sort-types';
|
||||
|
||||
import {
|
||||
addIcons,
|
||||
|
@ -43,10 +45,17 @@ import {
|
|||
} from "./custom-sort/icons";
|
||||
import {getStarredPlugin} from "./utils/StarredPluginSignature";
|
||||
import {
|
||||
BookmarksPluginInterface,
|
||||
getBookmarksPlugin
|
||||
} from "./utils/BookmarksCorePluginSignature";
|
||||
import {getIconFolderPlugin} from "./utils/ObsidianIconFolderPluginSignature";
|
||||
import {lastPathComponent} from "./utils/utils";
|
||||
import {
|
||||
collectSortingAndGroupingTypes,
|
||||
hasOnlyByBookmarkOrStandardObsidian,
|
||||
HasSortingOrGrouping,
|
||||
ImplicitSortspecForBookmarksIntegration
|
||||
} from "./custom-sort/custom-sort-utils";
|
||||
|
||||
interface CustomSortPluginSettings {
|
||||
additionalSortspecFile: string
|
||||
|
@ -70,7 +79,8 @@ const DEFAULT_SETTINGS: CustomSortPluginSettings = {
|
|||
bookmarksGroupToConsumeAsOrderingReference: 'sortspec'
|
||||
}
|
||||
|
||||
const DEFAULT_SETTING_FOR_FRESH_INSTALL_1_2_0: Partial<CustomSortPluginSettings> = {
|
||||
// On API 1.2.x+ enable the bookmarks integration by default
|
||||
const DEFAULT_SETTING_FOR_1_2_0_UP: Partial<CustomSortPluginSettings> = {
|
||||
automaticBookmarksIntegration: true,
|
||||
bookmarksContextMenus: true
|
||||
}
|
||||
|
@ -80,13 +90,6 @@ const SORTINGSPEC_YAML_KEY: string = 'sorting-spec'
|
|||
|
||||
const ERROR_NOTICE_TIMEOUT: number = 10000
|
||||
|
||||
const ImplicitSortspecForBookmarksIntegration: string = `
|
||||
target-folder: /*
|
||||
bookmarked:
|
||||
< by-bookmarks-order
|
||||
sorting: standard
|
||||
`
|
||||
|
||||
// the monkey-around package doesn't export the below type
|
||||
type MonkeyAroundUninstaller = () => void
|
||||
|
||||
|
@ -360,7 +363,7 @@ export default class CustomSortPlugin extends Plugin {
|
|||
item.onClick(() => {
|
||||
const bookmarksPlugin = getBookmarksPlugin(plugin.settings.bookmarksGroupToConsumeAsOrderingReference)
|
||||
if (bookmarksPlugin) {
|
||||
const orderedChildren: Array<TAbstractFile> = plugin.orderedFolderItemsForBookmarking(file.parent)
|
||||
const orderedChildren: Array<TAbstractFile> = plugin.orderedFolderItemsForBookmarking(file.parent, bookmarksPlugin)
|
||||
bookmarksPlugin.bookmarkSiblings(orderedChildren)
|
||||
bookmarksPlugin.saveDataAndUpdateBookmarkViews(true)
|
||||
}
|
||||
|
@ -429,12 +432,12 @@ export default class CustomSortPlugin extends Plugin {
|
|||
return sortSpec
|
||||
}
|
||||
|
||||
createProcessingContextForSorting(): ProcessingContext {
|
||||
createProcessingContextForSorting(has: HasSortingOrGrouping): ProcessingContext {
|
||||
const ctx: ProcessingContext = {
|
||||
_mCache: app.metadataCache,
|
||||
starredPluginInstance: getStarredPlugin(),
|
||||
bookmarksPluginInstance: getBookmarksPlugin(this.settings.bookmarksGroupToConsumeAsOrderingReference),
|
||||
iconFolderPluginInstance: getIconFolderPlugin(),
|
||||
starredPluginInstance: has.grouping.byStarred ? getStarredPlugin() : undefined,
|
||||
bookmarksPluginInstance: has.grouping.byBookmarks || has.sorting.byBookmarks ? getBookmarksPlugin(this.settings.bookmarksGroupToConsumeAsOrderingReference, false, true) : undefined,
|
||||
iconFolderPluginInstance: has.grouping.byIcon ? getIconFolderPlugin() : undefined,
|
||||
plugin: this
|
||||
}
|
||||
return ctx
|
||||
|
@ -466,8 +469,18 @@ export default class CustomSortPlugin extends Plugin {
|
|||
const folder: TFolder = this.file
|
||||
let sortSpec: CustomSortSpec | null | undefined = plugin.determineSortSpecForFolder(folder.path, folder.name)
|
||||
|
||||
// Performance optimization
|
||||
// Primary intention: when the implicit bookmarks integration is enabled, remain on std Obsidian, if no need to involve bookmarks
|
||||
let has: HasSortingOrGrouping = collectSortingAndGroupingTypes(sortSpec)
|
||||
if (hasOnlyByBookmarkOrStandardObsidian(has)) {
|
||||
const bookmarksPlugin: BookmarksPluginInterface|undefined = getBookmarksPlugin(plugin.settings.bookmarksGroupToConsumeAsOrderingReference, false, true)
|
||||
if ( !bookmarksPlugin?.bookmarksIncludeItemsInFolder(folder.path)) {
|
||||
sortSpec = null
|
||||
}
|
||||
}
|
||||
|
||||
if (sortSpec) {
|
||||
return folderSort.call(this, sortSpec, plugin.createProcessingContextForSorting());
|
||||
return folderSort.call(this, sortSpec, plugin.createProcessingContextForSorting(has));
|
||||
} else {
|
||||
return old.call(this, ...args);
|
||||
}
|
||||
|
@ -481,14 +494,21 @@ export default class CustomSortPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
orderedFolderItemsForBookmarking(folder: TFolder): Array<TAbstractFile> {
|
||||
orderedFolderItemsForBookmarking(folder: TFolder, bookmarksPlugin: BookmarksPluginInterface): Array<TAbstractFile> {
|
||||
let sortSpec: CustomSortSpec | null | undefined = undefined
|
||||
if (!this.settings.suspended) {
|
||||
sortSpec = this.determineSortSpecForFolder(folder.path, folder.name)
|
||||
}
|
||||
let uiSortOrder: string = this.getFileExplorer()?.sortOrder || ObsidianStandardDefaultSortingName
|
||||
|
||||
return sortFolderItemsForBookmarking(folder.children, sortSpec, this.createProcessingContextForSorting(), uiSortOrder)
|
||||
const has: HasSortingOrGrouping = collectSortingAndGroupingTypes(sortSpec)
|
||||
|
||||
return sortFolderItemsForBookmarking(
|
||||
folder.children,
|
||||
sortSpec,
|
||||
this.createProcessingContextForSorting(has),
|
||||
uiSortOrder
|
||||
)
|
||||
}
|
||||
|
||||
// Credits go to https://github.com/nothingislost/obsidian-bartender
|
||||
|
@ -511,10 +531,8 @@ export default class CustomSortPlugin extends Plugin {
|
|||
const data: any = await this.loadData() || {}
|
||||
const isFreshInstall: boolean = Object.keys(data).length === 0
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
|
||||
if (isFreshInstall) {
|
||||
if (requireApiVersion('1.2.0')) {
|
||||
this.settings = Object.assign(this.settings, DEFAULT_SETTING_FOR_FRESH_INSTALL_1_2_0)
|
||||
}
|
||||
if (requireApiVersion('1.2.0')) {
|
||||
this.settings = Object.assign(this.settings, DEFAULT_SETTING_FOR_1_2_0_UP)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,9 @@ export interface BookmarksPluginInterface {
|
|||
updateSortingBookmarksAfterItemRenamed(renamedItem: TAbstractFile, oldPath: string): void
|
||||
updateSortingBookmarksAfterItemDeleted(deletedItem: TAbstractFile): void
|
||||
isBookmarkedForSorting(item: TAbstractFile): boolean
|
||||
|
||||
// To support performance optimization
|
||||
bookmarksIncludeItemsInFolder(folderPath: string): boolean
|
||||
}
|
||||
|
||||
class BookmarksPluginWrapper implements BookmarksPluginInterface {
|
||||
|
@ -91,15 +94,21 @@ class BookmarksPluginWrapper implements BookmarksPluginInterface {
|
|||
// undefined ==> item not found in bookmarks
|
||||
// > 0 ==> item found in bookmarks at returned position
|
||||
// Intentionally not returning 0 to allow simple syntax of processing the result
|
||||
determineBookmarkOrder = (path: string): number | undefined => {
|
||||
//
|
||||
// Parameterless invocation enforces cache population, if empty
|
||||
determineBookmarkOrder = (path?: string): number | undefined => {
|
||||
if (!bookmarksCache) {
|
||||
bookmarksCache = getOrderedBookmarks(this.plugin!, this.groupNameForSorting)
|
||||
[bookmarksCache, bookmarksFoldersCoverage] = getOrderedBookmarks(this.plugin!, this.groupNameForSorting)
|
||||
bookmarksCacheTimestamp = Date.now()
|
||||
}
|
||||
|
||||
const bookmarkedItemPosition: number | undefined = bookmarksCache?.[path]?.order
|
||||
if (path && path.length > 0) {
|
||||
const bookmarkedItemPosition: number | undefined = bookmarksCache?.[path]?.order
|
||||
|
||||
return (bookmarkedItemPosition !== undefined && bookmarkedItemPosition >= 0) ? (bookmarkedItemPosition + 1) : undefined
|
||||
return (bookmarkedItemPosition !== undefined && bookmarkedItemPosition >= 0) ? (bookmarkedItemPosition + 1) : undefined
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
bookmarkFolderItem = (item: TAbstractFile) => {
|
||||
|
@ -166,11 +175,16 @@ class BookmarksPluginWrapper implements BookmarksPluginInterface {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
bookmarksIncludeItemsInFolder = (folderPath: string): boolean => {
|
||||
console.error(`C: for ${folderPath} is ${bookmarksFoldersCoverage?.[folderPath]}`)
|
||||
return !! bookmarksFoldersCoverage?.[folderPath]
|
||||
}
|
||||
}
|
||||
|
||||
export const BookmarksCorePluginId: string = 'bookmarks'
|
||||
|
||||
export const getBookmarksPlugin = (bookmarksGroupName?: string, forceFlushCache?: boolean): BookmarksPluginInterface | undefined => {
|
||||
export const getBookmarksPlugin = (bookmarksGroupName?: string, forceFlushCache?: boolean, ensureCachePopulated?: boolean): BookmarksPluginInterface | undefined => {
|
||||
invalidateExpiredBookmarksCache(forceFlushCache)
|
||||
const installedBookmarksPlugin: InstalledPlugin | undefined = app?.internalPlugins?.getPluginById(BookmarksCorePluginId)
|
||||
if (installedBookmarksPlugin && installedBookmarksPlugin.enabled && installedBookmarksPlugin.instance) {
|
||||
|
@ -179,6 +193,9 @@ export const getBookmarksPlugin = (bookmarksGroupName?: string, forceFlushCache?
|
|||
if (typeof bookmarksPluginInstance?.[BookmarksPlugin_getBookmarks_methodName] === 'function') {
|
||||
bookmarksPlugin.plugin = bookmarksPluginInstance
|
||||
bookmarksPlugin.groupNameForSorting = bookmarksGroupName
|
||||
if (ensureCachePopulated && !bookmarksCache) {
|
||||
bookmarksPlugin.determineBookmarkOrder()
|
||||
}
|
||||
return bookmarksPlugin
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +204,9 @@ export const getBookmarksPlugin = (bookmarksGroupName?: string, forceFlushCache?
|
|||
// cache can outlive the wrapper instances
|
||||
let bookmarksCache: OrderedBookmarks | undefined = undefined
|
||||
let bookmarksCacheTimestamp: number | undefined = undefined
|
||||
type FolderPath = string
|
||||
type FoldersCoverage = { [key: FolderPath]: boolean }
|
||||
let bookmarksFoldersCoverage: FoldersCoverage | undefined = undefined
|
||||
|
||||
const bookmarksPlugin: BookmarksPluginWrapper = new BookmarksPluginWrapper()
|
||||
|
||||
|
@ -203,6 +223,7 @@ const invalidateExpiredBookmarksCache = (force?: boolean): void => {
|
|||
if (flush) {
|
||||
bookmarksCache = undefined
|
||||
bookmarksCacheTimestamp = undefined
|
||||
bookmarksFoldersCoverage = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,8 +247,12 @@ const bookmarkLocationAndPathOverlap = (bookmarkParentGroupPath: string, fileOrF
|
|||
return fileOrFolderPath?.startsWith(bookmarkParentGroupPath) ? bookmarkParentGroupPath.length : 0
|
||||
}
|
||||
|
||||
const getOrderedBookmarks = (plugin: Bookmarks_PluginInstance, bookmarksGroupName?: string): OrderedBookmarks | undefined => {
|
||||
const ROOT_FOLDER_PATH = '/'
|
||||
|
||||
const getOrderedBookmarks = (plugin: Bookmarks_PluginInstance, bookmarksGroupName?: string): [OrderedBookmarks, FoldersCoverage] | [undefined, undefined] => {
|
||||
console.log(`getOrderedBookmarks()`)
|
||||
let bookmarksItems: Array<BookmarkedItem> | undefined = plugin?.[BookmarksPlugin_items_collectionName]
|
||||
let bookmarksCoveredFolders: FoldersCoverage = {}
|
||||
if (bookmarksItems) {
|
||||
if (bookmarksGroupName) {
|
||||
// scanning only top level items because by desing the bookmarks group for sorting is a top level item
|
||||
|
@ -249,6 +274,10 @@ const getOrderedBookmarks = (plugin: Bookmarks_PluginInstance, bookmarksGroupNam
|
|||
const path = isGroup ? pathOfGroup : (item as BookmarkWithPath).path
|
||||
const alreadyConsumed = orderedBookmarks[path]
|
||||
|
||||
const parentFolderPathOfBookmarkedItem = isGroup ? parentGroupsPath : extractParentFolderPath(path)
|
||||
console.log(`Add ${path}`)
|
||||
bookmarksCoveredFolders[parentFolderPathOfBookmarkedItem.length > 0 ? parentFolderPathOfBookmarkedItem : ROOT_FOLDER_PATH] = true
|
||||
console.log(bookmarksCoveredFolders)
|
||||
// for groups (they represent folders from sorting perspective) bookmark them unconditionally
|
||||
// the idea of better match is not applicable
|
||||
if (alreadyConsumed && isGroup && alreadyConsumed.group) {
|
||||
|
@ -277,9 +306,10 @@ const getOrderedBookmarks = (plugin: Bookmarks_PluginInstance, bookmarksGroupNam
|
|||
}
|
||||
|
||||
traverseBookmarksCollection(bookmarksItems, consumeItem)
|
||||
return orderedBookmarks
|
||||
return [orderedBookmarks, bookmarksCoveredFolders]
|
||||
}
|
||||
}
|
||||
return [undefined, undefined]
|
||||
}
|
||||
|
||||
const createBookmarkFileEntry = (path: string): BookmarkedFile => {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import {lastPathComponent, extractParentFolderPath} from "./utils";
|
||||
import {
|
||||
lastPathComponent,
|
||||
extractParentFolderPath
|
||||
} from "./utils";
|
||||
|
||||
describe('lastPathComponent and extractParentFolderPath', () => {
|
||||
it.each([
|
||||
|
|
Loading…
Reference in New Issue