schoolbox web extension :)
at main 5.2 kB view raw
1import type { Browser } from "#imports"; 2import { browser, defineBackground, storage } from "#imports"; 3import { logger } from "@/utils/logger"; 4import type { BackgroundMessage } from "@/utils/storage"; 5import { globalSettings, updated } from "@/utils/storage"; 6import semver from "semver"; 7 8export default defineBackground(() => { 9 browser.runtime.onInstalled.addListener(async ({ reason, previousVersion }) => { 10 if (reason === "install") { 11 logger.info("[background] Opening wiki page after install"); 12 browser.tabs.create({ url: "https://schooltape.github.io/installed" }); 13 14 if (import.meta.env.DEV) { 15 logger.info("[background] Opening development URLs"); 16 browser.tabs.create({ url: "https://help.schoolbox.com.au/account/anonymous.php?" }); 17 browser.tabs.create({ url: browser.runtime.getURL("/popup.html") }); 18 const schoolbox = { 19 url: import.meta.env.WXT_SCHOOLBOX_URL, 20 jwt: import.meta.env.WXT_SCHOOLBOX_JWT, 21 }; 22 if (schoolbox.url && schoolbox.jwt) { 23 browser.tabs.create({ url: `${schoolbox.url}/api/session?jwt=${schoolbox.jwt}` }); 24 } 25 } 26 } else if (reason === "update") { 27 logger.info("[background] Showing update badge"); 28 29 await updated.set({ icon: true, changelog: true }); 30 updateIcon(); 31 32 const manifest = browser.runtime.getManifest(); 33 const newVersion = manifest.version_name || manifest.version; 34 35 // hacky way of resetting the extension to fix migration issues 36 // new version is greater than or equal to v4.0.5 AND previous version was less than v4.0.5 37 if (previousVersion && semver.gte(newVersion, "4.0.5") && semver.lt(previousVersion, "4.0.5")) { 38 logger.info("[background] Clearing storage (v4.0.5 migration)"); 39 await storage.clear("local"); 40 } 41 42 if (import.meta.env.DEV) { 43 logger.info("[background] Opening development URLs"); 44 browser.tabs.create({ url: browser.runtime.getURL("/popup.html"), active: false }); 45 } 46 } 47 }); 48 49 // update icon when toggle or update is changed 50 globalSettings.watch(updateIcon); 51 52 browser.runtime.onMessage.addListener(async (msg: BackgroundMessage, sender: Browser.runtime.MessageSender) => { 53 logger.info("[background] received message", { message: msg, sender }); 54 55 switch (msg.type) { 56 case "resetSettings": 57 resetSettings(); 58 break; 59 case "updateIcon": 60 updateIcon(); 61 break; 62 case "closeTab": 63 if (!sender.tab?.id) break; 64 browser.tabs.remove(sender.tab.id); 65 break; 66 case "updateTabUrl": 67 if (!sender.tab?.id) break; 68 browser.tabs.update(sender.tab.id, { url: msg.url }); 69 break; 70 default: 71 logger.error(`[background] unknown message received: ${msg}`); 72 } 73 74 return true; // return success 75 }); 76 77 // context menus 78 let contexts: Browser.contextMenus.CreateProperties["contexts"]; 79 logger.info(`[background] Manifest version: ${import.meta.env.MANIFEST_VERSION}`); 80 if (import.meta.env.MANIFEST_VERSION === 2) { 81 contexts = ["browser_action"]; 82 } else { 83 contexts = ["action"]; 84 } 85 browser.contextMenus.create({ 86 id: "report-bug", 87 title: "Report a bug...", 88 contexts: contexts, 89 }); 90 browser.contextMenus.create({ 91 id: "feature-request", 92 title: "Request a feature...", 93 contexts: contexts, 94 }); 95 browser.contextMenus.create({ 96 id: "github", 97 title: "GitHub", 98 contexts: contexts, 99 }); 100 browser.contextMenus.onClicked.addListener((info) => { 101 const manifest = browser.runtime.getManifest(); 102 const version = manifest.version_name || manifest.version; 103 104 switch (info.menuItemId) { 105 case "report-bug": 106 browser.tabs.create({ 107 url: `https://github.com/schooltape/schooltape/issues/new?template=bug.yml&version=v${version}`, 108 }); 109 break; 110 case "feature-request": 111 browser.tabs.create({ 112 url: "https://github.com/schooltape/schooltape/issues/new?template=feature.yml", 113 }); 114 break; 115 case "github": 116 browser.tabs.create({ url: "https://github.com/schooltape/schooltape" }); 117 break; 118 } 119 }); 120}); 121 122async function resetSettings(): Promise<void> { 123 logger.info("[background] Clearing local storage"); 124 await storage.clear("local"); 125} 126 127async function updateIcon() { 128 logger.info("[background] Updating icon..."); 129 130 let iconSuffix = ""; 131 132 // if it's june 133 if (new Date().getMonth() === 5) { 134 iconSuffix += "-ctp"; 135 } 136 if ((await globalSettings.get()).global === false) { 137 iconSuffix += "-disabled"; 138 } 139 if ((await updated.get()).icon === true) { 140 iconSuffix += "-badge"; 141 } 142 143 if (import.meta.env.MANIFEST_VERSION === 2) { 144 browser.browserAction.setIcon({ 145 path: { 146 16: `/icon/16${iconSuffix}.png`, 147 32: `/icon/32${iconSuffix}.png`, 148 48: `/icon/48${iconSuffix}.png`, 149 128: `/icon/128${iconSuffix}.png`, 150 }, 151 }); 152 } else { 153 browser.action.setIcon({ 154 path: { 155 16: `/icon/16${iconSuffix}.png`, 156 32: `/icon/32${iconSuffix}.png`, 157 48: `/icon/48${iconSuffix}.png`, 158 128: `/icon/128${iconSuffix}.png`, 159 }, 160 }); 161 } 162}