Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/files/src/FilesApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -28,6 +27,9 @@ export default defineComponent({
},

setup() {
// Register global hotkeys
useHotKeys()

const isPublic = isPublicShare()

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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({
Expand All @@ -66,16 +96,15 @@ 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')
initialState.setAttribute('value', btoa(JSON.stringify({
allow_delete: true,
})))
document.body.appendChild(initialState)

mount(TestComponent)
})

it('Pressing d should open the sidebar once', () => {
Expand Down Expand Up @@ -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 () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,28 @@
*/
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'

/**
* This register the hotkeys for the Files app.
* 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,
Expand Down Expand Up @@ -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)
}
}
4 changes: 0 additions & 4 deletions apps/files/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 })
Expand Down
4 changes: 2 additions & 2 deletions dist/files-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/files-main.js.map

Large diffs are not rendered by default.

Loading