Bug 1939599: Tab groups can be restored by Ctrl+Shift+T r=dao,sthompson,sessionstore-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D233102
This commit is contained in:
@@ -5977,6 +5977,10 @@ function restoreLastClosedTabOrWindowOrSession() {
|
|||||||
undoCloseTab();
|
undoCloseTab();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SessionStore.LAST_ACTION_CLOSED_TAB_GROUP: {
|
||||||
|
undoCloseTabGroup(lastActionTaken.closedId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SessionStore.LAST_ACTION_CLOSED_WINDOW: {
|
case SessionStore.LAST_ACTION_CLOSED_WINDOW: {
|
||||||
undoCloseWindow();
|
undoCloseWindow();
|
||||||
break;
|
break;
|
||||||
@@ -6051,6 +6055,38 @@ function undoCloseTab(aIndex, sourceWindowSSId) {
|
|||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-open a closed tab group.
|
||||||
|
* @param {string} tabGroupId
|
||||||
|
* The tab group's unique ID.
|
||||||
|
* @returns {MozTabbrowserTabGroup} the reopened group.
|
||||||
|
*/
|
||||||
|
function undoCloseTabGroup(tabGroupId) {
|
||||||
|
let targetWindow = window;
|
||||||
|
|
||||||
|
// wallpaper patch to prevent an unnecessary blank tab (bug 343895)
|
||||||
|
let blankTabToRemove = null;
|
||||||
|
if (
|
||||||
|
targetWindow.gBrowser.visibleTabs.length == 1 &&
|
||||||
|
targetWindow.gBrowser.selectedTab.isEmpty
|
||||||
|
) {
|
||||||
|
blankTabToRemove = targetWindow.gBrowser.selectedTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
let group;
|
||||||
|
try {
|
||||||
|
group = SessionStore.undoCloseTabGroup(window, tabGroupId, targetWindow);
|
||||||
|
} catch (err) {
|
||||||
|
group = SessionStore.openSavedTabGroup(tabGroupId, targetWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group && blankTabToRemove) {
|
||||||
|
targetWindow.gBrowser.removeTab(blankTabToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-open a closed window.
|
* Re-open a closed window.
|
||||||
* @param aIndex
|
* @param aIndex
|
||||||
|
|||||||
@@ -90,6 +90,7 @@
|
|||||||
"AddKeywordForSearchField",
|
"AddKeywordForSearchField",
|
||||||
"restoreLastClosedTabOrWindowOrSession",
|
"restoreLastClosedTabOrWindowOrSession",
|
||||||
"undoCloseTab",
|
"undoCloseTab",
|
||||||
|
"undoCloseTabGroup",
|
||||||
"undoCloseWindow",
|
"undoCloseWindow",
|
||||||
"ReportFalseDeceptiveSite",
|
"ReportFalseDeceptiveSite",
|
||||||
"ReportSiteIssue",
|
"ReportSiteIssue",
|
||||||
|
|||||||
@@ -237,6 +237,10 @@ export var SessionStore = {
|
|||||||
return SessionStoreInternal._LAST_ACTION_CLOSED_TAB;
|
return SessionStoreInternal._LAST_ACTION_CLOSED_TAB;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get LAST_ACTION_CLOSED_TAB_GROUP() {
|
||||||
|
return SessionStoreInternal._LAST_ACTION_CLOSED_TAB_GROUP;
|
||||||
|
},
|
||||||
|
|
||||||
get LAST_ACTION_CLOSED_WINDOW() {
|
get LAST_ACTION_CLOSED_WINDOW() {
|
||||||
return SessionStoreInternal._LAST_ACTION_CLOSED_WINDOW;
|
return SessionStoreInternal._LAST_ACTION_CLOSED_WINDOW;
|
||||||
},
|
},
|
||||||
@@ -1047,6 +1051,8 @@ var SessionStoreInternal = {
|
|||||||
|
|
||||||
_LAST_ACTION_CLOSED_TAB: "tab",
|
_LAST_ACTION_CLOSED_TAB: "tab",
|
||||||
|
|
||||||
|
_LAST_ACTION_CLOSED_TAB_GROUP: "tab-group",
|
||||||
|
|
||||||
_LAST_ACTION_CLOSED_WINDOW: "window",
|
_LAST_ACTION_CLOSED_WINDOW: "window",
|
||||||
|
|
||||||
_log: null,
|
_log: null,
|
||||||
@@ -3046,6 +3052,15 @@ var SessionStoreInternal = {
|
|||||||
win,
|
win,
|
||||||
tabGroup
|
tabGroup
|
||||||
) {
|
) {
|
||||||
|
// don't update our internal state if we don't have to
|
||||||
|
if (this._max_tabs_undo == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the closed action right away to make sure it's also being
|
||||||
|
// recorded for groups that are saved and closed
|
||||||
|
this._addClosedAction(this._LAST_ACTION_CLOSED_TAB_GROUP, tabGroup.id);
|
||||||
|
|
||||||
if (this.getSavedTabGroup(tabGroup.id)) {
|
if (this.getSavedTabGroup(tabGroup.id)) {
|
||||||
// If a tab group is being removed from the tab strip but it's already
|
// If a tab group is being removed from the tab strip but it's already
|
||||||
// saved, then this is a "save and close" action; the saved tab group
|
// saved, then this is a "save and close" action; the saved tab group
|
||||||
@@ -3054,24 +3069,17 @@ var SessionStoreInternal = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't update our internal state if we don't have to
|
|
||||||
if (this._max_tabs_undo == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let closedGroups = this._windows[win.__SSi].closedGroups;
|
let closedGroups = this._windows[win.__SSi].closedGroups;
|
||||||
|
|
||||||
let tabGroupState = lazy.TabGroupState.closed(tabGroup, win.__SSi);
|
let tabGroupState = lazy.TabGroupState.closed(tabGroup, win.__SSi);
|
||||||
tabGroupState.tabs = this._collectClosedTabsForTabGroup(tabGroup.tabs, win);
|
tabGroupState.tabs = this._collectClosedTabsForTabGroup(tabGroup.tabs, win);
|
||||||
|
|
||||||
// TODO(jswinarton) it's unclear if updating lastClosedTabGroupCount is
|
// TODO(jswinarton) it's unclear if updating lastClosedTabGroupCount is
|
||||||
// necessary when restoring tab groups — it largely depends on how we
|
// necessary when restoring tab groups — it largely depends on how we
|
||||||
// decide to do the restore. If we add a _LAST_ACTION_CLOSED_TAB_GROUP
|
// decide to do the restore.
|
||||||
// item to the closed actions list, this may not be necessary.
|
|
||||||
// To address in bug1915174
|
// To address in bug1915174
|
||||||
this._windows[win.__SSi]._lastClosedTabGroupCount =
|
this._windows[win.__SSi]._lastClosedTabGroupCount =
|
||||||
tabGroupState.tabs.length;
|
tabGroupState.tabs.length;
|
||||||
closedGroups.push(tabGroupState);
|
closedGroups.unshift(tabGroupState);
|
||||||
this._closedObjectsChanged = true;
|
this._closedObjectsChanged = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3312,8 +3320,16 @@ var SessionStoreInternal = {
|
|||||||
* The tabData to be inserted.
|
* The tabData to be inserted.
|
||||||
* @param closedTabs (array)
|
* @param closedTabs (array)
|
||||||
* The list of closed tabs for a window.
|
* The list of closed tabs for a window.
|
||||||
|
* @param saveAction (boolean|null)
|
||||||
|
* Whether or not to add an action to the closed actions stack on save.
|
||||||
|
* True by default if the tab was not closed as part of a tab group; false otherwise.
|
||||||
*/
|
*/
|
||||||
saveClosedTabData(winData, closedTabs, tabData, saveAction = true) {
|
saveClosedTabData(winData, closedTabs, tabData, saveAction = null) {
|
||||||
|
if (saveAction === null) {
|
||||||
|
// By default, a closed action for this tab, but only if it wasn't closed as part of a tab group.
|
||||||
|
saveAction = closedTabs === winData._closedTabs;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the index of the first tab in the list
|
// Find the index of the first tab in the list
|
||||||
// of closed tabs that was closed before our tab.
|
// of closed tabs that was closed before our tab.
|
||||||
let index = closedTabs.findIndex(tab => {
|
let index = closedTabs.findIndex(tab => {
|
||||||
@@ -4128,7 +4144,7 @@ var SessionStoreInternal = {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
groupIdx < closedGroups.length &&
|
groupIdx < closedGroups.length &&
|
||||||
(tabIdx >= closedTabs.length || group?.closedAt < tab?.closedAt)
|
(tabIdx >= closedTabs.length || group?.closedAt > tab?.closedAt)
|
||||||
) {
|
) {
|
||||||
group.tabs.forEach((groupTab, idx) => {
|
group.tabs.forEach((groupTab, idx) => {
|
||||||
groupTab._originalStateIndex = idx;
|
groupTab._originalStateIndex = idx;
|
||||||
|
|||||||
@@ -173,6 +173,74 @@ add_task(async function test_undo_last_action() {
|
|||||||
"Window still has two open tabs"
|
"Window still has two open tabs"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// create a tab group, delete it, and re-open it
|
||||||
|
const groupedTab = BrowserTestUtils.addTab(
|
||||||
|
window.gBrowser,
|
||||||
|
"https://example.com"
|
||||||
|
);
|
||||||
|
await BrowserTestUtils.browserLoaded(groupedTab.linkedBrowser);
|
||||||
|
const tabGroup = window.gBrowser.addTabGroup([groupedTab]);
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabs.length,
|
||||||
|
3,
|
||||||
|
"Window has three tabs after creating tab group"
|
||||||
|
);
|
||||||
|
|
||||||
|
await TabStateFlusher.flushWindow(window);
|
||||||
|
let removePromise = BrowserTestUtils.waitForEvent(
|
||||||
|
tabGroup,
|
||||||
|
"TabGroupRemoved"
|
||||||
|
);
|
||||||
|
window.gBrowser.removeTabGroup(tabGroup);
|
||||||
|
await removePromise;
|
||||||
|
|
||||||
|
restoreLastClosedTabOrWindowOrSession();
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabs.length,
|
||||||
|
3,
|
||||||
|
"Window has three tabs after restoring tab group"
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabGroups.length,
|
||||||
|
1,
|
||||||
|
"Tab group exists on the tab strip after restore"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save and close the tab group, and then re-open it
|
||||||
|
const groupedTabToSave = BrowserTestUtils.addTab(
|
||||||
|
window.gBrowser,
|
||||||
|
"https://example.com"
|
||||||
|
);
|
||||||
|
await BrowserTestUtils.browserLoaded(groupedTabToSave.linkedBrowser);
|
||||||
|
const tabGroupToSave = window.gBrowser.addTabGroup([groupedTabToSave]);
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabs.length,
|
||||||
|
4,
|
||||||
|
"Window has four tabs after creating tab group"
|
||||||
|
);
|
||||||
|
|
||||||
|
await TabStateFlusher.flushWindow(window);
|
||||||
|
tabGroupToSave.save();
|
||||||
|
removePromise = BrowserTestUtils.waitForEvent(
|
||||||
|
tabGroupToSave,
|
||||||
|
"TabGroupRemoved"
|
||||||
|
);
|
||||||
|
window.gBrowser.removeTabGroup(tabGroupToSave);
|
||||||
|
await removePromise;
|
||||||
|
|
||||||
|
await TabStateFlusher.flushWindow(window);
|
||||||
|
restoreLastClosedTabOrWindowOrSession();
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabs.length,
|
||||||
|
4,
|
||||||
|
"Window has four tabs after restoring tab group"
|
||||||
|
);
|
||||||
|
Assert.equal(
|
||||||
|
window.gBrowser.tabGroups.length,
|
||||||
|
2,
|
||||||
|
"Tab group exists on the tab strip after restore"
|
||||||
|
);
|
||||||
|
|
||||||
gBrowser.removeAllTabsBut(gBrowser.tabs[0]);
|
gBrowser.removeAllTabsBut(gBrowser.tabs[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user