diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2023-04-07 13:32:11 +0200 |
---|---|---|
committer | John Molakvoæ <skjnldsv@protonmail.com> | 2023-04-12 12:10:44 +0200 |
commit | 34d22f19d3b15bf5a10ba4977288e6c285aba36b (patch) | |
tree | 48101d90d2788e5d23419f003a84c9e6c9ca82e1 | |
parent | 993a7fc8e638b0c4e8435980809efbc7e8ab056b (diff) | |
download | nextcloud-server-34d22f19d3b15bf5a10ba4977288e6c285aba36b.tar.gz nextcloud-server-34d22f19d3b15bf5a10ba4977288e6c285aba36b.zip |
feat(files): responsive design for mobile and narrow screens
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
-rw-r--r-- | apps/files/src/components/FileEntry.vue | 20 | ||||
-rw-r--r-- | apps/files/src/components/FilesListHeaderActions.vue | 24 | ||||
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 21 | ||||
-rw-r--r-- | apps/files/src/mixins/clientWidth.ts | 43 | ||||
-rw-r--r-- | apps/files/src/models/Setting.js | 2 | ||||
-rw-r--r-- | apps/files/src/store/actionsmenu.ts | 1 | ||||
-rw-r--r-- | apps/files/src/types.ts | 3 |
7 files changed, 100 insertions, 14 deletions
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 47ed5729a8d..58b86886319 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -115,6 +115,7 @@ import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js' import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' +import isMobileMixin from '@nextcloud/vue/dist/Mixins/isMobile.js' import Vue from 'vue' import { getFileActions } from '../services/FileAction.ts' @@ -146,6 +147,10 @@ export default Vue.extend({ NcLoadingIcon, }, + mixins: [ + isMobileMixin, + ], + props: { active: { type: Boolean, @@ -295,13 +300,20 @@ export default Vue.extend({ }, enabledInlineActions() { + if (this.isMobile) { + return [] + } return this.enabledActions.filter(action => action?.inline?.(this.source, this.currentView)) }, enabledMenuActions() { + if (this.isMobile) { + return this.enabledActions + } + return [ ...this.enabledInlineActions, - ...actions.filter(action => !action.inline), + ...this.enabledActions.filter(action => !action.inline), ] }, @@ -311,10 +323,10 @@ export default Vue.extend({ openedMenu: { get() { - return this.actionsMenuStore.opened === this + return this.actionsMenuStore.opened === this.uniqueId }, set(opened) { - this.actionsMenuStore.opened = opened ? this : null + this.actionsMenuStore.opened = opened ? this.uniqueId : null }, }, }, @@ -515,7 +527,7 @@ export default Vue.extend({ // If the clicked row is in the selection, open global menu const isMoreThanOneSelected = this.selectedFiles.length > 1 - this.actionsMenuStore.opened = this.isSelected && isMoreThanOneSelected ? 'global' : this + this.actionsMenuStore.opened = this.isSelected && isMoreThanOneSelected ? 'global' : this.uniqueId // Prevent any browser defaults event.preventDefault() diff --git a/apps/files/src/components/FilesListHeaderActions.vue b/apps/files/src/components/FilesListHeaderActions.vue index f136e281f09..13e24ec77e6 100644 --- a/apps/files/src/components/FilesListHeaderActions.vue +++ b/apps/files/src/components/FilesListHeaderActions.vue @@ -1,7 +1,7 @@ <!-- - - @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev> + - @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> - - - @author Gary Kim <gary@garykim.dev> + - @author John Molakvoæ <skjnldsv@protonmail.com> - - @license GNU AGPL version 3 or any later version - @@ -24,7 +24,8 @@ <NcActions ref="actionsMenu" :disabled="!!loading || areSomeNodesLoading" :force-title="true" - :inline="3" + :inline="inlineActions" + :menu-title="inlineActions === 0 ? t('files', 'Actions') : null" :open.sync="openedMenu"> <NcActionButton v-for="action in enabledActions" :key="action.id" @@ -43,8 +44,8 @@ <script lang="ts"> import { showError, showSuccess } from '@nextcloud/dialogs' import { translate } from '@nextcloud/l10n' -import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' +import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' import Vue from 'vue' @@ -52,6 +53,7 @@ import { getFileActions } from '../services/FileAction.ts' import { useActionsMenuStore } from '../store/actionsmenu.ts' import { useFilesStore } from '../store/files.ts' import { useSelectionStore } from '../store/selection.ts' +import clientWidthMixin from '../mixins/clientWidth.ts' import CustomSvgIconRender from './CustomSvgIconRender.vue' import logger from '../logger.js' @@ -68,6 +70,10 @@ export default Vue.extend({ NcLoadingIcon, }, + mixins: [ + clientWidthMixin, + ], + props: { currentView: { type: Object, @@ -122,6 +128,16 @@ export default Vue.extend({ this.actionsMenuStore.opened = opened ? 'global' : null }, }, + + inlineActions() { + if (this.clientWidth < 480) { + return 1 + } + if (this.clientWidth < 768) { + return 2 + } + return 3 + }, }, methods: { diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index 16e25e33d1f..fe9b9f635bc 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -226,6 +226,8 @@ export default Vue.extend({ // Show same padding as the checkbox right padding for visual balance margin-right: var(--checkbox-padding); color: var(--color-primary-element); + // No shrinking or growing allowed + flex: 0 0 var(--icon-preview-size); & > span { justify-content: flex-start; @@ -285,7 +287,7 @@ export default Vue.extend({ margin: 0 var(--cell-margin); } - & > button { + button { .button-vue__text { // Remove bold from default button styling font-weight: normal; @@ -316,7 +318,22 @@ export default Vue.extend({ .files-list__row-column-custom { width: calc(var(--row-height) * 2); } + + @media (max-width: 768px) { + // Hide any column after the size menu on mobile + .files-list__row-size ~ td, + .files-list__row-size ~ th { + display: none; + } + } + + @media (max-width: 480px) { + // Hide any column after the actions menu on short mobile + .files-list__row-actions ~ td, + .files-list__row-actions ~ th { + display: none; + } + } } } - </style> diff --git a/apps/files/src/mixins/clientWidth.ts b/apps/files/src/mixins/clientWidth.ts new file mode 100644 index 00000000000..ffbf21d0963 --- /dev/null +++ b/apps/files/src/mixins/clientWidth.ts @@ -0,0 +1,43 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @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 Vue from 'vue' + +export default Vue.extend({ + data() { + return { + clientWidth: null as number | null, + } + }, + created() { + window.addEventListener('resize', this.handleWindowResize) + this.handleWindowResize() + }, + beforeDestroy() { + window.removeEventListener('resize', this.handleWindowResize) + }, + methods: { + handleWindowResize() { + this.clientWidth = document.documentElement.clientWidth + }, + }, +}) diff --git a/apps/files/src/models/Setting.js b/apps/files/src/models/Setting.js index db276da85af..8387248d252 100644 --- a/apps/files/src/models/Setting.js +++ b/apps/files/src/models/Setting.js @@ -2,7 +2,7 @@ * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev> * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com> * - * @author Gary Kim <gary@garykim.dev> + * @author John Molakvoæ <skjnldsv@protonmail.com> * * @license AGPL-3.0-or-later * diff --git a/apps/files/src/store/actionsmenu.ts b/apps/files/src/store/actionsmenu.ts index b68f4998470..66b1914ffbd 100644 --- a/apps/files/src/store/actionsmenu.ts +++ b/apps/files/src/store/actionsmenu.ts @@ -21,7 +21,6 @@ */ /* eslint-disable */ import { defineStore } from 'pinia' -import Vue from 'vue' import type { ActionsMenuStore } from '../types' export const useActionsMenuStore = defineStore('actionsmenu', { diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts index 4c3d57d3e62..2e8358aa704 100644 --- a/apps/files/src/types.ts +++ b/apps/files/src/types.ts @@ -22,7 +22,6 @@ /* eslint-disable */ import type { Folder } from '@nextcloud/files' import type { Node } from '@nextcloud/files' -import type { ComponentInstance } from 'vue' // Global definitions export type Service = string @@ -91,5 +90,5 @@ export interface SelectionStore { // Actions menu store export type GlobalActions = 'global' export interface ActionsMenuStore { - opened: ComponentInstance|GlobalActions|null + opened: GlobalActions|string|null } |