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

Deadline notification #472

Closed
wants to merge 12 commits into from
Closed
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@swc/jest": "^0.2.23",
"@tsconfig/recommended": "1.0.1",
"@types/chrome": "0.0.200",
"@types/dexie": "^1.3.1",
"@types/jest": "^29.2.1",
"@types/lodash-es": "4.17.6",
"@types/node": "18.11.9",
Expand Down Expand Up @@ -51,5 +52,8 @@
"*.{js,jsx,ts,tsx}": [
"eslint"
]
},
"dependencies": {
"dexie": "^3.2.2"
}
}
8 changes: 8 additions & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@
"description": {
"message": "Description",
"description": "Description"
},
"test": {
"message": "Test",
"description": "Test"
},
"assignment": {
"message": "Assignment",
"description": "Assignment"
}
}
8 changes: 8 additions & 0 deletions public/_locales/ja/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@
"description": {
"message": "概要",
"description": "概要"
},
"test": {
"message": "小テスト",
"description": "小テスト"
},
"assignment": {
"message": "レポート",
"description": "レポート"
}
}
16 changes: 16 additions & 0 deletions public/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,22 @@ <h2>Enabled Features</h2>
<div class="checkbox-style" />
</div>
</li>
<li>
<label
class="checkboxLabel"
for="featuresAssignmentDeadlineNotification"
>
Notify when assignment deadline is approaching
</label>
<div class="checkbox">
<input
type="checkbox"
id="featuresAssignmentDeadlineNotification"
class="checkbox-features"
/>
<div class="checkbox-style" />
</div>
</li>
</ul>
</section>
<section class="section-keys">
Expand Down
68 changes: 68 additions & 0 deletions src/background/assignmentDeadlineNotifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @see {@link https://developer.chrome.com/docs/extensions/reference/notifications/#type-NotificationOptions | Chrome Notifications API}
*/

import { AssignmentData } from "../methods/AssignmentSync"

import { getCurrentTab } from "./main"

const setAssignmentNotification = (data: AssignmentData) =>
data.id &&
data.deadline &&
chrome.alarms.create(data.id, {
when: calcNotificationTime(new Date(data.deadline), 1),
})

const createAssignmentNotification = (data: AssignmentData) =>
data.id &&
data.deadline &&
chrome.notifications.create(data.id, {
type: "basic",
iconUrl: "icons/icon_128.png",
title: `${data.course}`,
contextMessage: `${data.title}`,
message: `${new Date(data.deadline).toLocaleString()}が期限です。タイプは${
data.type
}です。\nクリックして詳細を確認できます。`,
buttons: [
{
title: "manabaを開く",
},
],
})

const calcNotificationTime = (deadline: Date, timeDay: number): number =>
deadline.getTime() - 1000 * 60 * 60 * 24 * timeDay

const createManabaTab = (notificationId: string) =>
chrome.tabs.create({
url: `https://manaba.tsukuba.ac.jp/ct/${notificationId}`,
})

chrome.runtime.onMessage.addListener(
({ action, assignmentData }) =>
action === "assignmentDeadlineNotification" &&
setAssignmentNotification(assignmentData)
)

chrome.alarms.onAlarm.addListener(({ name }) =>
getCurrentTab((tab: chrome.tabs.Tab) =>
chrome.tabs.sendMessage(
tab.id || 0,
{
kind: "getAssignmentData",
id: name,
},
(data: AssignmentData) => createAssignmentNotification(data)
)
)
)

// TODO: Avoidance of the `notificationId` collision of event listeners for `chrome.notifications`.
chrome.notifications.onButtonClicked.addListener((notificationId) =>
yudukikun5120 marked this conversation as resolved.
Show resolved Hide resolved
createManabaTab(notificationId)
)

chrome.notifications.onClicked.addListener((notificationId) =>
yudukikun5120 marked this conversation as resolved.
Show resolved Hide resolved
createManabaTab(notificationId)
)
30 changes: 29 additions & 1 deletion src/background.ts → src/background/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict"

import { getStorage, setStorage, onStorageChanged } from "./network/storage"
import { getStorage, setStorage, onStorageChanged } from "../network/storage"

const removeAttachmentHeader = (
details: chrome.webRequest.WebResponseHeadersDetails
Expand Down Expand Up @@ -80,6 +80,8 @@ chrome.runtime.onInstalled.addListener((details) => {
featuresReportTemplate: storage.featuresReportTemplate ?? true,
featuresDisableForceFileSaving:
storage.featuresDisableForceFileSaving ?? true,
featuresAssignmentDeadlineNotification:
storage.featuresAssignmentDeadlineNotification ?? false,
},
})

Expand Down Expand Up @@ -135,3 +137,29 @@ chrome.runtime.onMessage.addListener(({ url, filename }) => {
})
return true
})

chrome.runtime.onMessage.addListener(
({ action, assignmentData }) =>
action === "alarm-delete-assignment-from-db" &&
chrome.alarms.create(`delete-assignment-${assignmentData.id}`, {
when: assignmentData.deadline.getTime() + 1000 * 60 * 60 * 24,
})
)

chrome.alarms.onAlarm.addListener(({ name }) => {
if (name.startsWith("delete-assignment-")) {
const id = name.replace("delete-assignment-", "")
getCurrentTab(
(tab) =>
tab.id &&
chrome.tabs.sendMessage(tab.id, { kind: "delete-assignment", id })
)
}
})

const getCurrentTab = (callback: (tab: chrome.tabs.Tab) => void) =>
chrome.tabs.query({ active: true, lastFocusedWindow: true }, ([tab]) =>
callback(tab)
)

export { getCurrentTab }
29 changes: 29 additions & 0 deletions src/contentScript/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict"

import { AssignmentSync } from "../methods/AssignmentSync"
import checkAssignmentDeadline from "../methods/checkAssignmentDeadline"
import checkPagePubDeadline from "../methods/checkPagePubDeadline"
import colorizeDeadline from "../methods/colorizeDeadline"
Expand Down Expand Up @@ -123,6 +124,20 @@ const main = (storageSync: Partial<StorageSync>) => {
dragAndDrop()
}

if (storageSync.featuresAssignmentDeadlineNotification)
new AssignmentSync().sync(
(assignmentData) =>
chrome.runtime.sendMessage({
action: "assignmentDeadlineNotification",
assignmentData,
}),
(assignmentData) =>
chrome.runtime.sendMessage({
action: "alarm-delete-assignment-from-db",
assignmentData,
})
)

if (window.location.href.includes("usermemo")) {
setUsermemoShortcuts()
}
Expand All @@ -136,4 +151,18 @@ const main = (storageSync: Partial<StorageSync>) => {
}
}
})

chrome.runtime.onMessage.addListener(
({ kind, id }, _sender, sendResponse) => {
kind === "getAssignmentData" &&
new AssignmentSync().getAssignmentData(id).then(sendResponse)
return true
}
)

chrome.runtime.onMessage.addListener(
({ kind, id }) =>
kind === "delete-assignment" &&
new AssignmentSync().deleteAssignmentData(id)
)
}
7 changes: 6 additions & 1 deletion src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const generateManifest = () => {
"webRequest",
"webRequestBlocking",
"downloads",
"notifications",
"alarms",
"*://manaba.tsukuba.ac.jp/*",
],
options_ui: {
Expand All @@ -33,7 +35,10 @@ const generateManifest = () => {
open_in_tab: true,
},
background: {
scripts: ["background.js"],
scripts: [
"background/main.js",
"background/assignmentDeadlineNotifier.js",
],
persistent: true,
},
content_scripts: [
Expand Down
Loading