refactor(files): move file action hotkeys to the file actions

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/56377/head
Ferdinand Thiessen 2025-11-11 17:24:55 +07:00
parent 2d012b6156
commit d94e4bcdb5
No known key found for this signature in database
GPG Key ID: 45FAE7268762B400
4 changed files with 106 additions and 80 deletions

@ -9,6 +9,7 @@ import NetworkOffSvg from '@mdi/svg/svg/network-off.svg?raw'
import TrashCanSvg from '@mdi/svg/svg/trash-can-outline.svg?raw'
import { FileAction, Permission } from '@nextcloud/files'
import { loadState } from '@nextcloud/initial-state'
import { t } from '@nextcloud/l10n'
import PQueue from 'p-queue'
import { TRASHBIN_VIEW_ID } from '../../../files_trashbin/src/files_views/trashbinView.ts'
import logger from '../logger.ts'
@ -110,4 +111,9 @@ export const action = new FileAction({
destructive: true,
order: 100,
hotkey: {
description: t('files', 'Delete'),
key: 'Delete',
},
})

@ -21,10 +21,10 @@ export const ACTION_FAVORITE = 'favorite'
const queue = new PQueue({ concurrency: 5 })
// If any of the nodes is not favorited, we display the favorite action.
/**
* If any of the nodes is not favorited, we display the favorite action.
*
* @param nodes
* @param nodes - The nodes to check
*/
function shouldFavorite(nodes: Node[]): boolean {
return nodes.some((node) => node.attributes.favorite !== 1)
@ -124,4 +124,9 @@ export const action = new FileAction({
},
order: -50,
hotkey: {
description: t('files', 'Add or remove favorite'),
key: 'S',
},
})

@ -51,4 +51,9 @@ export const action = new FileAction({
},
order: 10,
hotkey: {
description: t('files', 'Rename'),
key: 'F2',
},
})

@ -19,6 +19,94 @@ import '../css/fileEntryInlineSystemTags.scss'
// Init tag cache
const cache: TagWithId[] = []
export const action = new FileAction({
id: 'system-tags',
displayName: () => '',
iconSvgInline: () => '',
enabled(nodes: Node[]) {
// Only show the action on single nodes
if (nodes.length !== 1) {
return false
}
// Always show the action, even if there are no tags
// This will render an empty tag list and allow events to update it
return true
},
exec: async () => null,
renderInline,
order: 0,
hotkey: {
description: t('files', 'Manage tags'),
key: 'T',
},
})
// Subscribe to the events
subscribe('systemtags:node:updated', updateSystemTagsHtml)
subscribe('systemtags:tag:created', addTag)
subscribe('systemtags:tag:deleted', removeTag)
subscribe('systemtags:tag:updated', updateTag)
/**
* Update the system tags html when the node is updated
*
* @param node - The updated node
*/
function updateSystemTagsHtml(node: Node) {
renderInline(node).then((systemTagsHtml) => {
document.querySelectorAll(`[data-systemtags-fileid="${node.fileid}"]`).forEach((element) => {
element.replaceWith(systemTagsHtml)
})
})
}
/**
* Add and remove tags from the cache
*
* @param tag - The tag to add
*/
function addTag(tag: TagWithId) {
cache.push(tag)
}
/**
* Remove a tag from the cache
*
* @param tag - The tag to remove
*/
function removeTag(tag: TagWithId) {
cache.splice(cache.findIndex((t) => t.id === tag.id), 1)
}
/**
* Update a tag in the cache
*
* @param tag - The tag to update
*/
function updateTag(tag: TagWithId) {
const index = cache.findIndex((t) => t.id === tag.id)
if (index !== -1) {
cache[index] = tag
}
updateSystemTagsColorAttribute(tag)
}
/**
* Update the color attribute of the system tags
*
* @param tag - The tag to update
*/
function updateSystemTagsColorAttribute(tag: TagWithId) {
document.querySelectorAll(`[data-systemtag-name="${tag.displayName}"]`).forEach((element) => {
(element as HTMLElement).style.setProperty('--systemtag-color', `#${tag.color}`)
})
}
/**
*
* @param tag
@ -103,81 +191,3 @@ async function renderInline(node: Node): Promise<HTMLElement> {
return systemTagsElement
}
export const action = new FileAction({
id: 'system-tags',
displayName: () => '',
iconSvgInline: () => '',
enabled(nodes: Node[]) {
// Only show the action on single nodes
if (nodes.length !== 1) {
return false
}
// Always show the action, even if there are no tags
// This will render an empty tag list and allow events to update it
return true
},
exec: async () => null,
renderInline,
order: 0,
})
// Update the system tags html when the node is updated
/**
*
* @param node
*/
function updateSystemTagsHtml(node: Node) {
renderInline(node).then((systemTagsHtml) => {
document.querySelectorAll(`[data-systemtags-fileid="${node.fileid}"]`).forEach((element) => {
element.replaceWith(systemTagsHtml)
})
})
}
// Add and remove tags from the cache
/**
*
* @param tag
*/
function addTag(tag: TagWithId) {
cache.push(tag)
}
/**
*
* @param tag
*/
function removeTag(tag: TagWithId) {
cache.splice(cache.findIndex((t) => t.id === tag.id), 1)
}
/**
*
* @param tag
*/
function updateTag(tag: TagWithId) {
const index = cache.findIndex((t) => t.id === tag.id)
if (index !== -1) {
cache[index] = tag
}
updateSystemTagsColorAttribute(tag)
}
// Update the color attribute of the system tags
/**
*
* @param tag
*/
function updateSystemTagsColorAttribute(tag: TagWithId) {
document.querySelectorAll(`[data-systemtag-name="${tag.displayName}"]`).forEach((element) => {
(element as HTMLElement).style.setProperty('--systemtag-color', `#${tag.color}`)
})
}
// Subscribe to the events
subscribe('systemtags:node:updated', updateSystemTagsHtml)
subscribe('systemtags:tag:created', addTag)
subscribe('systemtags:tag:deleted', removeTag)
subscribe('systemtags:tag:updated', updateTag)