Skip to content

Commit 20e9a59

Browse files
committed
feat(safeMode): add chrome notification
1 parent 6e82f83 commit 20e9a59

File tree

12 files changed

+114
-20
lines changed

12 files changed

+114
-20
lines changed

extension/services/consts.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const ORIGIN = "https://web.simple-mmo.com"
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
import "./bosses"
22
import "./job"
3+
import "./safeMode"

extension/services/notifications/job/service.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { isServiceNotification } from "../utils"
22
import { JobNotificationData, isJobNotification } from "./types"
3+
import { ORIGIN } from "~/consts"
34

45
type SanitizedJobData = Omit<JobNotificationData, "timestamp">
56

67
function serializeJobData(job: JobNotificationData) {
7-
const { href, iconUrl } = job
8-
return JSON.stringify(["job", { href, iconUrl } as SanitizedJobData])
8+
const { iconUrl } = job
9+
return JSON.stringify(["job", { iconUrl } as SanitizedJobData])
910
}
1011

1112
function deserializeJobData(data: string) {
@@ -45,10 +46,10 @@ chrome.alarms.onAlarm.addListener(({ name: id }) => {
4546
})
4647

4748
chrome.notifications.onClicked.addListener((id) => {
48-
const [notification, { href }] = deserializeJobData(id)
49+
const [notification] = deserializeJobData(id)
4950
if (notification !== "job") return
5051

51-
chrome.tabs.create({ url: href })
52+
chrome.tabs.create({ url: ORIGIN })
5253
chrome.notifications.clear(id)
5354

5455
return true

extension/services/notifications/job/types.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { NotificationServiceMessage } from "../utils"
22

33
export interface JobNotificationData {
4-
href: string
54
timestamp: number
65
iconUrl: string
76
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { SafeModeNotification } from "./types"
2+
3+
export function sendSafeModeNotificationMessage(timestamp: string, toggle: boolean) {
4+
chrome.runtime.sendMessage<SafeModeNotification>({
5+
toggle,
6+
data: { timestamp },
7+
variant: "safeMode",
8+
type: "notification",
9+
})
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import "./service"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { isServiceNotification } from "../utils"
2+
import { SafeModeNotificationData, isSafeModeNotification } from "./types"
3+
import { ORIGIN } from "~/consts"
4+
5+
function serializeSafeModeData() {
6+
return JSON.stringify(["safeMode"])
7+
}
8+
9+
function deserializeSafeModeData(data: string) {
10+
return JSON.parse(data) as [string]
11+
}
12+
13+
function createSafeModeNotification(safeMode: SafeModeNotificationData) {
14+
chrome.alarms.create(serializeSafeModeData(), { when: new Date(safeMode.timestamp).valueOf() })
15+
}
16+
17+
function clearSafeModeNotification() {
18+
chrome.alarms.clear(serializeSafeModeData())
19+
}
20+
21+
chrome.runtime.onMessage.addListener((payload) => {
22+
if (!isServiceNotification(payload)) return
23+
if (!isSafeModeNotification(payload)) return
24+
25+
if (payload.toggle) createSafeModeNotification(payload.data)
26+
else clearSafeModeNotification()
27+
28+
return true
29+
})
30+
31+
chrome.alarms.onAlarm.addListener(({ name: id }) => {
32+
const [notification] = deserializeSafeModeData(id)
33+
if (notification !== "safeMode") return
34+
35+
chrome.notifications.create(id, {
36+
type: "basic",
37+
message: "Reactivate your safe mode now!",
38+
title: "Safe mode expired",
39+
iconUrl: ORIGIN + "/img/icons/E_Gold01.png",
40+
})
41+
42+
return true
43+
})
44+
45+
chrome.notifications.onClicked.addListener((id) => {
46+
const [notification] = deserializeSafeModeData(id)
47+
if (notification !== "safeMode") return
48+
49+
chrome.tabs.create({ url: ORIGIN + "/safemode" })
50+
chrome.notifications.clear(id)
51+
52+
return true
53+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NotificationServiceMessage } from "../utils"
2+
3+
export interface SafeModeNotificationData {
4+
timestamp: string
5+
}
6+
7+
export interface SafeModeNotification extends NotificationServiceMessage {
8+
variant: "safeMode"
9+
toggle: boolean
10+
data: SafeModeNotificationData
11+
}
12+
13+
export function isSafeModeNotification(val: NotificationServiceMessage): val is SafeModeNotification {
14+
return val.variant === "safeMode"
15+
}

src/views/Jobs/Job/Notification.vue

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ watchEffect(() => {
3232
{
3333
iconUrl: getNotificationIconUrl(),
3434
timestamp: getTimestamp(),
35-
href: window.location.origin,
3635
},
3736
shouldNotifyOnCompletion.value
3837
)

src/views/Notification/Items/SafeMode.vue

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import { Button } from "@/components"
55
import { useSafeModeStore } from "@/views/Settings/SafeMode/store"
66
import { storeToRefs } from "pinia"
77
import { addHours } from "date-fns"
8+
import { computed } from "vue"
89
910
const safeModeStore = useSafeModeStore()
10-
const { shouldShowSafeModeNotification, expirationTimestamp } = storeToRefs(safeModeStore)
11+
const { shouldRemindSafeMode, isSafeModeExpired, expirationTimestamp } = storeToRefs(safeModeStore)
12+
13+
const shouldShowSafeModeNotification = computed(() => shouldRemindSafeMode.value && isSafeModeExpired.value)
1114
</script>
1215

1316
<template>

src/views/Settings/SafeMode/SafeMode.vue

+22-10
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,36 @@
22
import { Controls, Checkbox } from "@/components"
33
import { useSafeModeStore } from "./store"
44
import { storeToRefs } from "pinia"
5-
import { onBeforeMount } from "vue"
5+
import { onBeforeMount, watchEffect } from "vue"
66
import { Duration, add } from "date-fns"
7+
import { sendSafeModeNotificationMessage } from "~/notifications/safeMode/client"
78
8-
const { shouldRemindSafeMode, shouldDisplayRemainingTimeInHeader, expirationTimestamp } = storeToRefs(
9-
useSafeModeStore()
10-
)
9+
const { shouldRemindSafeMode, shouldDisplayRemainingTimeInHeader, shouldUseChromeNotifications, expirationTimestamp } =
10+
storeToRefs(useSafeModeStore())
1111
12-
onBeforeMount(() => {
12+
function getRemainingDuration() {
1313
const timeDiv = document.querySelector<HTMLDivElement>("main .bg-white.mt-4 div.text-sm.text-gray-500")
14-
if (!timeDiv) {
15-
expirationTimestamp.value = new Date().toISOString()
16-
return
17-
}
14+
if (!timeDiv) return {}
1815
1916
const remainingTimeString = timeDiv.innerText.replace("Expires in ", "")
20-
const remainingDuration = remainingTimeString
17+
return remainingTimeString
2118
.split(/(,|and)/)
2219
.map((e) => e.trim().split(" "))
2320
.map((e): [number, keyof Duration] => [Number(e[0]), e[1] as keyof Duration])
2421
.reduce<Duration>((acc, [val, key]) => ({ ...acc, [key]: val }), {})
22+
}
23+
24+
const remainingDuration = getRemainingDuration()
2525
26+
onBeforeMount(() => {
2627
expirationTimestamp.value = add(new Date(), remainingDuration).toISOString()
2728
})
29+
30+
watchEffect(() => {
31+
if (!Object.keys(remainingDuration).length) return
32+
33+
sendSafeModeNotificationMessage(add(new Date(), remainingDuration).toISOString(), shouldUseChromeNotifications.value)
34+
})
2835
</script>
2936

3037
<template>
@@ -33,6 +40,11 @@ onBeforeMount(() => {
3340
<template #default> Remind to enable safe mode </template>
3441
<template #subtitle> A safe mode a day keeps the doctor away </template>
3542
</Checkbox>
43+
<Checkbox v-model="shouldUseChromeNotifications" :parent="shouldRemindSafeMode">
44+
<template #default> Show chrome notification </template>
45+
<template #subtitle> Be on point even outside simple mmo page </template>
46+
<template #requires> Requires reminder enabled </template>
47+
</Checkbox>
3648
<Checkbox v-model="shouldDisplayRemainingTimeInHeader" :parent="shouldRemindSafeMode">
3749
<template #default> Display remaining time in header </template>
3850
<template #subtitle> Know when the time to reenable is coming </template>

src/views/Settings/SafeMode/store.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ export const useSafeModeStore = defineStore(
77
() => {
88
const shouldRemindSafeMode = ref(false)
99
const shouldDisplayRemainingTimeInHeader = ref(false)
10+
const shouldUseChromeNotifications = ref(false)
1011

1112
const expirationTimestamp = ref(new Date().toISOString())
1213

1314
const isSafeModeExpired = computed(() => isAfter(new Date(), new Date(expirationTimestamp.value)))
1415

15-
const shouldShowSafeModeNotification = computed(() => shouldRemindSafeMode.value && isSafeModeExpired.value)
16-
1716
return {
1817
shouldRemindSafeMode,
1918
shouldDisplayRemainingTimeInHeader,
19+
shouldUseChromeNotifications,
2020
expirationTimestamp,
2121
isSafeModeExpired,
22-
shouldShowSafeModeNotification,
2322
}
2423
},
2524
{

0 commit comments

Comments
 (0)