From 783a3f7c157b7719935c9c10c0440070d61796b6 Mon Sep 17 00:00:00 2001 From: Riley Shaw Date: Sun, 18 Jan 2015 15:43:25 -1000 Subject: [PATCH] Prevent duplicate conversations and refocus on click (still buggy) --- background.html | 2 + index2.html | 3 + js/background.js | 8 ++ js/conversation_panel.js | 10 +-- js/panel_controller.js | 97 +++++++++++++++++++++++++ js/views/conversation_list_item_view.js | 16 +--- js/views/file_input_view.js | 1 + 7 files changed, 116 insertions(+), 21 deletions(-) create mode 100644 js/panel_controller.js diff --git a/background.html b/background.html index 9f665f44..30017728 100644 --- a/background.html +++ b/background.html @@ -24,6 +24,8 @@ + + diff --git a/index2.html b/index2.html index 9571a887..026bfbd8 100644 --- a/index2.html +++ b/index2.html @@ -57,6 +57,9 @@ + + + diff --git a/js/background.js b/js/background.js index b91f8c45..af872969 100644 --- a/js/background.js +++ b/js/background.js @@ -225,4 +225,12 @@ extension.on('log', console.log.bind(console)); + chrome.runtime.onConnect.addListener(function (port) { + if (port.name === 'panel_presence') { + port.onDisconnect.addListener(function (message) { + closeConversation(message.sender.tab.windowId); + }); + } + }); + })(); diff --git a/js/conversation_panel.js b/js/conversation_panel.js index 56feab88..afbf7ed6 100644 --- a/js/conversation_panel.js +++ b/js/conversation_panel.js @@ -26,12 +26,9 @@ }); }; - var windowId, windowMap = {}; - - extension.trigger('log', 'loaded page'); + var windowId, windowMap = JSON.parse(localStorage.getItem('idPairs')); window.addEventListener('storage', function (e) { - extension.trigger('log', 'got storage event'); if (e.key = 'idPairs') { windowMap = JSON.parse(e.newValue); @@ -48,12 +45,13 @@ chrome.windows.getCurrent(function (windowInfo) { window.document.title = windowId = windowInfo.id; - extension.trigger('log', 'got page id'); - var conversationId = windowMap[windowId]; if (typeof conversationId !== 'undefined') { loadConversation(conversationId); } }); + + // lets background.js know when a panel disconnects + var port = chrome.runtime.connect({name: "panel_presence"}); }()); diff --git a/js/panel_controller.js b/js/panel_controller.js new file mode 100644 index 00000000..9b29ebe2 --- /dev/null +++ b/js/panel_controller.js @@ -0,0 +1,97 @@ +/*global $, Whisper, Backbone, textsecure, extension*/ +/* vim: ts=4:sw=4:expandtab: + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +(function () { + 'use strict'; + + window.Whisper = window.Whisper || {}; + + // TODO: RJS + // resetting for now, but super fragile: + // 1. if this file is included in conversation.html we're doomed. + // 2. if index.html is refreshed, duplicates can be opened + // 2.5. ...and refreshing conversation windows will fuck up. + if (!localStorage.getItem('activeConversations')) { + localStorage.setItem('activeConversations', '{}'); + } + + if (!localStorage.getItem('idPairs')) { + localStorage.setItem('idPairs', '{}'); + } + + // TODO: RJS + // How do we normally export from modules like this? + // Is it necessary to have n copies of each of these scripts..? + // (n Whisper objects, etc in existence) Using localStorage for + // sync feels like a hack... + // + window.openConversation = function openConversation (modelId) { + var activeConversations = JSON.parse(localStorage.getItem('activeConversations')); + var windowId = activeConversations[modelId]; + + // prevent multiple copies of the same conversation from being opened + if (!windowId) { + localStorage.setItem('activeConversations', JSON.stringify(activeConversations)); + + // open the window + chrome.windows.create({ + url: 'conversation.html', + type: 'panel', + focused: true, + width: 280, + height: 420 + }, function (windowInfo) { + var idPairs = JSON.parse(localStorage.getItem('idPairs')); + var newWindowId = windowInfo.id; + + // TODO: RJS + // should we make a class for bijection? + // bit sketchy that we have to keep these two hashes synced... + activeConversations[modelId] = newWindowId; + idPairs[newWindowId] = modelId; + + localStorage.setItem('activeConversations', JSON.stringify(activeConversations)); + localStorage.setItem('idPairs', JSON.stringify(idPairs)); + }); + } else { + try { + chrome.windows.update(windowId, { focused: true }, function () { + if (chrome.runtime.lastError) { + window.closeConversation(windowId); + } else { + // Tab exists + } + }); + } catch (err) { + // TODO: RJS + // - should check the err type + // - should open a new panel here + } + } + }; + + window.closeConversation = function closeConversation (windowId) { + var activeConversations = JSON.parse(localStorage.getItem('activeConversations')); + var idPairs = JSON.parse(localStorage.getItem('idPairs')); + + delete activeConversations[idPairs[windowId]]; + delete idPairs[windowId]; + + localStorage.setItem('activeConversations', JSON.stringify(activeConversations)); + localStorage.setItem('idPairs', JSON.stringify(idPairs)); + }; +}()); diff --git a/js/views/conversation_list_item_view.js b/js/views/conversation_list_item_view.js index d527a390..e221d282 100644 --- a/js/views/conversation_list_item_view.js +++ b/js/views/conversation_list_item_view.js @@ -45,21 +45,7 @@ var Whisper = Whisper || {}; this.view = new Whisper.ConversationView({ model: this.model }); } - chrome.windows.create({ - url: 'conversation.html#' + modelId, - type: 'panel', - focused: true, - width: 280, - height: 420 - }, function (windowInfo) { - extension.trigger('log', 'maybe up here?'); - extension.trigger('log', localStorage.getItem('idPairs')); - - var idPairs = JSON.parse(localStorage.getItem('idPairs') || '{}'); - idPairs[windowInfo.id] = modelId; - localStorage.setItem('idPairs', JSON.stringify(idPairs)); - extension.trigger('log', 'set idPairs item'); - }); + openConversation(modelId); this.model.collection.trigger('selected', this.view); }, diff --git a/js/views/file_input_view.js b/js/views/file_input_view.js index 634b17f5..6b9f8709 100644 --- a/js/views/file_input_view.js +++ b/js/views/file_input_view.js @@ -17,6 +17,7 @@ var Whisper = Whisper || {}; (function () { 'use strict'; + Whisper.FileInputView = Backbone.View.extend({ tagName: 'span', className: 'file-input',