Skip to content

Commit

Permalink
Merge pull request #515 from Peergos/fix/lazy-picker
Browse files Browse the repository at this point in the history
speed up picker construction by using lazy loading of entries
  • Loading branch information
ianopolous authored Jul 31, 2023
2 parents fc28b1c + c46aa16 commit 52c99dc
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 22 deletions.
13 changes: 11 additions & 2 deletions src/components/picker/FilePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Spinner v-if="showSpinner"></Spinner>
<div class="file-picker-view" class="scroll-style">
<ul>
<SelectableTreeItem class="item" :model="treeData" :select_func="selectFile" :selectLeafOnly="selectLeafOnly"></TreeItem>
<SelectableTreeItem class="item" :model="treeData" :select_func="selectFile" :load_func="loadFolderLazily" :spinnerEnable_func="spinnerEnable" :spinnerDisable_func="spinnerDisable" :selectLeafOnly="selectLeafOnly"></TreeItem>
</ul>
</div>
<input style="background-color: lightgrey;"
Expand Down Expand Up @@ -64,7 +64,7 @@ module.exports = {
that.showSpinner = false;
that.spinnerMessage = '';
};
this.loadFoldersAndFiles(this.baseFolder + "/", this.pickerFileExtension, callback);
this.loadSubFoldersAndFiles(this.baseFolder + "/", this.pickerFileExtension, callback);
},
methods: {
close: function () {
Expand All @@ -73,6 +73,15 @@ module.exports = {
selectFile: function (file) {
this.selectedFile = file;
},
spinnerEnable: function () {
this.showSpinner = true;
},
spinnerDisable: function () {
this.showSpinner = false;
},
loadFolderLazily: function(path, callback) {
this.loadSubFoldersAndFiles(path, this.pickerFileExtension, callback);
},
fileSelected: function() {
this.selectedFile_func(this.selectedFile);
}
Expand Down
18 changes: 16 additions & 2 deletions src/components/picker/FolderPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
<Spinner v-if="showSpinner"></Spinner>
<div class="folder-picker-view" class="scroll-style">
<ul>
<TreeItem class="item" :model="treeData" :selectFolder_func="selectFolder"></TreeItem>
<TreeItem class="item"
:model="treeData"
:selectFolder_func="selectFolder"
:load_func="loadFolderLazily"
:spinnerEnable_func="spinnerEnable"
:spinnerDisable_func="spinnerDisable"></TreeItem>
</ul>
</div>
<h4>Selected:</h4>
Expand Down Expand Up @@ -70,12 +75,21 @@ module.exports = {
that.showSpinner = false;
that.spinnerMessage = '';
};
this.loadFolders(this.baseFolder + "/", callback);
this.loadSubFolders(this.baseFolder + "/", callback);
},
methods: {
close: function () {
this.selectedFolder_func([]);
},
spinnerEnable: function () {
this.showSpinner = true;
},
spinnerDisable: function () {
this.showSpinner = false;
},
loadFolderLazily: function(path, callback) {
this.loadSubFolders(path, callback);
},
selectFolder: function (folderName, add) {
if (add) {
this.selectedFoldersList.push(folderName);
Expand Down
14 changes: 11 additions & 3 deletions src/components/picker/NewFilePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div class="prompt__body">
<div class="folder-picker-view" class="scroll-style">
<ul>
<SelectableTreeItem class="item" :model="treeData" :select_func="selectFolder" :selectLeafOnly="selectLeafOnly"></SelectableTreeItem>
<SelectableTreeItem class="item" :model="treeData" :load_func="loadFolderLazily" :select_func="selectFolder" :spinnerEnable_func="spinnerEnable" :spinnerDisable_func="spinnerDisable" :selectLeafOnly="selectLeafOnly"></SelectableTreeItem>
</ul>
</div>
<input style="background-color: lightgrey;"
Expand Down Expand Up @@ -113,7 +113,7 @@ module.exports = {
that.showSpinner = false;
that.spinnerMessage = '';
};
this.loadFolders(this.context.username + "/", callback);
this.loadSubFolders(this.context.username + "/", callback);
},
methods: {
closePrompt() {
Expand All @@ -131,7 +131,15 @@ module.exports = {
this.$emit("hide-prompt");
}
},
spinnerEnable: function () {
this.showSpinner = true;
},
spinnerDisable: function () {
this.showSpinner = false;
},
loadFolderLazily: function(path, callback) {
this.loadSubFolders(path, callback);
},
selectFolder: function (folderName) {
this.folder_result = folderName;
},
Expand Down
33 changes: 26 additions & 7 deletions src/components/picker/SelectableTreeItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
</div>
<div v-if="selectLeafOnly && !isLeaf">
<span v-bind:id="model.path">{{ displayName(model.path) }}</span>
<span v-if="isFolder" @click="toggle">[{{ isOpen ? '-' : '+' }}]</span>
<span v-if="isFolder" @click="toggle">[{{ model.isOpen ? '-' : '+' }}]</span>
</div>
<div v-if="!selectLeafOnly">
<span @click="selectItem" v-bind:id="model.path">{{ displayName(model.path) }}</span>
<span v-if="isFolder" @click="toggle">[{{ isOpen ? '-' : '+' }}]</span>
<span v-if="isFolder" @click="toggle">[{{ model.isOpen ? '-' : '+' }}]</span>
</div>
<li v-show="isOpen" v-if="isFolder" style="list-style-type: none">
<li v-show="model.isOpen" v-if="isFolder" style="list-style-type: none">
<SelectableTreeItem
class="item"
v-for="model in model.children"
:model="model" :select_func="select_func" :selectLeafOnly="selectLeafOnly">
:model="model" :select_func="select_func" :load_func="load_func" :spinnerEnable_func="spinnerEnable_func" :spinnerDisable_func="spinnerDisable_func" :selectLeafOnly="selectLeafOnly">
</SelectableTreeItem>
</li>
</ul>
Expand All @@ -26,15 +26,17 @@ module.exports = {
name: 'SelectableTreeItem', // necessary for self-reference
props: {
model: Object,
load_func: Function,
select_func: Function,
selectLeafOnly: {
type: Boolean,
default: false,
}
},
spinnerEnable_func: Function,
spinnerDisable_func: Function,
},
data() {
return {
isOpen: false,
}
},
computed: {
Expand All @@ -57,9 +59,26 @@ module.exports = {
toggle(e) {
e.preventDefault()
if (this.isFolder) {
this.isOpen = !this.isOpen
if (this.model.isOpen) {
this.model.isOpen = !this.model.isOpen
} else {
this.lazyLoadSubFolders();
}
}
},
lazyLoadSubFolders() {
let that = this;
this.spinnerEnable_func();
let callback = (baseOfSubFolderTree) => {
that.model.children = [];
for(var i=0; i < baseOfSubFolderTree.children.length; i++) {
that.model.children.push(baseOfSubFolderTree.children[i]);
}
that.spinnerDisable_func();
that.model.isOpen = !that.model.isOpen;
};
this.load_func(this.model.path + "/", callback);
},
selectItem(selectedItem) {
this.select_func(selectedItem.currentTarget.id);
}
Expand Down
35 changes: 29 additions & 6 deletions src/components/picker/TreeItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
<span class="checkmark"></span>
<div :class="{ bold: isFolder }" @click="toggle">
{{ displayFolderName(model.path) }}
<span v-if="isFolder">[{{ isOpen ? '-' : '+' }}]</span>
<span v-if="isFolder">[{{ model.isOpen ? '-' : '+' }}]</span>
</div>
</label>
<li v-show="isOpen" v-if="isFolder" style="list-style-type: none">
<li v-show="model.isOpen" v-if="isFolder" style="list-style-type: none">
<TreeItem
class="item"
v-for="model in model.children"
:model="model" :selectFolder_func="selectFolder_func" >
:model="model"
:selectFolder_func="selectFolder_func"
:load_func="load_func"
:spinnerEnable_func="spinnerEnable_func"
:spinnerDisable_func="spinnerDisable_func">
</TreeItem>
</li>
</ul>
Expand All @@ -23,11 +27,13 @@ module.exports = {
name: 'TreeItem', // necessary for self-reference
props: {
model: Object,
selectFolder_func: Function
selectFolder_func: Function,
load_func: Function,
spinnerEnable_func: Function,
spinnerDisable_func: Function,
},
data() {
return {
isOpen: false,
}
},
computed: {
Expand All @@ -47,9 +53,26 @@ module.exports = {
toggle(e) {
e.preventDefault()
if (this.isFolder) {
this.isOpen = !this.isOpen
if (this.model.isOpen) {
this.model.isOpen = !this.model.isOpen
} else {
this.lazyLoadSubFolders();
}
}
},
lazyLoadSubFolders() {
let that = this;
this.spinnerEnable_func();
let callback = (baseOfSubFolderTree) => {
that.model.children = [];
for(var i=0; i < baseOfSubFolderTree.children.length; i++) {
that.model.children.push(baseOfSubFolderTree.children[i]);
}
that.spinnerDisable_func();
that.model.isOpen = !that.model.isOpen;
};
this.load_func(this.model.path + "/", callback);
},
addChild(selectedFolder) {
this.selectFolder_func(selectedFolder.currentTarget.value, selectedFolder.currentTarget.checked);
}
Expand Down
66 changes: 64 additions & 2 deletions src/mixins/tree-walker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ module.exports = {
loadFoldersAndFiles: function(path, fileExtension, callback) {
this.loadAllFolders(path, callback, true, fileExtension);
},
loadSubFoldersAndFiles: function(path, fileExtension, callback) {
this.loadSubFoldersNotRecursive(path, callback, true, fileExtension);
},
loadFolders: function(path, callback) {
this.loadAllFolders(path, callback, false, '');
},
loadSubFolders: function(path, callback) {
this.loadSubFoldersNotRecursive(path, callback, false, '');
},
loadAllFolders: function(path, callback, includeFiles, fileExtension) {
var that = this;
let folderTree = {};
Expand All @@ -28,6 +34,7 @@ module.exports = {
walk: function(file, path, currentTreeData, includeFiles, fileExtension) {
currentTreeData.path = path.substring(0, path.length -1);
currentTreeData.children = [];
currentTreeData.isOpen = false;
let that = this;
let future = peergos.shared.util.Futures.incomplete();
file.getChildren(that.context.crypto.hasher, that.context.network).thenApply(function(children) {
Expand Down Expand Up @@ -71,13 +78,68 @@ module.exports = {
});
return future;
},
addFile(file, path, currentTreeData, includeFiles) {
addFile(file, path, currentTreeData) {
let future = peergos.shared.util.Futures.incomplete();
currentTreeData.path = path + file.getName();
currentTreeData.children = [];
currentTreeData.isLeaf = true;
currentTreeData.isOpen = false;
future.complete(true);
return future;
}
},
loadSubFoldersNotRecursive: function(path, callback, includeFiles, fileExtension) {
var that = this;
let folderTree = {};
this.context.getByPath(path).thenApply(function(dirOpt){
let dir = dirOpt.get();
let folderProperties = dir.getFileProperties();
if (folderProperties.isDirectory && !folderProperties.isHidden) {
that.walkNotRecursive(dir, path, folderTree, includeFiles, fileExtension).thenApply( () => {
callback(folderTree);
});
} else {
callback(folderTree);
}
}).exceptionally(function(throwable) {
this.spinnerMessage = 'Unable to load sub folders...';
throwable.printStackTrace();
});
},

walkNotRecursive: function(file, path, currentTreeData, includeFiles, fileExtension) {
currentTreeData.path = path.substring(0, path.length -1);
currentTreeData.children = [];
currentTreeData.isOpen = false;
let that = this;
let future = peergos.shared.util.Futures.incomplete();
file.getChildren(that.context.crypto.hasher, that.context.network).thenApply(function(children) {
let arr = children.toArray();
arr.forEach(function(child, index){
let childProps = child.getFileProperties();
let newPath = childProps.isDirectory ? path + child.getFileProperties().name + '/' : path;
if (childProps.isDirectory && !childProps.isHidden) {
let node = {};
node.path = newPath.substring(0, newPath.length -1);
node.children = ['lazy'];
node.isOpen = false;
currentTreeData.children.push(node);
}
if (includeFiles === true && !childProps.isDirectory && !childProps.isHidden) {
let test = fileExtension == null || fileExtension.length == 0 ||
child.getFileProperties().name.endsWith(fileExtension);
if (test) {
let node = {};
node.path = newPath + child.getName();
node.children = [];
node.isLeaf = true;
node.isOpen = false;
currentTreeData.children.push(node);
}
}
});
future.complete(true);
});
return future;
},
}
}

0 comments on commit 52c99dc

Please sign in to comment.