Skip to content

Commit

Permalink
Allow cancel before loading is finished
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
  • Loading branch information
skjnldsv committed Oct 31, 2019
1 parent 13f8065 commit e01b429
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 44 deletions.
7 changes: 4 additions & 3 deletions src/services/FileInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ import { genFileInfo } from '../utils/fileUtils'
* Retrieve the files list
*
* @param {String} path the path relative to the user root
* @param {Object} [options] optional options for axios
* @returns {Array} the file list
*/
export default async function(path) {
const response = await client.stat(path, {
export default async function(path, options) {
const response = await client.stat(path, Object.assign({
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns"
Expand Down Expand Up @@ -57,6 +58,6 @@ export default async function(path) {
</d:prop>
</d:propfind>`,
details: true,
})
}, options))
return genFileInfo(response.data)
}
7 changes: 4 additions & 3 deletions src/services/FileList.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ import { genFileInfo } from '../utils/fileUtils'
* Retrieve the files list
*
* @param {String} path the path relative to the user root
* @param {Object} [options] optional options for axios
* @returns {Array} the file list
*/
export default async function(path) {
export default async function(path, options) {
// getDirectoryContents doesn't accept / for root
const fixedPath = path === '/' ? '' : path

const response = await client.getDirectoryContents(fixedPath, {
const response = await client.getDirectoryContents(fixedPath, Object.assign({
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns"
Expand Down Expand Up @@ -61,7 +62,7 @@ export default async function(path) {
</d:prop>
</d:propfind>`,
details: true,
})
}, options))

return response.data.map(genFileInfo)
}
57 changes: 57 additions & 0 deletions src/utils/CancelableRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @copyright Copyright (c) 2019 Marco Ambrosini <marcoambrosini@pm.me>
*
* @author Marco Ambrosini <marcoambrosini@pm.me>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* 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 axios from '@nextcloud/axios'

/**
* Creates a cancelable axios 'request object'.
*
* @param {function} request the axios promise request
* @returns {Object}
*/
const CancelableRequest = function(request) {
/**
* Generate an axios cancel token
*/
const CancelToken = axios.CancelToken
const source = CancelToken.source()

/**
* Execute the request
*
* @param {string} url the url to send the request to
* @param {Object} [options] optional config for the request
*/
const fetch = async function(url, options) {
return request(
url,
Object.assign({ cancelToken: source.token }, { options })
)
}
return {
request: fetch,
cancel: source.cancel,
}
}

export default CancelableRequest
98 changes: 60 additions & 38 deletions src/views/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ import getFileList from '../services/FileList'
import getFileInfo from '../services/FileInfo'
import PreviewUrl from '../mixins/PreviewUrl'

import cancelableRequest from '../utils/CancelableRequest'

export default {
name: 'Viewer',

Expand Down Expand Up @@ -154,6 +156,10 @@ export default {
isLoaded: false,
initiated: false,

// cancellable requests
cancelRequestFile: () => {},
cancelRequestFolder: () => {},

shownSidebar: false,
sidebarWidth: 0,

Expand Down Expand Up @@ -240,13 +246,21 @@ export default {
* @param {string} path the file path to open
*/
async openFile(path) {
// cancel any previous requests
this.cancelRequestFile()
this.cancelRequestFolder()

// do not open the same file again
if (path === this.currentFile.path) {
return
}

// initial loading start
this.initiated = true
const { request: fileRequest, cancel: cancelRequestFile } = cancelableRequest(getFileInfo)
const { request: folderRequest, cancel: cancelRequestFolder } = cancelableRequest(getFileList)
this.cancelRequestFile = cancelRequestFile
this.cancelRequestFolder = cancelRequestFolder

// extcrat needed info from path
const [dirPath, fileName] = extractFilePaths(path)
Expand All @@ -261,53 +275,57 @@ export default {
document.title = `${fileName} - ${OC.theme.title}`
}

// retrieve, sort and store file List
let fileInfo = await getFileInfo(path)
try {

// get original mime
let mime = fileInfo.mime
// retrieve, sort and store file List
let fileInfo = await fileRequest(path)

// check if part of a group, if so retrieve full files list
const group = this.mimeGroups[mime]
if (group) {
const mimes = this.mimeGroups[group]
? this.mimeGroups[group]
: [mime]
// get original mime
let mime = fileInfo.mime

// retrieve folder list
const fileList = await getFileList(dirPath)
// check if part of a group, if so retrieve full files list
const group = this.mimeGroups[mime]
if (group) {
const mimes = this.mimeGroups[group]
? this.mimeGroups[group]
: [mime]

// filter out the unwanted mimes
const filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1)
console.info(filteredFiles)
// retrieve folder list
const fileList = await folderRequest(dirPath)

// sort like the files list
// TODO: implement global sorting API
// https://github.com/nextcloud/server/blob/a83b79c5f8ab20ed9b4d751167417a65fa3c42b8/apps/files/lib/Controller/ApiController.php#L247
this.fileList = filteredFiles.sort((a, b) => sortCompare(a, b, 'basename'))
// filter out the unwanted mimes
const filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1)

// store current position
this.currentIndex = this.fileList.findIndex(file => file.basename === fileName)
} else {
this.currentIndex = 0
this.fileList = [fileInfo]
}
// sort like the files list
// TODO: implement global sorting API
// https://github.com/nextcloud/server/blob/a83b79c5f8ab20ed9b4d751167417a65fa3c42b8/apps/files/lib/Controller/ApiController.php#L247
this.fileList = filteredFiles.sort((a, b) => sortCompare(a, b, 'basename'))

// get saved fileInfo
fileInfo = this.fileList[this.currentIndex]
// store current position
this.currentIndex = this.fileList.findIndex(file => file.basename === fileName)
} else {
this.currentIndex = 0
this.fileList = [fileInfo]
}

// override mimetype if existing alias
if (!this.components[mime]) {
mime = mime.split('/')[0]
}
// get saved fileInfo
fileInfo = this.fileList[this.currentIndex]

// if we have a valid mime, show it!
if (this.components[mime]) {
this.currentFile = new File(fileInfo, mime, this.components[mime])
this.updatePreviousNext()
} else {
console.error(`The following file could not be displayed`, fileName, fileInfo)
this.close()
// override mimetype if existing alias
if (!this.components[mime]) {
mime = mime.split('/')[0]
}

// if we have a valid mime, show it!
if (this.components[mime]) {
this.currentFile = new File(fileInfo, mime, this.components[mime])
this.updatePreviousNext()
} else {
console.error(`The following file could not be displayed`, fileName, fileInfo)
this.close()
}
} catch (error) {
console.error(error)
}
},

Expand Down Expand Up @@ -488,6 +506,10 @@ export default {
this.initiated = false
this.hideAppsSidebar()

// cancel requests
this.cancelRequestFile()
this.cancelRequestFolder()

// restore default
document.body.style.overflow = null

Expand Down

0 comments on commit e01b429

Please sign in to comment.