mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-08-01 01:37:44 -04:00
* Bump the npm_and_yarn group across 2 directories with 2 updates Bumps the npm_and_yarn group with 1 update in the /apps/browser-extension directory: [ws](https://github.com/websockets/ws). Bumps the npm_and_yarn group with 1 update in the /apps/mobile-app directory: [postcss](https://github.com/postcss/postcss). Updates `ws` from 8.18.2 to 8.21.0 - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/8.18.2...8.21.0) Updates `ws` from 8.18.2 to 8.21.0 - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/8.18.2...8.21.0) Updates `postcss` from 8.4.49 to 8.5.15 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.49...8.5.15) Updates `postcss` from 8.4.49 to 8.5.15 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.49...8.5.15) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.15 dependency-type: indirect - dependency-name: ws dependency-version: 8.21.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> * Update package-lock.json (#2067) * Update NodeJS to latest 24.x LTS * Revert Expo back to 53.x (#2067) * Upgrade expo and react-native (#2067) * Update mobile app to support Expo 56 (#2067) * Update wxt (#2067) * Change util filenames to be consistent PascalCase (#2067) * Restore deep-linking behavior to work with new Expo Router (#2067) * Update eslint.config.js (#2067) * Update package-lock.json (#2067) * Refactor linting (#2067) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leendert de Borst <ldeborst@xivisoft.com>
181 lines
5.1 KiB
TypeScript
181 lines
5.1 KiB
TypeScript
import type { Folder } from './db/repositories/FolderRepository';
|
|
|
|
/**
|
|
* Maximum allowed folder nesting depth.
|
|
* Structure: Root (0) > Level 1 (1) > Level 2 (2) > Level 3 (3) > Level 4 (4)
|
|
* Folders at depth 4 cannot have subfolders.
|
|
*/
|
|
export const MAX_FOLDER_DEPTH = 4;
|
|
|
|
/**
|
|
* Get folder depth in the hierarchy.
|
|
* @param folderId - The folder ID to check
|
|
* @param folders - Flat array of all folders
|
|
* @returns Depth (0 = root, 1 = one level deep, etc.) or null if folder not found
|
|
*/
|
|
export function getFolderDepth(folderId: string, folders: Folder[]): number | null {
|
|
const folder = folders.find(f => f.Id === folderId);
|
|
if (!folder) {
|
|
return null;
|
|
}
|
|
|
|
let depth = 0;
|
|
let currentId: string | null = folderId;
|
|
|
|
// Traverse up to root, counting levels
|
|
while (currentId) {
|
|
const current = folders.find(f => f.Id === currentId);
|
|
if (!current || !current.ParentFolderId) {
|
|
break;
|
|
}
|
|
depth++;
|
|
currentId = current.ParentFolderId;
|
|
|
|
// Prevent infinite loops
|
|
if (depth > MAX_FOLDER_DEPTH) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return depth;
|
|
}
|
|
|
|
/**
|
|
* Get the full path of folder names from root to the specified folder.
|
|
* @param folderId - The folder ID
|
|
* @param folders - Flat array of all folders
|
|
* @returns Array of folder names from root to current folder, or empty array if not found
|
|
*/
|
|
export function getFolderPath(folderId: string | null, folders: Folder[]): string[] {
|
|
if (!folderId) {
|
|
return [];
|
|
}
|
|
|
|
const path: string[] = [];
|
|
let currentId: string | null = folderId;
|
|
let iterations = 0;
|
|
|
|
// Build path by traversing up to root
|
|
while (currentId && iterations < MAX_FOLDER_DEPTH + 1) {
|
|
const folder = folders.find(f => f.Id === currentId);
|
|
if (!folder) {
|
|
break;
|
|
}
|
|
path.unshift(folder.Name); // Add to beginning of array
|
|
currentId = folder.ParentFolderId;
|
|
iterations++;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
/**
|
|
* Get the full path of folder IDs from root to the specified folder.
|
|
* @param folderId - The folder ID
|
|
* @param folders - Flat array of all folders
|
|
* @returns Array of folder IDs from root to current folder, or empty array if not found
|
|
*/
|
|
export function getFolderIdPath(folderId: string | null, folders: Folder[]): string[] {
|
|
if (!folderId) {
|
|
return [];
|
|
}
|
|
|
|
const path: string[] = [];
|
|
let currentId: string | null = folderId;
|
|
let iterations = 0;
|
|
|
|
// Build path by traversing up to root
|
|
while (currentId && iterations < MAX_FOLDER_DEPTH + 1) {
|
|
const folder = folders.find(f => f.Id === currentId);
|
|
if (!folder) {
|
|
break;
|
|
}
|
|
path.unshift(folder.Id); // Add to beginning of array
|
|
currentId = folder.ParentFolderId;
|
|
iterations++;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
/**
|
|
* Format folder path for display with separator.
|
|
* @param pathSegments - Array of folder names
|
|
* @param separator - Separator string (default: " > ")
|
|
* @returns Formatted folder path string
|
|
*/
|
|
export function formatFolderPath(
|
|
pathSegments: string[],
|
|
separator: string = ' > '
|
|
): string {
|
|
return pathSegments.join(separator);
|
|
}
|
|
|
|
/**
|
|
* Check if a folder can have subfolders (not at max depth).
|
|
* @param folderId - The folder ID to check
|
|
* @param folders - Flat array of all folders
|
|
* @returns True if folder can have children, false otherwise
|
|
*/
|
|
export function canHaveSubfolders(folderId: string, folders: Folder[]): boolean {
|
|
const depth = getFolderDepth(folderId, folders);
|
|
return depth !== null && depth < MAX_FOLDER_DEPTH;
|
|
}
|
|
|
|
/**
|
|
* Get all descendant folder IDs (children, grandchildren, etc.).
|
|
* @param folderId - The parent folder ID
|
|
* @param folders - Flat array of all folders
|
|
* @returns Array of descendant folder IDs
|
|
*/
|
|
export function getDescendantFolderIds(folderId: string, folders: Folder[]): string[] {
|
|
const descendants: string[] = [];
|
|
|
|
/**
|
|
* Traverse a folder tree and get all descendant folder IDs.
|
|
*/
|
|
const traverse = (parentId: string): void => {
|
|
folders
|
|
.filter(f => f.ParentFolderId === parentId)
|
|
.forEach(child => {
|
|
descendants.push(child.Id);
|
|
traverse(child.Id);
|
|
});
|
|
};
|
|
|
|
traverse(folderId);
|
|
return descendants;
|
|
}
|
|
|
|
/**
|
|
* Get all direct child folder IDs.
|
|
* @param parentFolderId - The parent folder ID (null for root)
|
|
* @param folders - Flat array of all folders
|
|
* @returns Array of direct child folder IDs
|
|
*/
|
|
export function getDirectChildFolderIds(parentFolderId: string | null, folders: Folder[]): string[] {
|
|
return folders
|
|
.filter(f => f.ParentFolderId === parentFolderId)
|
|
.map(f => f.Id);
|
|
}
|
|
|
|
/**
|
|
* Get total count of items in a folder and all its subfolders.
|
|
* @param folderId - The folder ID to count items for
|
|
* @param allItems - All items in the vault
|
|
* @param allFolders - All folders in the vault
|
|
* @returns Total item count including subfolders
|
|
*/
|
|
export function getRecursiveItemCount(
|
|
folderId: string,
|
|
allItems: Array<{ FolderId?: string | null }>,
|
|
allFolders: Folder[]
|
|
): number {
|
|
// Get all descendant folder IDs
|
|
const descendantIds = getDescendantFolderIds(folderId, allFolders);
|
|
const allFolderIds = [folderId, ...descendantIds];
|
|
|
|
// Count items in current folder and all descendants
|
|
return allItems.filter(item => item.FolderId && allFolderIds.includes(item.FolderId)).length;
|
|
}
|