From afdd963e418ab04081e5c2087a8a4b4ef5abf177 Mon Sep 17 00:00:00 2001 From: tks-abe Date: Wed, 30 May 2018 10:44:40 +0900 Subject: [PATCH] Fixed issue that does not work with W-03. --- README.ja.md | 3 + README.md | 3 + package.json | 2 +- src/common/config.js | 3 +- src/common/resources.js | 2 + src/main/store/app-store.js | 10 ++- src/renderer/action/iothub-action.js | 18 +++-- src/renderer/view/filer.js | 110 ++++++++++++++++++++------- src/renderer/view/filer_tmpl.hbs | 5 ++ static/css/file-manager.css | 10 ++- 10 files changed, 125 insertions(+), 41 deletions(-) diff --git a/README.ja.md b/README.ja.md index e162264..e5592dd 100644 --- a/README.ja.md +++ b/README.ja.md @@ -78,6 +78,9 @@ FlashAir™の無線LAN機能を使い、FlashAir IoT Hubを経由する事で ## Changelog +- [0.3.2](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.2) + - W-03で動作しない事がある問題を修正しました。 + - iothub.luaの先頭行のバージョン番号が1.5.0未満の場合、最新のLuaスクリプトを[FlashAir IoT Hub](https://iot-hub.flashair-developers.com)からダウンロードしてください。 - [0.3.1](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.1) - OSの言語設定が英語と日本語以外の場合、起動に失敗する問題を修正しました。 - [0.3.0](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.0) diff --git a/README.md b/README.md index 034b130..e851f1c 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ Note: Since version 0.2.0, Lua scripts are using [FlashAir IoT Hub](https://iot- ## Changelog +- [0.3.2](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.2) + - Fixed issue that does not work with W-03. + - If the version number of the first line of `iothub.lua` is less than 1.5.0, download the latest Lua script from [FlashAir IoT Hub](https://iot-hub.flashair-developers.com). - [0.3.1](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.1) - Fixed issue that failed to start if OS locale is other than English and Japanese. - [0.3.0](https://github.com/FlashAirDevelopers/FlashAirFileManager/releases/tag/v0.3.0) diff --git a/package.json b/package.json index 66a5ac0..39bafaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flashair-file-manager", - "version": "0.3.1", + "version": "0.3.2", "description": "The application to browse and download files on FlashAir™ via the network.", "homepage": "https://github.com/FlashAirDevelopers/FlashAirFileManager", "main": "./src/main/main.js", diff --git a/src/common/config.js b/src/common/config.js index 4d10b56..56b8685 100644 --- a/src/common/config.js +++ b/src/common/config.js @@ -44,5 +44,6 @@ export const IoTHubApi = { }; export const FlashAIrScript = { LIST: '/list_file.lua', - UPLOAD: '/upload_file.lua' + LIST_FETCH_MAX: 10, + UPLOAD: '/upload_file_slim.lua' }; diff --git a/src/common/resources.js b/src/common/resources.js index abee27d..5fc3e25 100644 --- a/src/common/resources.js +++ b/src/common/resources.js @@ -35,6 +35,7 @@ export const resources = { filer_label_local_file_date: '更新日付', filer_label_remote_file_name: '名前', filer_label_remote_file_date: '更新日付', + filer_label_remote_show_more: '更に表示する', filer_msg_remote_download_progress: 'ダウンロード中...', filer_msg_remote_download_completed: 'ダウンロードが完了しました。', auth_msg_invalid_access_token: '認証処理が失敗しました。再度ログインし直してください。', @@ -56,6 +57,7 @@ export const resources = { filer_label_local_file_date: 'Update date', filer_label_remote_file_name: 'Name', filer_label_remote_file_date: 'Update date', + filer_label_remote_show_more: 'Show more', filer_msg_remote_download_progress: 'Downloading...', filer_msg_remote_download_completed: 'Download is completed.', auth_msg_invalid_access_token: 'Authentication processing failed. Please login again.', diff --git a/src/main/store/app-store.js b/src/main/store/app-store.js index a7adbdf..08b0759 100644 --- a/src/main/store/app-store.js +++ b/src/main/store/app-store.js @@ -45,17 +45,21 @@ export class AppStore extends EventEmitter { /* * [{ * path:, + * startIndex , * files:[{ * name: * mode: * size: * modification: + * } ...] * }, * {...} * ] */ localFiles: [], remoteFiles: [], + // boolean has more remote files + isMoreRemoteFiles: false, // String current local directory path localCurDir: os.homedir(), // String currnent remote direcotry path @@ -157,11 +161,12 @@ export class AppStore extends EventEmitter { this.state.isFetchingRemoteFileList = isFetchingRemoteFileList; this.emit(AppEvent.CHANGE_FLASHAIR, this.state); } - _requestFlashAirFileListOnStart({isFetchingRemoteFileList, flashairId, remoteCurDir}) { + _requestFlashAirFileListOnStart({isFetchingRemoteFileList, flashairId, remoteCurDir, isMoreRemoteFiles}) { this.state.isFetchingRemoteFileList = isFetchingRemoteFileList; this.state.flashairId = flashairId; this.state.remoteCurDir = remoteCurDir; this.state.curJobResponderId = null; + this.state.isMoreRemoteFiles = isMoreRemoteFiles; this.emit(AppEvent.REQUEST_REMOTE_FILE_LIST, this.state); } _requestFlashAirFileListOnSuccess({isFetchingRemoteFileList, curJobResponderId}) { @@ -198,9 +203,10 @@ export class AppStore extends EventEmitter { this.state.message = message; this.emit(AppEvent.DELETE_REMOTE_JOB_FAILURE); } - _updateRemoteFileList({remoteFiles, isFetchingRemoteFileList}) { + _updateRemoteFileList({remoteFiles, isFetchingRemoteFileList, isMoreRemoteFiles}) { this.state.isFetchingRemoteFileList = isFetchingRemoteFileList; this.state.remoteFiles = remoteFiles; + this.state.isMoreRemoteFiles = isMoreRemoteFiles; this.emit(AppEvent.UPDATE_REMOTE_FILE_LIST, this.state); } _getLocalFileListOnStart({isGetingLocalFileList}) { diff --git a/src/renderer/action/iothub-action.js b/src/renderer/action/iothub-action.js index 5216e3a..ea1a1a1 100644 --- a/src/renderer/action/iothub-action.js +++ b/src/renderer/action/iothub-action.js @@ -107,18 +107,20 @@ export class IoTHubAction { isFetchingRemoteFileList: false }); } - requestRemoteFileList(state = {accessToken, isFetchingRemoteFileList, flashairId, remoteCurDir}, useCache = false) { + requestRemoteFileList(state = {accessToken, isFetchingRemoteFileList, flashairId, remoteCurDir, isMoreRemoteFiles}, useCache = false, startIndex = 0) { if (state.isFetchingRemoteFileList || !state.flashairId) { return Promise.resolve(); } - return this._requestRemoteFileList(state, useCache); + return this._requestRemoteFileList(state, useCache, startIndex); } - _requestRemoteFileList(state = {accessToken, isFetchingRemoteFileList, flashairId, remoteCurDir}, useCache = false) { + _requestRemoteFileList(state = {accessToken, isFetchingRemoteFileList, flashairId, remoteCurDir, isMoreRemoteFiles}, useCache, startIndex) { // Notify fetch start event this.dispatcher.emit(AppEvent.REQUEST_REMOTE_FILE_LIST, { isFetchingRemoteFileList: true, flashairId: state.flashairId, - remoteCurDir: state.remoteCurDir + remoteCurDir: state.remoteCurDir, + remoteFileStartIndex: startIndex || 0, + isMoreRemoteFiles: state.isMoreRemoteFiles }); const requestBody = { request: { @@ -127,6 +129,9 @@ export class IoTHubAction { arguments: {current_path: state.remoteCurDir || '/'} } }; + if (startIndex !== undefined) { + requestBody.request.arguments.start_index = Number(startIndex); + } return fetch(`${IoTHubApi.baseUrl}${IoTHubApi.jobs.replace('{flashair_id}', state.flashairId)}`, { method: 'POST', headers: { @@ -251,10 +256,11 @@ export class IoTHubAction { }); }); } - updateFiles(state = {remoteFiles}) { + updateFiles(state = {remoteFiles, isMoreRemoteFiles}) { this.dispatcher.emit(AppEvent.UPDATE_REMOTE_FILE_LIST, { remoteFiles: state.remoteFiles, - isFetchingRemoteFileList: false + isFetchingRemoteFileList: false, + isMoreRemoteFiles: state.isMoreRemoteFiles }); } selectRemoteFile(fileName) { diff --git a/src/renderer/view/filer.js b/src/renderer/view/filer.js index 09872bb..1e42cf0 100644 --- a/src/renderer/view/filer.js +++ b/src/renderer/view/filer.js @@ -250,6 +250,8 @@ export class FilerPage { if (tmpRemoteFiles && tmpRemoteFiles.files) { templateVar.remoteFiles = tmpRemoteFiles.files; } + // Set fetch more files start index + templateVar.remoteStartIndex = tmpRemoteFiles.startIndex; } this._templateAddFileFlag(templateVar); const renderContent = filerTemplate(templateVar || this.baseTemplateVar); @@ -350,6 +352,10 @@ export class FilerPage { $('#remote-reload').on('click', this.refreshRemoteDirectory); $('#local-reload').on('click', this.refreshLocalDirectory); $('#download-button').on('click', this.onClickDownload); + $('#remote-file-row-more-item').on('click', (event) => { + const startIndex = $(event.currentTarget).attr('data-start-index'); + this.onClickMoreRemoteFiles(startIndex); + }); // Show FlashAir file loading if (templateVar.isFetchingFlashairs || templateVar.isFetchingRemoteFileList) { @@ -411,7 +417,11 @@ export class FilerPage { } changeRemoteDirecory(remoteNextDir, useCache) { this.iotHubAction.requestRemoteFileList(Object.assign( - appMain.store.getState(), {remoteCurDir: remoteNextDir, selectedRemoteFile: null} + appMain.store.getState(), { + remoteCurDir: remoteNextDir, + selectedRemoteFile: null, + isMoreRemoteFiles: false + } ,useCache) ) .catch(response => { @@ -480,6 +490,15 @@ export class FilerPage { } }); } + onClickMoreRemoteFiles(startIndex) { + this.iotHubAction.requestRemoteFileList(appMain.store.getState(), true, startIndex) + .catch(response => { + log.error(response); + if (response) { + this.notifyMessage('danger', resources[this.locale].common_msg_process_failure); + } + }); + } watchRequestJob() { const curState = appMain.store.getState(); this.iotHubAction.getJobs(curState) @@ -533,6 +552,31 @@ export class FilerPage { } } } + _comparetorFiles(a, b) { + // sort by mode(directory or file) + // directory than file + if (a.m < b.m) { + return -1; + } else if (b.m < a.m) { + return 1; + } + // sort by name + if (a.n.hasOwnProperty('localeCompare')) { + const nameCmp = a.n.localeCompare(b.n); + if (nameCmp !== 0) { + // ASC sort + return nameCmp; + } + } + // ASC sort + if (a.n < b.n) { + return -1; + } else if (b.n < a.n) { + return 1; + } + // sort by timestamp + return a.u - b.u; + } _fetchRemoteFileList(job) { const curState = appMain.store.getState(); if ((job.response) @@ -542,31 +586,14 @@ export class FilerPage { let fetchedDir = curRemoteFiles.filter(dir => { return dir.path !== job.request.arguments.current_path; }); - job.response.result.sort((a, b) => { - // sort by mode(directory or file) - // directory than file - if (a.m < b.m) { - return -1; - } else if (b.m < a.m) { - return 1; - } - // sort by name - if (a.n.hasOwnProperty('localeCompare')) { - const nameCmp = a.n.localeCompare(b.n); - if (nameCmp !== 0) { - // ASC sort - return nameCmp; - } - } - // ASC sort - if (a.n < b.n) { - return -1; - } else if (b.n < a.n) { - return 1; - } - // sort by timestamp - return a.u - b.u; + let prevDir = curRemoteFiles.filter(dir => { + return dir.path === job.request.arguments.current_path; }); + if (prevDir.length > 0) { + prevDir = prevDir[0]; + } else { + prevDir = null; + } job.response.result.forEach((file, index, array) => { // Mapping shot protperty to regureler property array[index].name = file.n; @@ -574,17 +601,44 @@ export class FilerPage { // formatting modification timestamp array[index].modification = dateFormat.format(fatDateToDate(file.u), 'yyyy/MM/dd'); }); + + let nextFiles = job.response.result; + let isMoreFiles = false; + // Cut fetch size + if (nextFiles.length > FlashAIrScript.LIST_FETCH_MAX) { + nextFiles = nextFiles.slice(0, FlashAIrScript.LIST_FETCH_MAX); + isMoreFiles = true; + } + // Add previous directory items + if (prevDir && prevDir.startIndex > 0) { + nextFiles = prevDir.files.concat(nextFiles); + // Remove parent directory item + nextFiles.shift(); + // Merge and Uniq + const newFileMap = new Map(); + nextFiles.forEach(file => newFileMap.set(file.name, file)); + nextFiles.length = 0; + for (let file of newFileMap.values()) { + nextFiles.push(file); + } + } + let remoteFileStartIndex = nextFiles.length; + nextFiles.sort(this._comparetorFiles); // Add move parent directory item - job.response.result.unshift({ + nextFiles.unshift({ name: Filer.files.special.PARENT_DIR, mode: Filer.files.mode.DIRECTORY, modification: '' }); fetchedDir = fetchedDir.concat([{ path: job.request.arguments.current_path, - files: job.response.result + startIndex: remoteFileStartIndex, + files: nextFiles }]); - this.iotHubAction.updateFiles({remoteFiles: fetchedDir}); + this.iotHubAction.updateFiles({ + remoteFiles: fetchedDir, + isMoreRemoteFiles: isMoreFiles + }); this.iotHubAction.deleteJob(curState, job) .catch(message => { log.error(message); diff --git a/src/renderer/view/filer_tmpl.hbs b/src/renderer/view/filer_tmpl.hbs index 0e4860c..02e6c13 100644 --- a/src/renderer/view/filer_tmpl.hbs +++ b/src/renderer/view/filer_tmpl.hbs @@ -36,6 +36,11 @@ {{modification}} {{/each}} + {{#if isMoreRemoteFiles}} + + {{filer_label_remote_show_more}} + + {{/if}} diff --git a/static/css/file-manager.css b/static/css/file-manager.css index 12fb8df..c1f390d 100644 --- a/static/css/file-manager.css +++ b/static/css/file-manager.css @@ -20,9 +20,13 @@ } .remote-files td:nth-child(2), .local-files td:nth-child(2) { - text-overflow:ellipsis; - overflow:hidden; - white-space:nowrap; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} +.remote-files .more-item { + cursor: pointer; + text-align: center; } .fa-dir-button {