Compare commits
4 Commits
4f9b7b81e0
...
645e0e066a
Author | SHA1 | Date |
---|---|---|
Bauke | 645e0e066a | |
Bauke | a05f54306a | |
Bauke | cd453b3e6f | |
Bauke | e5bf102aa3 |
|
@ -0,0 +1,56 @@
|
||||||
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
|
import {updateBadge} from '../utilities/badge.js';
|
||||||
|
|
||||||
|
type ContextMenu = browser.Menus.CreateCreatePropertiesType;
|
||||||
|
|
||||||
|
export function getContextMenus(): ContextMenu[] {
|
||||||
|
const actionContext =
|
||||||
|
import.meta.env.VITE_BROWSER === 'chromium' ? 'action' : 'browser_action';
|
||||||
|
|
||||||
|
const contextMenus: ContextMenu[] = [
|
||||||
|
{
|
||||||
|
id: 're-nav-toggle-redirects',
|
||||||
|
title: 'Toggle all redirects',
|
||||||
|
contexts: [actionContext],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return contextMenus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initializeContextMenus(): Promise<void> {
|
||||||
|
const contextMenus = getContextMenus();
|
||||||
|
|
||||||
|
await browser.contextMenus.removeAll();
|
||||||
|
|
||||||
|
for (const contextMenu of contextMenus) {
|
||||||
|
browser.contextMenus.create(contextMenu, contextCreated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function contextCreated(): void {
|
||||||
|
const error = browser.runtime.lastError;
|
||||||
|
|
||||||
|
if (error !== null && error !== undefined) {
|
||||||
|
console.error('Re-Nav', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function contextClicked(
|
||||||
|
contextMenuIds: Set<string>,
|
||||||
|
info: browser.Menus.OnClickData,
|
||||||
|
tab?: browser.Tabs.Tab,
|
||||||
|
): Promise<void> {
|
||||||
|
const id = info.menuItemId.toString();
|
||||||
|
if (!contextMenuIds.has(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id === 're-nav-toggle-redirects') {
|
||||||
|
const state = await browser.storage.local.get({redirectsEnabled: true});
|
||||||
|
const redirectsEnabled = !(state.redirectsEnabled as boolean);
|
||||||
|
await browser.storage.local.set({redirectsEnabled});
|
||||||
|
await updateBadge(redirectsEnabled);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,12 @@
|
||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
import storage from '../redirect/storage.js';
|
import storage from '../redirect/storage.js';
|
||||||
|
import {updateBadge} from '../utilities/badge.js';
|
||||||
|
import {
|
||||||
|
contextClicked,
|
||||||
|
getContextMenus,
|
||||||
|
initializeContextMenus,
|
||||||
|
} from './context-menus.js';
|
||||||
|
|
||||||
async function browserActionClicked() {
|
async function browserActionClicked() {
|
||||||
await browser.runtime.openOptionsPage();
|
await browser.runtime.openOptionsPage();
|
||||||
|
@ -10,15 +16,30 @@ if (import.meta.env.VITE_BROWSER === 'chromium') {
|
||||||
browser.action.onClicked.addListener(browserActionClicked);
|
browser.action.onClicked.addListener(browserActionClicked);
|
||||||
} else {
|
} else {
|
||||||
browser.browserAction.onClicked.addListener(browserActionClicked);
|
browser.browserAction.onClicked.addListener(browserActionClicked);
|
||||||
|
void initializeContextMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.runtime.onInstalled.addListener(async () => {
|
browser.runtime.onInstalled.addListener(async () => {
|
||||||
|
await initializeContextMenus();
|
||||||
|
await updateBadge();
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
await browser.runtime.openOptionsPage();
|
await browser.runtime.openOptionsPage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
browser.runtime.onStartup.addListener(async () => {
|
||||||
|
await updateBadge();
|
||||||
|
});
|
||||||
|
|
||||||
browser.webNavigation.onBeforeNavigate.addListener(async (details) => {
|
browser.webNavigation.onBeforeNavigate.addListener(async (details) => {
|
||||||
|
const {redirectsEnabled} = await browser.storage.local.get({
|
||||||
|
redirectsEnabled: true,
|
||||||
|
});
|
||||||
|
if (redirectsEnabled === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!details.url.startsWith('http') || details.frameId > 0) {
|
if (!details.url.startsWith('http') || details.frameId > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +50,10 @@ browser.webNavigation.onBeforeNavigate.addListener(async (details) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tab = await browser.tabs.query({active: true, lastFocusedWindow: true});
|
||||||
|
const currentTabUrl =
|
||||||
|
tab[0]?.url === undefined ? undefined : new URL(tab[0].url);
|
||||||
|
|
||||||
const url = new URL(details.url);
|
const url = new URL(details.url);
|
||||||
const {latestUrl} = await browser.storage.local.get('latestUrl');
|
const {latestUrl} = await browser.storage.local.get('latestUrl');
|
||||||
if (redirectDelta < 30_000 && url.href === latestUrl) {
|
if (redirectDelta < 30_000 && url.href === latestUrl) {
|
||||||
|
@ -41,6 +66,15 @@ browser.webNavigation.onBeforeNavigate.addListener(async (details) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redirect.isMatch(url)) {
|
if (redirect.isMatch(url)) {
|
||||||
|
// Don't redirect if the URL before going to a new page is also a match.
|
||||||
|
// This will happen when the user is already on a website that has a
|
||||||
|
// redirect, but for whatever reason hasn't redirected. So it's safe to
|
||||||
|
// assume that they want to stay on this website, rather than get
|
||||||
|
// redirected.
|
||||||
|
if (currentTabUrl !== undefined && redirect.isMatch(currentTabUrl)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const redirectedUrl = redirect.redirect(url);
|
const redirectedUrl = redirect.redirect(url);
|
||||||
await browser.tabs.update(details.tabId, {url: redirectedUrl.href});
|
await browser.tabs.update(details.tabId, {url: redirectedUrl.href});
|
||||||
await browser.storage.local.set({
|
await browser.storage.local.set({
|
||||||
|
@ -51,3 +85,12 @@ browser.webNavigation.onBeforeNavigate.addListener(async (details) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
browser.contextMenus.onClicked.addListener(async (info, tab) => {
|
||||||
|
const contextMenus = getContextMenus();
|
||||||
|
const contextMenuIds = new Set<string>(
|
||||||
|
contextMenus.map(({id}) => id ?? 're-nav-unknown'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await contextClicked(contextMenuIds, info, tab);
|
||||||
|
});
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default function createManifest(
|
||||||
name: 'Re-Nav',
|
name: 'Re-Nav',
|
||||||
description: 'Navigation redirects for the masses.',
|
description: 'Navigation redirects for the masses.',
|
||||||
version: '0.1.1',
|
version: '0.1.1',
|
||||||
permissions: ['storage', 'webNavigation'],
|
permissions: ['contextMenus', 'storage', 'tabs', 'webNavigation'],
|
||||||
options_ui: {
|
options_ui: {
|
||||||
page: 'options/index.html',
|
page: 'options/index.html',
|
||||||
open_in_tab: true,
|
open_in_tab: true,
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class PageMain extends Component<Props, State> {
|
||||||
id: await storage.nextRedirectId(),
|
id: await storage.nextRedirectId(),
|
||||||
matcherType: 'hostname',
|
matcherType: 'hostname',
|
||||||
matcherValue: 'example.com',
|
matcherValue: 'example.com',
|
||||||
redirectType: 'simple',
|
redirectType: 'hostname',
|
||||||
redirectValue: 'example.org',
|
redirectValue: 'example.org',
|
||||||
});
|
});
|
||||||
await storage.savePrepared(await storage.prepareForStorage(redirect));
|
await storage.savePrepared(await storage.prepareForStorage(redirect));
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
|
export async function updateBadge(redirectsEnabled?: boolean): Promise<void> {
|
||||||
|
if (redirectsEnabled === undefined) {
|
||||||
|
const state = await browser.storage.local.get({redirectsEnabled: true});
|
||||||
|
redirectsEnabled = state.redirectsEnabled as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let action: browser.Action.Static = browser.browserAction;
|
||||||
|
if (import.meta.env.VITE_BROWSER === 'chromium') {
|
||||||
|
action = browser.action;
|
||||||
|
}
|
||||||
|
|
||||||
|
await action.setBadgeText({
|
||||||
|
text: redirectsEnabled ? '' : '✗',
|
||||||
|
});
|
||||||
|
|
||||||
|
await action.setBadgeBackgroundColor({
|
||||||
|
color: '#f99fb1',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (import.meta.env.VITE_BROWSER === 'firefox') {
|
||||||
|
action.setBadgeTextColor({color: '#2a2041'});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue