fix #298: support cloud storages in iOS homescreen apps

This commit is contained in:
antelle 2017-04-16 18:05:58 +02:00
parent 312545cf08
commit 85d4f9797d
6 changed files with 46 additions and 19 deletions

View File

@ -15,14 +15,15 @@ const ExportApi = require('./comp/export-api');
const SettingsManager = require('./comp/settings-manager'); const SettingsManager = require('./comp/settings-manager');
const PluginManager = require('./plugins/plugin-manager'); const PluginManager = require('./plugins/plugin-manager');
const Launcher = require('./comp/launcher'); const Launcher = require('./comp/launcher');
const FeatureDetector = require('./util/feature-detector');
const KdbxwebInit = require('./util/kdbxweb-init'); const KdbxwebInit = require('./util/kdbxweb-init');
const Locale = require('./util/locale'); const Locale = require('./util/locale');
const ready = Launcher && Launcher.ready || $; const ready = Launcher && Launcher.ready || $;
ready(() => { ready(() => {
if (isPopup()) { if (FeatureDetector.isPopup && AuthReceiver.receive()) {
return AuthReceiver.receive(); return;
} }
loadMixins(); loadMixins();
@ -34,10 +35,6 @@ ready(() => {
.then(loadRemoteConfig) .then(loadRemoteConfig)
.then(showApp); .then(showApp);
function isPopup() {
return (window.parent !== window.top) || window.opener;
}
function loadMixins() { function loadMixins() {
require('./mixins/view'); require('./mixins/view');
require('./helpers'); require('./helpers');

View File

@ -1,9 +1,18 @@
const FeatureDetector = require('../util/feature-detector');
const Storage = require('../storage');
const AuthReceiver = { const AuthReceiver = {
receive: function() { receive: function() {
const opener = window.opener || window.parent; const opener = window.opener || window.parent;
const message = this.urlArgsToMessage(window.location.href); const message = this.urlArgsToMessage(window.location.href);
opener.postMessage(message, window.location.origin); if (FeatureDetector.isStandalone) {
window.close(); Storage[sessionStorage.authStorage].handleOAuthReturnMessage(message);
return false;
} else {
opener.postMessage(message, window.location.origin);
window.close();
return true;
}
}, },
urlArgsToMessage: function(url) { urlArgsToMessage: function(url) {

View File

@ -3,6 +3,7 @@ const Logger = require('../util/logger');
const AppSettingsModel = require('../models/app-settings-model'); const AppSettingsModel = require('../models/app-settings-model');
const RuntimeDataModel = require('../models/runtime-data-model'); const RuntimeDataModel = require('../models/runtime-data-model');
const Links = require('../const/links'); const Links = require('../const/links');
const FeatureDetector = require('../util/feature-detector');
const MaxRequestRetries = 3; const MaxRequestRetries = 3;
@ -32,6 +33,12 @@ _.extend(StorageBase.prototype, {
} }
} }
this.logger = new Logger('storage-' + this.name); this.logger = new Logger('storage-' + this.name);
if (this._oauthReturnMessage) {
this.logger.debug('OAuth return message', this._oauthReturnMessage);
this._oauthProcessReturn(this._oauthReturnMessage, _.noop);
delete this._oauthReturnMessage;
delete sessionStorage.authStorage;
}
return this; return this;
}, },
@ -39,6 +46,10 @@ _.extend(StorageBase.prototype, {
this.enabled = enabled; this.enabled = enabled;
}, },
handleOAuthReturnMessage(message) {
this._oauthReturnMessage = message;
},
_xhr: function(config) { _xhr: function(config) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
if (config.responseType) { if (config.responseType) {
@ -104,6 +115,9 @@ _.extend(StorageBase.prototype, {
location: 'yes' location: 'yes'
}; };
settings = Object.keys(settings).map(key => key + '=' + settings[key]).join(','); settings = Object.keys(settings).map(key => key + '=' + settings[key]).join(',');
if (FeatureDetector.isStandalone) {
sessionStorage.authStorage = this.name;
}
return window.open(url, title, settings); return window.open(url, title, settings);
}, },
@ -147,21 +161,25 @@ _.extend(StorageBase.prototype, {
} }
Backbone.off('popup-closed', popupClosed); Backbone.off('popup-closed', popupClosed);
window.removeEventListener('message', windowMessage); window.removeEventListener('message', windowMessage);
const token = this._oauthMsgToToken(e.data); this._oauthProcessReturn(e.data, callback);
if (token.error) {
this.logger.error('OAuth error', token.error, token.errorDescription);
callback(token.error);
} else {
this._oauthToken = token;
this.runtimeData.set(this.name + 'OAuthToken', token);
this.logger.debug('OAuth token received');
callback();
}
}; };
Backbone.on('popup-closed', popupClosed); Backbone.on('popup-closed', popupClosed);
window.addEventListener('message', windowMessage); window.addEventListener('message', windowMessage);
}, },
_oauthProcessReturn: function(message, callback) {
const token = this._oauthMsgToToken(message);
if (token.error) {
this.logger.error('OAuth error', token.error, token.errorDescription);
callback(token.error);
} else {
this._oauthToken = token;
this.runtimeData.set(this.name + 'OAuthToken', token);
this.logger.debug('OAuth token received');
callback();
}
},
_oauthMsgToToken: function(data) { _oauthMsgToToken: function(data) {
if (data.error || !data.token_type) { if (data.error || !data.token_type) {
return { error: data.error || 'no token', errorDescription: data.error_description }; return { error: data.error || 'no token', errorDescription: data.error_description };

View File

@ -6,7 +6,8 @@ const FeatureDetector = {
isWindows: navigator.platform.indexOf('Win') >= 0, isWindows: navigator.platform.indexOf('Win') >= 0,
isiOS: /iPad|iPhone|iPod/i.test(navigator.userAgent), isiOS: /iPad|iPhone|iPod/i.test(navigator.userAgent),
isMobile: MobileRegex.test(navigator.userAgent) || screen.width < MinDesktopScreenWidth, isMobile: MobileRegex.test(navigator.userAgent) || screen.width < MinDesktopScreenWidth,
isPopup: !!((window.parent !== window.top) || window.opener),
isStandalone: !!(navigator.standalone || window.matchMedia('(display-mode: standalone)').matches),
isBeta: window.location.href.toLowerCase().indexOf('beta.') > 0, isBeta: window.location.href.toLowerCase().indexOf('beta.') > 0,
actionShortcutSymbol: function(formatting) { actionShortcutSymbol: function(formatting) {

View File

@ -137,6 +137,7 @@
&__logs { &__logs {
@include user-select(text); @include user-select(text);
margin-top: $base-padding-v; margin-top: $base-padding-v;
word-break: break-all;
&-log { &-log {
margin: 0; margin: 0;
white-space: pre-wrap; white-space: pre-wrap;

View File

@ -4,6 +4,7 @@ Release notes
`+` plugins `+` plugins
`*` translations are available only as plugins `*` translations are available only as plugins
`*` Dropbox API V2 `*` Dropbox API V2
`+` support cloud providers in iOS homescreen apps
`+` mobile field editing improvements `+` mobile field editing improvements
`+` file path hint in recent files list `+` file path hint in recent files list
`+` cacheConfigSettings config option `+` cacheConfigSettings config option