Skip to content

Commit c893d32

Browse files
authored
Merge pull request #61107 from nextcloud/backport/60943/stable33
[stable33] fix(files): make sure nested changes are propagated to sidebar tabs
2 parents fb55292 + d0eafd3 commit c893d32

87 files changed

Lines changed: 158 additions & 135 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/files/src/components/FilesSidebar/FilesSidebarTab.vue

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
import type { ISidebarTab } from '@nextcloud/files'
88
99
import { NcIconSvgWrapper, NcLoadingIcon } from '@nextcloud/vue'
10-
import { ref, toRef, watch } from 'vue'
10+
import { computed, ref, toRef, watch } from 'vue'
1111
import NcAppSidebarTab from '@nextcloud/vue/components/NcAppSidebarTab'
1212
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
1313
import logger from '../../logger.ts'
14-
import { useActiveStore } from '../../store/active.ts'
1514
import { useSidebarStore } from '../../store/sidebar.ts'
1615
1716
const props = defineProps<{
@@ -27,7 +26,17 @@ const props = defineProps<{
2726
}>()
2827
2928
const sidebar = useSidebarStore()
30-
const activeStore = useActiveStore()
29+
30+
const context = computed(() => {
31+
if (!sidebar.currentContext) {
32+
return undefined
33+
}
34+
return {
35+
folder: sidebar.currentContext.folder.clone(),
36+
node: sidebar.currentContext.node.clone(),
37+
view: sidebar.currentContext.view,
38+
}
39+
})
3140
3241
const loading = ref(true)
3342
watch(toRef(props, 'active'), async (active) => {
@@ -65,7 +74,7 @@ const initializedTabs = new Set<string>()
6574
<template #icon>
6675
<NcIconSvgWrapper :svg="tab.iconSvgInline" />
6776
</template>
68-
<NcEmptyContent v-if="loading">
77+
<NcEmptyContent v-if="loading || !context">
6978
<template #icon>
7079
<NcLoadingIcon />
7180
</template>
@@ -75,8 +84,8 @@ const initializedTabs = new Set<string>()
7584
:is="tab.tagName"
7685
v-else
7786
:active.prop="active"
78-
:node.prop="sidebar.currentNode"
79-
:folder.prop="activeStore.activeFolder"
80-
:view.prop="activeStore.activeView" />
87+
:node.prop="context.node"
88+
:folder.prop="context.folder"
89+
:view.prop="context.view" />
8190
</NcAppSidebarTab>
8291
</template>

apps/files/src/store/files.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { defineStore } from 'pinia'
1111
import Vue, { ref } from 'vue'
1212
import logger from '../logger.ts'
1313
import { fetchNode } from '../services/WebdavClient.ts'
14+
import { useActiveStore } from './active.ts'
1415
import { usePathsStore } from './paths.ts'
1516

1617
/**
@@ -124,6 +125,12 @@ export const useFilesStore = defineStore('files', () => {
124125
}, {} as FilesStore)
125126

126127
files.value = { ...files.value, ...newNodes }
128+
129+
// handle updating the active node
130+
const activeStore = useActiveStore()
131+
if (activeStore.activeNode && activeStore.activeNode.source in newNodes) {
132+
activeStore.activeNode = files.value[activeStore.activeNode.source]
133+
}
127134
}
128135

129136
/**
@@ -232,7 +239,8 @@ export const useFilesStore = defineStore('files', () => {
232239
}
233240

234241
// Otherwise, it means we receive an event for a node that is not in the store
235-
fetchNode(node.path).then((n) => updateNodes([n]))
242+
const newNode = await fetchNode(node.path)
243+
updateNodes([newNode])
236244
}
237245

238246
/**

apps/files_versions/src/views/FilesVersionsSidebarTab.vue

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ import { showError, showSuccess } from '@nextcloud/dialogs'
4848
import { emit } from '@nextcloud/event-bus'
4949
import { t } from '@nextcloud/l10n'
5050
import { useIsMobile } from '@nextcloud/vue/composables/useIsMobile'
51-
import { computed, ref, toRef, watch } from 'vue'
51+
import { watchDebounced } from '@vueuse/core'
52+
import { computed, ref, watch } from 'vue'
5253
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
5354
import VersionEntry from '../components/VersionEntry.vue'
5455
import VersionLabelDialog from '../components/VersionLabelDialog.vue'
@@ -72,19 +73,6 @@ const loading = ref(false)
7273
const showVersionLabelForm = ref(false)
7374
const editedVersion = ref<Version | null>(null)
7475
75-
watch(toRef(() => props.node), async () => {
76-
if (!props.node) {
77-
return
78-
}
79-
80-
try {
81-
loading.value = true
82-
versions.value = await fetchVersions(props.node)
83-
} finally {
84-
loading.value = false
85-
}
86-
}, { immediate: true })
87-
8876
const currentVersionMtime = computed(() => props.node?.mtime?.getTime() ?? 0)
8977
9078
/**
@@ -139,6 +127,24 @@ const canCompare = computed(() => {
139127
&& window.OCA.Viewer?.mimetypesCompare?.includes(props.node?.mime)
140128
})
141129
130+
// When either the current node to show or its mtime changes we need to refetch the versions
131+
// When the id changed we immediately show changes
132+
watch(() => props.node.id, loadVersions, { immediate: true })
133+
// On mtime changes we debounce to prevent too many requests.
134+
watchDebounced(currentVersionMtime, loadVersions, { debounce: 600 })
135+
136+
/**
137+
* Load versions for the current node
138+
*/
139+
async function loadVersions() {
140+
try {
141+
loading.value = true
142+
versions.value = await fetchVersions(props.node)
143+
} finally {
144+
loading.value = false
145+
}
146+
}
147+
142148
/**
143149
* Handle restored event from Version.vue
144150
*
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import{b as g,q as y,s as v,c as p,u as o,o as n,H as h,w as _,g as V,t as b,v as x,r as M,j as d,e as f,F as q,C as w,_ as K,$ as U}from"./runtime-dom.esm-bundler-cd4tMQOC.chunk.mjs";import{c as j}from"./index-CPwHjAPR.chunk.mjs";import{a as C}from"./index-C1xmmKTZ-DKmPRT9t.chunk.mjs";import{t as s}from"./translation-DoG5ZELJ-DFt3Gk_P.chunk.mjs";import{g as N}from"./createElementId-DhjFt1I9-yLNeGKRZ.chunk.mjs";import{N as S}from"./logger-D3RVzcfQ-BiFhTTAc.chunk.mjs";import{N as A}from"./NcSelect-B1uITk_3-Nzy1TKZA.chunk.mjs";import{N as E}from"./NcCheckboxRadioSwitch-D0gFwEVl-CQqKxPRl.chunk.mjs";import{N as L}from"./NcPasswordField-BOLzDHBJ-CjV6dvT3.chunk.mjs";import{_ as z}from"./NcDateTime.vue_vue_type_script_setup_true_lang-B4upiZjL-C2ieIUJz.chunk.mjs";import{C as c,a as k}from"./types-BxBcKZMN.chunk.mjs";import{l as B}from"./logger-DaDjQfyb.chunk.mjs";const P=g({__name:"ConfigurationEntry",props:y({configKey:{},configOption:{}},{modelValue:{type:[String,Boolean],default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const a=v(e,"modelValue");return(t,i)=>e.configOption.type!==o(c).Boolean?(n(),p(h(e.configOption.type===o(c).Password?o(L):o(z)),{key:0,modelValue:a.value,"onUpdate:modelValue":i[0]||(i[0]=l=>a.value=l),name:e.configKey,required:!(e.configOption.flags&o(k).Optional),label:e.configOption.value,title:e.configOption.tooltip},null,8,["modelValue","name","required","label","title"])):(n(),p(o(E),{key:1,modelValue:a.value,"onUpdate:modelValue":i[1]||(i[1]=l=>a.value=l),type:"switch",title:e.configOption.tooltip},{default:_(()=>[V(b(e.configOption.value),1)]),_:1},8,["modelValue","title"]))}}),R=g({__name:"AuthMechanismRsa",props:y({authMechanism:{}},{modelValue:{required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const a=v(e,"modelValue"),t=M();x(t,()=>{t.value&&(a.value.private_key="",a.value.public_key="")});async function i(){try{const{data:l}=await j.post(N("/apps/files_external/ajax/public_key.php"),{keyLength:t.value});a.value.private_key=l.data.private_key,a.value.public_key=l.data.public_key}catch(l){B.error("Error generating RSA key pair",{error:l}),C(s("files_external","Error generating key pair"))}}return(l,m)=>(n(),d("div",null,[(n(!0),d(q,null,w(e.authMechanism.configuration,(r,u)=>K((n(),p(P,{key:r.value,modelValue:a.value[u],"onUpdate:modelValue":O=>a.value[u]=O,configKey:u,configOption:r},null,8,["modelValue","onUpdate:modelValue","configKey","configOption"])),[[U,!(r.flags&o(k).Hidden)]])),128)),f(o(A),{modelValue:t.value,"onUpdate:modelValue":m[0]||(m[0]=r=>t.value=r),clearable:!1,inputLabel:o(s)("files_external","Key size"),options:[1024,2048,4096],required:""},null,8,["modelValue","inputLabel"]),f(o(S),{disabled:!t.value,wide:"",onClick:i},{default:_(()=>[V(b(o(s)("files_external","Generate keys")),1)]),_:1},8,["disabled"])]))}}),Z=Object.freeze(Object.defineProperty({__proto__:null,default:R},Symbol.toStringTag,{value:"Module"}));export{Z as A,P as _};
2-
//# sourceMappingURL=AuthMechanismRsa-3Nt-tl8J.chunk.mjs.map
1+
import{b as g,q as y,s as v,c as p,u as o,o as n,H as h,w as _,g as V,t as b,v as x,r as M,j as d,e as f,F as q,C as w,_ as K,$ as U}from"./runtime-dom.esm-bundler-cd4tMQOC.chunk.mjs";import{c as j}from"./index-CPwHjAPR.chunk.mjs";import{a as C}from"./index-C1xmmKTZ-BfviRmbX.chunk.mjs";import{t as s}from"./translation-DoG5ZELJ-DFt3Gk_P.chunk.mjs";import{g as N}from"./createElementId-DhjFt1I9-yLNeGKRZ.chunk.mjs";import{N as S}from"./logger-D3RVzcfQ-BiFhTTAc.chunk.mjs";import{N as A}from"./NcSelect-B1uITk_3-Nzy1TKZA.chunk.mjs";import{N as E}from"./NcCheckboxRadioSwitch-D0gFwEVl-CQqKxPRl.chunk.mjs";import{N as L}from"./NcPasswordField-BOLzDHBJ-CjV6dvT3.chunk.mjs";import{_ as z}from"./NcDateTime.vue_vue_type_script_setup_true_lang-B4upiZjL-C2ieIUJz.chunk.mjs";import{C as c,a as k}from"./types-BxBcKZMN.chunk.mjs";import{l as B}from"./logger-DaDjQfyb.chunk.mjs";const P=g({__name:"ConfigurationEntry",props:y({configKey:{},configOption:{}},{modelValue:{type:[String,Boolean],default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const a=v(e,"modelValue");return(t,i)=>e.configOption.type!==o(c).Boolean?(n(),p(h(e.configOption.type===o(c).Password?o(L):o(z)),{key:0,modelValue:a.value,"onUpdate:modelValue":i[0]||(i[0]=l=>a.value=l),name:e.configKey,required:!(e.configOption.flags&o(k).Optional),label:e.configOption.value,title:e.configOption.tooltip},null,8,["modelValue","name","required","label","title"])):(n(),p(o(E),{key:1,modelValue:a.value,"onUpdate:modelValue":i[1]||(i[1]=l=>a.value=l),type:"switch",title:e.configOption.tooltip},{default:_(()=>[V(b(e.configOption.value),1)]),_:1},8,["modelValue","title"]))}}),R=g({__name:"AuthMechanismRsa",props:y({authMechanism:{}},{modelValue:{required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const a=v(e,"modelValue"),t=M();x(t,()=>{t.value&&(a.value.private_key="",a.value.public_key="")});async function i(){try{const{data:l}=await j.post(N("/apps/files_external/ajax/public_key.php"),{keyLength:t.value});a.value.private_key=l.data.private_key,a.value.public_key=l.data.public_key}catch(l){B.error("Error generating RSA key pair",{error:l}),C(s("files_external","Error generating key pair"))}}return(l,m)=>(n(),d("div",null,[(n(!0),d(q,null,w(e.authMechanism.configuration,(r,u)=>K((n(),p(P,{key:r.value,modelValue:a.value[u],"onUpdate:modelValue":O=>a.value[u]=O,configKey:u,configOption:r},null,8,["modelValue","onUpdate:modelValue","configKey","configOption"])),[[U,!(r.flags&o(k).Hidden)]])),128)),f(o(A),{modelValue:t.value,"onUpdate:modelValue":m[0]||(m[0]=r=>t.value=r),clearable:!1,inputLabel:o(s)("files_external","Key size"),options:[1024,2048,4096],required:""},null,8,["modelValue","inputLabel"]),f(o(S),{disabled:!t.value,wide:"",onClick:i},{default:_(()=>[V(b(o(s)("files_external","Generate keys")),1)]),_:1},8,["disabled"])]))}}),Z=Object.freeze(Object.defineProperty({__proto__:null,default:R},Symbol.toStringTag,{value:"Module"}));export{Z as A,P as _};
2+
//# sourceMappingURL=AuthMechanismRsa-Bb04w0qi.chunk.mjs.map
File renamed without changes.

0 commit comments

Comments
 (0)