mirror of
https://github.com/pulse-browser/browser.git
synced 2024-09-11 12:45:43 +03:00
parent
2e9d6dd09e
commit
b7d38c4094
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Pinned vertical tabs are no longer positioned. Sorta defeats their purpose, but it stops a semi-major bug
|
||||
- Sidebar sites now appear on new windows
|
||||
|
||||
## 1.0.0-a.75
|
||||
|
||||
|
@ -5,17 +5,17 @@
|
||||
//@ts-check
|
||||
/// <reference types="./experiment.d.ts">
|
||||
|
||||
"use strict";
|
||||
const sidebargetaroundUrl = "chrome://browser/content/webext-panels.xhtml";
|
||||
'use strict'
|
||||
const sidebargetaroundUrl = 'chrome://browser/content/webext-panels.xhtml'
|
||||
var { ExtensionParent } = ChromeUtils.import(
|
||||
"resource://gre/modules/ExtensionParent.jsm"
|
||||
);
|
||||
'resource://gre/modules/ExtensionParent.jsm'
|
||||
)
|
||||
|
||||
var { ContextMenu } = ChromeUtils.import(
|
||||
"resource://gre/modules/ContextMenu.jsm"
|
||||
);
|
||||
'resource://gre/modules/ContextMenu.jsm'
|
||||
)
|
||||
|
||||
var { IconDetails, StartupCache } = ExtensionParent;
|
||||
var { IconDetails, StartupCache } = ExtensionParent
|
||||
|
||||
class Sidebar {
|
||||
/**
|
||||
@ -38,99 +38,103 @@ class Sidebar {
|
||||
isBottom,
|
||||
browserStyle
|
||||
) {
|
||||
this.extentionIndex = id;
|
||||
this.extension = extention;
|
||||
this.extensionName = extention.name;
|
||||
this.title = name;
|
||||
this.webviewUrl = webviewUrl;
|
||||
this.iconUrl = iconUrl;
|
||||
this.isBottom = isBottom;
|
||||
this.browserStyle = browserStyle;
|
||||
this.extentionIndex = id
|
||||
this.extension = extention
|
||||
this.extensionName = extention.name
|
||||
this.title = name
|
||||
this.webviewUrl = webviewUrl
|
||||
this.iconUrl = iconUrl
|
||||
this.isBottom = isBottom
|
||||
this.browserStyle = browserStyle
|
||||
|
||||
this.baseId = `${this.extensionName.replaceAll(" ", "-")}-index-${
|
||||
this.baseId = `${this.extensionName.replaceAll(' ', '-')}-index-${
|
||||
this.extentionIndex
|
||||
}`;
|
||||
this.keyId = `ext-key-id-${this.baseId}`;
|
||||
this.menuId = `ext-menu-id-${this.baseId}`;
|
||||
this.buttonId = `ext-button-id-${this.baseId}`;
|
||||
}`
|
||||
this.keyId = `ext-key-id-${this.baseId}`
|
||||
this.menuId = `ext-menu-id-${this.baseId}`
|
||||
this.buttonId = `ext-button-id-${this.baseId}`
|
||||
|
||||
this.defaults = {
|
||||
enabled: true,
|
||||
title: this.title,
|
||||
icon: IconDetails.normalize({ path: this.iconUrl }, this.extension),
|
||||
panel: this.webviewUrl || "",
|
||||
panel: this.webviewUrl || '',
|
||||
isBottom: this.isBottom,
|
||||
};
|
||||
this.globals = Object.create(this.defaults);
|
||||
}
|
||||
this.globals = Object.create(this.defaults)
|
||||
|
||||
this.onRemoveEvents = [];
|
||||
this.onRemoveEvents = []
|
||||
|
||||
this.tabContext = new TabContext(target => {
|
||||
let window = target.ownerGlobal;
|
||||
this.tabContext = new TabContext((target) => {
|
||||
let window = target.ownerGlobal
|
||||
if (target === window) {
|
||||
return this.globals;
|
||||
return this.globals
|
||||
}
|
||||
return this.tabContext.get(window);
|
||||
});
|
||||
return this.tabContext.get(window)
|
||||
})
|
||||
|
||||
/**
|
||||
* @type {ContextMenu}
|
||||
*/
|
||||
this.contextMenu = new ContextMenu([
|
||||
{
|
||||
l10nId: "sidebar-context-delete",
|
||||
callId: "delete",
|
||||
l10nId: 'sidebar-context-delete',
|
||||
callId: 'delete',
|
||||
},
|
||||
]);
|
||||
])
|
||||
|
||||
this.contextMenu.addEvent(callId => {
|
||||
if (callId === "delete") {
|
||||
this.contextMenu.addEvent((callId) => {
|
||||
if (callId === 'delete') {
|
||||
for (let window of windowTracker.browserWindows()) {
|
||||
this.removeFromBrowserWindow(window);
|
||||
this.removeFromBrowserWindow(window)
|
||||
}
|
||||
}
|
||||
this.onRemoveEvents.filter(e => e).forEach(e => e(this.extentionIndex));
|
||||
});
|
||||
this.onRemoveEvents
|
||||
.filter((e) => e)
|
||||
.forEach((e) => e(this.extentionIndex))
|
||||
})
|
||||
|
||||
windowTracker.addOpenListener((window) => this.addToBrowserWindow(window))
|
||||
}
|
||||
|
||||
updateHeader(event) {
|
||||
let window = event.target.ownerGlobal;
|
||||
let details = this.tabContext.get(window.gBrowser.selectedTab);
|
||||
let header = window.document.getElementById("sidebar-switcher-target");
|
||||
let window = event.target.ownerGlobal
|
||||
let details = this.tabContext.get(window.gBrowser.selectedTab)
|
||||
let header = window.document.getElementById('sidebar-switcher-target')
|
||||
if (window.SidebarUI.currentID === this.keyId) {
|
||||
this.setMenuIcon(header, details);
|
||||
this.setMenuIcon(header, details)
|
||||
}
|
||||
}
|
||||
|
||||
getIcon(size) {
|
||||
return IconDetails.escapeUrl(
|
||||
IconDetails.getPreferredIcon(this.iconUrl, this.extension, size).icon
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
setMenuIcon(menuitem, icon) {
|
||||
menuitem.setAttribute(
|
||||
"style",
|
||||
'style',
|
||||
`
|
||||
--webextension-menuitem-image: url("${this.getIcon(16)}");
|
||||
--webextension-menuitem-image-2x: url("${this.getIcon(32)}");
|
||||
`
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
async removeFromBrowserWindow(window) {
|
||||
let { document, SidebarUI } = window;
|
||||
SidebarUI.sidebars.delete(this.keyId);
|
||||
document.getElementById("sidebar-background-" + this.keyId).remove();
|
||||
let { document, SidebarUI } = window
|
||||
SidebarUI.sidebars.delete(this.keyId)
|
||||
document.getElementById('sidebar-background-' + this.keyId).remove()
|
||||
document
|
||||
.getElementById("sidebar-switcher-target")
|
||||
.removeEventListener("SidebarShown", this.updateHeader.bind(this));
|
||||
SidebarUI.hide();
|
||||
.getElementById('sidebar-switcher-target')
|
||||
.removeEventListener('SidebarShown', this.updateHeader.bind(this))
|
||||
SidebarUI.hide()
|
||||
}
|
||||
|
||||
async addToBrowserWindow(window) {
|
||||
// Theft the sidebar UI from the window object
|
||||
let { document, SidebarUI } = window;
|
||||
let { document, SidebarUI } = window
|
||||
|
||||
// Add sidebar information to SidebarUI
|
||||
SidebarUI.sidebars.set(this.keyId, {
|
||||
@ -144,41 +148,41 @@ class Sidebar {
|
||||
iconurl: this.getIcon(32),
|
||||
panel: this.webviewUrl,
|
||||
isBottom: this.isBottom,
|
||||
});
|
||||
})
|
||||
|
||||
// Generate the header information
|
||||
let header = document.getElementById("sidebar-switcher-target");
|
||||
header.addEventListener("SidebarShown", this.updateHeader.bind(this));
|
||||
let header = document.getElementById('sidebar-switcher-target')
|
||||
header.addEventListener('SidebarShown', this.updateHeader.bind(this))
|
||||
|
||||
// Insert a menuitem for View->Show Sidebars.
|
||||
let menuitem = document.createXULElement("menuitem");
|
||||
menuitem.setAttribute("id", this.menuId);
|
||||
menuitem.setAttribute("type", "checkbox");
|
||||
menuitem.setAttribute("label", this.title);
|
||||
let menuitem = document.createXULElement('menuitem')
|
||||
menuitem.setAttribute('id', this.menuId)
|
||||
menuitem.setAttribute('type', 'checkbox')
|
||||
menuitem.setAttribute('label', this.title)
|
||||
menuitem.setAttribute(
|
||||
"oncommand",
|
||||
'oncommand',
|
||||
`SidebarUI.toggle("${this.extentionIndex}");`
|
||||
);
|
||||
menuitem.setAttribute("class", "menuitem-iconic webextension-menuitem");
|
||||
menuitem.setAttribute("key", this.keyId);
|
||||
this.setMenuIcon(menuitem, this.iconUrl);
|
||||
document.getElementById("viewSidebarMenu").appendChild(menuitem);
|
||||
)
|
||||
menuitem.setAttribute('class', 'menuitem-iconic webextension-menuitem')
|
||||
menuitem.setAttribute('key', this.keyId)
|
||||
this.setMenuIcon(menuitem, this.iconUrl)
|
||||
document.getElementById('viewSidebarMenu').appendChild(menuitem)
|
||||
|
||||
// Add to the sidebar tabs on the side of the window
|
||||
await SidebarUI.createSidebarItem(
|
||||
this.keyId,
|
||||
SidebarUI.sidebars.get(this.keyId)
|
||||
);
|
||||
)
|
||||
|
||||
// Get the element based on the id of `sidebar-background-${this.keyId}`
|
||||
// Set the attribute 'context' to 'hello'
|
||||
this.contextMenu.addToBrowser(window);
|
||||
this.contextMenu.addToBrowser(window)
|
||||
let sidebar = window.document.getElementById(
|
||||
`sidebar-background-${this.keyId}`
|
||||
);
|
||||
sidebar.setAttribute("context", this.contextMenu.contextMenuId);
|
||||
)
|
||||
sidebar.setAttribute('context', this.contextMenu.contextMenuId)
|
||||
|
||||
return menuitem;
|
||||
return menuitem
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,44 +191,44 @@ class ConfigAPI extends ExtensionAPI {
|
||||
* @param {any} extension
|
||||
*/
|
||||
constructor(extension) {
|
||||
super(extension);
|
||||
super(extension)
|
||||
|
||||
this.onRemoveEvents = [];
|
||||
this.onRemoveEvents = []
|
||||
|
||||
this.currentIndex = 0;
|
||||
this.currentIndex = 0
|
||||
/** @type {Map<number, Sidebar>} */
|
||||
this.sidebars = new Map();
|
||||
this.sidebars = new Map()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} context
|
||||
*/
|
||||
getAPI(context) {
|
||||
let { extension } = context;
|
||||
let { extension } = context
|
||||
|
||||
return {
|
||||
sidebars: {
|
||||
/**
|
||||
* @param {{ title: string, iconUrl: string, webviewUrl: string, isBottom?: boolean, browserStyle?: boolean }} config The config provided by the programer
|
||||
*/
|
||||
add: async config => {
|
||||
add: async (config) => {
|
||||
// Get a url that can be used by the browser for this specific panel
|
||||
// to work correctly
|
||||
|
||||
const url = context.uri.resolve(config.webviewUrl);
|
||||
const url = context.uri.resolve(config.webviewUrl)
|
||||
if (!context.checkLoadURL(url)) {
|
||||
return Promise.reject({
|
||||
message: `Access to the url ${url} (from ${config.webviewUrl}) was denied`,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// Get the icon url
|
||||
const iconUrl = IconDetails.normalize(
|
||||
{ path: config.iconUrl },
|
||||
extension
|
||||
);
|
||||
)
|
||||
|
||||
const id = ++this.currentIndex;
|
||||
const id = ++this.currentIndex
|
||||
const sidebar = new Sidebar(
|
||||
id,
|
||||
extension,
|
||||
@ -233,16 +237,16 @@ class ConfigAPI extends ExtensionAPI {
|
||||
iconUrl,
|
||||
config.isBottom || false,
|
||||
config.browserStyle || false
|
||||
);
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents;
|
||||
)
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents
|
||||
|
||||
for (let window of windowTracker.browserWindows()) {
|
||||
sidebar.addToBrowserWindow(window);
|
||||
sidebar.addToBrowserWindow(window)
|
||||
}
|
||||
|
||||
this.sidebars.set(id, sidebar);
|
||||
this.sidebars.set(id, sidebar)
|
||||
|
||||
return id;
|
||||
return id
|
||||
},
|
||||
|
||||
get: async (/** @type {any} */ id) => {
|
||||
@ -253,49 +257,49 @@ class ConfigAPI extends ExtensionAPI {
|
||||
webviewUrl: this.sidebars.get(id).webviewUrl,
|
||||
isBottom: this.sidebars.get(id).isBottom,
|
||||
browserStyle: this.sidebars.get(id).browserStyle,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
list: async () => {
|
||||
return [...this.sidebars.keys()];
|
||||
return [...this.sidebars.keys()]
|
||||
},
|
||||
|
||||
remove: async (/** @type {any} */ id) => {
|
||||
const sidebar = this.sidebars.get(id);
|
||||
const sidebar = this.sidebars.get(id)
|
||||
|
||||
for (let window of windowTracker.browserWindows()) {
|
||||
sidebar.removeFromBrowserWindow(window);
|
||||
sidebar.removeFromBrowserWindow(window)
|
||||
}
|
||||
|
||||
this.sidebars.delete(id);
|
||||
this.sidebars.delete(id)
|
||||
},
|
||||
|
||||
onRemove: new EventManager({
|
||||
context,
|
||||
name: "sidebars.onRemove",
|
||||
register: fire => {
|
||||
const callback = value => {
|
||||
fire.async(value);
|
||||
};
|
||||
const eventId = this.onRemoveEvents.length;
|
||||
this.onRemoveEvents.push(callback);
|
||||
name: 'sidebars.onRemove',
|
||||
register: (fire) => {
|
||||
const callback = (value) => {
|
||||
fire.async(value)
|
||||
}
|
||||
const eventId = this.onRemoveEvents.length
|
||||
this.onRemoveEvents.push(callback)
|
||||
|
||||
for (const sidebar of this.sidebars.values()) {
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents;
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents
|
||||
}
|
||||
|
||||
return () => {
|
||||
this.onRemoveEvents[eventId] = null;
|
||||
this.onRemoveEvents[eventId] = null
|
||||
for (const sidebar of this.sidebars.values()) {
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents;
|
||||
sidebar.onRemoveEvents = this.onRemoveEvents
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sidebars;
|
||||
sidebars = ConfigAPI;
|
||||
var sidebars
|
||||
sidebars = ConfigAPI
|
||||
|
Loading…
Reference in New Issue
Block a user