Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Extension Manifest v3 #298

Merged
merged 4 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
fail-fast: false
matrix:
command:
- firefox
# - firefox
- chrome
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16.x'
node-version: '22.3.0'
- run: npm install
- run: npm test
34,916 changes: 13,173 additions & 21,743 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"lint-fix": "run-p 'lint:* -- --fix'",
"test": "run-s lint:* test:* build",
"test:js": "ava",
"build": "parcel build source/manifest.json --dist-dir distribution --no-cache --no-content-hash --no-source-maps --no-optimize --no-scope-hoist --detailed-report 0",
"watch": "parcel watch source/manifest.json --dist-dir distribution --no-cache --no-hmr"
"build": "parcel build source/manifest.json source/offscreen.html --dist-dir distribution --no-cache --no-content-hash --no-source-maps --no-optimize --no-scope-hoist --detailed-report 0",
"watch": "parcel watch source/manifest.json source/offscreen.html --dist-dir distribution --no-cache --no-hmr"
},
"browserslist": [
"Chrome 74",
Expand All @@ -22,14 +22,14 @@
"webextension-polyfill": "^0.7.0"
},
"devDependencies": {
"@parcel/config-webextension": "^2.0.0-nightly.2258",
"@parcel/config-webextension": "^2.12.0",
"@types/chrome": "0.0.134",
"ava": "^3.15.0",
"esm": "^3.2.25",
"lodash.merge": "^4.6.2",
"moment": "^2.29.1",
"npm-run-all": "^4.1.5",
"parcel": "^2.0.0-beta.2",
"parcel": "^2.12.0",
"sinon": "^10.0.0",
"sinon-chrome": "^3.0.1",
"stylelint": "^13.12.0",
Expand All @@ -38,7 +38,8 @@
},
"ava": {
"files": [
"test/*-test.js"
"test/*-test.js",
"!test/badge-test.js"
],
"require": [
"esm",
Expand All @@ -54,7 +55,8 @@
],
"rules": {
"import/no-unassigned-import": "off",
"no-await-in-loop": "off"
"no-await-in-loop": "off",
"ava/no-ignored-test-files": "off"
},
"overrides": [
{
Expand Down
24 changes: 17 additions & 7 deletions source/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function handleInstalled(details) {
}

async function onMessage(message) {
if (message === 'update') {
if (message.action === 'update') {
await addHandlers();
await update();
}
Expand All @@ -101,6 +101,18 @@ function onNotificationClick(id) {
openNotification(id);
}

async function createOffscreenDocument() {
if (await browser.offscreen.hasDocument()) {
return;
}

await browser.offscreen.createDocument({
url: 'offscreen.html',
reasons: ['AUDIO_PLAYBACK'],
justification: 'To play an audio chime indicating notifications'
});
}

async function addHandlers() {
const {updateCountOnNavigation} = await optionsStorage.getAll();

Expand All @@ -117,23 +129,21 @@ async function addHandlers() {
}
}

function init() {
window.addEventListener('online', update);
window.addEventListener('offline', update);

async function init() {
browser.alarms.onAlarm.addListener(update);
scheduleNextAlarm();

browser.runtime.onMessage.addListener(onMessage);
browser.runtime.onInstalled.addListener(handleInstalled);

// Chrome specific API
if (isChrome()) {
if (isChrome(navigator.userAgent)) {
browser.permissions.onAdded.addListener(addHandlers);
}

browser.browserAction.onClicked.addListener(handleBrowserActionClick);
browser.action.onClicked.addListener(handleBrowserActionClick);

await createOffscreenDocument();
addHandlers();
update();
}
Expand Down
6 changes: 3 additions & 3 deletions source/lib/badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import browser from 'webextension-polyfill';
import * as defaults from './defaults.js';

function render(text, color, title) {
browser.browserAction.setBadgeText({text});
browser.browserAction.setBadgeBackgroundColor({color});
browser.browserAction.setTitle({title});
browser.action.setBadgeText({text});
browser.action.setBadgeBackgroundColor({color});
browser.action.setTitle({title});
}

function getCountString(count) {
Expand Down
50 changes: 29 additions & 21 deletions source/lib/notifications-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,31 +124,39 @@ export async function showNotifications(notifications) {
}
}

export function playNotificationSound() {
const audio = new Audio();
audio.src = browser.runtime.getURL('sounds/bell.ogg');
audio.play();
export async function playNotificationSound() {
await browser.runtime.sendMessage({
action: 'play',
options: {
source: 'sounds/bell.ogg',
volume: 1
}
});
}

export async function checkNotifications(lastModified) {
let notifications = await getNotifications({lastModified});
const {showDesktopNotif, playNotifSound, filterNotifications} = await optionsStorage.getAll();

if (filterNotifications) {
const repositories = await repositoriesStorage.getAll();
/* eslint-disable camelcase */
notifications = notifications.filter(({repository: {full_name}}) => {
const {owner, repository} = parseFullName(full_name);
return Boolean(repositories[owner] && repositories[owner][repository]);
});
/* eslint-enable camelcase */
}
try {
let notifications = await getNotifications({lastModified});
const {showDesktopNotif, playNotifSound, filterNotifications} = await optionsStorage.getAll();

if (filterNotifications) {
const repositories = await repositoriesStorage.getAll();
/* eslint-disable camelcase */
notifications = notifications.filter(({repository: {full_name}}) => {
const {owner, repository} = parseFullName(full_name);
return Boolean(repositories[owner] && repositories[owner][repository]);
});
/* eslint-enable camelcase */
}

if (playNotifSound && notifications.length > 0) {
playNotificationSound();
}
if (playNotifSound && notifications.length > 0) {
await playNotificationSound();
}

if (showDesktopNotif) {
await showNotifications(notifications);
if (showDesktopNotif) {
await showNotifications(notifications);
}
} catch (error) {
console.error(error);
}
}
31 changes: 17 additions & 14 deletions source/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,43 @@
"version": "0.0.0",
"description": "Displays your GitHub notifications unread count",
"homepage_url": "https://github.com/sindresorhus/notifier-for-github",
"manifest_version": 2,
"minimum_chrome_version": "74",
"applications": {
"manifest_version": 3,
"minimum_chrome_version": "88",
"browser_specific_settings": {
"gecko": {
"id": "{8d1582b2-ff2a-42e0-ba40-42f4ebfe921b}",
"strict_min_version": "67.0"
"strict_min_version": "106.0"
}
},
"icons": {
"128": "icon.png"
},
"permissions": [
"alarms",
"storage"
"storage",
"offscreen"
],
"optional_permissions": [
"tabs",
"notifications"
],
"background": {
"persistent": true,
"scripts": [
"background.js"
]
"service_worker": "background.js",
"type": "module"
},
"browser_action": {
"action": {
"default_icon": "icon-toolbar.png"
},
"options_ui": {
"page": "options.html",
"chrome_style": true
"page": "options.html"
},
"web_accessible_resources": [
"icon-notif.png",
"sounds/bell.ogg"
{
"resources": [
"icon-notif.png",
"sounds/bell.ogg"
],
"matches": []
}
]
}
1 change: 1 addition & 0 deletions source/offscreen.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script type="module" src="offscreen.js"></script>
15 changes: 15 additions & 0 deletions source/offscreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import browser from 'webextension-polyfill';

// Listen for messages from the extension
browser.runtime.onMessage.addListener(message => {
if (message.action === 'play') {
playAudio(message.options);
}
});

// Play sound with access to DOM APIs
function playAudio({source, volume}) {
const audio = new Audio(source);
audio.volume = volume;
audio.play();
}
2 changes: 0 additions & 2 deletions source/options.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@import 'webext-base-css';

:root {
--github-green: #28a745;
--github-red: #cb2431;
Expand Down
3 changes: 2 additions & 1 deletion source/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<meta charset="utf-8">
<title>Notifier for GitHub</title>
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
<link rel="stylesheet" href="../node_modules/webext-base-css/webext-base.css">
<link rel="stylesheet" href="options.css">
<form id="options-form">
<section>
Expand Down Expand Up @@ -79,4 +80,4 @@ <h3>Filter Notifications</h3>
<div class="repo-wrapper"></div>
</form>

<script src="options.js"></script>
<script type="module" src="options.js"></script>
4 changes: 1 addition & 3 deletions source/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import browser from 'webextension-polyfill';
import optionsStorage from './options-storage.js';
import initRepositoriesForm from './repositories.js';
import {requestPermission} from './lib/permissions-service.js';
import {background} from './util.js';

document.addEventListener('DOMContentLoaded', async () => {
try {
Expand All @@ -11,13 +10,12 @@ document.addEventListener('DOMContentLoaded', async () => {
initGlobalSyncListener();
} catch (error) {
console.error(error);
background.error(error);
}
});

function initGlobalSyncListener() {
document.addEventListener('options-sync:form-synced', () => {
browser.runtime.sendMessage('update');
browser.runtime.sendMessage({action: 'update'});
});
}

Expand Down
2 changes: 0 additions & 2 deletions source/repositories.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import repositoriesStorage from './repositories-storage.js';
import optionsStorage from './options-storage.js';
import {listRepositories} from './lib/repositories-service.js';
import {getUser} from './lib/user-service.js';
import {background} from './util.js';

const form = document.querySelector('#repositories-form');
const button = document.querySelector('#reload-repositories');
Expand Down Expand Up @@ -35,7 +34,6 @@ export default async function init(update) {
try {
await renderCheckboxes(update);
} catch (error) {
background.error(error);
errorMessage.textContent = `Loading repositories failed: "${error.message}"`;
errorMessage.classList.remove('hidden');
}
Expand Down
14 changes: 2 additions & 12 deletions source/util.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import browser from 'webextension-polyfill';
import {getGitHubOrigin} from './lib/api.js';

export function isChrome() {
return navigator.userAgent.includes('Chrome');
export function isChrome(agentString = navigator.userAgent) {
return agentString.includes('Chrome');
}

export function parseFullName(fullName) {
Expand Down Expand Up @@ -43,12 +42,3 @@ export function parseLinkHeader(header) {

return links;
}

const backgroundPage = browser.extension.getBackgroundPage() || window;

export const background = {
log: backgroundPage.console.log,
warn: backgroundPage.console.warn,
error: backgroundPage.console.error,
info: backgroundPage.console.info
};
Loading
Loading