summaryrefslogtreecommitdiffstats
path: root/apps/files/src
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-10-04 13:49:57 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-10-07 09:40:59 +0200
commit4de6e807714560329e55c3ed09d6ff029a1eb6df (patch)
treef79cad4ba84ca7c54503e53eea4c15bba9d58a5b /apps/files/src
parent843d799a2e2c884026883e3f41b81066801a877d (diff)
downloadnextcloud-server-4de6e807714560329e55c3ed09d6ff029a1eb6df.tar.gz
nextcloud-server-4de6e807714560329e55c3ed09d6ff029a1eb6df.zip
Upgrade lifecycle and vue parent context
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
Diffstat (limited to 'apps/files/src')
-rw-r--r--apps/files/src/components/SidebarTab.vue56
-rw-r--r--apps/files/src/models/Tab.js36
-rw-r--r--apps/files/src/sidebar.js2
-rw-r--r--apps/files/src/views/Sidebar.vue81
4 files changed, 106 insertions, 69 deletions
diff --git a/apps/files/src/components/SidebarTab.vue b/apps/files/src/components/SidebarTab.vue
index ecf04e9c9b3..1fc93486bc0 100644
--- a/apps/files/src/components/SidebarTab.vue
+++ b/apps/files/src/components/SidebarTab.vue
@@ -23,21 +23,28 @@
<template>
<AppSidebarTab
:id="id"
+ ref="tab"
:name="name"
:icon="icon">
+ <!-- Fallback loading -->
+ <EmptyContent v-if="loading" icon="icon-loading" />
+
<!-- Using a dummy div as Vue mount replace the element directly
It does NOT append to the content -->
- <div ref="mount"></div>
+ <div ref="mount" />
</AppSidebarTab>
</template>
<script>
import AppSidebarTab from '@nextcloud/vue/dist/Components/AppSidebarTab'
+import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
+
export default {
name: 'SidebarTab',
components: {
AppSidebarTab,
+ EmptyContent,
},
props: {
@@ -58,36 +65,61 @@ export default {
type: String,
required: true,
},
- render: {
+
+ /**
+ * Lifecycle methods.
+ * They are prefixed with `on` to avoid conflict with Vue
+ * methods like this.destroy
+ */
+ onMount: {
type: Function,
required: true,
},
+ onUpdate: {
+ type: Function,
+ required: true,
+ },
+ onDestroy: {
+ type: Function,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ loading: true,
+ }
},
computed: {
- // TODO: implement a better way to force pass a prop fromm Sidebar
+ // TODO: implement a better way to force pass a prop from Sidebar
activeTab() {
return this.$parent.activeTab
},
},
watch: {
- fileInfo(newFile, oldFile) {
+ async fileInfo(newFile, oldFile) {
+ // Update fileInfo on change
if (newFile.id !== oldFile.id) {
- this.mountTab()
+ this.loading = true
+ await this.onUpdate(this.fileInfo)
+ this.loading = false
}
},
},
- mounted() {
- this.mountTab()
+ async mounted() {
+ this.loading = true
+ // Mount the tab: mounting point, fileInfo, vue context
+ await this.onMount(this.$refs.mount, this.fileInfo, this.$refs.tab)
+ this.loading = false
},
- methods: {
- mountTab() {
- // Mount the tab into this component
- this.render(this.$refs.mount, this.fileInfo)
- },
+ async beforeDestroy() {
+ // unmount the tab
+ await this.onDestroy()
},
+
}
</script>
diff --git a/apps/files/src/models/Tab.js b/apps/files/src/models/Tab.js
index 753b9c9c282..2c587e5f70a 100644
--- a/apps/files/src/models/Tab.js
+++ b/apps/files/src/models/Tab.js
@@ -25,7 +25,9 @@ export default class Tab {
#id
#name
#icon
- #render
+ #mount
+ #update
+ #destroy
#enabled
/**
@@ -35,10 +37,12 @@ export default class Tab {
* @param {string} options.id the unique id of this tab
* @param {string} options.name the translated tab name
* @param {string} options.icon the vue component
- * @param {Function} options.render function to render the tab
+ * @param {Function} options.mount function to mount the tab
+ * @param {Function} options.update function to update the tab
+ * @param {Function} options.destroy function to destroy the tab
* @param {Function} [options.enabled] define conditions whether this tab is active. Must returns a boolean
*/
- constructor({ id, name, icon, render, enabled }) {
+ constructor({ id, name, icon, mount, update, destroy, enabled } = {}) {
if (enabled === undefined) {
enabled = () => true
}
@@ -53,8 +57,14 @@ export default class Tab {
if (typeof icon !== 'string' || icon.trim() === '') {
throw new Error('The icon argument is not a valid string')
}
- if (typeof render !== 'function') {
- throw new Error('The render argument should be a function')
+ if (typeof mount !== 'function') {
+ throw new Error('The mount argument should be a function')
+ }
+ if (typeof update !== 'function') {
+ throw new Error('The update argument should be a function')
+ }
+ if (typeof destroy !== 'function') {
+ throw new Error('The destroy argument should be a function')
}
if (typeof enabled !== 'function') {
throw new Error('The enabled argument should be a function')
@@ -63,7 +73,9 @@ export default class Tab {
this.#id = id
this.#name = name
this.#icon = icon
- this.#render = render
+ this.#mount = mount
+ this.#update = update
+ this.#destroy = destroy
this.#enabled = enabled
}
@@ -80,8 +92,16 @@ export default class Tab {
return this.#icon
}
- get render() {
- return this.#render
+ get mount() {
+ return this.#mount
+ }
+
+ get update() {
+ return this.#update
+ }
+
+ get destroy() {
+ return this.#destroy
}
get enabled() {
diff --git a/apps/files/src/sidebar.js b/apps/files/src/sidebar.js
index 508093465d4..54293bd24c8 100644
--- a/apps/files/src/sidebar.js
+++ b/apps/files/src/sidebar.js
@@ -21,6 +21,8 @@
*/
import Vue from 'vue'
+import { translate as t } from '@nextcloud/l10n'
+
import SidebarView from './views/Sidebar.vue'
import Sidebar from './services/Sidebar'
import Tab from './models/Tab'
diff --git a/apps/files/src/views/Sidebar.vue b/apps/files/src/views/Sidebar.vue
index 6fa5c35dca2..664bc6f4075 100644
--- a/apps/files/src/views/Sidebar.vue
+++ b/apps/files/src/views/Sidebar.vue
@@ -52,33 +52,38 @@
</template>
<!-- Error display -->
- <div v-if="error" class="emptycontent">
- <div class="icon-error" />
- <h2>{{ error }}</h2>
- </div>
+ <EmptyContent v-if="error" icon="icon-error">
+ {{ error }}
+ </EmptyContent>
- <!-- If fileInfo fetch is complete, display tabs -->
- <template v-else-if="fileInfo" v-for="tab in tabs">
+ <!-- If fileInfo fetch is complete, render tabs -->
+ <template v-for="tab in tabs" v-else-if="fileInfo">
+ <!-- Hide them if we're loading another file but keep them mounted -->
<SidebarTab
v-if="tab.enabled(fileInfo)"
+ v-show="!loading"
:id="tab.id"
:key="tab.id"
:name="tab.name"
:icon="tab.icon"
- :render="tab.render"
+ :on-mount="tab.mount"
+ :on-update="tab.update"
+ :on-destroy="tab.destroy"
:file-info="fileInfo" />
</template>
</AppSidebar>
</template>
<script>
+import { encodePath } from '@nextcloud/paths'
import $ from 'jquery'
import axios from '@nextcloud/axios'
import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
+import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
+
import FileInfo from '../services/FileInfo'
import SidebarTab from '../components/SidebarTab'
import LegacyView from '../components/LegacyView'
-import { encodePath } from '@nextcloud/paths'
export default {
name: 'Sidebar',
@@ -86,8 +91,9 @@ export default {
components: {
ActionButton,
AppSidebar,
- SidebarTab,
+ EmptyContent,
LegacyView,
+ SidebarTab,
},
data() {
@@ -95,6 +101,7 @@ export default {
// reactive state
Sidebar: OCA.Files.Sidebar.state,
error: null,
+ loading: true,
fileInfo: null,
starLoading: false,
}
@@ -185,15 +192,16 @@ export default {
appSidebar() {
if (this.fileInfo) {
return {
- background: this.background,
+ 'data-mimetype': this.fileInfo.mimetype,
+ 'star-loading': this.starLoading,
active: this.activeTab,
+ background: this.background,
class: { 'has-preview': this.fileInfo.hasPreview },
compact: !this.fileInfo.hasPreview,
- 'star-loading': this.starLoading,
+ loading: this.loading,
starred: this.fileInfo.isFavourited,
subtitle: this.subtitle,
title: this.fileInfo.name,
- 'data-mimetype': this.fileInfo.mimetype,
}
} else if (this.error) {
return {
@@ -201,12 +209,12 @@ export default {
subtitle: '',
title: '',
}
- } else {
- return {
- class: 'icon-loading',
- subtitle: '',
- title: '',
- }
+ }
+ // no fileInfo yet, showing empty data
+ return {
+ loading: this.loading,
+ subtitle: '',
+ title: '',
}
},
@@ -241,35 +249,6 @@ export default {
},
},
- watch: {
- // update the sidebar data
- async file(curr, prev) {
- this.resetData()
- if (curr && curr.trim() !== '') {
- try {
- this.fileInfo = await FileInfo(this.davPath)
- // adding this as fallback because other apps expect it
- this.fileInfo.dir = this.file.split('/').slice(0, -1).join('/')
-
- // DEPRECATED legacy views
- // TODO: remove
- this.views.forEach(view => {
- view.setFileInfo(this.fileInfo)
- })
-
- this.$nextTick(() => {
- if (this.$refs.tabs) {
- this.$refs.tabs.updateTabs()
- }
- })
- } catch (error) {
- this.error = t('files', 'Error while loading the file data')
- console.error('Error while loading the file data', error)
- }
- }
- },
- },
-
methods: {
/**
* Can this tab be displayed ?
@@ -403,9 +382,11 @@ export default {
// update current opened file
this.Sidebar.file = path
- // reset previous data
- this.resetData()
if (path && path.trim() !== '') {
+ // reset data, keep old fileInfo to not reload all tabs and just hide them
+ this.error = null
+ this.loading = true
+
try {
this.fileInfo = await FileInfo(this.davPath)
// adding this as fallback because other apps expect it
@@ -427,6 +408,8 @@ export default {
console.error('Error while loading the file data', error)
throw new Error(error)
+ } finally {
+ this.loading = false
}
}
},