diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
commit | da4c7e7ed675c3bf405668739c3012d140856109 (patch) | |
tree | cdd868dba063fecba609a1d819de271f0d51b23e /browser/components/firefoxview/syncedtabs.mjs | |
parent | Adding upstream version 125.0.3. (diff) | |
download | firefox-da4c7e7ed675c3bf405668739c3012d140856109.tar.xz firefox-da4c7e7ed675c3bf405668739c3012d140856109.zip |
Adding upstream version 126.0.upstream/126.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/firefoxview/syncedtabs.mjs')
-rw-r--r-- | browser/components/firefoxview/syncedtabs.mjs | 387 |
1 files changed, 69 insertions, 318 deletions
diff --git a/browser/components/firefoxview/syncedtabs.mjs b/browser/components/firefoxview/syncedtabs.mjs index d64da45a30..1c65650c10 100644 --- a/browser/components/firefoxview/syncedtabs.mjs +++ b/browser/components/firefoxview/syncedtabs.mjs @@ -4,13 +4,9 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { - BrowserUtils: "resource://gre/modules/BrowserUtils.sys.mjs", - SyncedTabs: "resource://services-sync/SyncedTabs.sys.mjs", + SyncedTabsController: "resource:///modules/SyncedTabsController.sys.mjs", }); -const { SyncedTabsErrorHandler } = ChromeUtils.importESModule( - "resource:///modules/firefox-view-synced-tabs-error-handler.sys.mjs" -); const { TabsSetupFlowManager } = ChromeUtils.importESModule( "resource:///modules/firefox-view-tabs-setup-manager.sys.mjs" ); @@ -24,43 +20,52 @@ import { ViewPage } from "./viewpage.mjs"; import { escapeHtmlEntities, isSearchEnabled, - searchTabList, MAX_TABS_FOR_RECENT_BROWSING, + navigateToLink, } from "./helpers.mjs"; -const SYNCED_TABS_CHANGED = "services.sync.tabs.changed"; -const TOPIC_SETUPSTATE_CHANGED = "firefox-view.setupstate.changed"; const UI_OPEN_STATE = "browser.tabs.firefox-view.ui-state.tab-pickup.open"; class SyncedTabsInView extends ViewPage { + controller = new lazy.SyncedTabsController(this, { + contextMenu: true, + pairDeviceCallback: () => + Services.telemetry.recordEvent( + "firefoxview_next", + "fxa_mobile", + "sync", + null, + { + has_devices: TabsSetupFlowManager.secondaryDeviceConnected.toString(), + } + ), + signupCallback: () => + Services.telemetry.recordEvent( + "firefoxview_next", + "fxa_continue", + "sync", + null + ), + }); + constructor() { super(); this._started = false; - this.boundObserve = (...args) => this.observe(...args); - this._currentSetupStateIndex = -1; - this.errorState = null; this._id = Math.floor(Math.random() * 10e6); - this.currentSyncedTabs = []; if (this.recentBrowsing) { this.maxTabsLength = MAX_TABS_FOR_RECENT_BROWSING; } else { // Setting maxTabsLength to -1 for no max this.maxTabsLength = -1; } - this.devices = []; this.fullyUpdated = false; - this.searchQuery = ""; this.showAll = false; this.cumulativeSearches = 0; + this.onSearchQuery = this.onSearchQuery.bind(this); } static properties = { ...ViewPage.properties, - errorState: { type: Number }, - currentSyncedTabs: { type: Array }, - _currentSetupStateIndex: { type: Number }, - devices: { type: Array }, - searchQuery: { type: String }, showAll: { type: Boolean }, cumulativeSearches: { type: Number }, }; @@ -72,26 +77,19 @@ class SyncedTabsInView extends ViewPage { tabLists: { all: "fxview-tab-list" }, }; - connectedCallback() { - super.connectedCallback(); - this.addEventListener("click", this); - } - start() { if (this._started) { return; } this._started = true; - Services.obs.addObserver(this.boundObserve, TOPIC_SETUPSTATE_CHANGED); - Services.obs.addObserver(this.boundObserve, SYNCED_TABS_CHANGED); - - this.updateStates(); + this.controller.addSyncObservers(); + this.controller.updateStates(); this.onVisibilityChange(); if (this.recentBrowsing) { this.recentBrowsingElement.addEventListener( "fxview-search-textbox-query", - this + this.onSearchQuery ); } } @@ -103,75 +101,21 @@ class SyncedTabsInView extends ViewPage { this._started = false; TabsSetupFlowManager.updateViewVisibility(this._id, "unloaded"); this.onVisibilityChange(); - - Services.obs.removeObserver(this.boundObserve, TOPIC_SETUPSTATE_CHANGED); - Services.obs.removeObserver(this.boundObserve, SYNCED_TABS_CHANGED); + this.controller.removeSyncObservers(); if (this.recentBrowsing) { this.recentBrowsingElement.removeEventListener( "fxview-search-textbox-query", - this + this.onSearchQuery ); } } - willUpdate(changedProperties) { - if (changedProperties.has("searchQuery")) { - this.cumulativeSearches = this.searchQuery - ? this.cumulativeSearches + 1 - : 0; - } - } - disconnectedCallback() { super.disconnectedCallback(); this.stop(); } - handleEvent(event) { - if (event.type == "click" && event.target.dataset.action) { - const { ErrorType } = SyncedTabsErrorHandler; - switch (event.target.dataset.action) { - case `${ErrorType.SYNC_ERROR}`: - case `${ErrorType.NETWORK_OFFLINE}`: - case `${ErrorType.PASSWORD_LOCKED}`: { - TabsSetupFlowManager.tryToClearError(); - break; - } - case `${ErrorType.SIGNED_OUT}`: - case "sign-in": { - TabsSetupFlowManager.openFxASignup(event.target.ownerGlobal); - break; - } - case "add-device": { - TabsSetupFlowManager.openFxAPairDevice(event.target.ownerGlobal); - break; - } - case "sync-tabs-disabled": { - TabsSetupFlowManager.syncOpenTabs(event.target); - break; - } - case `${ErrorType.SYNC_DISCONNECTED}`: { - const win = event.target.ownerGlobal; - const { switchToTabHavingURI } = - win.docShell.chromeEventHandler.ownerGlobal; - switchToTabHavingURI( - "about:preferences?action=choose-what-to-sync#sync", - true, - {} - ); - break; - } - } - } - if (event.type == "change") { - TabsSetupFlowManager.syncOpenTabs(event.target); - } - if (this.recentBrowsing && event.type === "fxview-search-textbox-query") { - this.onSearchQuery(event); - } - } - viewVisibleCallback() { this.start(); } @@ -196,90 +140,16 @@ class SyncedTabsInView extends ViewPage { this.toggleVisibilityInCardContainer(); } - async observe(subject, topic, errorState) { - if (topic == TOPIC_SETUPSTATE_CHANGED) { - this.updateStates(errorState); - } - if (topic == SYNCED_TABS_CHANGED) { - this.getSyncedTabData(); - } - } - - updateStates(errorState) { - let stateIndex = TabsSetupFlowManager.uiStateIndex; - errorState = errorState || SyncedTabsErrorHandler.getErrorType(); - - if (stateIndex == 4 && this._currentSetupStateIndex !== stateIndex) { - // trigger an initial request for the synced tabs list - this.getSyncedTabData(); - } - - this._currentSetupStateIndex = stateIndex; - this.errorState = errorState; - } - - actionMappings = { - "sign-in": { - header: "firefoxview-syncedtabs-signin-header", - description: "firefoxview-syncedtabs-signin-description", - buttonLabel: "firefoxview-syncedtabs-signin-primarybutton", - }, - "add-device": { - header: "firefoxview-syncedtabs-adddevice-header", - description: "firefoxview-syncedtabs-adddevice-description", - buttonLabel: "firefoxview-syncedtabs-adddevice-primarybutton", - descriptionLink: { - name: "url", - url: "https://support.mozilla.org/kb/how-do-i-set-sync-my-computer#w_connect-additional-devices-to-sync", - }, - }, - "sync-tabs-disabled": { - header: "firefoxview-syncedtabs-synctabs-header", - description: "firefoxview-syncedtabs-synctabs-description", - buttonLabel: "firefoxview-tabpickup-synctabs-primarybutton", - }, - loading: { - header: "firefoxview-syncedtabs-loading-header", - description: "firefoxview-syncedtabs-loading-description", - }, - }; - - generateMessageCard({ error = false, action, errorState }) { - errorState = errorState || this.errorState; - let header, - description, - descriptionLink, - buttonLabel, - headerIconUrl, - mainImageUrl; - let descriptionArray; - if (error) { - let link; - ({ header, description, link, buttonLabel } = - SyncedTabsErrorHandler.getFluentStringsForErrorType(errorState)); - action = `${errorState}`; - headerIconUrl = "chrome://global/skin/icons/info-filled.svg"; - mainImageUrl = - "chrome://browser/content/firefoxview/synced-tabs-error.svg"; - descriptionArray = [description]; - if (errorState == "password-locked") { - descriptionLink = {}; - // This is ugly, but we need to special case this link so we can - // coexist with the old view. - descriptionArray.push("firefoxview-syncedtab-password-locked-link"); - descriptionLink.name = "syncedtab-password-locked-link"; - descriptionLink.url = link.href; - } - } else { - header = this.actionMappings[action].header; - description = this.actionMappings[action].description; - buttonLabel = this.actionMappings[action].buttonLabel; - descriptionLink = this.actionMappings[action].descriptionLink; - mainImageUrl = - "chrome://browser/content/firefoxview/synced-tabs-error.svg"; - descriptionArray = [description]; - } - + generateMessageCard({ + action, + buttonLabel, + descriptionArray, + descriptionLink, + error, + header, + headerIconUrl, + mainImageUrl, + }) { return html` <fxview-empty-state headerLabel=${header} @@ -299,7 +169,7 @@ class SyncedTabsInView extends ViewPage { ?hidden=${!buttonLabel} data-l10n-id="${ifDefined(buttonLabel)}" data-action="${action}" - @click=${this.handleEvent} + @click=${e => this.controller.handleEvent(e)} aria-details="empty-container" ></button> </fxview-empty-state> @@ -307,28 +177,19 @@ class SyncedTabsInView extends ViewPage { } onOpenLink(event) { - let currentWindow = this.getWindow(); - if (currentWindow.openTrustedLinkIn) { - let where = lazy.BrowserUtils.whereToOpenLink( - event.detail.originalEvent, - false, - true - ); - if (where == "current") { - where = "tab"; + navigateToLink(event); + + Services.telemetry.recordEvent( + "firefoxview_next", + "synced_tabs", + "tabs", + null, + { + page: this.recentBrowsing ? "recentbrowsing" : "syncedtabs", } - currentWindow.openTrustedLinkIn(event.originalTarget.url, where); - Services.telemetry.recordEvent( - "firefoxview_next", - "synced_tabs", - "tabs", - null, - { - page: this.recentBrowsing ? "recentbrowsing" : "syncedtabs", - } - ); - } - if (this.searchQuery) { + ); + + if (this.controller.searchQuery) { const searchesHistogram = Services.telemetry.getKeyedHistogramById( "FIREFOX_VIEW_CUMULATIVE_SEARCHES" ); @@ -384,7 +245,7 @@ class SyncedTabsInView extends ViewPage { class="blackbox notabs search-results-empty" data-l10n-id="firefoxview-search-results-empty" data-l10n-args=${JSON.stringify({ - query: escapeHtmlEntities(this.searchQuery), + query: escapeHtmlEntities(this.controller.searchQuery), })} ></div> `, @@ -405,7 +266,8 @@ class SyncedTabsInView extends ViewPage { } onSearchQuery(e) { - this.searchQuery = e.detail.query; + this.controller.searchQuery = e.detail.query; + this.cumulativeSearches = e.detail.query ? this.cumulativeSearches + 1 : 0; this.showAll = false; } @@ -422,7 +284,7 @@ class SyncedTabsInView extends ViewPage { secondaryActionClass="options-button" hasPopup="menu" .tabItems=${ifDefined(tabItems)} - .searchQuery=${this.searchQuery} + .searchQuery=${this.controller.searchQuery} maxTabsLength=${this.showAll ? -1 : this.maxTabsLength} @fxview-tab-list-primary-action=${this.onOpenLink} @fxview-tab-list-secondary-action=${this.onContextMenu} @@ -434,33 +296,9 @@ class SyncedTabsInView extends ViewPage { generateTabList() { let renderArray = []; - let renderInfo = {}; - for (let tab of this.currentSyncedTabs) { - if (!(tab.client in renderInfo)) { - renderInfo[tab.client] = { - name: tab.device, - deviceType: tab.deviceType, - tabs: [], - }; - } - renderInfo[tab.client].tabs.push(tab); - } - - // Add devices without tabs - for (let device of this.devices) { - if (!(device.id in renderInfo)) { - renderInfo[device.id] = { - name: device.name, - deviceType: device.clientType, - tabs: [], - }; - } - } - + let renderInfo = this.controller.getRenderInfo(); for (let id in renderInfo) { - let tabItems = this.searchQuery - ? searchTabList(this.searchQuery, this.getTabItems(renderInfo[id].tabs)) - : this.getTabItems(renderInfo[id].tabs); + let tabItems = renderInfo[id].tabItems; if (tabItems.length) { const template = this.recentBrowsing ? this.deviceTemplate( @@ -509,7 +347,7 @@ class SyncedTabsInView extends ViewPage { isShowAllLinkVisible(tabItems) { return ( this.recentBrowsing && - this.searchQuery && + this.controller.searchQuery && tabItems.length > this.maxTabsLength && !this.showAll ); @@ -536,35 +374,10 @@ class SyncedTabsInView extends ViewPage { } generateCardContent() { - switch (this._currentSetupStateIndex) { - case 0 /* error-state */: - if (this.errorState) { - return this.generateMessageCard({ error: true }); - } - return this.generateMessageCard({ action: "loading" }); - case 1 /* not-signed-in */: - if (Services.prefs.prefHasUserValue("services.sync.lastversion")) { - // If this pref is set, the user has signed out of sync. - // This path is also taken if we are disconnected from sync. See bug 1784055 - return this.generateMessageCard({ - error: true, - errorState: "signed-out", - }); - } - return this.generateMessageCard({ action: "sign-in" }); - case 2 /* connect-secondary-device*/: - return this.generateMessageCard({ action: "add-device" }); - case 3 /* disabled-tab-sync */: - return this.generateMessageCard({ action: "sync-tabs-disabled" }); - case 4 /* synced-tabs-loaded*/: - // There seems to be an edge case where sync says everything worked - // fine but we have no devices. - if (!this.devices.length) { - return this.generateMessageCard({ action: "add-device" }); - } - return this.generateTabList(); - } - return html``; + const cardProperties = this.controller.getMessageCard(); + return cardProperties + ? this.generateMessageCard(cardProperties) + : this.generateTabList(); } render() { @@ -589,7 +402,7 @@ class SyncedTabsInView extends ViewPage { data-l10n-id="firefoxview-synced-tabs-header" ></h2> ${when( - isSearchEnabled() || this._currentSetupStateIndex === 4, + isSearchEnabled() || this.controller.currentSetupStateIndex === 4, () => html`<div class="syncedtabs-header"> ${when( isSearchEnabled(), @@ -606,12 +419,12 @@ class SyncedTabsInView extends ViewPage { </div>` )} ${when( - this._currentSetupStateIndex === 4, + this.controller.currentSetupStateIndex === 4, () => html` <button class="small-button" data-action="add-device" - @click=${this.handleEvent} + @click=${e => this.controller.handleEvent(e)} > <img class="icon" @@ -635,9 +448,9 @@ class SyncedTabsInView extends ViewPage { html`<card-container preserveCollapseState shortPageName="syncedtabs" - ?showViewAll=${this._currentSetupStateIndex == 4 && - this.currentSyncedTabs.length} - ?isEmptyState=${!this.currentSyncedTabs.length} + ?showViewAll=${this.controller.currentSetupStateIndex == 4 && + this.controller.currentSyncedTabs.length} + ?isEmptyState=${!this.controller.currentSyncedTabs.length} > > <h3 @@ -656,71 +469,9 @@ class SyncedTabsInView extends ViewPage { return renderArray; } - async onReload() { - await TabsSetupFlowManager.syncOnPageReload(); - } - - getTabItems(tabs) { - tabs = tabs || this.tabs; - return tabs?.map(tab => ({ - icon: tab.icon, - title: tab.title, - time: tab.lastUsed * 1000, - url: tab.url, - primaryL10nId: "firefoxview-tabs-list-tab-button", - primaryL10nArgs: JSON.stringify({ targetURI: tab.url }), - secondaryL10nId: "fxviewtabrow-options-menu-button", - secondaryL10nArgs: JSON.stringify({ tabTitle: tab.title }), - })); - } - - updateTabsList(syncedTabs) { - if (!syncedTabs.length) { - this.currentSyncedTabs = syncedTabs; - this.sendTabTelemetry(0); - } - - const tabsToRender = syncedTabs; - - // Return early if new tabs are the same as previous ones - if ( - JSON.stringify(tabsToRender) == JSON.stringify(this.currentSyncedTabs) - ) { - return; - } - - this.currentSyncedTabs = tabsToRender; - // Record the full tab count - this.sendTabTelemetry(syncedTabs.length); - } - - async getSyncedTabData() { - this.devices = await lazy.SyncedTabs.getTabClients(); - let tabs = await lazy.SyncedTabs.createRecentTabsList(this.devices, 50, { - removeAllDupes: false, - removeDeviceDupes: true, - }); - - this.updateTabsList(tabs); - } - updated() { this.fullyUpdated = true; this.toggleVisibilityInCardContainer(); } - - sendTabTelemetry(numTabs) { - /* - Services.telemetry.recordEvent( - "firefoxview_next", - "synced_tabs", - "tabs", - null, - { - count: numTabs.toString(), - } - ); -*/ - } } customElements.define("view-syncedtabs", SyncedTabsInView); |