Merge pull request #37642 from nextcloud/fix/reactivity-files

pull/37696/head
John Molakvoæ 1 year ago committed by GitHub
commit f37b29eb2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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
-

@ -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
-

@ -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
-
@ -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()
@ -529,8 +541,6 @@ export default Vue.extend({
</script>
<style scoped lang='scss'>
@import '../mixins/fileslist-row.scss';
/* Hover effect on tbody lines only */
tr {
&:hover,

@ -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
-
@ -140,8 +140,6 @@ export default Vue.extend({
</script>
<style scoped lang="scss">
@import '../mixins/fileslist-row.scss';
// Scoped row
tr {
padding-bottom: 300px;

@ -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
-
@ -207,7 +207,6 @@ export default Vue.extend({
</script>
<style scoped lang="scss">
@import '../mixins/fileslist-row.scss';
.files-list__column {
user-select: none;
// Make sure the cell colors don't apply to column headers

@ -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: {

@ -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
-

@ -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
-
@ -166,11 +166,6 @@ export default Vue.extend({
background-color: var(--color-main-background);
}
/**
* Common row styling. tr are handled by
* vue-virtual-scroller, so we need to
* have those rules in here.
*/
tr {
position: absolute;
display: flex;
@ -178,7 +173,167 @@ export default Vue.extend({
width: 100%;
border-bottom: 1px solid var(--color-border);
}
td, th {
display: flex;
align-items: center;
flex: 0 0 auto;
justify-content: left;
width: var(--row-height);
height: var(--row-height);
margin: 0;
padding: 0;
color: var(--color-text-maxcontrast);
border: none;
// Columns should try to add any text
// node wrapped in a span. That should help
// with the ellipsis on overflow.
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.files-list__row-checkbox {
justify-content: center;
.checkbox-radio-switch {
display: flex;
justify-content: center;
--icon-size: var(--checkbox-size);
label.checkbox-radio-switch__label {
width: var(--clickable-area);
height: var(--clickable-area);
margin: 0;
padding: calc((var(--clickable-area) - var(--checkbox-size)) / 2);
}
.checkbox-radio-switch__icon {
margin: 0 !important;
}
}
}
.files-list__row-icon {
display: flex;
align-items: center;
justify-content: center;
width: var(--icon-preview-size);
height: 100%;
// 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;
}
svg {
width: var(--icon-preview-size);
height: var(--icon-preview-size);
}
&-preview {
overflow: hidden;
width: var(--icon-preview-size);
height: var(--icon-preview-size);
border-radius: var(--border-radius);
background-repeat: no-repeat;
// Center and contain the preview
background-position: center;
background-size: contain;
}
}
.files-list__row-name {
// Prevent link from overflowing
overflow: hidden;
// Take as much space as possible
flex: 1 1 auto;
a {
display: flex;
align-items: center;
// Fill cell height and width
width: 100%;
height: 100%;
// Keyboard indicator a11y
&:focus .files-list__row-name-text,
&:focus-visible .files-list__row-name-text {
outline: 2px solid var(--color-main-text) !important;
border-radius: 20px;
}
}
.files-list__row-name-text {
// Make some space for the outline
padding: 5px 10px;
margin-left: -10px;
}
}
.files-list__row-actions {
width: auto;
// Add margin to all cells after the actions
& ~ td,
& ~ th {
margin: 0 var(--cell-margin);
}
button {
.button-vue__text {
// Remove bold from default button styling
font-weight: normal;
}
&:not(:hover, :focus, :active) .button-vue__wrapper {
// Also apply color-text-maxcontrast to non-active button
color: var(--color-text-maxcontrast);
}
}
}
.files-list__row-size {
// Right align text
justify-content: flex-end;
width: calc(var(--row-height) * 1.5);
// opacity varies with the size
color: var(--color-main-text);
// Icon is before text since size is right aligned
.files-list__column-sort-button {
padding: 0 16px 0 4px !important;
.button-vue__wrapper {
flex-direction: row;
}
}
}
.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>

@ -1,7 +1,7 @@
<!--
- @copyright Copyright (c) 2020 Gary Kim <gary@garykim.dev>
-
- @author Gary Kim <gary@garykim.dev>
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-

@ -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
},
},
})

@ -1,170 +0,0 @@
/**
* @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/>.
*
*/
/**
*
* This file is for every column styling that must be
* shared between BOTH the files list AND the list header.
*
*/
td, th {
display: flex;
align-items: center;
flex: 0 0 auto;
justify-content: left;
width: var(--row-height);
height: var(--row-height);
margin: 0;
padding: 0;
color: var(--color-text-maxcontrast);
border: none;
// Columns should try to add any text
// node wrapped in a span. That should help
// with the ellipsis on overflow.
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.files-list__row-checkbox {
justify-content: center;
&::v-deep .checkbox-radio-switch {
display: flex;
justify-content: center;
--icon-size: var(--checkbox-size);
label.checkbox-radio-switch__label {
width: var(--clickable-area);
height: var(--clickable-area);
margin: 0;
padding: calc((var(--clickable-area) - var(--checkbox-size)) / 2);
}
.checkbox-radio-switch__icon {
margin: 0 !important;
}
}
}
.files-list__row-icon {
display: flex;
align-items: center;
justify-content: center;
width: var(--icon-preview-size);
height: 100%;
// Show same padding as the checkbox right padding for visual balance
margin-right: var(--checkbox-padding);
color: var(--color-primary-element);
& > span {
justify-content: flex-start;
}
&::v-deep svg {
width: var(--icon-preview-size);
height: var(--icon-preview-size);
}
&-preview {
overflow: hidden;
width: var(--icon-preview-size);
height: var(--icon-preview-size);
border-radius: var(--border-radius);
background-repeat: no-repeat;
// Center and contain the preview
background-position: center;
background-size: contain;
}
}
.files-list__row-name {
// Prevent link from overflowing
overflow: hidden;
// Take as much space as possible
flex: 1 1 auto;
a {
display: flex;
align-items: center;
// Fill cell height and width
width: 100%;
height: 100%;
// Keyboard indicator a11y
&:focus .files-list__row-name-text,
&:focus-visible .files-list__row-name-text {
outline: 2px solid var(--color-main-text) !important;
border-radius: 20px;
}
}
.files-list__row-name-text {
// Make some space for the outline
padding: 5px 10px;
margin-left: -10px;
}
}
.files-list__row-actions {
width: auto;
// Add margin to all cells after the actions
& ~ td,
& ~ th {
margin: 0 var(--cell-margin);
}
&::v-deep > button {
.button-vue__text {
// Remove bold from default button styling
font-weight: normal;
}
&:not(:hover, :focus, :active) .button-vue__wrapper {
// Also apply color-text-maxcontrast to non-active button
color: var(--color-text-maxcontrast);
}
}
}
.files-list__row-size {
// Right align text
justify-content: flex-end;
width: calc(var(--row-height) * 1.5);
// opacity varies with the size
color: var(--color-main-text);
// Icon is before text since size is right aligned
::v-deep .files-list__column-sort-button {
padding: 0 16px 0 4px !important;
.button-vue__wrapper {
flex-direction: row;
}
}
}
.files-list__row-column-custom {
width: calc(var(--row-height) * 2);
}

@ -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
*

@ -1,7 +1,7 @@
/**
* @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
*
* @author Gary Kim <gary@garykim.dev>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*

@ -1,7 +1,7 @@
/**
* @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
*
* @author Gary Kim <gary@garykim.dev>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*

@ -21,7 +21,6 @@
*/
/* eslint-disable */
import { defineStore } from 'pinia'
import Vue from 'vue'
import type { ActionsMenuStore } from '../types'
export const useActionsMenuStore = defineStore('actionsmenu', {

@ -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
}

@ -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
-

@ -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
-

@ -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
-

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -23,7 +23,7 @@
/**
* @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
*
* @author Gary Kim <gary@garykim.dev>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
@ -46,7 +46,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
*

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save