Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
82
gaia/shared/pages/import/curtain.html
Executable file
82
gaia/shared/pages/import/curtain.html
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
|
||||
<title>Facebook</title>
|
||||
|
||||
<!-- Building Blocks -->
|
||||
<link href="/shared/style/headers.css" rel="stylesheet">
|
||||
<link href="/shared/style/confirm.css" rel="stylesheet">
|
||||
<link href="/shared/style/progress_activity.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/root.css">
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/curtain.css">
|
||||
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="en-US">
|
||||
<link rel="localization" href="/shared/locales/import_contacts/import_contacts.{locale}.properties">
|
||||
<script type="text/javascript" src="/shared/js/l10n.js"></script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<section id="curtain">
|
||||
<form role="dialog" data-type="confirm">
|
||||
|
||||
<!-- Progress activity card -->
|
||||
<section id="progress">
|
||||
<h1 id="progressTitle"></h1>
|
||||
<p role="status">
|
||||
<span id="progressMsg"></span>
|
||||
<progress id="progressElement" class="pack-activity" value="0" max="100"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Message card -->
|
||||
<section id="message">
|
||||
<h1 id="messageMsg"></h1>
|
||||
<p role="status">
|
||||
<span></span>
|
||||
<progress class="pack-activity" max="100" value="0"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Waiting card -->
|
||||
<section id="wait">
|
||||
<h1 id="waitMsg" data-l10n-id="wait1">Please wait</h1>
|
||||
<p role="status">
|
||||
<span></span>
|
||||
<progress class="pack-activity" max="100" value="0"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Error card -->
|
||||
<section id="error">
|
||||
<h1 id="errorMsg">Error</h1>
|
||||
<p data-l10n-id="error2">Do you want to retry?</p>
|
||||
</section>
|
||||
|
||||
<!-- Timeout card -->
|
||||
<section id="timeout">
|
||||
<h1 id="timeoutMsg">Exceeded timeout</h1>
|
||||
<p data-l10n-id="timeout2">Do you want to retry?</p>
|
||||
</section>
|
||||
|
||||
<!-- Alert card -->
|
||||
<section id="alert">
|
||||
<h1 id="alertMsg"></h1>
|
||||
<p> </p>
|
||||
</section>
|
||||
|
||||
<menu>
|
||||
<button data-l10n-id="curtainCancel" id="cancel">Cancel</button>
|
||||
<button data-l10n-id="curtainRetry" id="retry" class="recommend">Retry</button>
|
||||
<button data-l10n-id="curtainOK" id="ok" class="recommend">OK</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
57
gaia/shared/pages/import/elements/curtain.html
Executable file
57
gaia/shared/pages/import/elements/curtain.html
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
<element name="curtain" extends="section">
|
||||
<template>
|
||||
<form role="dialog" data-type="confirm">
|
||||
<!-- Progress activity card -->
|
||||
<section id="progress">
|
||||
<h1 id="progressTitle"></h1>
|
||||
<p role="status">
|
||||
<span id="progressMsg"></span>
|
||||
<progress id="progressElement" class="pack-activity" value="0" max="100"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Message card -->
|
||||
<section id="message">
|
||||
<h1 id="messageMsg"></h1>
|
||||
<p role="status">
|
||||
<span></span>
|
||||
<progress class="pack-activity" max="100" value="0"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Waiting card -->
|
||||
<section id="wait">
|
||||
<h1 id="waitMsg" data-l10n-id="wait1">Please wait</h1>
|
||||
<p role="status">
|
||||
<span></span>
|
||||
<progress class="pack-activity" max="100" value="0"></progress>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Error card -->
|
||||
<section id="error">
|
||||
<h1 id="errorMsg">Error</h1>
|
||||
<p data-l10n-id="error2">Do you want to retry?</p>
|
||||
</section>
|
||||
|
||||
<!-- Timeout card -->
|
||||
<section id="timeout">
|
||||
<h1 id="timeoutMsg">Exceeded timeout</h1>
|
||||
<p data-l10n-id="timeout2">Do you want to retry?</p>
|
||||
</section>
|
||||
|
||||
<!-- Alert card -->
|
||||
<section id="alert">
|
||||
<h1 id="alertMsg"></h1>
|
||||
<p></p>
|
||||
</section>
|
||||
|
||||
<menu>
|
||||
<button data-l10n-id="curtainCancel" id="cancel">Cancel</button>
|
||||
<button data-l10n-id="curtainRetry" id="retry" class="recommend">Retry</button>
|
||||
<button data-l10n-id="curtainOK" id="ok" class="recommend">OK</button>
|
||||
</menu>
|
||||
</form>
|
||||
</template>
|
||||
</element>
|
||||
|
||||
193
gaia/shared/pages/import/import.html
Executable file
193
gaia/shared/pages/import/import.html
Executable file
|
|
@ -0,0 +1,193 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="en-US">
|
||||
<link rel="localization" href="/shared/locales/import_contacts/import_contacts.{locale}.properties">
|
||||
<script type="text/javascript" src="/shared/js/l10n.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/shared/js/async_storage.js"></script>
|
||||
<script type="text/javascript" src="/shared/js/lazy_loader.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/text_normalizer.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/simple_phone_matcher.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contact_photo_helper.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/shared/pages/import/js/flow.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/oauth20.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/parameters.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/curtain.js"></script>
|
||||
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/contacts_matcher.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/contacts_merger.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/merger_adapter.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/contacts_shortcuts.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/contacts_cleaner.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/image_square.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/image_thumbnail.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/dom.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/http_rest.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/templates.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/event_listeners.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/utilities/image_loader.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/contacts_importer.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/importer_ui.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/import_init.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/import_status_data.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/utilities/misc.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/component_utils.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/elements/gaia_buttons/script.js"></script>
|
||||
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/import/friends_list.js"></script>
|
||||
|
||||
<script defer type="text/javascript" src="/shared/js/utilities.js"></script>
|
||||
<script defer type="text/javascript" src="/shared/js/contacts/search.js"></script>
|
||||
|
||||
<!-- To include these files on the standard app
|
||||
<link href="/shared/js/binary_search.js">
|
||||
<link href="/shared/js/fb/fb_tel_index.js">
|
||||
<link href="/shared/js/fb/fb_request.js">
|
||||
<link href="/shared/js/fb/fb_data_reader.js">
|
||||
|
||||
<link href="/shared/js/contacts/import/gmail/gmail_connector.js">
|
||||
<link href="/shared/js/contacts/import/live/live_connector.js">
|
||||
<link href="/shared/js/contacts/import/facebook/facebook_connector.js">
|
||||
|
||||
<link href="/shared/js/contacts/import/utilities/config.js">
|
||||
<link href="/shared/js/image_utils.js">
|
||||
-->
|
||||
|
||||
<!--
|
||||
<link href="/shared/pages/import/redirects/redirect.html">
|
||||
<link href="/shared/pages/import/redirects/dialogs_end.html">
|
||||
-->
|
||||
|
||||
<!--
|
||||
<link href="/shared/js/contacts/import/facebook/fb_data.js">
|
||||
<link href="/shared/js/contacts/import/facebook/fb_utils.js">
|
||||
<link href="/shared/js/contacts/import/facebook/fb_contact_utils.js">
|
||||
<link href="/shared/js/contacts/import/facebook/fb_query.js">
|
||||
<link href="/shared/js/contacts/import/facebook/fb_contact.js">
|
||||
-->
|
||||
|
||||
<!-- Building Blocks -->
|
||||
<link href="/shared/style/progress_activity.css" rel="stylesheet">
|
||||
<link href="/shared/style/status.css" rel="stylesheet">
|
||||
<link href="/shared/style/headers.css" rel="stylesheet">
|
||||
<link href="/shared/style/input_areas.css" rel="stylesheet">
|
||||
<link href="/shared/style/switches.css" rel="stylesheet">
|
||||
<link href="/shared/style/lists.css" rel="stylesheet">
|
||||
<link href="/shared/style/confirm.css" rel="stylesheet">
|
||||
<link href="/shared/style/scrolling.css" rel="stylesheet">
|
||||
<link href="/shared/style/animations.css" rel="stylesheet">
|
||||
|
||||
<!-- Web Components -->
|
||||
<!-- <link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css" /> -->
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-theme/gaia-theme.css" />
|
||||
<script defer src="/shared/elements/config.js"></script>
|
||||
<script defer src="/shared/elements/gaia-header/dist/gaia-header.js"></script>
|
||||
|
||||
<!--
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/root.css">
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/facebook.css">
|
||||
-->
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/import.css">
|
||||
<link rel="stylesheet" href="/shared/pages/import/style/search.css">
|
||||
</head>
|
||||
|
||||
<body role="application" class="theme-communications skin-comms">
|
||||
<section role="region" id="content" class="import">
|
||||
|
||||
<gaia-header id="header" action="close">
|
||||
<h1>Service</h1>
|
||||
<button id="import-action" data-l10n-id="import" disabled>Import</button>
|
||||
</gaia-header>
|
||||
|
||||
<section id="main">
|
||||
<!-- Contacts List Section -->
|
||||
<section id='mainContent' data-state="selection">
|
||||
<form id="search-container" role="search" class="search">
|
||||
<p>
|
||||
<label for="search" id="search-start">
|
||||
<input type="search" name="search" class="textfield" placeholder="Search"
|
||||
data-l10n-id="search-contact">
|
||||
</label>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<section class="friends-msg">
|
||||
<output id="num-friends" hidden></output>
|
||||
<p id="friends-msg"></p>
|
||||
</section>
|
||||
<section id="groups-list" class="unbordered import-list active" data-type="list">
|
||||
<section id="group-#group#" data-template>
|
||||
<header>#group#</header>
|
||||
<ol id="contacts-list-#group#">
|
||||
<li data-template data-uuid="#uid#" data-search="#search#" aria-disabled="false" class="block-item">
|
||||
<label class="pack-checkbox">
|
||||
<input type="checkbox" name="#uid#"></input>
|
||||
<span></span>
|
||||
</label>
|
||||
<aside class="pack-end">
|
||||
<span data-type="img" data-src="#contactPictureUri#"></span>
|
||||
</aside>
|
||||
<p data-order-by="firstName" class="contact-text"><bdi><strong>#givenName#</strong> #familyName#</bdi></p>
|
||||
<p data-order-by="lastName" class="contact-text"><bdi>#givenName# <strong>#familyName#</strong></bdi></p>
|
||||
<p><bdi>#email1#</bdi></p>
|
||||
</li>
|
||||
</ol>
|
||||
</section> <!-- group template content -->
|
||||
</section> <!-- groupsList -->
|
||||
</section> <!-- mainContent -->
|
||||
|
||||
<form role="dialog" data-type="confirm" class="no-overlay">
|
||||
<gaia-buttons id="select-all-wrapper">
|
||||
<button id="deselect-all" class="edit-button" data-l10n-id="deselectAll">
|
||||
Deselect all
|
||||
</button>
|
||||
<button id="select-all" class="edit-button" data-l10n-id="selectAll">
|
||||
Select all
|
||||
</button>
|
||||
</gaia-buttons>
|
||||
</form>
|
||||
|
||||
<nav data-type="scrollbar">
|
||||
<p></p>
|
||||
<ol>
|
||||
<li data-template data-anchor="group-#anchor#" data-letter="#anchor#">
|
||||
<a href="#">#anchor#</a>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</section> <!-- main -->
|
||||
|
||||
<section id="search-view" class="view" role="region">
|
||||
<form id="searchview-container" role="search" class="search">
|
||||
<p>
|
||||
<label for="search-contact">
|
||||
<input type="search" name="search" class="textfield"
|
||||
placeholder="Search" id="search-contact" data-l10n-id="search-contact">
|
||||
<button type="reset">Clear</button>
|
||||
</label>
|
||||
</p>
|
||||
<button id='done-search' type="submit" data-l10n-id="done-search">Done</button>
|
||||
</form>
|
||||
<section id="groups-list-search">
|
||||
<ol id="search-list" class="selecting active" data-type="list">
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section id="search-process">
|
||||
<p id="no-result" class="hide" data-l10n-id="noResults">No contacts found</p>
|
||||
<p id="search-progress" class="hidden" role="status">
|
||||
<progress class="small"></progress>
|
||||
</p>
|
||||
</section>
|
||||
</section> <!-- search-view section -->
|
||||
|
||||
</section> <!-- role region -->
|
||||
</body>
|
||||
</html>
|
||||
270
gaia/shared/pages/import/js/curtain.js
Executable file
270
gaia/shared/pages/import/js/curtain.js
Executable file
|
|
@ -0,0 +1,270 @@
|
|||
'use strict';
|
||||
|
||||
/* exported Curtain */
|
||||
|
||||
/*
|
||||
* XXX: This is a class to load an <iframe> for loading the
|
||||
* curtain. This **MUST** be deprecated when [1] will be ready.
|
||||
* We need to get rid of all complexity passing messages, and reduce
|
||||
* the memory consumption in the apps.
|
||||
*
|
||||
* [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1183561
|
||||
*/
|
||||
|
||||
var Curtain = (function() {
|
||||
|
||||
var curtainFrame = parent.document.querySelector('#iframe_curtain');
|
||||
|
||||
if (!curtainFrame) {
|
||||
curtainFrame = document.createElement('iframe');
|
||||
curtainFrame.id = 'iframe_curtain';
|
||||
curtainFrame.src = '/shared/pages/import/curtain.html';
|
||||
parent.document.body.appendChild(curtainFrame);
|
||||
}
|
||||
|
||||
function getDoc() {
|
||||
return curtainFrame.contentWindow.document;
|
||||
}
|
||||
|
||||
var cpuWakeLock, cancelButton, retryButton, okButton, progressElement, form,
|
||||
progressTitle;
|
||||
var messages = [];
|
||||
var elements = ['error', 'timeout', 'wait', 'message', 'progress', 'alert'];
|
||||
|
||||
if (getDoc().readyState === 'complete') {
|
||||
init();
|
||||
} else {
|
||||
// The curtain could not be loaded at this moment
|
||||
curtainFrame.addEventListener('load', function loaded() {
|
||||
curtainFrame.removeEventListener('load', loaded);
|
||||
init();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
var doc = getDoc();
|
||||
cancelButton = doc.querySelector('#cancel');
|
||||
retryButton = doc.querySelector('#retry');
|
||||
okButton = doc.querySelector('#ok');
|
||||
|
||||
progressElement = doc.querySelector('#progressElement');
|
||||
|
||||
form = doc.querySelector('form');
|
||||
|
||||
elements.forEach(function createElementRef(name) {
|
||||
messages[name] = doc.getElementById(name + 'Msg');
|
||||
});
|
||||
|
||||
progressTitle = doc.getElementById('progressTitle');
|
||||
}
|
||||
|
||||
function doShow(type) {
|
||||
form.classList.remove('no-menu');
|
||||
form.dataset.state = type;
|
||||
curtainFrame.classList.add('visible');
|
||||
curtainFrame.classList.remove('fade-out');
|
||||
curtainFrame.classList.add('fade-in');
|
||||
}
|
||||
|
||||
function capitalize(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
function Progress(pfrom) {
|
||||
var from = pfrom;
|
||||
var counter = 0;
|
||||
var total = 0;
|
||||
|
||||
progressElement.setAttribute('value', 0);
|
||||
|
||||
function showMessage() {
|
||||
document.l10n.setAttributes(
|
||||
messages.progress,
|
||||
'progressFB',
|
||||
{ current: counter, total: total }
|
||||
);
|
||||
}
|
||||
|
||||
this.update = function() {
|
||||
progressElement.setAttribute('value', (++counter * 100) / total);
|
||||
showMessage();
|
||||
};
|
||||
|
||||
this.setFrom = function(pfrom) {
|
||||
from = capitalize(pfrom);
|
||||
progressTitle.setAttribute(
|
||||
'data-l10n-id', 'progressFB3' + from + 'Title');
|
||||
};
|
||||
|
||||
this.setTotal = function(ptotal) {
|
||||
total = ptotal;
|
||||
showMessage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current value
|
||||
*/
|
||||
this.getValue = function() {
|
||||
return counter;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Shows the curtain
|
||||
*
|
||||
* @param {String} type
|
||||
* Curtain type oneOf('wait', 'timeout', 'error',
|
||||
* 'message' and 'progress').
|
||||
*
|
||||
* @param {String} from
|
||||
* The origin of the message.
|
||||
*
|
||||
* @return {Object} progress. When 'type' === 'progress' .
|
||||
* This object defines an <update> method to refresh the progress bar UI.
|
||||
*
|
||||
*/
|
||||
show: function(type, from) {
|
||||
var out;
|
||||
|
||||
from = capitalize(from);
|
||||
|
||||
switch (type) {
|
||||
case 'wait':
|
||||
messages[type].setAttribute('data-l10n-id', type + from);
|
||||
break;
|
||||
|
||||
case 'timeout':
|
||||
document.l10n.formatValue('timeout' + from).then((from) => {
|
||||
document.l10n.setAttributes(messages[type], 'timeout1', {
|
||||
from: from
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
document.l10n.formatValue('type' + from).then((from) => {
|
||||
document.l10n.setAttributes(messages[type], 'error1', {
|
||||
from: from
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case 'alert':
|
||||
case 'message':
|
||||
messages[type].setAttribute('data-l10n-id', type + from);
|
||||
break;
|
||||
|
||||
case 'progress':
|
||||
progressTitle.setAttribute('data-l10n-id',
|
||||
type + 'FB3' + from + 'Title');
|
||||
out = new Progress(from);
|
||||
cpuWakeLock = navigator.requestWakeLock('cpu');
|
||||
break;
|
||||
}
|
||||
|
||||
doShow(type);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the curtain
|
||||
*
|
||||
* @param {Function} hiddenCB
|
||||
* triggered when the curtain has been hidden.
|
||||
*
|
||||
*/
|
||||
hide: function c_hide(hiddenCB) {
|
||||
if (cpuWakeLock) {
|
||||
cpuWakeLock.unlock();
|
||||
cpuWakeLock = null;
|
||||
}
|
||||
|
||||
curtainFrame.classList.add('fade-out');
|
||||
curtainFrame.addEventListener('animationend', function cu_fadeOut(ev) {
|
||||
curtainFrame.removeEventListener('animationend', cu_fadeOut);
|
||||
curtainFrame.classList.remove('visible');
|
||||
curtainFrame.classList.remove('fade-out');
|
||||
curtainFrame.classList.remove('fade-in');
|
||||
delete form.dataset.state;
|
||||
if (typeof hiddenCB === 'function') {
|
||||
hiddenCB();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* cancels the operation ongoing
|
||||
*
|
||||
* @param {Function} cancelCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set oncancel(cancelCb) {
|
||||
if (typeof cancelCb === 'function') {
|
||||
delete cancelButton.onclick;
|
||||
cancelButton.onclick = function on_cancel(e) {
|
||||
delete cancelButton.onclick;
|
||||
cancelCb();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* retries the operation ongoing
|
||||
*
|
||||
* @param {Function} retryCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set onretry(retryCb) {
|
||||
if (typeof retryCb === 'function') {
|
||||
delete retryButton.onclick;
|
||||
retryButton.onclick = function on_retry(e) {
|
||||
delete retryButton.onclick;
|
||||
retryCb();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* clicks on ok button
|
||||
*
|
||||
* @param {Function} okCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set onok(okCb) {
|
||||
if (typeof okCb === 'function') {
|
||||
delete okButton.onclick;
|
||||
okButton.onclick = function on_ok(e) {
|
||||
delete okButton.onclick;
|
||||
okCb();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the visibility state of the curtain
|
||||
*
|
||||
* @return {boolean} visibility state.
|
||||
*
|
||||
*/
|
||||
get visible() {
|
||||
return curtainFrame.classList.contains('visible');
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the menu
|
||||
*/
|
||||
hideMenu: function c_hideMenu() {
|
||||
form.classList.add('no-menu');
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
310
gaia/shared/pages/import/js/curtain_panel.js
Executable file
310
gaia/shared/pages/import/js/curtain_panel.js
Executable file
|
|
@ -0,0 +1,310 @@
|
|||
'use strict';
|
||||
/* global LazyLoader */
|
||||
/* exported Curtain */
|
||||
|
||||
/*
|
||||
* XXX:The name it's quite confusing, but we are going to work in several
|
||||
* steps in order to split this 'panel' in a small set, in order to load
|
||||
* just the JS you need.
|
||||
*
|
||||
* 'Curtain' is a panel which let you to show 'progress', 'confirm'...
|
||||
* within the .html related with 'import', 'matching'...
|
||||
*
|
||||
* We are going to keep the name by now, but this must be revisited when
|
||||
* refactoring how all these .html work.
|
||||
* In order to keep backwards compatibility, let's keep the same interface
|
||||
* by now.
|
||||
*/
|
||||
|
||||
|
||||
var Curtain = (function() {
|
||||
|
||||
var cancelButton, retryButton, okButton,
|
||||
progressElement, progressTitle;
|
||||
var cpuWakeLock;
|
||||
var messages = [];
|
||||
var elements = ['error', 'timeout', 'wait', 'message', 'progress', 'alert'];
|
||||
var _cancelCB = function foo() {};
|
||||
var _retryCB = function foo() {};
|
||||
var _okCB = function foo() {};
|
||||
|
||||
var form;
|
||||
|
||||
var panel = document.createElement('panel');
|
||||
panel.id = 'curtain';
|
||||
|
||||
var link = document.createElement('link');
|
||||
link.setAttribute('rel', 'import');
|
||||
link.setAttribute('href', '/shared/pages/import/elements/curtain.html');
|
||||
|
||||
function addListeners() {
|
||||
okButton.onclick = function on_ok(e) {
|
||||
delete okButton.onclick;
|
||||
_okCB();
|
||||
_okCB = null;
|
||||
};
|
||||
|
||||
retryButton.onclick = function on_retry(e) {
|
||||
delete retryButton.onclick;
|
||||
_retryCB();
|
||||
_retryCB = null;
|
||||
};
|
||||
|
||||
cancelButton.onclick = function on_cancel(e) {
|
||||
delete cancelButton.onclick;
|
||||
_cancelCB();
|
||||
_cancelCB = null;
|
||||
};
|
||||
}
|
||||
|
||||
function cacheElements() {
|
||||
cancelButton = document.querySelector('#cancel');
|
||||
retryButton = document.querySelector('#retry');
|
||||
okButton = document.querySelector('#ok');
|
||||
|
||||
progressElement = document.querySelector('#progressElement');
|
||||
|
||||
elements.forEach(function createElementRef(name) {
|
||||
messages[name] = document.getElementById(name + 'Msg');
|
||||
});
|
||||
|
||||
progressTitle = document.getElementById('progressTitle');
|
||||
}
|
||||
|
||||
function init() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
document.head.appendChild(link);
|
||||
|
||||
panel.setAttribute('is', 'curtain');
|
||||
panel.className = 'fade-out';
|
||||
document.body.appendChild(panel);
|
||||
LazyLoader.load([
|
||||
document.getElementById('curtain')
|
||||
], function() {
|
||||
cacheElements();
|
||||
addListeners();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function clean() {
|
||||
document.body.removeChild(panel);
|
||||
// Clean unnecessary dom elements:
|
||||
form = null;
|
||||
cancelButton = null;
|
||||
retryButton = null;
|
||||
okButton = null;
|
||||
progressElement = null;
|
||||
progressTitle = null;
|
||||
}
|
||||
|
||||
function doShow(type) {
|
||||
if (!form) {
|
||||
form = panel.querySelector('form');
|
||||
}
|
||||
form.dataset.state = type;
|
||||
|
||||
panel.classList.remove('no-menu');
|
||||
panel.classList.add('visible');
|
||||
panel.classList.remove('fade-out');
|
||||
// Don't do fancy animation on alerts.
|
||||
if (type !== 'alert') {
|
||||
panel.classList.add('fade-in');
|
||||
}
|
||||
}
|
||||
|
||||
function capitalize(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
function Progress(pfrom) {
|
||||
var from = pfrom;
|
||||
var counter = 0;
|
||||
var total = 0;
|
||||
|
||||
progressElement.setAttribute('value', 0);
|
||||
|
||||
function showMessage() {
|
||||
navigator.mozL10n.setAttributes(
|
||||
messages.progress,
|
||||
'progressFB',
|
||||
{ current: counter, total: total }
|
||||
);
|
||||
}
|
||||
|
||||
this.update = function() {
|
||||
progressElement.setAttribute('value', (++counter * 100) / total);
|
||||
showMessage();
|
||||
};
|
||||
|
||||
this.setFrom = function(pfrom) {
|
||||
from = capitalize(pfrom);
|
||||
progressTitle.setAttribute('data-l10n-id', 'progressFB3' + from +
|
||||
'Title');
|
||||
};
|
||||
|
||||
this.setTotal = function(ptotal) {
|
||||
total = ptotal;
|
||||
showMessage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current value
|
||||
*/
|
||||
this.getValue = function() {
|
||||
return counter;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Shows the curtain
|
||||
*
|
||||
* @param {String} type
|
||||
* Curtain type oneOf('wait', 'timeout', 'error',
|
||||
* 'message' and 'progress').
|
||||
*
|
||||
* @param {String} from
|
||||
* The origin of the message.
|
||||
*
|
||||
* @return {Object} progress. When 'type' === 'progress' .
|
||||
* This object defines an <update> method to refresh the progress bar UI.
|
||||
*
|
||||
*/
|
||||
show: function(type, from) {
|
||||
init().then(function() {
|
||||
var out;
|
||||
|
||||
from = capitalize(from);
|
||||
|
||||
switch (type) {
|
||||
case 'wait':
|
||||
messages[type].setAttribute('data-l10n-id', type + from);
|
||||
break;
|
||||
|
||||
case 'timeout':
|
||||
navigator.mozL10n.formatValue('timeout' + from).then(from => {
|
||||
navigator.mozL10n.setAttributes(messages[type], 'timeout1', {
|
||||
from: from
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
navigator.mozL10n.formatValue(type + from).then(from => {
|
||||
navigator.mozL10n.setAttributes(messages[type], 'error1', {
|
||||
from: from
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case 'alert':
|
||||
case 'message':
|
||||
messages[type].setAttribute('data-l10n-id', type + from);
|
||||
break;
|
||||
|
||||
case 'progress':
|
||||
progressTitle.setAttribute('data-l10n-id',
|
||||
type + 'FB3' + from + 'Title');
|
||||
out = new Progress(from);
|
||||
cpuWakeLock = navigator.requestWakeLock('cpu');
|
||||
break;
|
||||
}
|
||||
|
||||
doShow(type);
|
||||
|
||||
return out;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the curtain
|
||||
*
|
||||
* @param {Function} hiddenCB
|
||||
* triggered when the curtain has been hidden.
|
||||
*
|
||||
*/
|
||||
hide: function c_hide(hiddenCB) {
|
||||
if (cpuWakeLock) {
|
||||
cpuWakeLock.unlock();
|
||||
cpuWakeLock = null;
|
||||
}
|
||||
|
||||
panel.classList.add('fade-out');
|
||||
panel.addEventListener('animationend', function cu_fadeOut(ev) {
|
||||
panel.removeEventListener('animationend', cu_fadeOut);
|
||||
delete form.dataset.state;
|
||||
clean();
|
||||
if (typeof hiddenCB === 'function') {
|
||||
hiddenCB();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* cancels the operation ongoing
|
||||
*
|
||||
* @param {Function} cancelCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set oncancel(cancelCb) {
|
||||
if (typeof cancelCb === 'function') {
|
||||
_cancelCB = cancelCb;
|
||||
} else {
|
||||
_cancelCB = function foo(){};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* retries the operation ongoing
|
||||
*
|
||||
* @param {Function} retryCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set onretry(retryCb) {
|
||||
if (typeof retryCb === 'function') {
|
||||
_retryCB = retryCb;
|
||||
} else {
|
||||
_retryCB = function foo(){};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set a event handler that will be invoked when the user
|
||||
* clicks on ok button
|
||||
*
|
||||
* @param {Function} okCb . Event handler.
|
||||
*
|
||||
*/
|
||||
set onok(okCb) {
|
||||
if (typeof okCb === 'function') {
|
||||
_okCB = okCb;
|
||||
} else {
|
||||
_okCB = function foo(){};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the visibility state of the curtain
|
||||
*
|
||||
* @return {boolean} visibility state.
|
||||
*
|
||||
*/
|
||||
get visible() {
|
||||
return panel.classList.contains('visible');
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the menu
|
||||
*/
|
||||
hideMenu: function c_hideMenu() {
|
||||
panel.classList.add('no-menu');
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
93
gaia/shared/pages/import/js/flow.js
Executable file
93
gaia/shared/pages/import/js/flow.js
Executable file
|
|
@ -0,0 +1,93 @@
|
|||
/* global oauthflow */
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* Module: Facebook integration
|
||||
*
|
||||
* This script file contains all the logic that allows to obtain an access
|
||||
* token through an OAuth 2.0 implicit grant flow
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
if (typeof window.oauthflow === 'undefined') {
|
||||
(function(document) {
|
||||
|
||||
var OAuthFlow = window.oauthflow = {};
|
||||
|
||||
var OAUTH_REDIRECT = 'redirectURI';
|
||||
var ENDPOINT = 'loginPage';
|
||||
var APP_ID = 'applicationId';
|
||||
var SCOPE = 'scope';
|
||||
var APP_ORIGIN = location.origin;
|
||||
|
||||
/**
|
||||
* Initialization function it tries to find an access token
|
||||
*
|
||||
*/
|
||||
OAuthFlow.init = function(service) {
|
||||
var hash = document.location.hash.substring(1);
|
||||
var parameters = {};
|
||||
|
||||
var dataStart = hash.indexOf('access_token');
|
||||
if (dataStart !== -1) {
|
||||
var elements = hash.split('&');
|
||||
|
||||
elements.forEach(function(p) {
|
||||
var values = p.split('=');
|
||||
parameters[values[0]] = values[1];
|
||||
});
|
||||
|
||||
window.opener.postMessage(parameters, APP_ORIGIN);
|
||||
|
||||
// Finally the window is closed
|
||||
window.close();
|
||||
}
|
||||
}; // init
|
||||
|
||||
|
||||
OAuthFlow.start = function(state, service) {
|
||||
getAccessToken(state, service);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the access token. The access token is retrieved from the local
|
||||
* storage and if not present a OAuth 2.0 flow is started
|
||||
*
|
||||
*
|
||||
*/
|
||||
function getAccessToken(state, service) {
|
||||
startOAuth(state, service);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a OAuth 2.0 flow to obtain the user information
|
||||
*
|
||||
*/
|
||||
function startOAuth(state, service) {
|
||||
var params = oauthflow.params[service];
|
||||
|
||||
var redirect_uri = encodeURIComponent(params[OAUTH_REDIRECT]);
|
||||
|
||||
var scope = params[SCOPE].join(',');
|
||||
var scopeParam = encodeURIComponent(scope);
|
||||
|
||||
var queryParams = ['client_id=' + params[APP_ID],
|
||||
'redirect_uri=' + redirect_uri,
|
||||
'response_type=token',
|
||||
'scope=' + scopeParam,
|
||||
// Only needed for Gmail (see Bug 962377)
|
||||
'approval_prompt=force',
|
||||
'state=' + state
|
||||
]; // Query params
|
||||
|
||||
var query = queryParams.join('&');
|
||||
var url = params[ENDPOINT] + query;
|
||||
|
||||
window.open(url, '', 'dialog');
|
||||
}
|
||||
|
||||
})(document);
|
||||
}
|
||||
138
gaia/shared/pages/import/js/oauth20.js
Executable file
138
gaia/shared/pages/import/js/oauth20.js
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
/* global ImportStatusData, oauthflow, Curtain */
|
||||
'use strict';
|
||||
|
||||
var fb = window.fb || {};
|
||||
|
||||
if (typeof window.oauth2 === 'undefined') {
|
||||
(function(document) {
|
||||
var oauth2 = window.oauth2 = {};
|
||||
// <callback> is invoked when an access token is ready
|
||||
// and the hash state matches <state>
|
||||
var accessTokenCbData;
|
||||
|
||||
var STORAGE_KEY = 'tokenData';
|
||||
|
||||
var APP_ORIGIN = location.origin;
|
||||
|
||||
/**
|
||||
* Clears credential data stored locally
|
||||
*
|
||||
*/
|
||||
function clearStorage(service) {
|
||||
ImportStatusData.remove(getKey(service));
|
||||
}
|
||||
|
||||
function getKey(service) {
|
||||
var key = STORAGE_KEY;
|
||||
if (service !== 'facebook') {
|
||||
key = STORAGE_KEY + '_' + service;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the access token. The access token is retrieved from the local
|
||||
* storage and if not present a OAuth 2.0 flow is started
|
||||
*
|
||||
*
|
||||
*/
|
||||
oauth2.getAccessToken = function(ready, state, service) {
|
||||
accessTokenCbData = {
|
||||
callback: ready,
|
||||
state: state,
|
||||
service: service
|
||||
};
|
||||
|
||||
// Enables simple access to test tokens for hacking up the app
|
||||
// This code will need to be deleted once we have a final product
|
||||
fb.testToken = fb.testToken || (parent.fb && parent.fb.testToken);
|
||||
if (service === 'facebook' && typeof fb.testToken === 'string' &&
|
||||
fb.testToken.trim().length > 0) {
|
||||
window.console.warn('Facebook. A test token will be used!');
|
||||
tokenDataReady({
|
||||
data: {
|
||||
access_token: fb.testToken,
|
||||
expires_in: 0,
|
||||
state: state
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ImportStatusData.get(getKey(service)).then(
|
||||
function getAccessToken(tokenData) {
|
||||
if (!tokenData || !tokenData.access_token) {
|
||||
startOAuth(state, service);
|
||||
return;
|
||||
}
|
||||
|
||||
var access_token = tokenData.access_token;
|
||||
var expires = Number(tokenData.expires);
|
||||
var token_ts = tokenData.token_ts;
|
||||
|
||||
if (expires !== 0 && Date.now() - token_ts >= expires) {
|
||||
window.console.warn('Access token has expired, restarting flow');
|
||||
startOAuth(state, service);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof ready === 'function') {
|
||||
ready(access_token);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts a OAuth 2.0 flow to obtain the user information
|
||||
*
|
||||
*/
|
||||
function startOAuth(state, service) {
|
||||
clearStorage(service);
|
||||
|
||||
// This page will be in charge of handling authorization
|
||||
oauthflow.start(state, service);
|
||||
}
|
||||
|
||||
function tokenDataReady(e) {
|
||||
var parameters = e.data;
|
||||
if (!parameters || !parameters.access_token) {
|
||||
return;
|
||||
}
|
||||
if (e.origin !== APP_ORIGIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
Curtain.show('wait', accessTokenCbData.state);
|
||||
|
||||
window.setTimeout(function do_token_ready() {
|
||||
var access_token = parameters.access_token;
|
||||
if (parameters.state === accessTokenCbData.state) {
|
||||
accessTokenCbData.callback(access_token);
|
||||
} else {
|
||||
window.console.error('FB: Error in state', parameters.state,
|
||||
accessTokenCbData.state);
|
||||
return;
|
||||
}
|
||||
|
||||
var end = parameters.expires_in;
|
||||
|
||||
ImportStatusData.put(getKey(accessTokenCbData.service), {
|
||||
access_token: access_token,
|
||||
expires: end * 1000,
|
||||
token_ts: Date.now()
|
||||
}).then(function notify_parent() {
|
||||
parent.postMessage({
|
||||
type: 'token_stored',
|
||||
data: ''
|
||||
}, APP_ORIGIN);
|
||||
});
|
||||
},0);
|
||||
} // tokenReady
|
||||
|
||||
window.addEventListener('message', tokenDataReady);
|
||||
|
||||
}
|
||||
)(document);
|
||||
}
|
||||
51
gaia/shared/pages/import/js/oauth_frame.js
Executable file
51
gaia/shared/pages/import/js/oauth_frame.js
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
/* globals Curtain, oauth2 */
|
||||
|
||||
if (typeof window.oauthFrame === 'undefined') {
|
||||
(function() {
|
||||
|
||||
var targetService;
|
||||
var oauthFrame = window.oauthFrame = {};
|
||||
var CONTACTS_APP_ORIGIN = location.origin;
|
||||
|
||||
function notifyParent(message, origin) {
|
||||
parent.postMessage({
|
||||
type: message.type || '',
|
||||
data: message.data || ''
|
||||
}, origin);
|
||||
}
|
||||
|
||||
function cancelCb() {
|
||||
Curtain.hide(notifyParent.bind(null, {
|
||||
type: 'abort'
|
||||
}, CONTACTS_APP_ORIGIN));
|
||||
}
|
||||
|
||||
oauthFrame.start = function(from, service) {
|
||||
targetService = service;
|
||||
oauth2.getAccessToken(function tokenReady(access_token) {
|
||||
Curtain.oncancel = cancelCb;
|
||||
|
||||
if (!Curtain.visible) {
|
||||
Curtain.show('wait', from);
|
||||
}
|
||||
|
||||
parent.postMessage({
|
||||
type: 'authenticated',
|
||||
data: access_token
|
||||
}, CONTACTS_APP_ORIGIN);
|
||||
}, from, service);
|
||||
};
|
||||
|
||||
window.addEventListener('message', function messageHandler(e) {
|
||||
if (e.origin !== CONTACTS_APP_ORIGIN) {
|
||||
return;
|
||||
}
|
||||
var data = e.data;
|
||||
if (data && data.type === 'start') {
|
||||
oauthFrame.start(data.data.from, data.data.service);
|
||||
}
|
||||
});
|
||||
})();
|
||||
}
|
||||
24
gaia/shared/pages/import/oauth.html
Executable file
24
gaia/shared/pages/import/oauth.html
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="en-US">
|
||||
<link rel="localization" href="/shared/locales/import_contacts/import_contacts.{locale}.properties">
|
||||
<script type="text/javascript" src="/shared/js/l10n.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/shared/js/lazy_loader.js"></script>
|
||||
<script type="text/javascript" src="/shared/js/contacts/import/import_status_data.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/flow.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/oauth20.js"></script>
|
||||
<script type="text/javascript" src="js/parameters.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/curtain.js"></script>
|
||||
<script type="text/javascript" src="/shared/pages/import/js/oauth_frame.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
11
gaia/shared/pages/import/redirects/dialogs_end.html
Executable file
11
gaia/shared/pages/import/redirects/dialogs_end.html
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="UTF-8">
|
||||
<script src="/shared/pages/import/redirects/dialogs_end_init.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
7
gaia/shared/pages/import/redirects/dialogs_end_init.js
Executable file
7
gaia/shared/pages/import/redirects/dialogs_end_init.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var COMMS_APP_ORIGIN = document.location.protocol + '//' +
|
||||
document.location.host;
|
||||
|
||||
window.opener.postMessage('closed', COMMS_APP_ORIGIN);
|
||||
window.close();
|
||||
3
gaia/shared/pages/import/redirects/logout.json
Executable file
3
gaia/shared/pages/import/redirects/logout.json
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"success": true
|
||||
}
|
||||
11
gaia/shared/pages/import/redirects/redirect.html
Executable file
11
gaia/shared/pages/import/redirects/redirect.html
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>OAuth Redirection</title>
|
||||
<script defer src="/shared/pages/import/redirects/redirect.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
36
gaia/shared/pages/import/redirects/redirect.js
Executable file
36
gaia/shared/pages/import/redirects/redirect.js
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
var Redirect = function Redirect() {
|
||||
|
||||
var COMMS_APP_ORIGIN = document.location.protocol + '//' +
|
||||
document.location.host;
|
||||
|
||||
var init = function init() {
|
||||
var hash = document.location.hash.substring(1);
|
||||
var parameters = {};
|
||||
|
||||
var dataStart = hash.indexOf('access_token');
|
||||
|
||||
if (dataStart !== -1) {
|
||||
var elements = hash.split('&');
|
||||
|
||||
elements.forEach(function(p) {
|
||||
var values = p.split('=');
|
||||
parameters[values[0]] = values[1];
|
||||
});
|
||||
|
||||
window.opener.postMessage(parameters, COMMS_APP_ORIGIN);
|
||||
window.close();
|
||||
} else {
|
||||
window.close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
'init': init
|
||||
};
|
||||
|
||||
}();
|
||||
|
||||
Redirect.init();
|
||||
79
gaia/shared/pages/import/style/curtain.css
Executable file
79
gaia/shared/pages/import/style/curtain.css
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
html, body {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#curtain {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="alert"] menu #ok {
|
||||
margin-left: 0;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="wait"] #cancel,
|
||||
form[role="dialog"][data-type="confirm"][data-state="progress"] #cancel {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="wait"] #retry {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="progress"] #progress {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form.no-menu[role="dialog"][data-type="confirm"] menu,
|
||||
form[role="dialog"][data-type="confirm"][data-state="progress"] menu #retry,
|
||||
form[role="dialog"][data-type="confirm"][data-state="alert"] menu #retry,
|
||||
form[role="dialog"][data-type="confirm"][data-state="alert"] menu #cancel,
|
||||
form[role="dialog"][data-type="confirm"]:not([data-state="alert"]) menu #ok,
|
||||
form[role="dialog"][data-type="confirm"][data-state="message"] menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="error"] menu #retry,
|
||||
form[role="dialog"][data-type="confirm"][data-state="timeout"] menu #retry {
|
||||
-moz-margin-start: 1rem;
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="wait"] #wait {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="message"] #message {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="error"] #error {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="timeout"] #timeout {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"][data-state="alert"] #alert {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p[role="status"] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#progress p[role="status"] {
|
||||
text-align: start;
|
||||
}
|
||||
17
gaia/shared/pages/import/style/curtain_frame.css
Executable file
17
gaia/shared/pages/import/style/curtain_frame.css
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#iframe_curtain {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#iframe_curtain.visible {
|
||||
pointer-events: auto;
|
||||
z-index: 1001;
|
||||
}
|
||||
34
gaia/shared/pages/import/style/facebook.css
Executable file
34
gaia/shared/pages/import/style/facebook.css
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
@import url("root.css");
|
||||
|
||||
/* BB Headers */
|
||||
section[role="region"] > header:first-child,
|
||||
.skin-comms section[role="region"] > header:first-child {
|
||||
background: #3b5998;
|
||||
}
|
||||
|
||||
section[role="region"] > header:first-child a, section[role="region"] > header:first-child button,
|
||||
.skin-comms section[role="region"] > header:first-child a, section[role="region"] > header:first-child button {
|
||||
color: rgba(255,255,255, 0.6);
|
||||
}
|
||||
|
||||
/* BB lists */
|
||||
.import-list header {
|
||||
border-color: #4D77CF;
|
||||
color: #4D77CF;
|
||||
}
|
||||
|
||||
#groups-list.import-list label input + span,
|
||||
#search-list label input + span {
|
||||
background-image: url(/contacts/style/images/fb-check.png);
|
||||
}
|
||||
|
||||
/* Force having blue highlight */
|
||||
.link #mainContent li[data-uuid] *:not(input) {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.link #mainContent li[data-uuid] p,
|
||||
.link #mainContent li[data-uuid] img,
|
||||
.link #mainContent li[data-uuid] aside {
|
||||
pointer-events: none;
|
||||
}
|
||||
215
gaia/shared/pages/import/style/import.css
vendored
Executable file
215
gaia/shared/pages/import/style/import.css
vendored
Executable file
|
|
@ -0,0 +1,215 @@
|
|||
@import url("root.css");
|
||||
|
||||
.hide, *[data-template] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
html, body {
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* BB Confirm */
|
||||
form[role="dialog"].no-overlay {
|
||||
background: none;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
form[role="dialog"].no-overlay button {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* BB lists */
|
||||
.import-list header {
|
||||
-moz-padding-start: 1.5rem;
|
||||
position: sticky;
|
||||
top: -3.7rem;
|
||||
background: #fff;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Force having always checkboxes */
|
||||
#groups-list.import-list label,
|
||||
#search-list label {
|
||||
left: 0;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
[data-type="list"].import-list {
|
||||
padding: 0;
|
||||
-moz-padding-start: 1.5rem;
|
||||
-moz-padding-end: 4rem;
|
||||
}
|
||||
|
||||
[data-type="list"].import-list.active li:after {
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
[data-type="list"].import-list aside span[data-type="img"],
|
||||
[data-type="list"].link-list aside span[data-type="img"] {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
[data-type="list"].import-list li[data-visited="true"] aside span[data-type="img"],
|
||||
[data-type="list"].link-list li[data-visited="true"] aside span[data-type="img"] {
|
||||
box-shadow: 0 0 0 0.1rem #dedede;
|
||||
}
|
||||
|
||||
#groups-list.import-list li,
|
||||
.import #search-list[data-type="list"] li {
|
||||
-moz-padding-start: 3.5rem;
|
||||
}
|
||||
|
||||
#groups-list.active li:not(:active):after,
|
||||
#search-list.active li:not(:active):after {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* End BB */
|
||||
|
||||
.view {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#curtain {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.friends-msg {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
border-bottom: 0.1rem solid #E6E6E6;
|
||||
padding: 0.4rem 0;
|
||||
}
|
||||
|
||||
p#friends-msg {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.8rem;
|
||||
margin: 0 3rem;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#main {
|
||||
position: fixed;
|
||||
top: 5rem;
|
||||
height: calc(100% - 5rem);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#mainContent {
|
||||
width: calc(100% + 1rem); /* Hide scrollbar */
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-moz-box-sizing: border-box;
|
||||
color: #333;
|
||||
text-align: start;
|
||||
height: calc(100% - 6.9rem);
|
||||
padding-top: 3.7rem; /* Equal to search form height */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.link #mainContent {
|
||||
padding-top: 0; /* Remove search form height */
|
||||
}
|
||||
|
||||
#main.no-proposal #mainContent {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#main.no-proposal > form[role="dialog"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#groups-list > li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#groups-list li[data-uuid] * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
cursor: default;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* JUMPER */
|
||||
|
||||
nav[data-type="scrollbar"] {
|
||||
z-index:100;
|
||||
bottom: 4.2rem;
|
||||
}
|
||||
|
||||
nav[data-type="scrollbar"] li {
|
||||
line-height: 1.3rem;
|
||||
}
|
||||
|
||||
nav[data-type="scrollbar"] ol > li > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#mainContent li[data-uuid] *:not(input) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
ol.unbordered > li {
|
||||
border: none !important;
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
li[data-uuid]{
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
li[data-uuid]:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
#done-search {
|
||||
min-width: 8.2rem;
|
||||
}
|
||||
|
||||
/* RTL View */
|
||||
html[dir="rtl"] #groups-list.import-list label,
|
||||
html[dir="rtl"] #search-list label {
|
||||
left: unset;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] nav[data-type="scrollbar"] {
|
||||
direction: ltr;
|
||||
right: 0;
|
||||
left: unset;
|
||||
}
|
||||
|
||||
html[dir="rtl"] nav[data-type="scrollbar"] p {
|
||||
left: unset;
|
||||
right: 10rem;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .block-item {
|
||||
left: unset;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
[data-type="list"] li.block-item bdi {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
}
|
||||
33
gaia/shared/pages/import/style/root.css
Executable file
33
gaia/shared/pages/import/style/root.css
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
font-size: 62.5%;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
ul, ol, li, dl, dt, dd,
|
||||
p, input, textarea, select, button,
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup,
|
||||
menu, nav, section, video, audio, canvas, progress, meter, time {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul, ol, dl, dt, dd {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
p, li {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
body > section[role=region] {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
166
gaia/shared/pages/import/style/search.css
Executable file
166
gaia/shared/pages/import/style/search.css
Executable file
|
|
@ -0,0 +1,166 @@
|
|||
/* Search */
|
||||
/* Common search styles */
|
||||
|
||||
html[dir="ltr"] form.search,
|
||||
html[dir="ltr"] #groups-list-search,
|
||||
html[dir="ltr"] #no-result { text-align: left; }
|
||||
html[dir="rtl"] form.search,
|
||||
html[dir="rtl"] #groups-list-search,
|
||||
html[dir="rtl"] #no-result { text-align: right; }
|
||||
|
||||
form.search {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#search-container {
|
||||
padding-right: 2.5rem; /* XXX BiDi alert */
|
||||
}
|
||||
|
||||
#search-view:not(.insearchmode) form.search * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#search-view.insearchmode form.search input {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
form.search p {
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#search-view.insearchmode form.search p {
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
form.search label {
|
||||
display: block;
|
||||
background: none;
|
||||
}
|
||||
|
||||
form.search input {
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
form.search input {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
form.search button[type="submit"] {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Search view */
|
||||
#search-view {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#view-screenshot.search {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#view-screenshot.search > #view-screenshot-body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: -moz-element(#search-view);
|
||||
}
|
||||
|
||||
.facebook #search-view, .import #search-view {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#search-view.insearchmode {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#no-result {
|
||||
margin-top: 9.5rem;
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
padding-top: 1.5rem;
|
||||
color: #000;
|
||||
font-size: 2.4rem;
|
||||
font-weight: 300;
|
||||
border-top: 0.1rem solid #bdbdbd;
|
||||
}
|
||||
|
||||
#search-progress {
|
||||
margin-top: 7.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#search-progress.hidden > progress {
|
||||
opacity: 0;
|
||||
animation-name: none;
|
||||
}
|
||||
|
||||
/* facebook search */
|
||||
.facebook #search-view button[type="submit"],
|
||||
.import #search-view button[type="submit"] {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#search-view > section {
|
||||
position: absolute;
|
||||
top: 3.7rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: calc(100% - 3.7rem);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#groups-list-search {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#search-process {
|
||||
z-index: 2; /* Above groups-list-search */
|
||||
background-color: transparent!important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#search-list {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#search-list[data-type="list"] li:after {
|
||||
right: -1.5rem; /* XXX BiDi alert */
|
||||
}
|
||||
|
||||
#search-list > li[data-uuid] > a *,
|
||||
.facebook #search-list > li[data-uuid] *:not(input),
|
||||
.import #search-list > li[data-uuid] *:not(input) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#search-list.selecting label.pack-checkbox {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#search-list label.pack-checkbox {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
mark {
|
||||
background-color: #b2f2ff;
|
||||
}
|
||||
|
||||
#searchview-container p input::-moz-placeholder,
|
||||
#search-container p input::-moz-placeholder {
|
||||
background: none;
|
||||
}
|
||||
Loading…
Reference in a new issue