-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sidebar Fixes and Cleanup
- Loading branch information
Showing
11 changed files
with
309 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"semi": false, | ||
"singleQuote": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# sidebar-tabs | ||
An add-on for Pulse Browser that lets you save pages directly to your sidebar. This add-on was developed solely for Pulse Browser and makes use of its specific APIs. | ||
|
||
#### Sidebar View Icon | ||
Sidebar View Icon from Side-View [\[MPL-2.0\]](https://github.com/mozilla/side-view/blob/master/LICENSE) - Available at https://github.com/mozilla/side-view/blob/master/addon/images/in-content-icon.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
</head> | ||
<body> | ||
<script type="module" src="js/background.js"></script> | ||
</body> | ||
</html> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,16 @@ | ||
<!DOCTYPE html> | ||
<html lang=""> | ||
<head> | ||
<meta charset="utf-8"> | ||
<link rel="stylesheet" href="styles/main.css"> | ||
<meta charset="utf-8" /> | ||
<link rel="stylesheet" href="styles/main.css" /> | ||
</head> | ||
<body> | ||
<p id="instructions">Add websites/items to your sidebar for ease of access.</p> | ||
<input type="text" id="url" placeholder="Enter URL"> | ||
<img src="images/in-content-icon.png" width="200" /> | ||
<p id="instructions"> | ||
Add websites/items to your sidebar for ease of access. | ||
</p> | ||
<input type="text" id="url" placeholder="Enter URL" /> | ||
<button id="addPageButton">Add Page</button> | ||
<script src="js/main.js"></script> | ||
<script type="module" src="js/main.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,124 @@ | ||
browser.sidebars.add({ | ||
title: "Add Shortcut to Sidebar", | ||
iconUrl: "plus.svg", | ||
webviewUrl: "index.html", | ||
isBottom: true, | ||
}) | ||
import { MessageTypeValues } from './message.js' | ||
import { Mutex } from './mutex.js' | ||
|
||
// ============================================================================= | ||
// Types | ||
// @ts-check | ||
|
||
/** | ||
* @typedef {object} SidebarItem | ||
* | ||
* @property {number} id The id of this specific sidebar item. Valid for a browser session | ||
* @property {string} title The title of the sidebar item, generally the webpage title | ||
* @property {string} iconUrl The website's favicon | ||
* @property {string} webviewUrl The url of the website to navigate to | ||
*/ | ||
|
||
/** | ||
* This is an incomplete version of {@link SidebarItem} intended for sending | ||
* creation data around with. Currently it only excludes `id`. | ||
* | ||
* @typedef {object} SidebarItemData | ||
* | ||
* @property {string} title The title of the sidebar item, generally the webpage title | ||
* @property {string} iconUrl The website's favicon | ||
* @property {string} webviewUrl The url of the website to navigate to | ||
*/ | ||
|
||
// ============================================================================= | ||
// Functions | ||
|
||
getFromStorage().then(createSidebarItems); | ||
const storageMutex = new Mutex() | ||
|
||
/** | ||
* @returns {Promise<{ sidebaritems: SidebarItem[] }>} | ||
* | ||
* @note We assume that the parent caller has already locked {@see storageMutex} to avoid a race condition | ||
*/ | ||
async function getFromStorage() { | ||
//get from storage | ||
let sidebaritems = await browser.storage.local.get("sidebaritems"); | ||
console.log(sidebaritems); | ||
return sidebaritems; | ||
const storage = await browser.storage.local.get('sidebaritems') | ||
return storage | ||
} | ||
|
||
async function createSidebarItems(sidebaritems) { | ||
//create sidebar items | ||
for (let i = 0; i < sidebaritems.sidebaritems.length; i++) { | ||
browser.sidebars.add({ | ||
title: sidebaritems.sidebaritems[i].title, | ||
iconUrl: sidebaritems.sidebaritems[i].iconUrl, | ||
webviewUrl: sidebaritems.sidebaritems[i].webviewUrl, | ||
}); | ||
} | ||
async function spawnExistingSidebarItems() { | ||
const { unlock } = await storageMutex.lock() | ||
let storage = await getFromStorage() | ||
let { sidebaritems: sidebarItems } = storage | ||
|
||
if (typeof sidebarItems === 'undefined') { | ||
sidebarItems = [] | ||
} | ||
|
||
for (let i = 0; i < sidebarItems.length; i++) { | ||
const item = sidebarItems[i] | ||
const id = await browser.sidebars.add(item) | ||
|
||
sidebarItems[i].id = id | ||
} | ||
|
||
storage.sidebaritems = sidebarItems | ||
await browser.storage.local.set(storage) | ||
unlock() | ||
} | ||
|
||
async function removeSidebarItems(itemId) | ||
{ | ||
const item = await browser.sidebars.get(itemId); | ||
/** | ||
* @param {number} idToRemove The id of the sidebar item you wish to remove | ||
*/ | ||
async function removeSidebarItems(idToRemove) { | ||
const { unlock } = await storageMutex.lock() | ||
let storage = await getFromStorage() | ||
|
||
storage.sidebaritems = storage.sidebaritems.filter( | ||
(item) => item.id !== idToRemove | ||
) | ||
|
||
//remove from storage | ||
let storagearray = await getFromStorage(); | ||
let storageitems = storagearray.sidebaritems; | ||
await browser.storage.local.set(storage) | ||
unlock() | ||
} | ||
|
||
/** | ||
* Creates a sidebar item and registers it, storing it for future browser | ||
* instances | ||
* | ||
* @param {SidebarItemData} itemInfo Information about the sidebar to be created | ||
*/ | ||
async function createSidebarItem(itemInfo) { | ||
const { unlock } = await storageMutex.lock() | ||
const storage = await getFromStorage() | ||
|
||
for (let i = 0; i < storageitems.length; i++) { | ||
if (storageitems[i].webviewUrl == item.webviewUrl) { | ||
storageitems.splice(i, 1); | ||
} | ||
} | ||
const id = await browser.sidebars.add(itemInfo) | ||
storage.sidebaritems.push({ ...itemInfo, id }) | ||
|
||
browser.storage.local.set(storagearray); | ||
await browser.storage.local.set(storage) | ||
unlock() | ||
} | ||
|
||
browser.sidebars.onRemove.addListener((itemId) => { | ||
removeSidebarItems(itemId); | ||
// ============================================================================= | ||
// Init logic | ||
|
||
browser.sidebars.add({ | ||
title: 'Add Shortcut to Sidebar', | ||
iconUrl: 'plus.svg', | ||
webviewUrl: 'index.html', | ||
isBottom: true, | ||
}) | ||
|
||
spawnExistingSidebarItems() | ||
|
||
browser.sidebars.onRemove.addListener((itemId) => removeSidebarItems(itemId)) | ||
|
||
// ============================================================================= | ||
// Messages from UI | ||
|
||
browser.runtime.onMessage.addListener(({ type, data }, sender) => { | ||
switch (type) { | ||
case MessageTypeValues.CREATE_SIDEBAR_ITEMS: | ||
createSidebarItem(data) | ||
break | ||
|
||
default: | ||
throw new Error(`Unknown message type: ${type}`) | ||
} | ||
|
||
return null | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,105 @@ | ||
// @ts-check | ||
import { MessageTypeValues } from './message.js' | ||
|
||
/** | ||
* Send a message to the background page to be processed | ||
* @param {import("./message").MessageType} type | ||
* @param {*} data | ||
*/ | ||
async function sendMessageToBackgroundScript(type, data) { | ||
return await browser.runtime.sendMessage({ type, data }) | ||
} | ||
|
||
async function createSidebarItem(title, iconUrl, webviewUrl) { | ||
await sendMessageToBackgroundScript(MessageTypeValues.CREATE_SIDEBAR_ITEMS, { | ||
title, | ||
iconUrl, | ||
webviewUrl, | ||
}) | ||
} | ||
|
||
async function addPage() { | ||
var pageURL = (document.getElementById("url").value); | ||
if (!pageURL) { | ||
return; | ||
/** @type {HTMLInputElement?} */ | ||
// @ts-ignore | ||
const pageUrlElement = document.getElementById('url') | ||
|
||
if (!pageUrlElement) { | ||
throw new Error('Could not find the URL element') | ||
} | ||
|
||
// remove https:// or http:// from the url | ||
pageURL = pageURL.replace(/^https?:\/\//, ''); | ||
const pageUrl = pageUrlElement.value.replace(/^https?:\/\//, '') | ||
let pageIcon = 'chrome://global/skin/icons/link.svg' | ||
|
||
let pageIcon = "chrome://global/skin/icons/link.svg"; | ||
if (!navigator.onLine) { | ||
createSidebarItem(pageUrl, pageIcon, 'https://' + pageUrl) | ||
return | ||
} | ||
|
||
if (navigator.onLine) { | ||
//fetch https://icons.duckduckgo.com/ip3 image for icon | ||
var response = await fetch(`https://icons.duckduckgo.com/ip3/${pageURL}.ico`); | ||
if (response.ok) { | ||
//Update pageIcon with the fetched icon | ||
pageIcon = ('https://icons.duckduckgo.com/ip3/'+pageURL+'.ico') | ||
} | ||
const response = await fetch( | ||
`https://icons.duckduckgo.com/ip3/${pageUrl}.ico` | ||
) | ||
if (response.ok) { | ||
pageIcon = `https://icons.duckduckgo.com/ip3/${pageUrl}.ico` | ||
} | ||
|
||
if (navigator.onLine) { | ||
//create new tab | ||
let newtab = browser.tabs.create({ url: "https://"+pageURL, active: true}); | ||
//newtab await complete load | ||
newtab.then(function(tab) { | ||
browser.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) { | ||
if (tabId == tab.id && changeInfo.status == "complete") { | ||
//remove listener | ||
browser.tabs.onUpdated.removeListener(listener); | ||
browser.tabs.get(tab.id).then(function(tab) { | ||
//create new sidebar item | ||
browser.sidebars.add({ | ||
title: tab.title, | ||
iconUrl: pageIcon, | ||
webviewUrl: tab.url, | ||
}); | ||
|
||
//save to storage | ||
saveToStorage({ | ||
title: tab.title, | ||
iconUrl: pageIcon, | ||
webviewUrl: tab.url, | ||
}); | ||
}); | ||
} | ||
}); | ||
}); | ||
|
||
const tab = await browser.tabs.create({ | ||
url: 'https://' + pageUrl, | ||
active: true, | ||
}) | ||
|
||
browser.tabs.onUpdated.addListener(async function listener( | ||
tabId, | ||
changeInfo, | ||
tab | ||
) { | ||
if (tabId == tab.id && changeInfo.status == 'complete') { | ||
browser.tabs.onUpdated.removeListener(listener) | ||
createSidebarItem(tab.title, pageIcon, tab.url) | ||
} | ||
}) | ||
} | ||
|
||
document.getElementById('addPageButton').addEventListener('click', addPage) | ||
|
||
//Stolen from https://github.com/mdn/webextensions-examples | ||
function setSidebarStyle(theme) { | ||
const body = document.body | ||
|
||
if (theme.colors && theme.colors.frame) { | ||
body.style.backgroundColor = theme.colors.frame | ||
} else { | ||
body.style.backgroundColor = 'white' | ||
} | ||
else | ||
{ | ||
//If the user is offline, create a sidebar item with the title as the url | ||
//and the icon as the default icon so the browser sidebar is functional offline | ||
browser.sidebars.add({ | ||
title: pageURL, | ||
iconUrl: pageIcon, | ||
webviewUrl: pageURL, | ||
}); | ||
|
||
if (theme.colors && theme.colors.toolbar) { | ||
body.style.backgroundColor = theme.colors.toolbar | ||
} else { | ||
body.style.backgroundColor = '#ebebeb' | ||
} | ||
|
||
if (theme.colors && theme.colors.toolbar_text) { | ||
body.style.color = theme.colors.toolbar_text | ||
} else { | ||
body.style.color = 'black' | ||
} | ||
} | ||
|
||
async function saveToStorage({title: title, iconUrl: iconUrl, webviewUrl: webviewUrl}) { | ||
//save to sidebaritems | ||
let sidebaritems = await browser.storage.local.get("sidebaritems"); | ||
if (sidebaritems.sidebaritems == undefined) { | ||
sidebaritems.sidebaritems = []; | ||
} | ||
sidebaritems.sidebaritems.push({ | ||
title: title, | ||
iconUrl: iconUrl, | ||
webviewUrl: webviewUrl, | ||
}); | ||
browser.storage.local.set(sidebaritems); | ||
// Set the element style when the extension page loads | ||
async function setInitialStyle() { | ||
const theme = await browser.theme.getCurrent() | ||
setSidebarStyle(theme) | ||
} | ||
setInitialStyle() | ||
|
||
document.getElementById("addPageButton").addEventListener("click", addPage); | ||
// Watch for theme updates | ||
browser.theme.onUpdated.addListener(async ({ theme, windowId }) => { | ||
const sidebarWindow = await browser.windows.getCurrent() | ||
/* | ||
Only update theme if it applies to the window the sidebar is in. | ||
If a windowId is passed during an update, it means that the theme is applied to that specific window. | ||
Otherwise, the theme is applied globally to all windows. | ||
*/ | ||
if (!windowId || windowId == sidebarWindow.id) { | ||
setSidebarStyle(theme) | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* @typedef {string} MessageType | ||
*/ | ||
|
||
/** | ||
* @readonly | ||
* @enum {MessageType} | ||
*/ | ||
export const MessageTypeValues = { | ||
CREATE_SIDEBAR_ITEMS: 'createSidebarItems', | ||
} |
Oops, something went wrong.