diff options
Diffstat (limited to 'apps/files/src')
18 files changed, 130 insertions, 116 deletions
diff --git a/apps/files/src/FilesApp.vue b/apps/files/src/FilesApp.vue index 54821a03457..6fc02113162 100644 --- a/apps/files/src/FilesApp.vue +++ b/apps/files/src/FilesApp.vue @@ -12,11 +12,10 @@ <script lang="ts"> import { isPublicShare } from '@nextcloud/sharing/public' import { defineComponent } from 'vue' - import NcContent from '@nextcloud/vue/components/NcContent' - import Navigation from './views/Navigation.vue' import FilesList from './views/FilesList.vue' +import { useHotKeys } from './composables/useHotKeys' export default defineComponent({ name: 'FilesApp', @@ -28,6 +27,9 @@ export default defineComponent({ }, setup() { + // Register global hotkeys + useHotKeys() + const isPublic = isPublicShare() return { diff --git a/apps/files/src/actions/deleteAction.ts b/apps/files/src/actions/deleteAction.ts index 3e9e441a63c..fa4fdfe8cdc 100644 --- a/apps/files/src/actions/deleteAction.ts +++ b/apps/files/src/actions/deleteAction.ts @@ -2,10 +2,8 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { showInfo } from '@nextcloud/dialogs' import { Permission, Node, View, FileAction } from '@nextcloud/files' import { loadState } from '@nextcloud/initial-state' -import { translate as t } from '@nextcloud/l10n' import PQueue from 'p-queue' import CloseSvg from '@mdi/svg/svg/close.svg?raw' @@ -64,7 +62,6 @@ export const action = new FileAction({ // If the user cancels the deletion, we don't want to do anything if (confirm === false) { - showInfo(t('files', 'Deletion cancelled')) return null } @@ -88,7 +85,6 @@ export const action = new FileAction({ // If the user cancels the deletion, we don't want to do anything if (confirm === false) { - showInfo(t('files', 'Deletion cancelled')) return Promise.all(nodes.map(() => null)) } diff --git a/apps/files/src/actions/moveOrCopyAction.ts b/apps/files/src/actions/moveOrCopyAction.ts index af68120bb1b..06e32c98090 100644 --- a/apps/files/src/actions/moveOrCopyAction.ts +++ b/apps/files/src/actions/moveOrCopyAction.ts @@ -158,7 +158,6 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth } } catch (error) { // User cancelled - showError(t('files', 'Move cancelled')) return } } @@ -330,7 +329,6 @@ export const action = new FileAction({ return false } if (result === false) { - showInfo(t('files', 'Cancelled move or copy of "{filename}".', { filename: node.displayname })) return null } @@ -352,10 +350,6 @@ export const action = new FileAction({ const result = await openFilePickerForAction(action, dir, nodes) // Handle cancellation silently if (result === false) { - showInfo(nodes.length === 1 - ? t('files', 'Cancelled move or copy of "{filename}".', { filename: nodes[0].displayname }) - : t('files', 'Cancelled move or copy operation'), - ) return nodes.map(() => null) } diff --git a/apps/files/src/actions/sidebarAction.spec.ts b/apps/files/src/actions/sidebarAction.spec.ts index 75ed8c97b47..9085bf595ad 100644 --- a/apps/files/src/actions/sidebarAction.spec.ts +++ b/apps/files/src/actions/sidebarAction.spec.ts @@ -17,7 +17,7 @@ describe('Open sidebar action conditions tests', () => { test('Default values', () => { expect(action).toBeInstanceOf(FileAction) expect(action.id).toBe('details') - expect(action.displayName([], view)).toBe('Open details') + expect(action.displayName([], view)).toBe('Details') expect(action.iconSvgInline([], view)).toMatch(/<svg.+<\/svg>/) expect(action.default).toBeUndefined() expect(action.order).toBe(-50) diff --git a/apps/files/src/actions/sidebarAction.ts b/apps/files/src/actions/sidebarAction.ts index 0b8ad91741e..8f020b4ee8d 100644 --- a/apps/files/src/actions/sidebarAction.ts +++ b/apps/files/src/actions/sidebarAction.ts @@ -16,7 +16,7 @@ export const ACTION_DETAILS = 'details' export const action = new FileAction({ id: ACTION_DETAILS, - displayName: () => t('files', 'Open details'), + displayName: () => t('files', 'Details'), iconSvgInline: () => InformationSvg, // Sidebar currently supports user folder only, /files/USER diff --git a/apps/files/src/components/FilesListTableHeaderActions.vue b/apps/files/src/components/FilesListTableHeaderActions.vue index 53b7e7ef21b..6a808355c58 100644 --- a/apps/files/src/components/FilesListTableHeaderActions.vue +++ b/apps/files/src/components/FilesListTableHeaderActions.vue @@ -305,16 +305,16 @@ export default defineComponent({ return } - showError(this.t('files', '"{displayName}" failed on some elements', { displayName })) + showError(this.t('files', '{displayName}: failed on some elements', { displayName })) return } // Show success message and clear selection - showSuccess(this.t('files', '"{displayName}" batch action executed successfully', { displayName })) + showSuccess(this.t('files', '{displayName}: done', { displayName })) this.selectionStore.reset() } catch (e) { logger.error('Error while executing action', { action, e }) - showError(this.t('files', '"{displayName}" action failed', { displayName })) + showError(this.t('files', '{displayName}: failed', { displayName })) } finally { // Remove loading markers this.loading = null diff --git a/apps/files/src/components/FilesNavigationSearch.vue b/apps/files/src/components/FilesNavigationSearch.vue index e34d4bf0971..0890dffcb39 100644 --- a/apps/files/src/components/FilesNavigationSearch.vue +++ b/apps/files/src/components/FilesNavigationSearch.vue @@ -55,9 +55,9 @@ const isSearchView = computed(() => currentView.value.id === VIEW_ID) */ const searchLabel = computed(() => { if (searchStore.scope === 'globally') { - return t('files', 'Search globally by filename …') + return t('files', 'Search everywhere …') } - return t('files', 'Search here by filename …') + return t('files', 'Search here …') }) </script> @@ -72,13 +72,13 @@ const searchLabel = computed(() => { <template #icon> <NcIconSvgWrapper :path="mdiMagnify" /> </template> - {{ t('files', 'Filter and search from this location') }} + {{ t('files', 'Search here') }} </NcActionButton> <NcActionButton close-after-click @click="searchStore.scope = 'globally'"> <template #icon> <NcIconSvgWrapper :path="mdiSearchWeb" /> </template> - {{ t('files', 'Search globally') }} + {{ t('files', 'Search everywhere') }} </NcActionButton> </NcActions> </template> diff --git a/apps/files/src/components/LegacyView.vue b/apps/files/src/components/LegacyView.vue index d9baeeb1b07..b5a792d9029 100644 --- a/apps/files/src/components/LegacyView.vue +++ b/apps/files/src/components/LegacyView.vue @@ -33,7 +33,7 @@ export default { }, methods: { setFileInfo(fileInfo) { - this.component.setFileInfo(new OCA.Files.FileInfoModel(fileInfo)) + this.component.setFileInfo(fileInfo) }, }, } diff --git a/apps/files/src/services/HotKeysService.spec.ts b/apps/files/src/composables/useHotKeys.spec.ts index 92430c8e6ad..9c001e8b5ff 100644 --- a/apps/files/src/services/HotKeysService.spec.ts +++ b/apps/files/src/composables/useHotKeys.spec.ts @@ -1,10 +1,14 @@ -/** +/* * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + +import type { Location } from 'vue-router' + import { File, Folder, Permission, View } from '@nextcloud/files' -import { describe, it, vi, expect, beforeEach, beforeAll, afterEach } from 'vitest' -import { nextTick } from 'vue' +import { enableAutoDestroy, mount } from '@vue/test-utils' +import { describe, it, vi, expect, beforeEach, afterEach } from 'vitest' +import { defineComponent, nextTick } from 'vue' import axios from '@nextcloud/axios' import { getPinia } from '../store/index.ts' @@ -15,38 +19,64 @@ import { action as deleteAction } from '../actions/deleteAction.ts' import { action as favoriteAction } from '../actions/favoriteAction.ts' import { action as renameAction } from '../actions/renameAction.ts' import { action as sidebarAction } from '../actions/sidebarAction.ts' -import { registerHotkeys } from './HotKeysService.ts' +import { useHotKeys } from './useHotKeys.ts' import { useUserConfigStore } from '../store/userconfig.ts' +// this is the mocked current route +const route = vi.hoisted(() => ({ + name: 'test', + params: { + fileId: 123, + }, + query: { + openFile: 'false', + dir: '/parent/dir', + }, +})) + +// mocked router +const router = vi.hoisted(() => ({ + push: vi.fn<(route: Location) => void>(), +})) + +vi.mock('../actions/sidebarAction.ts', { spy: true }) +vi.mock('../actions/deleteAction.ts', { spy: true }) +vi.mock('../actions/favoriteAction.ts', { spy: true }) +vi.mock('../actions/renameAction.ts', { spy: true }) + +vi.mock('vue-router/composables', () => ({ + useRoute: vi.fn(() => route), + useRouter: vi.fn(() => router), +})) + let file: File const view = { id: 'files', name: 'Files', } as View -vi.mock('../actions/sidebarAction.ts', { spy: true }) -vi.mock('../actions/deleteAction.ts', { spy: true }) -vi.mock('../actions/favoriteAction.ts', { spy: true }) -vi.mock('../actions/renameAction.ts', { spy: true }) +const TestComponent = defineComponent({ + name: 'test', + setup() { + useHotKeys() + }, + template: '<div />', +}) describe('HotKeysService testing', () => { const activeStore = useActiveStore(getPinia()) - const goToRouteMock = vi.fn() - let initialState: HTMLInputElement + enableAutoDestroy(afterEach) + afterEach(() => { document.body.removeChild(initialState) }) - beforeAll(() => { - registerHotkeys() - }) - beforeEach(() => { // Make sure the router is reset before each test - goToRouteMock.mockClear() + router.push.mockClear() // Make sure the file is reset before each test file = new File({ @@ -66,9 +96,6 @@ describe('HotKeysService testing', () => { activeStore.activeNode = file window.OCA = { Files: { Sidebar: { open: () => {}, setActiveTab: () => {} } } } - // We only mock what needed, we do not need Files.Router.goTo or Files.Navigation - window.OCP = { Files: { Router: { goToRoute: goToRouteMock, params: {}, query: {} } } } - initialState = document.createElement('input') initialState.setAttribute('type', 'hidden') initialState.setAttribute('id', 'initial-state-files_trashbin-config') @@ -76,6 +103,8 @@ describe('HotKeysService testing', () => { allow_delete: true, }))) document.body.appendChild(initialState) + + mount(TestComponent) }) it('Pressing d should open the sidebar once', () => { @@ -135,13 +164,11 @@ describe('HotKeysService testing', () => { }) it('Pressing alt+up should go to parent directory', () => { - expect(goToRouteMock).toHaveBeenCalledTimes(0) - window.OCP.Files.Router.query = { dir: '/foo/bar' } - + expect(router.push).toHaveBeenCalledTimes(0) dispatchEvent({ key: 'ArrowUp', code: 'ArrowUp', altKey: true }) - expect(goToRouteMock).toHaveBeenCalledOnce() - expect(goToRouteMock.mock.calls[0][2].dir).toBe('/foo') + expect(router.push).toHaveBeenCalledOnce() + expect(router.push.mock.calls[0][0].query?.dir).toBe('/parent') }) it('Pressing v should toggle grid view', async () => { diff --git a/apps/files/src/services/HotKeysService.ts b/apps/files/src/composables/useHotKeys.ts index 1ed369b061b..ff56627b2f9 100644 --- a/apps/files/src/services/HotKeysService.ts +++ b/apps/files/src/composables/useHotKeys.ts @@ -4,13 +4,15 @@ */ import { useHotKey } from '@nextcloud/vue/composables/useHotKey' import { dirname } from 'path' +import { useRoute, useRouter } from 'vue-router/composables' import { action as deleteAction } from '../actions/deleteAction.ts' import { action as favoriteAction } from '../actions/favoriteAction.ts' import { action as renameAction } from '../actions/renameAction.ts' import { action as sidebarAction } from '../actions/sidebarAction.ts' -import { executeAction } from '../utils/actionUtils.ts' import { useUserConfigStore } from '../store/userconfig.ts' +import { useRouteParameters } from './useRouteParameters.ts' +import { executeAction } from '../utils/actionUtils.ts' import logger from '../logger.ts' /** @@ -18,7 +20,12 @@ import logger from '../logger.ts' * As much as possible, we try to have all the hotkeys in one place. * Please make sure to add tests for the hotkeys after adding a new one. */ -export const registerHotkeys = function() { +export function useHotKeys(): void { + const userConfigStore = useUserConfigStore() + const { directory } = useRouteParameters() + const router = useRouter() + const route = useRoute() + // d opens the sidebar useHotKey('d', () => executeAction(sidebarAction), { stop: true, @@ -57,26 +64,23 @@ export const registerHotkeys = function() { }) logger.debug('Hotkeys registered') -} - -const goToParentDir = function() { - const params = window.OCP.Files.Router?.params || {} - const query = window.OCP.Files.Router?.query || {} - const currentDir = (query?.dir || '/') as string - const parentDir = dirname(currentDir) + /** + * Use the router to go to the parent directory + */ + function goToParentDir() { + const dir = dirname(directory.value) - logger.debug('Navigating to parent directory', { parentDir }) - window.OCP.Files.Router.goToRoute( - null, - { ...params }, - { ...query, dir: parentDir }, - ) -} + logger.debug('Navigating to parent directory', { dir }) + router.push({ params: { ...route.params }, query: { ...route.query, dir } }) + } -const toggleGridView = function() { - const userConfigStore = useUserConfigStore() - const value = userConfigStore?.userConfig?.grid_view - logger.debug('Toggling grid view', { old: value, new: !value }) - userConfigStore.update('grid_view', !value) + /** + * Toggle the grid view + */ + function toggleGridView() { + const value = userConfigStore.userConfig.grid_view + logger.debug('Toggling grid view', { old: value, new: !value }) + userConfigStore.update('grid_view', !value) + } } diff --git a/apps/files/src/filters/TypeFilter.ts b/apps/files/src/filters/TypeFilter.ts index 94b109ea7a4..3170e22b260 100644 --- a/apps/files/src/filters/TypeFilter.ts +++ b/apps/files/src/filters/TypeFilter.ts @@ -73,7 +73,7 @@ const getTypePresets = async () => [ { id: 'image', // TRANSLATORS: This is for filtering files, e.g. PNG or JPEG, so photos, drawings, or images in general - label: t('files', 'Photos and images'), + label: t('files', 'Images'), icon: svgImage, mime: ['image'], }, diff --git a/apps/files/src/main.ts b/apps/files/src/main.ts index 4b8aca9efd4..463ecaf6239 100644 --- a/apps/files/src/main.ts +++ b/apps/files/src/main.ts @@ -8,7 +8,6 @@ import { PiniaVuePlugin } from 'pinia' import Vue from 'vue' import { getPinia } from './store/index.ts' -import { registerHotkeys } from './services/HotKeysService.ts' import FilesApp from './FilesApp.vue' import router from './router/router' import RouterService from './services/RouterService' @@ -40,9 +39,6 @@ if (!window.OCP.Files.Router) { // Init Pinia store Vue.use(PiniaVuePlugin) -// Init HotKeys AFTER pinia is set up -registerHotkeys() - // Init Files App Settings Service const Settings = new SettingsService() Object.assign(window.OCA.Files, { Settings }) diff --git a/apps/files/src/newMenu/newFolder.ts b/apps/files/src/newMenu/newFolder.ts index bc82d389e54..f0f854d2801 100644 --- a/apps/files/src/newMenu/newFolder.ts +++ b/apps/files/src/newMenu/newFolder.ts @@ -8,7 +8,7 @@ import { basename } from 'path' import { emit } from '@nextcloud/event-bus' import { getCurrentUser } from '@nextcloud/auth' import { Permission, Folder } from '@nextcloud/files' -import { showError, showInfo, showSuccess } from '@nextcloud/dialogs' +import { showError, showSuccess } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' import axios from '@nextcloud/axios' @@ -51,7 +51,6 @@ export const entry = { async handler(context: Folder, content: Node[]) { const name = await newNodeName(t('files', 'New folder'), content) if (name === null) { - showInfo(t('files', 'New folder creation cancelled')) return } try { diff --git a/apps/files/src/utils/actionUtils.ts b/apps/files/src/utils/actionUtils.ts index f6d43727c29..adacf621b4c 100644 --- a/apps/files/src/utils/actionUtils.ts +++ b/apps/files/src/utils/actionUtils.ts @@ -59,13 +59,13 @@ export const executeAction = async (action: FileAction) => { } if (success) { - showSuccess(t('files', '"{displayName}" action executed successfully', { displayName })) + showSuccess(t('files', '{displayName}: done', { displayName })) return } - showError(t('files', '"{displayName}" action failed', { displayName })) + showError(t('files', '{displayName}: failed', { displayName })) } catch (error) { logger.error('Error while executing action', { action, error }) - showError(t('files', '"{displayName}" action failed', { displayName })) + showError(t('files', '{displayName}: failed', { displayName })) } finally { // Reset the loading marker Vue.set(currentNode, 'status', undefined) diff --git a/apps/files/src/utils/davUtils.ts b/apps/files/src/utils/davUtils.ts index d8dc12d069d..54c1a6ea966 100644 --- a/apps/files/src/utils/davUtils.ts +++ b/apps/files/src/utils/davUtils.ts @@ -29,7 +29,7 @@ export function humanizeWebDAVError(error: unknown) { } else if (status === 403) { return t('files', 'This operation is forbidden') } else if (status === 500) { - return t('files', 'This directory is unavailable, please check the logs or contact the administrator') + return t('files', 'This folder is unavailable, please try again later or contact the administration') } else if (status === 503) { return t('files', 'Storage is temporarily not available') } diff --git a/apps/files/src/utils/filesViews.spec.ts b/apps/files/src/utils/filesViews.spec.ts index e8c2ab3a6c1..03b0bb9aeb0 100644 --- a/apps/files/src/utils/filesViews.spec.ts +++ b/apps/files/src/utils/filesViews.spec.ts @@ -26,11 +26,7 @@ describe('hasPersonalFilesView', () => { }) describe('defaultView', () => { - beforeEach(() => { - document.querySelectorAll('input[type="hidden"]').forEach((el) => { - el.remove() - }) - }) + beforeEach(removeInitialState) test('Returns files view if set', () => { mockInitialState('files', 'config', { default_view: 'files' }) @@ -57,6 +53,8 @@ function removeInitialState(): void { document.querySelectorAll('input[type="hidden"]').forEach((el) => { el.remove() }) + // clear the cache + delete globalThis._nc_initial_state } /** diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index 3f993e24958..f9e517e92ee 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -816,13 +816,13 @@ export default defineComponent({ } if (success) { - showSuccess(t('files', '"{displayName}" action executed successfully', { displayName })) + showSuccess(t('files', '{displayName}: done', { displayName })) return } - showError(t('files', '"{displayName}" action failed', { displayName })) + showError(t('files', '{displayName}: failed', { displayName })) } catch (error) { logger.error('Error while executing action', { action, error }) - showError(t('files', '"{displayName}" action failed', { displayName })) + showError(t('files', '{displayName}: failed', { displayName })) } finally { this.loadingAction = null } diff --git a/apps/files/src/views/Settings.vue b/apps/files/src/views/Settings.vue index 0838d308af9..bfac8e0b3d6 100644 --- a/apps/files/src/views/Settings.vue +++ b/apps/files/src/views/Settings.vue @@ -8,7 +8,7 @@ :name="t('files', 'Files settings')" @update:open="onClose"> <!-- Settings API--> - <NcAppSettingsSection id="settings" :name="t('files', 'Files settings')"> + <NcAppSettingsSection id="settings" :name="t('files', 'General')"> <fieldset class="files-settings__default-view" data-cy-files-settings-setting="default_view"> <legend> @@ -42,12 +42,12 @@ <NcCheckboxRadioSwitch data-cy-files-settings-setting="folder_tree" :checked="userConfig.folder_tree" @update:checked="setConfig('folder_tree', $event)"> - {{ t('files', 'Enable folder tree') }} + {{ t('files', 'Folder tree') }} </NcCheckboxRadioSwitch> </NcAppSettingsSection> - <!-- Visual settings --> - <NcAppSettingsSection id="settings" :name="t('files', 'Visual settings')"> + <!-- Appearance --> + <NcAppSettingsSection id="settings" :name="t('files', 'Appearance')"> <NcCheckboxRadioSwitch data-cy-files-settings-setting="show_hidden" :checked="userConfig.show_hidden" @update:checked="setConfig('show_hidden', $event)"> @@ -58,16 +58,16 @@ @update:checked="setConfig('show_mime_column', $event)"> {{ t('files', 'Show file type column') }} </NcCheckboxRadioSwitch> + <NcCheckboxRadioSwitch data-cy-files-settings-setting="show_files_extensions" + :checked="userConfig.show_files_extensions" + @update:checked="setConfig('show_files_extensions', $event)"> + {{ t('files', 'Show file extensions') }} + </NcCheckboxRadioSwitch> <NcCheckboxRadioSwitch data-cy-files-settings-setting="crop_image_previews" :checked="userConfig.crop_image_previews" @update:checked="setConfig('crop_image_previews', $event)"> {{ t('files', 'Crop image previews') }} </NcCheckboxRadioSwitch> - <NcCheckboxRadioSwitch data-cy-files-settings-setting="show_files_extensions" - :checked="userConfig.show_files_extensions" - @update:checked="setConfig('show_files_extensions', $event)"> - {{ t('files', 'Show files extensions') }} - </NcCheckboxRadioSwitch> </NcAppSettingsSection> <!-- Settings API--> @@ -85,7 +85,7 @@ :label="t('files', 'WebDAV URL')" :show-trailing-button="true" :success="webdavUrlCopied" - :trailing-button-label="t('files', 'Copy to clipboard')" + :trailing-button-label="t('files', 'Copy')" :value="webdavUrl" class="webdav-url-input" readonly="readonly" @@ -101,7 +101,7 @@ :href="webdavDocs" target="_blank" rel="noreferrer noopener"> - {{ t('files', 'Use this address to access your Files via WebDAV.') }} ↗ + {{ t('files', 'How to access files using WebDAV') }} ↗ </a> </em> <br> @@ -113,22 +113,20 @@ </NcAppSettingsSection> <NcAppSettingsSection id="warning" :name="t('files', 'Warnings')"> - <em>{{ t('files', 'Prevent warning dialogs from open or reenable them.') }}</em> <NcCheckboxRadioSwitch type="switch" :checked="userConfig.show_dialog_file_extension" @update:checked="setConfig('show_dialog_file_extension', $event)"> - {{ t('files', 'Show a warning dialog when changing a file extension.') }} + {{ t('files', 'Warn before changing a file extension') }} </NcCheckboxRadioSwitch> <NcCheckboxRadioSwitch type="switch" :checked="userConfig.show_dialog_deletion" @update:checked="setConfig('show_dialog_deletion', $event)"> - {{ t('files', 'Show a warning dialog when deleting files.') }} + {{ t('files', 'Warn before deleting files') }} </NcCheckboxRadioSwitch> </NcAppSettingsSection> <NcAppSettingsSection id="shortcuts" :name="t('files', 'Keyboard shortcuts')"> - <em>{{ t('files', 'Speed up your Files experience with these quick shortcuts.') }}</em> <h3>{{ t('files', 'Actions') }}</h3> <dl> @@ -137,7 +135,7 @@ <kbd>a</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Open the actions menu for a file') }} + {{ t('files', 'File actions') }} </dd> </div> <div> @@ -145,7 +143,7 @@ <kbd>F2</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Rename a file') }} + {{ t('files', 'Rename') }} </dd> </div> <div> @@ -153,7 +151,7 @@ <kbd>Del</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Delete a file') }} + {{ t('files', 'Delete') }} </dd> </div> <div> @@ -161,7 +159,7 @@ <kbd>s</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Favorite or remove a file from favorites') }} + {{ t('files', 'Add or remove favorite') }} </dd> </div> <div v-if="isSystemtagsEnabled"> @@ -169,7 +167,7 @@ <kbd>t</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Manage tags for a file') }} + {{ t('files', 'Manage tags') }} </dd> </div> </dl> @@ -189,7 +187,7 @@ <kbd>ESC</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Deselect all files') }} + {{ t('files', 'Deselect all') }} </dd> </div> <div> @@ -197,7 +195,7 @@ <kbd>Ctrl</kbd> + <kbd>Space</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Select or deselect a file') }} + {{ t('files', 'Select or deselect') }} </dd> </div> <div> @@ -205,7 +203,7 @@ <kbd>Ctrl</kbd> + <kbd>Shift</kbd> <span>+ <kbd>Space</kbd></span> </dt> <dd class="shortcut-description"> - {{ t('files', 'Select a range of files') }} + {{ t('files', 'Select a range') }} </dd> </div> </dl> @@ -217,7 +215,7 @@ <kbd>Alt</kbd> + <kbd>↑</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Navigate to the parent folder') }} + {{ t('files', 'Go to parent folder') }} </dd> </div> <div> @@ -225,7 +223,7 @@ <kbd>↑</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Navigate to the file above') }} + {{ t('files', 'Go to file above') }} </dd> </div> <div> @@ -233,7 +231,7 @@ <kbd>↓</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Navigate to the file below') }} + {{ t('files', 'Go to file below') }} </dd> </div> <div> @@ -241,7 +239,7 @@ <kbd>←</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Navigate to the file on the left (in grid mode)') }} + {{ t('files', 'Go left in grid') }} </dd> </div> <div> @@ -249,7 +247,7 @@ <kbd>→</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Navigate to the file on the right (in grid mode)') }} + {{ t('files', 'Go right in grid') }} </dd> </div> </dl> @@ -261,7 +259,7 @@ <kbd>V</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Toggle the grid view') }} + {{ t('files', 'Toggle grid view') }} </dd> </div> <div> @@ -269,7 +267,7 @@ <kbd>D</kbd> </dt> <dd class="shortcut-description"> - {{ t('files', 'Open the sidebar for a file') }} + {{ t('files', 'Open file sidebar') }} </dd> </div> <div> @@ -400,7 +398,7 @@ export default { await navigator.clipboard.writeText(this.webdavUrl) this.webdavUrlCopied = true - showSuccess(t('files', 'WebDAV URL copied to clipboard')) + showSuccess(t('files', 'WebDAV URL copied')) setTimeout(() => { this.webdavUrlCopied = false }, 5000) |