diff --git a/background_mozilla.html b/background_mozilla.html new file mode 100644 index 0000000000..a355311dab --- /dev/null +++ b/background_mozilla.html @@ -0,0 +1,374 @@ + + + + + + + + + Signal for Firefox + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index_mozilla.html b/index_mozilla.html new file mode 100644 index 0000000000..e63e98a5e1 --- /dev/null +++ b/index_mozilla.html @@ -0,0 +1,33 @@ + + + + + + + Signal + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/background.js b/js/background.js index 8a15b4c6f1..ccef61db0d 100644 --- a/js/background.js +++ b/js/background.js @@ -5,7 +5,7 @@ ;(function() { 'use strict'; // register some chrome listeners - if (chrome.notifications) { + if (typeof chrome != 'undefined' && chrome.notifications) { chrome.notifications.onClicked.addListener(function() { extension.notification.clear(); Whisper.Notifications.onclick(); @@ -22,14 +22,22 @@ Whisper.Notifications.clear(); } }); + } else { + // TODO: fallback + console.log("TODO: fallback (chrome.notifications addListener)"); } // Close and reopen existing windows - var open = false; - chrome.app.window.getAll().forEach(function(appWindow) { - open = true; - appWindow.close(); - }); + if (typeof chrome != 'undefined') { + var open = false; + chrome.app.window.getAll().forEach(function(appWindow) { + open = true; + appWindow.close(); + }); + } else { + // TODO: fallback? + console.log("TODO: fallback? (close and reopen existing windows)"); + } // start a background worker for ecc textsecure.protocol_wrapper.startWorker(); @@ -38,7 +46,6 @@ ConversationController.updateInbox(); extension.onLaunched(function() { - console.log('extension launched'); storage.onready(function() { if (textsecure.registration.isDone()) { openInbox(); diff --git a/js/chromium.js b/js/chromium.js index 47b2c08569..44472f08be 100644 --- a/js/chromium.js +++ b/js/chromium.js @@ -1,8 +1,11 @@ /* * vim: ts=4:sw=4:expandtab */ +var windowscope = this; + (function () { 'use strict'; + // Browser specific functions for Chrom* window.extension = window.extension || {}; @@ -19,16 +22,27 @@ self.tabs = tabs; self.setBadgeText = function (text) { - if (chrome.browserAction && chrome.browserAction.setBadgeText) { + if (typeof chrome != 'undefined' && chrome.browserAction && chrome.browserAction.setBadgeText) { chrome.browserAction.setBadgeText({text: String(text)}); + } else { + document.title = text; } }; return self; }()); + window.extension.messageListeners = []; + window.extension.trigger = function (name, object) { + if (typeof chrome != 'undefined') { chrome.runtime.sendMessage(null, { name: name, data: object }); + } else { + // fallback + for (var listener of window.extension.messageListeners) { + listener({ name: name, data: object }); + } + } }; window.extension.on = function (name, callback) { @@ -37,15 +51,25 @@ // might be worth making a map of 'name' -> [callbacks, ...] // so we can fire a single listener that calls only the necessary // calllbacks for that message name - chrome.runtime.onMessage.addListener(function(e) { + if (typeof chrome != 'undefined') { + chrome.runtime.onMessage.addListener(function(e) { + if (e.name === name) { + callback(e.data); + } + }); + } else { + // fallback + window.extension.messageListeners.push(function(e) { if (e.name === name) { callback(e.data); } - }); + }); + } }; extension.windows = { open: function(options, callback) { + if (typeof chrome != 'undefined') { if (chrome.windows) { chrome.windows.create(options, callback); } else if (chrome.app.window) { @@ -53,9 +77,31 @@ delete options.url; chrome.app.window.create(url, options, callback); } + } else { + // TODO: fallback + console.log("TODO: windows.open", options, callback); + + if (options !== undefined && options.url !== undefined && + options.url != location.pathname) { + location.href = options.url; + } + + if (callback !== undefined) { + callback({ + id: url, + contentWindow: window, + onClosed: { + addListener: function(callback){ + console.log("TODO: store callback (appWindow.onClosed.addListener)"); + } + }, + }); + } + } }, focus: function(id, callback) { + if (typeof chrome != 'undefined') { if (chrome.windows) { chrome.windows.update(id, { focused: true }, function() { callback(chrome.runtime.lastError); @@ -70,38 +116,64 @@ callback('No window found for id ' + id); } } + } else { + // TODO: fallback + console.log("TODO: fallback (windows.focus)"); + } }, getCurrent: function(callback) { + if (typeof chrome != 'undefined') { if (chrome.windows) { chrome.windows.getCurrent(callback); } else if (chrome.app.window) { callback(chrome.app.window.current()); } + } else { + // TODO: is the following object complete? + + callback({ + textsecure: textsecure, + storage: window.storage, + getAccountManager: window.getAccountManager, + openInbox: window.openInbox, + contentWindow: window, + console: console + }); + } }, remove: function(windowId) { - if (chrome.windows) { - chrome.windows.remove(windowId); - } else if (chrome.app.window) { - chrome.app.window.get(windowId).close(); + if (typeof chrome != 'undefined') { + if (chrome.windows) { + chrome.windows.remove(windowId); + } else if (chrome.app.window) { + chrome.app.window.get(windowId).close(); + } + } else { + // TODO: fallback + console.log("TODO: fallback (windows.remove)"); } }, getBackground: function(callback) { var getBackground; - if (chrome.extension) { + if (typeof chrome != 'undefined') { + if (chrome.extension) { var bg = chrome.extension.getBackgroundPage(); bg.storage.onready(function() { callback(bg); resolve(); }); - } else if (chrome.runtime) { - chrome.runtime.getBackgroundPage(function(bg) { - bg.storage.onready(function() { - callback(bg); - }); - }); + } else if (chrome.runtime) { + chrome.runtime.getBackgroundPage(function(bg) { + bg.storage.onready(function() { + callback(bg); + }); + }); + } + } else { + extension.windows.getCurrent(callback); } }, @@ -115,8 +187,24 @@ } }, + getLocation: function(id) { + if (typeof chrome != 'undefined') { + return { + 'index': 'index.html', + 'installer': 'options.html', + 'register': 'register.html' + }[id]; + } else { + return { + 'index': '/background_mozilla.html', + 'installer': '/options_mozilla.html', + 'register': '/register_mozilla.html' + }[id]; + } + }, + onSuspend: function(callback) { - if (chrome.runtime) { + if (typeof chrome != 'undefined' && chrome.runtime) { chrome.runtime.onSuspend.addListener(callback); } else { window.addEventListener('beforeunload', callback); @@ -132,34 +220,73 @@ }, drawAttention: function(window_id) { - if (chrome.app.window) { + if (typeof chrome != 'undefined' && chrome.app.window) { var w = chrome.app.window.get(window_id); w.clearAttention(); w.drawAttention(); + } else { + // TODO: implement something better + if (document.title[0] != "!") { + document.title = "! " + document.title + } } }, clearAttention: function(window_id) { - if (chrome.app.window) { + if (typeof chrome != 'undefined' && chrome.app.window) { var w = chrome.app.window.get(window_id); w.clearAttention(); + } else { + // TODO: implement something better + if (document.title[0] == "!") { + document.title = document.title.substr(2); + } } } }; extension.onLaunched = function(callback) { + if (typeof chrome != 'undefined') { if (chrome.browserAction && chrome.browserAction.onClicked) { chrome.browserAction.onClicked.addListener(callback); } if (chrome.app && chrome.app.runtime) { chrome.app.runtime.onLaunched.addListener(callback); } + } else { + document.addEventListener('DOMContentLoaded', function() { + callback(); + }, false); + } }; // Translate + window.i18nData = null; window.i18n = function(message) { - return chrome.i18n.getMessage(message); + if (typeof chrome != 'undefined') { + return chrome.i18n.getMessage(message); + } else { + if (window.i18nData === null) { + for (var lang of navigator.languages.concat("en")) { + $.ajax({ + url: "_locales/" + lang + "/messages.json", + success: function(data) { + window.i18nData = data; + }, + async: false, + dataType: "json" + }); + if (window.i18nData !== null) { + break; + } + } + } + if (window.i18nData[message] === undefined) { + return "missing translation"; + } + return window.i18nData[message].message + } }; window.textsecure = window.textsecure || {}; @@ -176,18 +303,30 @@ extension.install = function(mode) { var id = 'installer'; - var url = 'options.html'; + var url = extension.windows.getLocation('installer'); if (mode === 'standalone') { id = 'standalone-installer'; - url = 'register.html'; + url = extension.windows.getLocation('register'); } - if (!chrome.app.window.get(id)) { + if (typeof chrome != 'undefined') { + if (!chrome.app.window.get(id)) { + extension.windows.open({ + id: id, + url: url, + bounds: { width: 800, height: 666, }, + minWidth: 800, + minHeight: 666 + }); + } + } else { + if (location.pathname == + extension.windows.getLocation('register')) { + console.log("Refusing to redirect from register to options."); + return; + } extension.windows.open({ id: id, - url: url, - bounds: { width: 800, height: 666, }, - minWidth: 800, - minHeight: 666 + url: url }); } }; @@ -202,7 +341,7 @@ }); }, update: function(options) { - if (chrome) { + if (typeof chrome != 'undefined') { var chromeOpts = { type : options.type, title : options.title, @@ -223,33 +362,58 @@ }); }); }); - } else { - var notification = new Notification(options.title, { - body : options.message, - icon : options.iconUrl, - tag : 'signal' - }); - notification.onclick = function() { - Whisper.Notifications.onclick(); - }; + } else if("Notification" in window) { + var notify = function() { + var notification = new Notification(options.title, { + body : options.message, + icon : options.iconUrl, + tag : 'signal' + }); + notification.onclick = function() { + Whisper.Notifications.onclick(); + }; + } + + if (Notification.permission === "granted") { + notify(); + } else if (Notification.permission !== 'denied') { + Notification.requestPermission(function (permission) { + if (permission === "granted") { + notify(); + } + }); + } } } }; + // ask for permission to show Notifications + if("Notification" in window && Notification.permission !== 'denied') { + Notification.requestPermission(); + } + extension.keepAwake = function() { - if (chrome && chrome.alarms) { + if (typeof chrome != 'undefined' && chrome && chrome.alarms) { chrome.alarms.onAlarm.addListener(function() { // nothing to do. }); chrome.alarms.create('awake', {periodInMinutes: 1}); + } else { + // TODO: fallback + console.log("TODO: fallback (keepAwake)"); } }; - if (chrome.runtime.onInstalled) { - chrome.runtime.onInstalled.addListener(function(options) { - if (options.reason === 'install') { - extension.install(); - } - }); + if (typeof chrome != 'undefined') { + if (chrome.runtime.onInstalled) { + chrome.runtime.onInstalled.addListener(function(options) { + if (options.reason === 'install') { + extension.install(); + } + }); + } + } else { + // TODO: fallback + console.log("TODO: fallback (install)"); } }()); diff --git a/js/conversation_panel.js b/js/conversation_panel.js index 385629c3d9..4c07e13100 100644 --- a/js/conversation_panel.js +++ b/js/conversation_panel.js @@ -14,6 +14,7 @@ var conversation = bg.getConversationForWindow(windowInfo.id); if (conversation) { window.document.title = conversation.getTitle(); + console.log("new conversationview"); var view = new bg.Whisper.ConversationView({ model: conversation, appWindow: windowInfo diff --git a/js/index_mozilla.js b/js/index_mozilla.js new file mode 100644 index 0000000000..a5749dcfc3 --- /dev/null +++ b/js/index_mozilla.js @@ -0,0 +1,28 @@ +/*global $, Whisper, Backbone, textsecure, extension*/ +/* + * vim: ts=4:sw=4:expandtab + */ +(function () { + 'use strict'; + + var view; + + function render() { + var $body = $('body', document).empty(); + extension.windows.getCurrent(function(appWindow) { + view = new Whisper.InboxView({appWindow: appWindow}); + $body.append(view.$el); + + window.openConversation = function(conversation) { + if (conversation) { + view.openConversation(null, conversation); + } + }; + openConversation(getOpenConversation()); + }); + } + + //window.addEventListener('onload', render); + window.onload = render; + //render(); +}()); diff --git a/js/libaxolotl-worker.js b/js/libaxolotl-worker.js index df8c4ff6c9..d993d96aa0 100644 --- a/js/libaxolotl-worker.js +++ b/js/libaxolotl-worker.js @@ -116,7 +116,7 @@ else if (ENVIRONMENT_IS_SHELL) { } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { Module['read'] = function read(url) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; @@ -3858,7 +3858,7 @@ function copyTempDouble(ptr) { } LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { // Find length - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('HEAD', url, false); xhr.send(null); if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); @@ -3875,7 +3875,7 @@ function copyTempDouble(ptr) { if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); @@ -4789,7 +4789,7 @@ function copyTempDouble(ptr) { Browser.mouseY = y; } },xhrLoad:function (url, onload, onerror) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onload = function xhr_onload() { diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 75d720593e..3422d04a2f 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -214,7 +214,7 @@ else if (ENVIRONMENT_IS_SHELL) { } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { Module['read'] = function read(url) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; @@ -3956,7 +3956,7 @@ function copyTempDouble(ptr) { } LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { // Find length - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('HEAD', url, false); xhr.send(null); if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); @@ -3973,7 +3973,7 @@ function copyTempDouble(ptr) { if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); @@ -4887,7 +4887,7 @@ function copyTempDouble(ptr) { Browser.mouseY = y; } },xhrLoad:function (url, onload, onerror) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onload = function xhr_onload() { @@ -36211,7 +36211,7 @@ var TextSecureServer = (function() { function promise_ajax(url, options) { return new Promise(function (resolve, reject) { console.log(options.type, url); - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open(options.type, url, true /*async*/); if ( options.responseType ) { diff --git a/js/panel_controller.js b/js/panel_controller.js index db014378e7..013aa56c57 100644 --- a/js/panel_controller.js +++ b/js/panel_controller.js @@ -33,7 +33,7 @@ inboxOpened = true; extension.windows.open({ id: 'inbox', - url: 'index.html', + url: extension.windows.getLocation('index'), focused: true, width: 580, height: 440, diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index a3065ac74a..7672668935 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -28,6 +28,8 @@ }; }, initialize: function(options) { + console.log("init", options); + this.listenTo(this.model, 'destroy', this.stopListening); this.listenTo(this.model, 'change:avatar', this.updateAvatar); this.listenTo(this.model, 'change:name', this.updateTitle); @@ -63,13 +65,18 @@ }.bind(this); this.appWindow.contentWindow.addEventListener('focus', onFocus); - this.appWindow.onClosed.addListener(function () { - this.appWindow.contentWindow.removeEventListener('resize', onResize); - this.appWindow.contentWindow.removeEventListener('focus', onFocus); - window.autosize.destroy(this.$messageField); - this.remove(); - this.model.messageCollection.reset([]); - }.bind(this)); + if (typeof chrome != 'undefined') { + this.appWindow.onClosed.addListener(function () { + this.appWindow.contentWindow.removeEventListener('resize', onResize); + this.appWindow.contentWindow.removeEventListener('focus', onFocus); + window.autosize.destroy(this.$messageField); + this.remove(); + this.model.messageCollection.reset([]); + }.bind(this)); + } else { + // TODO: fallback + console.log("TODO: fallback"); + } this.fetchMessages(); }, @@ -145,9 +152,9 @@ var their_number = this.model.id; var our_number = textsecure.storage.user.getNumber(); textsecure.storage.axolotl.getIdentityKey(their_number).then(function(their_key) { - textsecure.storage.axolotl.getIdentityKey(our_number).then(function(our_key) { + textsecure.storage.axolotl.getMyIdentityKey().then(function(our_key) { var view = new Whisper.KeyVerificationView({ - model: { their_key: their_key, your_key: our_key } + model: { their_key: their_key, your_key: our_key.pubKey } }).render(); this.listenBack(view); }.bind(this)); diff --git a/js/views/file_input_view.js b/js/views/file_input_view.js index 11a534d4e9..2e2140835e 100644 --- a/js/views/file_input_view.js +++ b/js/views/file_input_view.js @@ -40,7 +40,7 @@ open: function() { // hack - if (this.window && this.window.chrome && this.window.chrome.fileSystem) { + if (typeof chrome != 'undefined' && this.window.chrome.fileSystem) { this.window.chrome.fileSystem.chooseEntry({type: 'openFile'}, function(entry) { if (!entry) { return; @@ -250,7 +250,10 @@ }, openDropped: function(e) { - if (e.originalEvent.dataTransfer.types[0] != 'Files') return; + var dropType = e.originalEvent.dataTransfer.types[0]; + if (dropType != 'Files' && dropType != 'application/x-moz-file') { + return; + } e.stopPropagation(); e.preventDefault(); @@ -260,7 +263,10 @@ }, showArea: function(e) { - if (e.originalEvent.dataTransfer.types[0] != 'Files') return; + var dropType = e.originalEvent.dataTransfer.types[0]; + if (dropType != 'Files' && dropType != 'application/x-moz-file') { + return; + } e.stopPropagation(); e.preventDefault(); @@ -268,7 +274,10 @@ }, hideArea: function(e) { - if (e.originalEvent.dataTransfer.types[0] != 'Files') return; + var dropType = e.originalEvent.dataTransfer.types[0]; + if (dropType != 'Files' && dropType != 'application/x-moz-file') { + return; + } e.stopPropagation(); e.preventDefault(); diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index 9a6a64005c..60b019c20d 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -37,7 +37,11 @@ 'click': 'reloadBackgroundPage' }, reloadBackgroundPage: function() { - chrome.runtime.reload(); + if (typeof chrome != 'undefined') { + chrome.runtime.reload(); + } else { + location.reload(); + } } }); diff --git a/libtextsecure/api.js b/libtextsecure/api.js index a72161d5e8..0fdeabd564 100644 --- a/libtextsecure/api.js +++ b/libtextsecure/api.js @@ -28,7 +28,7 @@ var TextSecureServer = (function() { function promise_ajax(url, options) { return new Promise(function (resolve, reject) { console.log(options.type, url); - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open(options.type, url, true /*async*/); if ( options.responseType ) { diff --git a/libtextsecure/libaxolotl.js b/libtextsecure/libaxolotl.js index 5ead4bc0a4..51378116fc 100644 --- a/libtextsecure/libaxolotl.js +++ b/libtextsecure/libaxolotl.js @@ -116,7 +116,7 @@ else if (ENVIRONMENT_IS_SHELL) { } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { Module['read'] = function read(url) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; @@ -3858,7 +3858,7 @@ function copyTempDouble(ptr) { } LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { // Find length - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('HEAD', url, false); xhr.send(null); if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); @@ -3875,7 +3875,7 @@ function copyTempDouble(ptr) { if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, false); if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); @@ -4789,7 +4789,7 @@ function copyTempDouble(ptr) { Browser.mouseY = y; } },xhrLoad:function (url, onload, onerror) { - var xhr = new XMLHttpRequest(); + var xhr = new XMLHttpRequest({mozSystem: true}); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onload = function xhr_onload() { diff --git a/manifest.webapp b/manifest.webapp new file mode 100644 index 0000000000..b5f999f8b2 --- /dev/null +++ b/manifest.webapp @@ -0,0 +1,26 @@ +{ + "manifest_version": 2, + + "name": "Signal", + "short_name": "Signal", + "description": "Private Messenger", + "version": "0.0.1", + "offline_enabled": false, + + "type": "privileged", + + "permissions": { + "systemXHR": { + "description": "Required to load remote content" + } + }, + + "icons": { + "16": "images/icon_16.png", + "32": "images/icon_32.png", + "48": "images/icon_48.png", + "128": "images/icon_128.png" + }, + + "launch_path": "/index_mozilla.html" +} diff --git a/options_mozilla.html b/options_mozilla.html new file mode 100644 index 0000000000..c18bdd3cd0 --- /dev/null +++ b/options_mozilla.html @@ -0,0 +1,115 @@ + + + + Signal + + + + + +
+
+ + +
+ +
+ + +
+ +
+
+

Open Signal on your phone and navigate to Settings > Devices. Tap the + button to add a new device, then scan the code above.

+ +
+ +
+

Linking with

+

+ +

This computer's name will be

+
+ +
+ +
+ +
+ +
+

+
+
+ +
+ +
+
+
+ Sorry, you have too many devices registered already. + Try removing some. +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/register_mozilla.html b/register_mozilla.html new file mode 100644 index 0000000000..cef0a2b3d8 --- /dev/null +++ b/register_mozilla.html @@ -0,0 +1,78 @@ + + + + Register for Signal + + + + + +
+
+
+
+ +
+
+

Create your Signal Account

+

Private messaging from your web browser.

+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+

+ + +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss index 0b6a7067c3..6adf42f8e9 100644 --- a/stylesheets/_conversation.scss +++ b/stylesheets/_conversation.scss @@ -555,6 +555,7 @@ z-index: 5; resize: none; font-size: 1em; + background: inherit; } } diff --git a/stylesheets/_index.scss b/stylesheets/_index.scss index a7288e19a2..0d7f71c648 100644 --- a/stylesheets/_index.scss +++ b/stylesheets/_index.scss @@ -1,3 +1,7 @@ +.inbox { + overflow: hidden; +} + .gutter { padding: $header-height 0 0; } diff --git a/stylesheets/manifest.css b/stylesheets/manifest.css index df34b4bb0e..019314e0c5 100644 --- a/stylesheets/manifest.css +++ b/stylesheets/manifest.css @@ -376,6 +376,9 @@ img.emoji { text-align: center; -webkit-user-select: text; } +.inbox { + overflow: hidden; } + .gutter { padding: 36px 0 0; } @@ -423,7 +426,7 @@ img.emoji { display: block; } .conversation-header { - border-bottom: solid 1px #d9d9d9; + border-bottom: solid 1px #dadada; margin-bottom: 4px; padding-bottom: 5px; } .conversation-header .avatar { @@ -992,7 +995,8 @@ input.search { outline: 0; z-index: 5; resize: none; - font-size: 1em; } + font-size: 1em; + background: inherit; } .toast { position: absolute;