Skip to content

Commit

Permalink
🚧 WIP: Add support for dragging the tab's x position
Browse files Browse the repository at this point in the history
  • Loading branch information
kierandrewett committed Aug 19, 2023
1 parent c8a14fc commit d949d8d
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 20 deletions.
98 changes: 84 additions & 14 deletions components/tabs/BrowserTabs.sys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const { NavigationHelper } = ChromeUtils.importESModule(
"resource://gre/modules/NavigationHelper.sys.mjs"
);

const { BrowserTabsUtils } = ChromeUtils.importESModule(
"resource://gre/modules/BrowserTabsUtils.sys.mjs"
);

/**
* Clamps a number between a min and max value
* @param {number} value
Expand All @@ -23,15 +27,6 @@ function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}

// Ensure that these icons match up with the actual page favicon
// Reflect any changes here with base/content/browser-init.ts
const INITIAL_FAVICONS = {
"about:home": "chrome://dot/skin/home.svg",
"about:newtab": "chrome://dot/skin/home.svg",
"about:welcome": "chrome://branding/content/icon32.png",
"about:privatebrowsing": "chrome://browser/skin/privatebrowsing/favicon.svg"
};

const {
LOAD_FLAGS_NONE,
LOAD_FLAGS_FROM_EXTERNAL,
Expand Down Expand Up @@ -165,6 +160,12 @@ BrowserTabs.prototype = {
return this._win.document.getElementById("tabspanel");
},

/**
* The tab that is currently being dragged
* @type {BrowserTab}
*/
draggingTab: null,

/**
* Initialises and creates the <tab> element
* @private
Expand Down Expand Up @@ -416,12 +417,13 @@ BrowserTabs.prototype = {
openWindowInfo
});

this._setInitialIcon(tabEl, uri.spec);
this.setInitialMetadata(tabEl, uri.spec);
}

this._insertTabWebContents(tabEl, options.webContents);

tabEl.registerEventListeners();
this._setupTabDragListeners();
} catch (e) {
console.error("Error while creating tab!");
console.error(e);
Expand Down Expand Up @@ -533,13 +535,35 @@ BrowserTabs.prototype = {
},

/**
* Sets the initial icon of a tab to avoid preloading
* Clear a tab's favicon
*
* @param {BrowserTab} tab
*/
clearIcon(tab) {
tab.clearIcon();
},

/**
* Update a tab's title
*
* @param {BrowserTab} tab
* @param {string} title
*/
setTitle(tab, title) {
tab.updateLabel(title);
},

