Skip to content

File actions: resolve editor actions via an extension index instead of filtering all 200+ of them#3178

Description

@JammingBen

Follow-up of #3166.

Current situation

editorActions in packages/web-pkg/src/composables/actions/files/useFileActions.ts maps every entry of appsStore.fileExtensions into a full FileAction. A default instance registers 200+ file extensions, so the computed builds 200+ action objects and rebuilds all of them whenever appsStore.fileExtensions or the embed mode changes.

getAllOpenWithActions then calls isVisible on all 200+ for a single resource. At most one or two of them can ever match, because the last thing isVisible does is compare the resource's extension or mimeType against the one the action was built for.

Every consumer pays this:

  • getDefaultAction via getResourceLink, once per rendered file list row or tile
  • triggerDefaultAction on click
  • the "Open with" list in ContextActions.vue and FileActions.vue

Proposal

Build an index from appsStore.fileExtensions once, keyed by

  • lowercased extension
  • lowercased mimeType
  • lowercased top-level mime type, so a registration for image still matches image/jpeg the way isVisible does today

Then look up the one or two candidates for a resource and only evaluate (ideally only construct) actions for those. This turns the per-resource cost from O(number of installed extensions) into O(1).

Things to keep in mind:

  • Order matters. editorActions currently preserves the appsStore.fileExtensions order and then sorts by hasPriority. The index has to preserve both, otherwise the default app for a file type can silently change.
  • getAllOpenWithActions needs all matching editor actions, not just the first one, for the "Open with" submenu.
  • The non-extension parts of isVisible still have to run per candidate: canDownload()/secureView, the trash location check, the isInVault + external-* app check, and router.hasRoute().
  • Constructing actions lazily per candidate would also remove the cost of rebuilding all 209 objects whenever the computed re-evaluates.
  • appsStore.fileExtensions is also read for icon mapping and the new-file menu. Those consumers are not affected, but may benefit from the same index.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type:MaintenanceE.g. technical debt, packaging, etc.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions