Skip to content

Commit 609991a

Browse files
skjnldsvnpmbuildbot[bot]
authored andcommitted
Allow cancel before loading is finished
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
1 parent 547290e commit 609991a

File tree

8 files changed

+218
-60421
lines changed

8 files changed

+218
-60421
lines changed

appinfo/app.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@
2323

2424
namespace OCA\Viewer\AppInfo;
2525

26-
// Query the app instance in the hope it's instantiated exactly once
2726
\OC::$server->query(\OCA\Viewer\AppInfo\Application::class);

js/viewer.js

Lines changed: 90 additions & 60369 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/viewer.js.map

Lines changed: 1 addition & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/AppInfo/Application.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232

3333
class Application extends App {
3434

35-
const appID = 'viewer';
35+
const APP_ID = 'viewer';
3636

3737
public function __construct() {
38-
parent::__construct(self::appID);
38+
parent::__construct(self::APP_ID);
3939

4040
// listen to sidebar loading event
4141
$server = $this->getContainer()->getServer();

src/services/FileInfo.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ import { genFileInfo } from '../utils/fileUtils'
2626
* Retrieve the files list
2727
*
2828
* @param {String} path the path relative to the user root
29+
* @param {Object} [options] optional options for axios
2930
* @returns {Array} the file list
3031
*/
31-
export default async function(path) {
32-
const response = await client.stat(path, {
32+
export default async function(path, options) {
33+
const response = await client.stat(path, Object.assign({
3334
data: `<?xml version="1.0"?>
3435
<d:propfind xmlns:d="DAV:"
3536
xmlns:oc="http://owncloud.org/ns"
@@ -57,6 +58,6 @@ export default async function(path) {
5758
</d:prop>
5859
</d:propfind>`,
5960
details: true,
60-
})
61+
}, options))
6162
return genFileInfo(response.data)
6263
}

src/services/FileList.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ import { genFileInfo } from '../utils/fileUtils'
2727
* Retrieve the files list
2828
*
2929
* @param {String} path the path relative to the user root
30+
* @param {Object} [options] optional options for axios
3031
* @returns {Array} the file list
3132
*/
32-
export default async function(path) {
33+
export default async function(path, options) {
3334
// getDirectoryContents doesn't accept / for root
3435
const fixedPath = path === '/' ? '' : path
3536

36-
const response = await client.getDirectoryContents(fixedPath, {
37+
const response = await client.getDirectoryContents(fixedPath, Object.assign({
3738
data: `<?xml version="1.0"?>
3839
<d:propfind xmlns:d="DAV:"
3940
xmlns:oc="http://owncloud.org/ns"
@@ -61,7 +62,7 @@ export default async function(path) {
6162
</d:prop>
6263
</d:propfind>`,
6364
details: true,
64-
})
65+
}, options))
6566

6667
return response.data.map(genFileInfo)
6768
}

src/utils/CancelableRequest.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @copyright Copyright (c) 2019 Marco Ambrosini <marcoambrosini@pm.me>
3+
*
4+
* @author Marco Ambrosini <marcoambrosini@pm.me>
5+
* @author John Molakvoæ <skjnldsv@protonmail.com>
6+
*
7+
* @license GNU AGPL version 3 or any later version
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as
11+
* published by the Free Software Foundation, either version 3 of the
12+
* License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
import axios from '@nextcloud/axios'
25+
26+
/**
27+
* Creates a cancelable axios 'request object'.
28+
*
29+
* @param {function} request the axios promise request
30+
* @returns {Object}
31+
*/
32+
const CancelableRequest = function(request) {
33+
/**
34+
* Generate an axios cancel token
35+
*/
36+
const CancelToken = axios.CancelToken
37+
const source = CancelToken.source()
38+
39+
/**
40+
* Execute the request
41+
*
42+
* @param {string} url the url to send the request to
43+
* @param {Object} [options] optional config for the request
44+
*/
45+
const fetch = async function(url, options) {
46+
return request(
47+
url,
48+
Object.assign({ cancelToken: source.token }, { options })
49+
)
50+
}
51+
return {
52+
request: fetch,
53+
cancel: source.cancel,
54+
}
55+
}
56+
57+
export default CancelableRequest

src/views/Viewer.vue

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ import getFileList from '../services/FileList'
125125
import getFileInfo from '../services/FileInfo'
126126
import PreviewUrl from '../mixins/PreviewUrl'
127127
128+
import cancelableRequest from '../utils/CancelableRequest'
129+
128130
export default {
129131
name: 'Viewer',
130132
@@ -154,6 +156,10 @@ export default {
154156
isLoaded: false,
155157
initiated: false,
156158
159+
// cancellable requests
160+
cancelRequestFile: () => {},
161+
cancelRequestFolder: () => {},
162+
157163
shownSidebar: false,
158164
sidebarWidth: 0,
159165
@@ -240,13 +246,21 @@ export default {
240246
* @param {string} path the file path to open
241247
*/
242248
async openFile(path) {
249+
// cancel any previous requests
250+
this.cancelRequestFile()
251+
this.cancelRequestFolder()
252+
243253
// do not open the same file again
244254
if (path === this.currentFile.path) {
245255
return
246256
}
247257
248258
// initial loading start
249259
this.initiated = true
260+
const { request: fileRequest, cancel: cancelRequestFile } = cancelableRequest(getFileInfo)
261+
const { request: folderRequest, cancel: cancelRequestFolder } = cancelableRequest(getFileList)
262+
this.cancelRequestFile = cancelRequestFile
263+
this.cancelRequestFolder = cancelRequestFolder
250264
251265
// extcrat needed info from path
252266
const [dirPath, fileName] = extractFilePaths(path)
@@ -261,53 +275,57 @@ export default {
261275
document.title = `${fileName} - ${OC.theme.title}`
262276
}
263277
264-
// retrieve, sort and store file List
265-
let fileInfo = await getFileInfo(path)
278+
try {
266279
267-
// get original mime
268-
let mime = fileInfo.mime
280+
// retrieve, sort and store file List
281+
let fileInfo = await fileRequest(path)
269282
270-
// check if part of a group, if so retrieve full files list
271-
const group = this.mimeGroups[mime]
272-
if (group) {
273-
const mimes = this.mimeGroups[group]
274-
? this.mimeGroups[group]
275-
: [mime]
283+
// get original mime
284+
let mime = fileInfo.mime
276285
277-
// retrieve folder list
278-
const fileList = await getFileList(dirPath)
286+
// check if part of a group, if so retrieve full files list
287+
const group = this.mimeGroups[mime]
288+
if (group) {
289+
const mimes = this.mimeGroups[group]
290+
? this.mimeGroups[group]
291+
: [mime]
279292
280-
// filter out the unwanted mimes
281-
const filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1)
282-
console.info(filteredFiles)
293+
// retrieve folder list
294+
const fileList = await folderRequest(dirPath)
283295
284-
// sort like the files list
285-
// TODO: implement global sorting API
286-
// https://github.com/nextcloud/server/blob/a83b79c5f8ab20ed9b4d751167417a65fa3c42b8/apps/files/lib/Controller/ApiController.php#L247
287-
this.fileList = filteredFiles.sort((a, b) => sortCompare(a, b, 'basename'))
296+
// filter out the unwanted mimes
297+
const filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1)
288298
289-
// store current position
290-
this.currentIndex = this.fileList.findIndex(file => file.basename === fileName)
291-
} else {
292-
this.currentIndex = 0
293-
this.fileList = [fileInfo]
294-
}
299+
// sort like the files list
300+
// TODO: implement global sorting API
301+
// https://github.com/nextcloud/server/blob/a83b79c5f8ab20ed9b4d751167417a65fa3c42b8/apps/files/lib/Controller/ApiController.php#L247
302+
this.fileList = filteredFiles.sort((a, b) => sortCompare(a, b, 'basename'))
295303
296-
// get saved fileInfo
297-
fileInfo = this.fileList[this.currentIndex]
304+
// store current position
305+
this.currentIndex = this.fileList.findIndex(file => file.basename === fileName)
306+
} else {
307+
this.currentIndex = 0
308+
this.fileList = [fileInfo]
309+
}
298310
299-
// override mimetype if existing alias
300-
if (!this.components[mime]) {
301-
mime = mime.split('/')[0]
302-
}
311+
// get saved fileInfo
312+
fileInfo = this.fileList[this.currentIndex]
303313
304-
// if we have a valid mime, show it!
305-
if (this.components[mime]) {
306-
this.currentFile = new File(fileInfo, mime, this.components[mime])
307-
this.updatePreviousNext()
308-
} else {
309-
console.error(`The following file could not be displayed`, fileName, fileInfo)
310-
this.close()
314+
// override mimetype if existing alias
315+
if (!this.components[mime]) {
316+
mime = mime.split('/')[0]
317+
}
318+
319+
// if we have a valid mime, show it!
320+
if (this.components[mime]) {
321+
this.currentFile = new File(fileInfo, mime, this.components[mime])
322+
this.updatePreviousNext()
323+
} else {
324+
console.error(`The following file could not be displayed`, fileName, fileInfo)
325+
this.close()
326+
}
327+
} catch (error) {
328+
console.error(error)
311329
}
312330
},
313331
@@ -488,6 +506,10 @@ export default {
488506
this.initiated = false
489507
this.hideAppsSidebar()
490508
509+
// cancel requests
510+
this.cancelRequestFile()
511+
this.cancelRequestFolder()
512+
491513
// restore default
492514
document.body.style.overflow = null
493515

0 commit comments

Comments
 (0)