/**
* Sets the initial metadata of a tab to avoid preloading
* @param {BrowserTab} tab
* @param {string} uri
*/
_setInitialIcon(tab, uri) {
if (uri && uri in INITIAL_FAVICONS) {
this.setIcon(tab, INITIAL_FAVICONS[uri]);
setInitialMetadata(tab, uri) {
if (uri && uri in BrowserTabsUtils.INTERNAL_PAGES) {
const data = BrowserTabsUtils.INTERNAL_PAGES[uri];

this.setIcon(tab, data.icon);
this.setTitle(tab, data.title);
}
},

Expand Down Expand Up @@ -822,6 +846,52 @@ BrowserTabs.prototype = {
return parseInt(webContents.id);
},

/**
* Handles incoming tab drag events
* @param {MouseEvent} event
*/
_onHandleTabDragEvent(event) {
const target = /** @type {HTMLElement} */ (event.target);
const tab = /** @type {BrowserTab} */ (target && target.nodeType == Node.ELEMENT_NODE && target.closest("tab"));

if (tab) {
switch (event.type) {
case "mousedown":
this.draggingTab = tab;
break;
}
}

switch (event.type) {
case "mouseup":
if (this.draggingTab) {
this.draggingTab.style.transform = `translateX(0px)`
this.draggingTab = null;
}
break;
case "mousemove":
if (this.draggingTab) {
this.draggingTab.style.transform = `translateX(${event.clientX}px)`
}
break;
}
},

_tabDragListenersInit: false,

/**
* Initialises the tab dragging event listeners
*/
_setupTabDragListeners() {
if (this._tabDragListenersInit) return;

this._win.addEventListener("mousemove", this._onHandleTabDragEvent.bind(this));
this._win.addEventListener("mouseup", this._onHandleTabDragEvent.bind(this));
this._win.addEventListener("mousedown", this._onHandleTabDragEvent.bind(this));

this._tabDragListenersInit = true;
},

/**
* Find a tab using its webContents
* @param {ChromeBrowser | Element} webContents
Expand Down
57 changes: 51 additions & 6 deletions components/tabs/content/browser-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ function injectCompat(tab) {

const kDefaultTabIcon = "chrome://dot/skin/globe.svg";

const kDefaultTabTitles = {
"about:blank": "New Tab",
"about:home": "New Tab",
"about:newtab": "New Tab",
}

/**
* @typedef {import("third_party/dothq/gecko-types/lib").ChromeBrowser} ChromeBrowser
*/
Expand All @@ -29,6 +35,10 @@ class BrowserTab extends MozElements.MozTab {
TAB_PROGRESS_BUSY = 1;
TAB_PROGRESS_TRANSIT = 2;

REGISTERED_EVENTS = [
"mousedown",
]

constructor() {
super();

Expand Down Expand Up @@ -138,6 +148,13 @@ class BrowserTab extends MozElements.MozTab {
this.setAttribute("progress", val.toString());
}

/**
* Determines the tab's dragging state
*/
get dragging() {
return gDot.tabs.draggingTab && gDot.tabs.draggingTab.id == this.id;
}

_progressPercent = 0;

/**
Expand All @@ -149,6 +166,7 @@ class BrowserTab extends MozElements.MozTab {

set progressPercent(val) {
this.style.setProperty("--tab-load-percent", val + "%");
console.log(val + "%");
this._progressPercent = val;
}

Expand Down Expand Up @@ -216,8 +234,15 @@ class BrowserTab extends MozElements.MozTab {
connectedCallback() {
if (this.delayConnectedCallback()) return;

this.appendChild(html("img", { class: "browser-tab-icon" }));
this.appendChild(html("div", { class: "browser-tab-spinner" }));
this.appendChild(
html(
"div",
{ class: "browser-tab-icon-container" },
html("img", { class: "browser-tab-icon" }),
html("div", { class: "browser-tab-spinner" })
)
);

this.appendChild(
html(
"div",
Expand All @@ -234,14 +259,20 @@ class BrowserTab extends MozElements.MozTab {
this.updateIcon(kDefaultTabIcon);
}

this.addEventListener("mousedown", this);
for (const event of this.REGISTERED_EVENTS) {
this.addEventListener(event, this);
}

document.addEventListener("BrowserTabs::TabSelect", this);
}

disconnectedCallback() {
if (this.delayConnectedCallback()) return;

this.removeEventListener("mousedown", this);
for (const event of this.REGISTERED_EVENTS) {
this.removeEventListener(event, this);
}

document.removeEventListener("BrowserTabs::TabSelect", this);

this.webContents.removeEventListener("pagetitlechanged", this);
Expand All @@ -263,6 +294,7 @@ class BrowserTab extends MozElements.MozTab {
if (this.webContents.tagName == "browser") {
this.updateLabel(/** @type {ChromeBrowser} */(this.webContents).contentTitle);
}
break;
}
}

Expand All @@ -271,12 +303,16 @@ class BrowserTab extends MozElements.MozTab {
* @param {string} newLabel
*/
updateLabel(newLabel) {
if (newLabel.trim().length <= 0) {
newLabel = /** @type {ChromeBrowser} */(this.webContents).contentTitle;
}

if (newLabel.trim().length <= 0) {
try {
newLabel = /** @type {ChromeBrowser} */(this.webContents).currentURI.spec

if (newLabel == "about:blank") {
newLabel = "New Tab";
if (kDefaultTabTitles[newLabel]) {
newLabel = kDefaultTabTitles[newLabel];
}
} catch (e) {
console.error("Unable to use currentURI for tab title:", e);
Expand All @@ -293,10 +329,19 @@ class BrowserTab extends MozElements.MozTab {
* @param {string} newIconURI
*/
updateIcon(newIconURI) {
if (!newIconURI) newIconURI = kDefaultTabIcon;

this.elements.icon.src = newIconURI;
this.setAttribute("icon", newIconURI);
}

/**
* Clears the tab's icon
*/
clearIcon() {
this.updateIcon(null);
}

// @ts-ignore
_onTabMouseDown(event) {
if (this.selected) return;
Expand Down

0 comments on commit d949d8d

Please sign in to comment.