Skip to content

Commit

Permalink
fix(files): Do not show files from hidden folders in "Recent"-view if…
Browse files Browse the repository at this point in the history
… hidden files are disabled by user

Needed to adjust the store creation to be able to inject pinia before the vue app is initialized.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Apr 17, 2024
1 parent 38bd20b commit 17d28ed
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 6 deletions.
6 changes: 3 additions & 3 deletions apps/files/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Vue from 'vue'
import { createPinia, PiniaVuePlugin } from 'pinia'
import { PiniaVuePlugin } from 'pinia'
import { getNavigation } from '@nextcloud/files'
import { getRequestToken } from '@nextcloud/auth'
import Vue from 'vue'

import { pinia } from './store/index.ts'
import router from './router/router'
import RouterService from './services/RouterService'
import SettingsModel from './models/Setting.js'
Expand Down Expand Up @@ -30,7 +31,6 @@ Object.assign(window.OCP.Files, { Router })

// Init Pinia store
Vue.use(PiniaVuePlugin)
const pinia = createPinia()

// Init Navigation Service
// This only works with Vue 2 - with Vue 3 this will not modify the source but return just a oberserver
Expand Down
24 changes: 22 additions & 2 deletions apps/files/src/services/Recent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import type { ContentsWithRoot } from '@nextcloud/files'
import type { ContentsWithRoot, Node } from '@nextcloud/files'
import type { FileStat, ResponseDataDetailed } from 'webdav'

import { getCurrentUser } from '@nextcloud/auth'
import { Folder, Permission, davGetRecentSearch, davGetClient, davResultToNode, davRootPath, davRemoteURL } from '@nextcloud/files'
import { useUserConfigStore } from '../store/userconfig.ts'
import { pinia } from '../store/index.ts'

const client = davGetClient()

const lastTwoWeeksTimestamp = Math.round((Date.now() / 1000) - (60 * 60 * 24 * 14))

/**
* Get recently changed nodes
*
* This takes the users preference about hidden files into account.
* If hidden files are not shown, then also recently changed files *in* hidden directories are filtered.
*
* @param path Path to search for recent changes
*/
export const getContents = async (path = '/'): Promise<ContentsWithRoot> => {
const store = useUserConfigStore(pinia)
/**
* Filter function that returns only the visible nodes - or hidden if explicitly configured
* @param node The node to check
*/
const filterHidden = (node: Node) =>
path !== '/' // We need to hide files from hidden directories in the root if not configured to show
|| store.userConfig.show_hidden // If configured to show hidden files we can early return
|| !node.dirname.split('/').some((dir) => dir.startsWith('.')) // otherwise only include the file if non of the parent directories is hidden

const contentsResponse = await client.getDirectoryContents(path, {
details: true,
data: davGetRecentSearch(lastTwoWeeksTimestamp),
Expand All @@ -53,6 +73,6 @@ export const getContents = async (path = '/'): Promise<ContentsWithRoot> => {
owner: getCurrentUser()?.uid || null,
permissions: Permission.READ,
}),
contents: contents.map((r) => davResultToNode(r)),
contents: contents.map((r) => davResultToNode(r)).filter(filterHidden),
}
}
25 changes: 25 additions & 0 deletions apps/files/src/store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import { createPinia } from 'pinia'

export const pinia = createPinia()
8 changes: 8 additions & 0 deletions apps/files/src/views/FilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ export default defineComponent({
loading: true,
promise: null,
Type,
_unsubscribeStore: () => {},
}
},
Expand Down Expand Up @@ -452,10 +454,16 @@ export default defineComponent({
subscribe('files:node:updated', this.onUpdatedNode)
subscribe('nextcloud:unified-search.search', this.onSearch)
subscribe('nextcloud:unified-search.reset', this.onSearch)
// reload on settings change
this._unsubscribeStore = this.userConfigStore.$subscribe(() => this.fetchContent(), { deep: true })
},
unmounted() {
unsubscribe('files:node:updated', this.onUpdatedNode)
unsubscribe('nextcloud:unified-search.search', this.onSearch)
unsubscribe('nextcloud:unified-search.reset', this.onSearch)
this._unsubscribeStore()
},
methods: {
Expand Down
2 changes: 1 addition & 1 deletion apps/files/src/views/recent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { View, getNavigation } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import HistorySvg from '@mdi/svg/svg/history.svg?raw'

import { getContents } from '../services/Recent'
import { View, getNavigation } from '@nextcloud/files'

export default () => {
const Navigation = getNavigation()
Expand Down
116 changes: 116 additions & 0 deletions cypress/e2e/files/files-settings.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de>
*
* @author Ferdinand Thiessen <opensource@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import type { User } from '@nextcloud/cypress'
import { getRowForFile } from './FilesUtils'

const showHiddenFiles = () => {
// Open the files settings
cy.get('[data-cy-files-navigation-settings-button] a').click({ force: true })
// Toggle the hidden files setting
cy.get('[data-cy-files-settings-setting="show_hidden"]').within(() => {
cy.get('input').should('not.be.checked')
cy.get('input').check({ force: true })
})
// Close the dialog
cy.get('[data-cy-files-navigation-settings] button[aria-label="Close"]').click()
}

describe('files: Hide or show hidden files', { testIsolation: true }, () => {
let user: User

const setupFiles = () => cy.createRandomUser().then(($user) => {
user = $user

cy.uploadContent(user, new Blob([]), 'text/plain', '/.file')
cy.uploadContent(user, new Blob([]), 'text/plain', '/visible-file')
cy.mkdir(user, '/.folder')
cy.login(user)
})

context('view: All files', { testIsolation: false }, () => {
before(setupFiles)

it('hides dot-files by default', () => {
cy.visit('/apps/files')

getRowForFile('visible-file').should('be.visible')
getRowForFile('.file').should('not.exist')
getRowForFile('.folder').should('not.exist')
})

it('can show hidden files', () => {
showHiddenFiles()
// Now the files should be visible
getRowForFile('.file').should('be.visible')
getRowForFile('.folder').should('be.visible')
})
})

context('view: Personal files', { testIsolation: false }, () => {
before(setupFiles)

it('hides dot-files by default', () => {
cy.visit('/apps/files/personal')

getRowForFile('visible-file').should('be.visible')
getRowForFile('.file').should('not.exist')
getRowForFile('.folder').should('not.exist')
})

it('can show hidden files', () => {
showHiddenFiles()
// Now the files should be visible
getRowForFile('.file').should('be.visible')
getRowForFile('.folder').should('be.visible')
})
})

context('view: Recent files', { testIsolation: false }, () => {
before(() => {
setupFiles().then(() => {
// also add hidden file in hidden folder
cy.uploadContent(user, new Blob([]), 'text/plain', '/.folder/other-file')
cy.login(user)
})
})

it('hides dot-files by default', () => {
cy.visit('/apps/files/recent')

getRowForFile('visible-file').should('be.visible')
getRowForFile('.file').should('not.exist')
getRowForFile('.folder').should('not.exist')
getRowForFile('other-file').should('not.exist')
})

it('can show hidden files', () => {
showHiddenFiles()

getRowForFile('visible-file').should('be.visible')
// Now the files should be visible
getRowForFile('.file').should('be.visible')
getRowForFile('.folder').should('be.visible')
getRowForFile('other-file').should('be.visible')
})
})
})

0 comments on commit 17d28ed

Please sign in to comment.