From 1dccda5e2a66c71cb317f757012092e9aa246e45 Mon Sep 17 00:00:00 2001 From: hzsunshx Date: Tue, 22 Sep 2015 17:16:46 +0800 Subject: [PATCH] add filesystem(file explorer) support, done --- lib/units/device/plugins/filesystem.js | 80 ++++--------------- lib/units/websocket/index.js | 10 +++ lib/wire/wire.proto | 11 --- .../components/stf/control/control-service.js | 6 ++ .../control-panes/control-panes-controller.js | 6 ++ .../control-panes/filesystem/fs-controller.js | 50 ++++++++++++ res/app/control-panes/filesystem/fs-spec.js | 17 ++++ res/app/control-panes/filesystem/fs.jade | 30 +++++++ res/app/control-panes/filesystem/fs.less | 0 res/app/control-panes/filesystem/index.js | 37 +++++++++ res/app/control-panes/index.js | 1 + 11 files changed, 174 insertions(+), 74 deletions(-) create mode 100644 res/app/control-panes/filesystem/fs-controller.js create mode 100644 res/app/control-panes/filesystem/fs-spec.js create mode 100644 res/app/control-panes/filesystem/fs.jade create mode 100644 res/app/control-panes/filesystem/fs.less create mode 100644 res/app/control-panes/filesystem/index.js diff --git a/lib/units/device/plugins/filesystem.js b/lib/units/device/plugins/filesystem.js index fc2fb990..16060a55 100644 --- a/lib/units/device/plugins/filesystem.js +++ b/lib/units/device/plugins/filesystem.js @@ -65,68 +65,22 @@ module.exports = syrup.serial() }) }) + router.on(wire.FileSystemListMessage, function(channel, message){ + var reply = wireutil.reply(options.serial) + adb.readdir(options.serial, message.dir) + .then(function(files){ + push.send([ + channel, + reply.okay('success', files) + ]) + }) + .catch(function(err){ + log.error('Dir list %s failed\n%s', message.dir, err.stack) + push.send([ + channel, + reply.fail(err.message) + ]) + }) + }) return plugin; - - - - // function projectionFormat() { - // return util.format( - // '%dx%d@%dx%d/%d' - // , display.properties.width - // , display.properties.height - // , display.properties.width - // , display.properties.height - // , display.properties.rotation - // ) - // } - - // plugin.capture = function() { - // log.info('Capturing screenshot') - - // var file = util.format('/data/local/tmp/minicap_%d.jpg', Date.now()) - // return minicap.run(util.format( - // '-P %s -s >%s', projectionFormat(), file)) - // .then(adbkit.util.readAll) - // .then(function() { - // return adb.stat(options.serial, file) - // }) - // .then(function(stats) { - // if (stats.size === 0) { - // throw new Error('Empty screenshot; possibly secure screen?') - // } - - // return adb.pull(options.serial, file) - // .then(function(transfer) { - // return storage.store('image', transfer, { - // filename: util.format('%s.jpg', options.serial) - // , contentType: 'image/jpeg' - // , knownLength: stats.size - // }) - // }) - // }) - // .finally(function() { - // return adb.shell(options.serial, ['rm', '-f', file]) - // .then(adbkit.util.readAll) - // }) - // } - - // router.on(wire.ScreenCaptureMessage, function(channel) { - // var reply = wireutil.reply(options.serial) - // plugin.capture() - // .then(function(file) { - // push.send([ - // channel - // , reply.okay('success', file) - // ]) - // }) - // .catch(function(err) { - // log.error('Screen capture failed', err.stack) - // push.send([ - // channel - // , reply.fail(err.message) - // ]) - // }) - // }) - - // return plugin }) diff --git a/lib/units/websocket/index.js b/lib/units/websocket/index.js index cd6b980e..7aeccb79 100644 --- a/lib/units/websocket/index.js +++ b/lib/units/websocket/index.js @@ -836,6 +836,16 @@ module.exports = function(options) { ) ]) }) + .on('fs.list', function(channel, responseChannel, data){ + joinChannel(responseChannel) + push.send([ + channel + , wireutil.transaction( + responseChannel + , new wire.FileSystemListMessage(data) + ) + ]) + }) }) .finally(function() { // Clean up all listeners and subscriptions diff --git a/lib/wire/wire.proto b/lib/wire/wire.proto index 2af27426..50793ec2 100644 --- a/lib/wire/wire.proto +++ b/lib/wire/wire.proto @@ -72,23 +72,12 @@ enum MessageType { AccountRemoveMessage = 55; SdStatusMessage = 61; ReverseForwardsEvent = 72; - FileSystemListEvent = 80; FileSystemListMessage = 81; FileSystemGetMessage = 82; } -message FileSystemListEvent { - required string serial = 1; - required string dir = 2; -} message FileSystemListMessage { required string dir = 1; - repeated FileSystemProperty files = 2; -} - -message FileSystemProperty { - required string name = 1; - required string mod = 2; } message FileSystemGetMessage { diff --git a/res/app/components/stf/control/control-service.js b/res/app/components/stf/control/control-service.js index 0a7642a3..5db6b015 100644 --- a/res/app/components/stf/control/control-service.js +++ b/res/app/components/stf/control/control-service.js @@ -231,6 +231,12 @@ module.exports = function ControlServiceFactory( }) } + this.fslist = function(dir){ + return sendTwoWay('fs.list', { + dir: dir, + }) + } + this.checkAccount = function(type, account) { return sendTwoWay('account.check', { type: type diff --git a/res/app/control-panes/control-panes-controller.js b/res/app/control-panes/control-panes-controller.js index faf503da..924c1fd9 100644 --- a/res/app/control-panes/control-panes-controller.js +++ b/res/app/control-panes/control-panes-controller.js @@ -22,6 +22,12 @@ module.exports = templateUrl: 'control-panes/advanced/advanced.jade', filters: ['native', 'web'] }, + { + title: gettext('FileSystem'), + icon: 'fa-info color-orange', + templateUrl: 'control-panes/filesystem/fs.jade', + filters: ['native', 'web'] + }, { title: gettext('Info'), icon: 'fa-info color-orange', diff --git a/res/app/control-panes/filesystem/fs-controller.js b/res/app/control-panes/filesystem/fs-controller.js new file mode 100644 index 00000000..4e67c63b --- /dev/null +++ b/res/app/control-panes/filesystem/fs-controller.js @@ -0,0 +1,50 @@ +module.exports = function FsCtrl($scope, $timeout) { + $scope.search = '' + $scope.files = []; + $scope.paths = []; + + var listdir = function(){ + var path = '/'+$scope.paths.join('/'); + $scope.control.fslist(path) + .then(function(result){ + $scope.files = result.body; + $scope.$digest(); + }) + .catch(function(err){ + alert(err.message); + }) + } + + $scope.dirEnter = function(name){ + if (name){ + $scope.paths.push(name); + } + listdir(); + $scope.search = ''; + } + + $scope.dirJump = function(){ + if ($scope.paths.length !== 0){ + $scope.paths.pop(); + } + listdir(); + } + + $scope.getFile = function(file){ + var path = '/'+$scope.paths.join('/')+'/'+file; + $scope.control.fsretrive(path) + .then(function(result){ + location.href = result.body.href+"?download" + }) + .catch(function(err){ + alert(err.message); + }) + } + + + // init + // $scope.list($scope.dir); // FIXME(ssx): can't call immediately, do not known why. + $timeout(function(){ + listdir(); + }, 800); +} diff --git a/res/app/control-panes/filesystem/fs-spec.js b/res/app/control-panes/filesystem/fs-spec.js new file mode 100644 index 00000000..3cc0d0ae --- /dev/null +++ b/res/app/control-panes/filesystem/fs-spec.js @@ -0,0 +1,17 @@ +describe('FsCtrl', function () { + + beforeEach(angular.mock.module(require('./').name)); + + var scope, ctrl; + + beforeEach(inject(function ($rootScope, $controller) { + scope = $rootScope.$new(); + ctrl = $controller('FsCtrl', {$scope: scope}); + })); + + it('should ...', inject(function () { + expect(1).toEqual(1); + + })); + +}); diff --git a/res/app/control-panes/filesystem/fs.jade b/res/app/control-panes/filesystem/fs.jade new file mode 100644 index 00000000..1a739532 --- /dev/null +++ b/res/app/control-panes/filesystem/fs.jade @@ -0,0 +1,30 @@ +.stf-fs(ng-controller='FsCtrl') + .row: .col-md-6 + + span /{{paths.join("/")}} + button.btn.btn-xm.btn-primary-outline(ng-click='dirJump()') + span(translate) Back + + form.input-group.form-inline(ng-submit='dirEnter(search)') + input(type=text, ng-model='search', placeholder="dir or file ...").form-control + span.input-group-btn + button.btn.btn-default.btn-primary-outline(type='submit') + i.fa.fa-search + span(translate) Enter + + table.table + tr(ng-repeat='f in files | filter:search | orderBy: "-mode|isdir"') + td + span + i.fa.fa-folder-open(ng-show='f.mode|isdir') + i.fa.fa-file-o(ng-hide='f.mode|isdir') + td + button.btn.btn-sm.btn-primary-outline( + ng-click='dirEnter(f.name)', ng-show='f.mode|isdir') + {{f.name}} + button.btn.btn-sm.btn-primary-outline( + ng-click='getFile(f.name)', ng-hide='f.mode|isdir') + {{f.name}} + td + i {{f.mode|mode2unix}} + td {{f.size}} diff --git a/res/app/control-panes/filesystem/fs.less b/res/app/control-panes/filesystem/fs.less new file mode 100644 index 00000000..e69de29b diff --git a/res/app/control-panes/filesystem/index.js b/res/app/control-panes/filesystem/index.js new file mode 100644 index 00000000..40271601 --- /dev/null +++ b/res/app/control-panes/filesystem/index.js @@ -0,0 +1,37 @@ +require('./fs.less') + +module.exports = angular.module('stf.filesystem', []) + .run(["$templateCache", function ($templateCache) { + $templateCache.put('control-panes/filesystem/fs.jade', + require('./fs.jade') + ) + }]) + .filter('mode2unix', function(){ + return function(mode){ + if(mode !== null){ + var res = []; + var s = ['x', 'w', 'r']; + for (var i = 0; i < 3; i++) { + for (var j = 0; j < 3; j++) { + if ((mode >> (i*3+j)) & 1 !== 0){ + res.unshift(s[j]) + } else { + res.unshift('-') + } + } + } + res.unshift(mode & 040000 ? 'd' : '-'); + return res.join(''); + } + } + }) + .filter('isdir', function(){ + return function(mode){ + if(mode !== null){ + mode = parseInt(mode, 10) + mode = mode - (mode & 0777); + return (mode == 040000) || (mode == 0120000); + } + } + }) + .controller('FsCtrl', require('./fs-controller')) diff --git a/res/app/control-panes/index.js b/res/app/control-panes/index.js index b802d6e7..bd901545 100644 --- a/res/app/control-panes/index.js +++ b/res/app/control-panes/index.js @@ -13,6 +13,7 @@ module.exports = angular.module('control-panes', [ require('./logs').name, //require('./resources').name, require('./screenshots').name, + require('./filesystem').name, require('./info').name ]) .config(['$routeProvider', function ($routeProvider) {