added fingerprint hooks

This commit is contained in:
Alex Shpak 2017-02-05 22:01:46 +01:00
parent 0820394e50
commit 159d08d6c2
6 changed files with 320 additions and 6 deletions

View File

@ -0,0 +1,194 @@
'use strict';
const Alerts = require('../comp/alerts');
// const Locale = require('../util/locale');
const Launcher = {
name: 'android',
version: '6.0.0',
autoTypeSupported: false,
ready: function(callback) {
document.addEventListener('deviceready', () => {
callback();
// window.addEventListener('filePluginIsReady', () => {}, false);
}, false);
},
platform: function() {
return 'cordova';
},
openLink: function(href) {
window.open(href, '_system');
},
getSaveFileName: function(defaultPath, callback) {
if (defaultPath) {
defaultPath = [this.externalRoot, defaultPath].join('/');
Alerts.yesno({
header: 'Save file',
body: defaultPath,
success: () => {
callback(defaultPath);
}
});
}
},
getDir: function() {
const storagePath = window.cordova.file.externalDataDirectory;
return [storagePath].concat(Array.from(arguments)).filter(s => !!s);
},
getUserDataPath: function(fileName) {
return this.getDir('userdata', fileName).join('/');
},
getTempPath: function(fileName) {
return this.getDir('temp', fileName).join('/');
},
getDocumentsPath: function(fileName) {
return this.getDir('documents', fileName).join('/');
},
getAppPath: function(fileName) {
return this.getDir(fileName).join('/');
},
getWorkDirPath: function(fileName) {
return this.getDir(fileName).join('/');
},
writeFile: function(path, data, callback) {
const writeFile = fileEntry => {
fileEntry.createWriter(fileWriter => {
fileWriter.onerror = callback;
fileWriter.onwriteend = () => callback();
fileWriter.write(data);
}, callback);
};
const createDir = (dirEntry, path, callback) => {
const name = path.shift();
dirEntry.getDirectory(name, { create: true }, dirEntry => {
if (path.length) { // there is more to create
createDir(dirEntry, path, callback);
} else {
callback(dirEntry);
}
}, callback);
};
if (path.startsWith(this.appStorage)) { // file://
const localPath = path.replace(this.appStorage, '').split('/').filter(s => !!s);
const fileName = localPath.pop();
if (localPath.length) {
window.resolveLocalFileSystemURL(this.appStorage, dirEntry => {
createDir(dirEntry, localPath, destDir => {
destDir.getFile(fileName, { create: true }, writeFile, callback, callback);
});
}, callback);
} else {
window.resolveLocalFileSystemURL(path, writeFile, callback, callback);
}
} else { // cdvfile://
window.resolveLocalFileSystemURL(path, writeFile, callback, callback);
}
},
readFile: function(path, encoding, callback) {
window.resolveLocalFileSystemURL(path, fileEntry => {
fileEntry.file(file => {
const reader = new FileReader();
reader.onerror = callback;
reader.onloadend = () => {
const contents = new Uint8Array(reader.result);
callback(encoding ? String.fromCharCode.apply(null, contents) : contents);
};
reader.readAsArrayBuffer(file);
}, err => callback(undefined, err));
}, err => callback(undefined, err));
},
fileExists: function(path, callback) {
window.resolveLocalFileSystemURL(path, fileEntry => callback(true), err => callback(false)); // eslint-disable-line handle-callback-err
},
deleteFile: function(path, callback) {
window.resolveLocalFileSystemURL(path, fileEntry => {
fileEntry.remove(callback, callback, callback);
}, callback);
},
statFile: function(path, callback) {
window.resolveLocalFileSystemURL(path, fileEntry => {
fileEntry.file(file => {
callback({
ctime: new Date(file.lastModified),
mtime: new Date(file.lastModified)
});
}, err => callback(undefined, err));
}, err => callback(undefined, err));
},
mkdir: function(dir) {
// TODO
},
parsePath: function(fileName) {
const parts = fileName.split('/');
return {
path: fileName,
dir: parts.pop(),
file: parts.join('/')
};
},
createFsWatcher: function(path) {
return null; // not in android with content provider
},
preventExit: function(e) {
e.returnValue = false;
return false;
},
exit: function() {
// skip
},
requestRestart: function() {
window.location.reload();
},
cancelRestart: function() {
// skip
},
setClipboardText: function(text) {
return document.execCommand('copy');
},
getClipboardText: function() {
// TODO
},
clearClipboardText: function() {
// TODO
},
minimizeApp: function() {
this.hideApp();
},
canMinimize: function() {
return true;
},
updaterEnabled: function() {
return false;
},
resolveProxy: function(url, callback) {
// TODO
},
openWindow: function(opts) {
// skip
},
hideApp: function() { // home button
// TODO
},
isAppFocused: function() {
return false; // skip
},
showMainWindow: function() {
// skip
},
fingerprints: {
register: function(appModel, fileInfo, password) {
},
auth: function(fileInfo, callback) {
}
}
};
module.exports = Launcher;

View File

@ -3,7 +3,7 @@ let Launcher;
if (window.process && window.process.versions && window.process.versions.electron) {
Launcher = require('./launcher-electron');
} else if (window.cordova) {
// Launcher = require('./launcher-cordova');
Launcher = require('./launcher-cordova');
}
module.exports = Launcher;

View File

@ -16,6 +16,7 @@ const FeatureDetector = require('../util/feature-detector');
const Format = require('../util/format');
const UrlUtil = require('../util/url-util');
const AutoType = require('../auto-type');
const Launcher = require('../comp/launcher');
require('../mixins/protected-value-ex');
@ -489,7 +490,7 @@ const AppModel = Backbone.Model.extend({
}
const rev = params.rev || fileInfo && fileInfo.get('rev');
this.setFileOpts(file, params.opts);
this.addToLastOpenFiles(file, rev);
this.addToLastOpenFiles(file, fileInfo, params.password, rev);
this.addFile(file);
callback(null, file);
this.fileOpened(file, data);
@ -515,7 +516,7 @@ const AppModel = Backbone.Model.extend({
});
},
addToLastOpenFiles: function(file, rev) {
addToLastOpenFiles: function(file, existing, password, rev) {
this.appLogger.debug('Add last open file', file.id, file.get('name'), file.get('storage'), file.get('path'), rev);
const dt = new Date();
const fileInfo = new FileInfoModel({
@ -529,7 +530,8 @@ const AppModel = Backbone.Model.extend({
rev: rev,
syncDate: file.get('syncDate') || dt,
openDate: dt,
backup: file.get('backup')
backup: file.get('backup'),
fingerprint: existing && existing.get('fingerprint')
});
switch (this.settings.get('rememberKeyFiles')) {
case 'data':
@ -547,6 +549,10 @@ const AppModel = Backbone.Model.extend({
this.fileInfos.remove(file.id);
this.fileInfos.unshift(fileInfo);
this.fileInfos.save();
if (Launcher.fingerprints && !existing) {
Launcher.fingerprints.register(this, fileInfo, password);
}
},
getStoreOpts: function(file) {

View File

@ -14,7 +14,8 @@ const FileInfoModel = Backbone.Model.extend({
keyFileName: null,
keyFileHash: null,
opts: null,
backup: null
backup: null,
fingerprint: null
},
initialize: function(data, options) {

View File

@ -11,10 +11,12 @@ const Locale = require('../util/locale');
const UrlUtil = require('../util/url-util');
const InputFx = require('../util/input-fx');
const Storage = require('../storage');
const Launcher = require('../comp/launcher');
const logger = new Logger('open-view');
const OpenView = Backbone.View.extend({
template: require('templates/open.hbs'),
events: {
@ -317,7 +319,12 @@ const OpenView = Backbone.View.extend({
openAny: function(reading, ext) {
this.reading = reading;
this.params[reading] = null;
this.$el.find('.open__file-ctrl').attr('accept', ext || '').val(null).click();
if (Launcher && Launcher.openFileChooser) {
Launcher.openFileChooser(this);
} else {
this.$el.find('.open__file-ctrl').attr('accept', ext || '').val(null).click();
}
},
openLast: function(e) {
@ -344,6 +351,16 @@ const OpenView = Backbone.View.extend({
this.removeFile(id);
return;
}
if (Launcher && Launcher.fingerprints) {
const fileInfo = this.model.fileInfos.get(id);
Launcher.fingerprints.auth(fileInfo, password => {
this.inputEl.val(password);
this.inputEl.trigger('input');
this.openDb();
});
}
this.showOpenFileInfo(this.model.fileInfos.get(id));
},

View File

@ -35,3 +35,99 @@
@import "areas/menu";
@import "areas/open";
@import "areas/settings";
@include mobile {
.app {
&__menu {
position: absolute;
top: 4em;
bottom: 0;
width: 75%;
z-index: 1;
box-shadow: 0 0.1em 0.5em rgba(0, 0, 0, 0.5);
&-drag {
display: none !important;
}
@include th {
background: background-color();
}
@include mobile {
transition: .3s ease-in-out;
left: 0;
&:not(.menu-visible) {
transform: translate(-100%, 0);
display: flex;
}
}
}
}
.list {
&__search {
box-shadow: 0 0 .5em rgba(0, 0, 0, 0.5);
&-icon-search {
@include th {
color: text-color();
}
}
&-btn-menu {
background: transparent !important;
}
&-adv {
padding: 1em .6em 0em .6em;
&-text {
font-weight: 600;
font-size: 0.9em;
margin-top: 1em;
}
}
&-check {
padding: .3em 0;
label {
margin: 0;
font-weight: 400;
}
}
input {
@include th {
margin: 0;
border: 0;
box-shadow: 0 0 0 !important;
border-bottom: 1px solid action-color();
}
}
}
&__items .scroller {
:first-child {
margin-top: .5em;
}
:last-child {
margin-bottom: .5em;
}
}
&__item {
padding: .5em 1.5em;
}
}
.menu {
&__item-body {
padding: 1em;
line-height: 1;
}
}
}