diff options
Diffstat (limited to 'browser/components/syncedtabs/SyncedTabsListStore.js')
-rw-r--r-- | browser/components/syncedtabs/SyncedTabsListStore.js | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/browser/components/syncedtabs/SyncedTabsListStore.js b/browser/components/syncedtabs/SyncedTabsListStore.js deleted file mode 100644 index 8f03d9a89..000000000 --- a/browser/components/syncedtabs/SyncedTabsListStore.js +++ /dev/null @@ -1,235 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -let { EventEmitter } = Cu.import("resource:///modules/syncedtabs/EventEmitter.jsm", {}); - -this.EXPORTED_SYMBOLS = [ - "SyncedTabsListStore" -]; - -/** - * SyncedTabsListStore - * - * Instances of this store encapsulate all of the state associated with a synced tabs list view. - * The state includes the clients, their tabs, the row that is currently selected, - * and the filtered query. - */ -function SyncedTabsListStore(SyncedTabs) { - EventEmitter.call(this); - this._SyncedTabs = SyncedTabs; - this.data = []; - this._closedClients = {}; - this._selectedRow = [-1, -1]; - this.filter = ""; - this.inputFocused = false; -} - -Object.assign(SyncedTabsListStore.prototype, EventEmitter.prototype, { - // This internal method triggers the "change" event that views - // listen for. It denormalizes the state so that it's easier for - // the view to deal with. updateType hints to the view what - // actually needs to be rerendered or just updated, and can be - // empty (to (re)render everything), "searchbox" (to rerender just the tab list), - // or "all" (to skip rendering and just update all attributes of existing nodes). - _change(updateType) { - let selectedParent = this._selectedRow[0]; - let selectedChild = this._selectedRow[1]; - let rowSelected = false; - // clone the data so that consumers can't mutate internal storage - let data = Cu.cloneInto(this.data, {}); - let tabCount = 0; - - data.forEach((client, index) => { - client.closed = !!this._closedClients[client.id]; - - if (rowSelected || selectedParent < 0) { - return; - } - if (this.filter) { - if (selectedParent < tabCount + client.tabs.length) { - client.tabs[selectedParent - tabCount].selected = true; - client.tabs[selectedParent - tabCount].focused = !this.inputFocused; - rowSelected = true; - } else { - tabCount += client.tabs.length; - } - return; - } - if (selectedParent === index && selectedChild === -1) { - client.selected = true; - client.focused = !this.inputFocused; - rowSelected = true; - } else if (selectedParent === index) { - client.tabs[selectedChild].selected = true; - client.tabs[selectedChild].focused = !this.inputFocused; - rowSelected = true; - } - }); - - // If this were React the view would be smart enough - // to not re-render the whole list unless necessary. But it's - // not, so updateType is a hint to the view of what actually - // needs to be rerendered. - this.emit("change", { - clients: data, - canUpdateAll: updateType === "all", - canUpdateInput: updateType === "searchbox", - filter: this.filter, - inputFocused: this.inputFocused - }); - }, - - /** - * Moves the row selection from a child to its parent, - * which occurs when the parent of a selected row closes. - */ - _selectParentRow() { - this._selectedRow[1] = -1; - }, - - _toggleBranch(id, closed) { - this._closedClients[id] = closed; - if (this._closedClients[id]) { - this._selectParentRow(); - } - this._change("all"); - }, - - _isOpen(client) { - return !this._closedClients[client.id]; - }, - - moveSelectionDown() { - let branchRow = this._selectedRow[0]; - let childRow = this._selectedRow[1]; - let branch = this.data[branchRow]; - - if (this.filter) { - this.selectRow(branchRow + 1); - return; - } - - if (branchRow < 0) { - this.selectRow(0, -1); - } else if ((!branch.tabs.length || childRow >= branch.tabs.length - 1 || !this._isOpen(branch)) && branchRow < this.data.length) { - this.selectRow(branchRow + 1, -1); - } else if (childRow < branch.tabs.length) { - this.selectRow(branchRow, childRow + 1); - } - }, - - moveSelectionUp() { - let branchRow = this._selectedRow[0]; - let childRow = this._selectedRow[1]; - - if (this.filter) { - this.selectRow(branchRow - 1); - return; - } - - if (branchRow < 0) { - this.selectRow(0, -1); - } else if (childRow < 0 && branchRow > 0) { - let prevBranch = this.data[branchRow - 1]; - let newChildRow = this._isOpen(prevBranch) ? prevBranch.tabs.length - 1 : -1; - this.selectRow(branchRow - 1, newChildRow); - } else if (childRow >= 0) { - this.selectRow(branchRow, childRow - 1); - } - }, - - // Selects a row and makes sure the selection is within bounds - selectRow(parent, child) { - let maxParentRow = this.filter ? this._tabCount() : this.data.length; - let parentRow = parent; - if (parent <= -1) { - parentRow = 0; - } else if (parent >= maxParentRow) { - return; - } - - let childRow = child; - if (parentRow === -1 || this.filter || typeof child === "undefined" || child < -1) { - childRow = -1; - } else if (child >= this.data[parentRow].tabs.length) { - childRow = this.data[parentRow].tabs.length - 1; - } - - if (this._selectedRow[0] === parentRow && this._selectedRow[1] === childRow) { - return; - } - - this._selectedRow = [parentRow, childRow]; - this.inputFocused = false; - this._change("all"); - }, - - _tabCount() { - return this.data.reduce((prev, curr) => curr.tabs.length + prev, 0); - }, - - toggleBranch(id) { - this._toggleBranch(id, !this._closedClients[id]); - }, - - closeBranch(id) { - this._toggleBranch(id, true); - }, - - openBranch(id) { - this._toggleBranch(id, false); - }, - - focusInput() { - this.inputFocused = true; - // A change type of "all" updates rather than rebuilds, which is what we - // want here - only the selection/focus has changed. - this._change("all"); - }, - - blurInput() { - this.inputFocused = false; - // A change type of "all" updates rather than rebuilds, which is what we - // want here - only the selection/focus has changed. - this._change("all"); - }, - - clearFilter() { - this.filter = ""; - this._selectedRow = [-1, -1]; - return this.getData(); - }, - - // Fetches data from the SyncedTabs module and triggers - // and update - getData(filter) { - let updateType; - let hasFilter = typeof filter !== "undefined"; - if (hasFilter) { - this.filter = filter; - this._selectedRow = [-1, -1]; - - // When a filter is specified we tell the view that only the list - // needs to be rerendered so that it doesn't disrupt the input - // field's focus. - updateType = "searchbox"; - } - - // return promise for tests - return this._SyncedTabs.getTabClients(this.filter) - .then(result => { - if (!hasFilter) { - // Only sort clients and tabs if we're rendering the whole list. - this._SyncedTabs.sortTabClientsByLastUsed(result); - } - this.data = result; - this._change(updateType); - }) - .catch(Cu.reportError); - } -}); |