Make extention acceptable by Edge Add-Ons website

This commit is contained in:
Christian Basler 2024-09-02 16:18:40 +02:00
parent d22252a9af
commit ce4907b8c4
27 changed files with 2955 additions and 100 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.yarn
node_modules
build

BIN
.yarn/install-state.gz Normal file

Binary file not shown.

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# A Toasty Owa <img src="public/icons/icon_128.png" style="float:right">
Show desktop notifications for new mail and calendar alerts.
## Features
- Show notifications for new mail and calendar alerts
- Add quick switch buttons for Inbox, Calendar, People and Tasks
## Install
### Chrome
### Edge
TODO
### Development
## Contribution
Suggestions and pull requests are welcomed!.

View File

@ -1,80 +0,0 @@
'use strict';
console.log("Loading background script....");
let notificationMap = {};
chrome.runtime.onMessage.addListener(
function (message, sender) {
if (message.type === 'quick-links') {
chrome.storage.sync.get('showQuickLinks', (data) => {
if (data.showQuickLinks) {
chrome.tabs.executeScript(sender.tab.id, { code: "$('#quick-links').show()" });
}
});
} else if (message.type === 'email') {
const { from, subject, body } = message;
chrome.notifications.create(null, {
type: "basic",
iconUrl: "images/email.png",
title: subject,
message: `From: ${from}\n${body}`,
requireInteraction: true
}, (notificationId) => {
notificationMap[notificationId] = { type: 'email', tabId: sender.tab.id, windowId: sender.tab.windowId };
startCloseNotificationTimer(notificationId, 'email');
});
} else {
const { title, duration } = message;
chrome.notifications.create(null, {
type: "basic",
iconUrl: "images/calendar.png",
title,
message: duration,
requireInteraction: true
}, (notificationId) => {
notificationMap[notificationId] = { type: 'calendar', tabId: sender.tab.id, windowId: sender.tab.windowId };
startCloseNotificationTimer(notificationId, 'calendar');
});
}
}
);
chrome.notifications.onClicked.addListener((notificationId) => {
if (notificationMap[notificationId]) {
const { type, tabId, windowId } = notificationMap[notificationId];
chrome.tabs.update(tabId, { active: true, highlighted: true });
chrome.windows.update(windowId, { focused: true });
chrome.notifications.clear(notificationId);
if (type === 'email') {
chrome.tabs.executeScript(tabId, { code: `$('#quick-link-mail')[0].click()` });
} else {
chrome.tabs.executeScript(tabId, { code: `$('#quick-link-calendar')[0].click()` });
}
}
});
chrome.runtime.onInstalled.addListener(function() {
chrome.storage.sync.set({emailDelay: -1, calendarDelay: -1, showQuickLinks: true});
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
css: ["body[aria-label='Outlook']"]
})],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});
function startCloseNotificationTimer(notificationId, type) {
chrome.storage.sync.get(`${type}Delay`, (data) => {
const delay = data[`${type}Delay`];
if (delay > 0 ) {
console.log(`Showing notification for ${delay} seconds`);
setTimeout(() => {
chrome.notifications.clear(notificationId);
}, delay * 1000);
}
});
}

10
config/paths.js Normal file
View File

@ -0,0 +1,10 @@
'use strict';
const path = require('path');
const PATHS = {
src: path.resolve(__dirname, '../src'),
build: path.resolve(__dirname, '../build'),
};
module.exports = PATHS;

58
config/webpack.common.js Normal file
View File

@ -0,0 +1,58 @@
'use strict';
const SizePlugin = require('size-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const PATHS = require('./paths');
const { ProvidePlugin } = require('webpack');
// To re-use webpack configuration across templates,
// CLI maintains a common webpack configuration file - `webpack.common.js`.
// Whenever user creates an extension, CLI adds `webpack.common.js` file
// in template's `config` folder
const common = {
output: {
// the build folder to output bundles and assets in.
path: PATHS.build,
// the filename template for entry chunks
filename: '[name].js',
},
devtool: 'source-map',
stats: {
all: false,
errors: true,
builtAt: true,
},
module: {
rules: [
// Check for images imported in .js files and
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
name: '[name].[ext]',
},
},
],
},
],
},
plugins: [
// Print file sizes
new SizePlugin(),
// Copy static assets from `public` folder to `build` folder
new CopyWebpackPlugin({
patterns: [
{
from: '**/*',
context: 'public',
},
]
}),
],
};
module.exports = common;

18
config/webpack.config.js Normal file
View File

@ -0,0 +1,18 @@
'use strict';
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const PATHS = require('./paths');
// Merge webpack configuration files
const config = merge(common, {
entry: {
popup: PATHS.src + '/popup.js',
service_worker: PATHS.src + '/service_worker.js',
contentScript: PATHS.src + '/contentScript.js',
jquery: 'jquery',
},
});
module.exports = config;

File diff suppressed because one or more lines are too long

22
package.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "a-toasty-owa",
"version": "1.0.2",
"description": "Show desktop notifications for new mail and calendar alerts",
"private": true,
"scripts": {
"watch": "yarn run webpack --mode=development --watch --config config/webpack.config.js",
"build": "yarn run webpack --mode=production --config config/webpack.config.js"
},
"packageManager": "yarn@4.4.1",
"devDependencies": {
"copy-webpack-plugin": "^6.4.1",
"file-loader": "^6.2.0",
"size-plugin": "^2.0.2",
"webpack": "^5.94.0",
"webpack-cli": "^4.10.0",
"webpack-merge": "^5.10.0"
},
"dependencies": {
"jquery": "^3.7.1"
}
}

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 717 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 429 B

After

Width:  |  Height:  |  Size: 429 B

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,23 +1,27 @@
{
"manifest_version": 3,
"name": "A Toasty OWA",
"version": "1.0.1",
"version": "1.0.2",
"description": "Show desktop notifications for new mail and calendar alerts",
"icons": {
"32": "icons/icon_32.png",
"48": "icons/icon_48.png",
"128": "icons/icon_128.png"
},
"permissions": [
"activeTab",
"declarativeContent",
"storage",
"notifications",
"tabs",
"http://*/*",
"https://*/*"
"scripting"
],
"host_permissions": [
"https://*/owa/*"
],
"background": {
"scripts": [
"background.js"
],
"persistent": false
"service_worker": "service_worker.js"
},
"page_action": {
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
@ -26,15 +30,8 @@
"https://*/owa/*"
],
"js": [
"jquery.3.3.1.slim.js",
"contentScript.js"
]
}
],
"icons": {
"32": "images/icon_32.png",
"48": "images/icon_48.png",
"128": "images/icon_128.png"
},
"manifest_version": 2
]
}

View File

@ -4,7 +4,7 @@
<head>
<style>
body {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
margin: 10px;
width: 220px;
}

1
size-plugin.json Normal file
View File

@ -0,0 +1 @@
[{"timestamp":1725286622851,"files":[{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"popup.js","previous":287,"size":30655,"diff":30368},{"filename":"service_worker.js","previous":849,"size":815,"diff":-34},{"filename":"contentScript.js","previous":0,"size":31387,"diff":31387},{"filename":"jquery.js","previous":0,"size":30459,"diff":30459}]},{"timestamp":1724674251968,"files":[{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"popup.js","previous":287,"size":287,"diff":0},{"filename":"service_worker.js","previous":804,"size":849,"diff":45}]},{"timestamp":1724672835507,"files":[{"filename":"app.js","previous":286,"size":0,"diff":-286},{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"background.js","previous":797,"size":0,"diff":-797},{"filename":"popup.js","previous":0,"size":287,"diff":287},{"filename":"service_worker.js","previous":0,"size":804,"diff":804}]},{"timestamp":1724672752620,"files":[{"filename":"app.js","previous":286,"size":286,"diff":0},{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"service_worker.js","previous":797,"size":0,"diff":-797},{"filename":"background.js","previous":0,"size":797,"diff":797}]},{"timestamp":1724672366631,"files":[{"filename":"app.js","previous":286,"size":286,"diff":0},{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"service_worker.js","previous":800,"size":797,"diff":-3}]},{"timestamp":1724672146257,"files":[{"filename":"app.js","previous":286,"size":286,"diff":0},{"filename":"service_worker.js","previous":800,"size":0,"diff":-800},{"filename":"options.html","previous":530,"size":530,"diff":0},{"filename":"popup.html","previous":543,"size":543,"diff":0},{"filename":"service_worker.js","previous":0,"size":800,"diff":800}]},{"timestamp":1724327326539,"files":[{"filename":"app.js","previous":0,"size":286,"diff":286},{"filename":"service_worker.js","previous":0,"size":800,"diff":800},{"filename":"options.html","previous":0,"size":530,"diff":530},{"filename":"popup.html","previous":0,"size":543,"diff":543}]}]

View File

@ -1,3 +1,5 @@
const $ = require('jquery');
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
const bodyObserver = new MutationObserver(bodyMutationHandler);
const popUpObserver = new MutationObserver(popUpAreaHandler);
@ -5,8 +7,10 @@ const obsConfig = { childList: true };
let insertedQuickLinks = false;
bodyObserver.observe($('body').get()[0], obsConfig);
window.$ = $;
$('body').append(`
<script src="jquery.js"></script>
<style>
.quick-links-container {
display: none;

View File

@ -1,5 +1,7 @@
'use strict';
const $ = require('jquery');
$('#emailDelay').change((event) => {
chrome.storage.sync.set({ emailDelay: parseInt(event.target.value) });
});

View File

@ -1,5 +1,7 @@
'use strict';
const $ = require('jquery');
$('#emailDelay').change((event) => {
chrome.storage.sync.set({ emailDelay: parseInt(event.target.value) });
});

89
src/service_worker.js Normal file
View File

@ -0,0 +1,89 @@
'use strict';
console.log("Loading service worker....");
let notificationMap = {};
chrome.runtime.onInstalled.addListener(() => {
chrome.storage.sync.set({ emailDelay: -1, calendarDelay: -1, showQuickLinks: true });
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
css: ["body[aria-label='Outlook']"]
})],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});
chrome.runtime.onMessage.addListener((message, sender) => {
if (message.type === 'quick-links') {
chrome.storage.sync.get('showQuickLinks', (data) => {
if (data.showQuickLinks) {
chrome.scripting.executeScript({
target: { tabId: sender.tab.id },
func: () => { $('#quick-links').show() }
});
}
});
} else if (message.type === 'email') {
const { from, subject, body } = message;
chrome.notifications.create(null, {
type: "basic",
iconUrl: "images/email.png",
title: subject,
message: `From: ${from}\n${body}`,
requireInteraction: true
}, (notificationId) => {
notificationMap[notificationId] = { type: 'email', tabId: sender.tab.id, windowId: sender.tab.windowId };
startCloseNotificationTimer(notificationId, 'email');
});
} else {
const { title, duration } = message;
chrome.notifications.create(null, {
type: "basic",
iconUrl: "images/calendar.png",
title,
message: duration,
requireInteraction: true
}, (notificationId) => {
notificationMap[notificationId] = { type: 'calendar', tabId: sender.tab.id, windowId: sender.tab.windowId };
startCloseNotificationTimer(notificationId, 'calendar');
});
}
}
);
chrome.notifications.onClicked.addListener((notificationId) => {
if (notificationMap[notificationId]) {
const { type, tabId, windowId } = notificationMap[notificationId];
chrome.tabs.update(tabId, { active: true, highlighted: true });
chrome.windows.update(windowId, { focused: true });
chrome.notifications.clear(notificationId);
if (type === 'email') {
chrome.scripting.executeScript({
target: { tabId: tabId },
func: () => { $('#quick-link-mail')[0].click() }
});
} else {
chrome.scripting.executeScript({
target: { tabId: tabId },
tabId,
func: () => { $('#quick-link-calendar')[0].click() }
});
}
}
});
function startCloseNotificationTimer(notificationId, type) {
chrome.storage.sync.get(`${type}Delay`, (data) => {
const delay = data[`${type}Delay`];
if (delay > 0) {
console.log(`Showing notification for ${delay} seconds`);
setTimeout(() => {
chrome.notifications.clear(notificationId);
}, delay * 1000);
}
});
}

2707
yarn.lock Normal file

File diff suppressed because it is too large Load Diff