diff --git a/.vscode/settings.json b/.vscode/settings.json index 8ed726b..df862f0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,5 +15,6 @@ }, "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "typescript.tsserver.experimental.enableProjectDiagnostics": true } diff --git a/Todo.md b/Todo.md index 6fad85d..8bdc17e 100644 --- a/Todo.md +++ b/Todo.md @@ -1,18 +1,43 @@ ## Todo -### ウェブサイト +### ゲーミング -- [ ] [mdl.media.gunma-u.ac.jp](https://mdl.media.gunma-u.ac.jp/GU/index.php) -- [ ] [www.kyomu-sys.gunma-u.ac.jp](https://www.kyomu-sys.gunma-u.ac.jp/Portal/) -- [ ] [www.media.gunma-u.ac.jp](https://www.media.gunma-u.ac.jp/) -- [ ] [www.gunma-u.ac.jp](https://www.gunma-u.ac.jp/) +- SSOログイン画面 + - [x] 基本的な実装 + - [ ] 見やすさの改善 +- [mdl.media.gunma-u.ac.jp](https://mdl.media.gunma-u.ac.jp/GU/index.php) + - [x] 基本的な実装 +- [www.kyomu-sys.gunma-u.ac.jp](https://www.kyomu-sys.gunma-u.ac.jp/Portal/) + - [x] 基本的な実装 +- [www.media.gunma-u.ac.jp](https://www.media.gunma-u.ac.jp/) + - [x] 基本的な実装 +- [opac.lib.gunma-u.ac.jp](https://opac.lib.gunma-u.ac.jp/opc/) + - [x] 基本的な実装 +- [www.gunma-u.ac.jp](https://www.gunma-u.ac.jp/) + - [ ] 基本的な実装 + +### ダークモード + +- SSOログイン画面 + - [ ] 基本的な実装 +- [mdl.media.gunma-u.ac.jp](https://mdl.media.gunma-u.ac.jp/GU/index.php) + - [ ] 基本的な実装 +- [www.kyomu-sys.gunma-u.ac.jp](https://www.kyomu-sys.gunma-u.ac.jp/Portal/) + - [ ] 基本的な実装 +- [www.media.gunma-u.ac.jp](https://www.media.gunma-u.ac.jp/) + - [ ] 基本的な実装 +- [opac.lib.gunma-u.ac.jp](https://opac.lib.gunma-u.ac.jp/opc/) + - [ ] 基本的な実装 +- [www.gunma-u.ac.jp](https://www.gunma-u.ac.jp/) + - [ ] 基本的な実装 ### 開発 - [ ] [webpack-chrome-extension-reloader](https://www.npmjs.com/package/webpack-chrome-extension-reloader)でホットリロードに対応する -- [ ] SCSSで直にスタイルを書き込んだ場合に無効化できない問題を修正する +- [x] SCSSで直にスタイルを書き込んだ場合に無効化できない問題を修正する - [ ] リロードなしで有効化/無効化できるようにする - [ ] Reactコンポーネントを最適化する - [ ] テストを書く - [ ] ドキュメントを書く -- [ ] 設定を開いている間はポップアップを無効化する +- [x] 設定を開いている間はポップアップを無効化する +- [ ] ポップアップでの設定変更後に手動でリロードする必要がある問題を修正する diff --git a/package.json b/package.json index 7c48b6c..e377e5b 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "webpack-merge": "^5.10.0" }, "volta": { - "node": "18.18.1" + "node": "20.9.0" }, "dependencies": { "classnames": "^2.3.2", diff --git a/src/class/ClassApplicator.ts b/src/class/ClassApplicator.ts new file mode 100644 index 0000000..0b2971e --- /dev/null +++ b/src/class/ClassApplicator.ts @@ -0,0 +1,83 @@ +import { addClass, Elements, removeClass } from "../utils/addClass"; + +const rainbowBg = "rainbow-bg"; +const rainbowText = "rainbow-text"; +const rainbowBgShadow = "rainbow-bg-shadow"; +const rainbowTextShadow = "rainbow-text-shadow"; + +// 要素にclassNameを追加します +// baseとclassesで追加するclassNameを指定し、applyで適用、removeで削除します +// selectorで適用されるセレクタを取得できます +// baseは初期化に必ず指定する必要があり書き換えるべきではありませんが、classesは追加で個別の設定を行うために指定できます +export class classApplicator { + #base: string[]; + classes: string[]; + constructor(base: string[]) { + this.#base = base; + this.classes = []; + } + + apply(...elements: Elements[]) { + addClass(elements, [...this.#base, ...this.classes]); + } + remove(...elements: Elements[]) { + removeClass(elements, [...this.#base, ...this.classes]); + } + selector() { + if (this.classes.length === 0) return `.${this.#base}`; + else return `.${this.#base}.${this.classes.join(".")}`; + } +} + +export class ApplicatorBase { + enable() {} + disable() {} +} + +// classApplicatorを用いて虹色にするクラス +export class RainbowApplicator extends ApplicatorBase { + text: classApplicator; + bg: classApplicator; + textShadow: classApplicator; + bgShadow: classApplicator; + + constructor() { + super(); + this.text = new classApplicator([rainbowText]); + this.bg = new classApplicator([rainbowBg]); + this.textShadow = new classApplicator([rainbowText, rainbowTextShadow]); + this.bgShadow = new classApplicator([rainbowBg, rainbowBgShadow]); + } +} + +// 隠し機能を有効化するクラス +export class HiddenApplicator extends ApplicatorBase {} + +// classApplicatorを用いてダークテーマにするクラス +export class DarkApplicator extends ApplicatorBase { + bgBase: classApplicator; + bgBaseDarker: classApplicator; + bgContent: classApplicator; + bgNeutral: classApplicator; + bgAccent: classApplicator; + textBase: classApplicator; + textBaseDarker: classApplicator; + textContent: classApplicator; + textNeutral: classApplicator; + textAccent: classApplicator; + + constructor() { + super(); + + this.bgBase = new classApplicator(["bg-base"]); + this.bgBaseDarker = new classApplicator(["bg-base-darker"]); + this.bgContent = new classApplicator(["bg-content"]); + this.bgNeutral = new classApplicator(["bg-neutral"]); + this.bgAccent = new classApplicator(["bg-accent"]); + this.textBase = new classApplicator(["text-base"]); + this.textBaseDarker = new classApplicator(["text-base-darker"]); + this.textContent = new classApplicator(["text-content"]); + this.textNeutral = new classApplicator(["text-neutral"]); + this.textAccent = new classApplicator(["text-accent"]); + } +} diff --git a/src/class/Kyomu/index.ts b/src/class/Kyomu/index.ts index a26b81b..a6368c0 100644 --- a/src/class/Kyomu/index.ts +++ b/src/class/Kyomu/index.ts @@ -5,7 +5,7 @@ import { GundaiWebSite } from "../UnivWebsite"; export const Kyomu = new GundaiWebSite("kyomu"); -Kyomu.enableRainbow = function () { +Kyomu.rainbow.enable = function () { // ログインボタン // https://qiita.com/Sekky0905/items/a88721f2af41050c93f2 const loginBtn: HTMLInputElement = document.getElementById("ctl21_btnLoginShibbolethGunma"); @@ -14,19 +14,19 @@ Kyomu.enableRainbow = function () { } // ページ遷移リンク - this.rainbowText.apply(".commonTopPageLink", ".commonTopPageLinkWithPadding"); + this.text.apply(".commonTopPageLink", ".commonTopPageLinkWithPadding"); - this.rainbowText.apply( + this.text.apply( "#CtlInfLstBfrLginEmrgncy_LblTitle", "#CtlInfLstBfrLginNrml_LblTitle", "#AllAnnualList_LblTitle", "#JeLblSyllabiHeader_lbl", ); - this.rainbowBg.apply(".infoListEntryOrgName"); - this.rainbowBg.apply(".infoListBeforeLoginGrid"); + this.bg.apply(".infoListEntryOrgName"); + this.bg.apply(".infoListBeforeLoginGrid"); // ログイン後のトップページ - this.rainbowBg.apply(".top_title_header", ".top_now_title"); + this.bg.apply(".top_title_header", ".top_now_title"); // トップページのウェルカムメッセージ changeQueryInnerHTML("#loginHeader_lblWelcome_1_lbl", "よおこそ、群馬大学ゲーミング教務システムへ"); @@ -39,7 +39,7 @@ Kyomu.enableRainbow = function () { changeQueryInnerHTML("#AllAnnualList_LblTitle", "ゲーミング ライフ スタイル"); // 受信メッセージ一覧 - this.rainbowBgShadow.apply("#ctl00_phContents_ctlMesReceive_gridMes tr"); + this.bgShadow.apply("#ctl00_phContents_ctlMesReceive_gridMes tr"); // リンクを挿入 if (["/portal/login.aspx", "/portal/"].includes(location.pathname.toLowerCase())) { @@ -52,5 +52,5 @@ Kyomu.enableRainbow = function () { } //ヘッダー上部の名前 - this.rainbowText.apply("#ctl00_bhHeader_lblName"); + this.text.apply("#ctl00_bhHeader_lblName"); }; diff --git a/src/class/Media/index.ts b/src/class/Media/index.ts index a3203e9..bb29418 100644 --- a/src/class/Media/index.ts +++ b/src/class/Media/index.ts @@ -3,10 +3,10 @@ import { GundaiWebSite } from "../UnivWebsite"; export const Media = new GundaiWebSite("media"); -Media.enableRainbow = function () { - this.rainbowBgShadow.apply(".banner_list li"); - this.rainbowBgShadow.apply(".banner_list li a"); - this.rainbowBgShadow.apply(".menu_category h3"); - this.rainbowText.apply("#news_list li a"); - this.rainbowBg.apply("#news_category_list .active"); +Media.rainbow.enable = function () { + this.bgShadow.apply(".banner_list li"); + this.bgShadow.apply(".banner_list li a"); + this.bgShadow.apply(".menu_category h3"); + this.text.apply("#news_list li a"); + this.bg.apply("#news_category_list .active"); }; diff --git a/src/class/Moodle/DisableRainbow.ts b/src/class/Moodle/DisableRainbow.ts deleted file mode 100644 index 8d34612..0000000 --- a/src/class/Moodle/DisableRainbow.ts +++ /dev/null @@ -1,12 +0,0 @@ -import changeQueryInnerHTML from "../../utils/changeQueryInnerHTML"; -import { Moodle } from "./type"; - -export const DisableRainbowBg = (moodle: Moodle) => { - moodle.rainbowBg.remove(".navbar", ".addinghtml"); - moodle.rainbowBg.remove(".page-header-headings h1"); - moodle.rainbowBg.remove("a"); -}; - -export const ReplaceImagesToDefault = () => { - changeQueryInnerHTML("#instance-320-header", "現在のログイン人数"); -}; diff --git a/src/class/Moodle/disable-utils.ts b/src/class/Moodle/disable-utils.ts new file mode 100644 index 0000000..7734897 --- /dev/null +++ b/src/class/Moodle/disable-utils.ts @@ -0,0 +1,12 @@ +import changeQueryInnerHTML from "../../utils/changeQueryInnerHTML"; +import { RainbowApplicator } from "../ClassApplicator"; + +export const DisableRainbowBg = (rainbow: RainbowApplicator) => { + rainbow.bg.remove(".navbar", ".addinghtml"); + rainbow.bg.remove(".page-header-headings h1"); + rainbow.bg.remove("a"); +}; + +export const ReplaceImagesToDefault = () => { + changeQueryInnerHTML("#instance-320-header", "現在のログイン人数"); +}; diff --git a/src/class/Moodle/EnableRainbow.ts b/src/class/Moodle/enable-utils.ts similarity index 65% rename from src/class/Moodle/EnableRainbow.ts rename to src/class/Moodle/enable-utils.ts index 98a4249..2eb39bd 100644 --- a/src/class/Moodle/EnableRainbow.ts +++ b/src/class/Moodle/enable-utils.ts @@ -1,23 +1,23 @@ -import { removeClass } from "../../utils/addClass"; import changeQueryInnerHTML from "../../utils/changeQueryInnerHTML"; +import { RainbowApplicator } from "../ClassApplicator"; import { GundaiWebSite } from "../UnivWebsite"; -import { Moodle } from "./type"; import { MoodleAdditionalInfo } from "./type"; -export const EnableRainbowTextAndBg = (moodle: Moodle) => { - moodle.rainbowBg.apply(".navbar", "#action-menu-0-menu"); +export const enableRainbowTextAndBg = (rainbow: RainbowApplicator) => { + rainbow.bg.apply(".navbar", "#action-menu-0-menu"); - moodle.rainbowText.apply(".page-header-headings h1"); - moodle.rainbowText.apply("#page-content a:not(#inst301 a)"); - moodle.rainbowText.apply("#instance-301-header"); + rainbow.text.apply(".page-header-headings h1"); + rainbow.text.apply("#page-content a:not(#inst301 a)"); + rainbow.text.apply("#instance-301-header"); // rainbowBgの中のrainbowTextを無効化 - const rainbowBgSelector = moodle.rainbowBg.selector(); - const targetElementsSelector = `${rainbowBgSelector} ${moodle.rainbowText.selector()}`; - removeClass([targetElementsSelector], moodle.rainbowText.base); + const rainbowBgSelector = rainbow.bg.selector(); + const targetElementsSelector = `${rainbowBgSelector} ${rainbow.text.selector()}`; + //removeClass([targetElementsSelector], rainbow.text.base); + rainbow.text.remove(targetElementsSelector); }; -export const InjectLink = () => { +export const injectLink = () => { const supportSection = document.querySelector(".footer-support-link"); if (supportSection) supportSection.innerHTML = @@ -25,17 +25,19 @@ export const InjectLink = () => { `Gaming Edition開発者に連絡する`; }; -export const ReplaceImagesToGamimg = () => { +export const replaceLMSLogo = () => { document.querySelectorAll(".logo").forEach((e) => { if (e.getAttribute("src")) e.setAttribute("src", chrome.runtime.getURL("assets/GULMS.png")); }); +}; +export const replaceImagesToGamimg = () => { document.querySelectorAll("img.userpicture").forEach((e) => { if (e.getAttribute("src")) e.setAttribute("src", chrome.runtime.getURL("assets/partyparrot.gif")); }); }; -export const ReplaceTextToGaimg = (moodle: GundaiWebSite) => { +export const replaceTextToGaimg = (moodle: GundaiWebSite) => { const headerText = moodle.additionalInfo.headerText; document.querySelectorAll(".page-header-headings h1").forEach((e) => { diff --git a/src/class/Moodle/index.ts b/src/class/Moodle/index.ts index ae8e959..882d724 100644 --- a/src/class/Moodle/index.ts +++ b/src/class/Moodle/index.ts @@ -1,8 +1,8 @@ // 情報の信頼性は社会の構築において重要な要素である // 個人の信頼性は家庭の構築において重要な要素である import { GundaiWebSite } from "../UnivWebsite"; -import { DisableRainbowBg, ReplaceImagesToDefault } from "./DisableRainbow"; -import { EnableRainbowTextAndBg, InjectLink, ReplaceImagesToGamimg, ReplaceTextToGaimg } from "./EnableRainbow"; +import { DisableRainbowBg, ReplaceImagesToDefault } from "./disable-utils"; +import { enableRainbowTextAndBg, injectLink, replaceImagesToGamimg, replaceLMSLogo, replaceTextToGaimg } from "./enable-utils"; import { MoodleAdditionalInfo } from "./type"; export const Moodle = new GundaiWebSite("moodle"); @@ -10,11 +10,12 @@ Moodle.additionalInfo = { headerText: " Gaming Edition🎮", }; -Moodle.enableRainbow = function () { - EnableRainbowTextAndBg(this); - InjectLink(); - ReplaceImagesToGamimg(); - ReplaceTextToGaimg(this); +Moodle.rainbow.enable = function () { + enableRainbowTextAndBg(this); + injectLink(); + replaceImagesToGamimg(); + replaceTextToGaimg(Moodle); + replaceLMSLogo(); // メニューバーでホバー時にclassを追加 document.querySelectorAll(".moremenu .nav-link").forEach((e) => { @@ -30,17 +31,18 @@ Moodle.enableRainbow = function () { }); }; -Moodle.disableRainbow = function () { +Moodle.rainbow.disable = function () { DisableRainbowBg(this); ReplaceImagesToDefault(); + ReplaceImagesToDefault(); - const headerText = this.additionalInfo.headerText; + const headerText = Moodle.additionalInfo.headerText; document.querySelectorAll(".page-header-headings h1").forEach((e) => { if (e.innerHTML.includes(headerText)) e.innerHTML.replace(headerText, ""); }); }; -Moodle.enableHidden = () => { +Moodle.hidden.enable = () => { const cardElement = document.querySelector(".card-text .no-overflow"); if (!cardElement) return; const playCountUnderTextElement = cardElement.getElementsByTagName("p")[1]; @@ -48,3 +50,22 @@ Moodle.enableHidden = () => { playCountUnderTextElement.innerHTML = "想定最大利用者乳首数:4,000"; }; + +Moodle.dark.enable = function () { + // 画像差し替え + replaceLMSLogo(); + + // トップページ + Moodle.dark.bgBase.apply("#page,#page.drawers .main-inner,#region-main"); + this.textContent.apply("#page"); + this.bgNeutral.apply(".activity-item .description .activity-altcontent.course-description-item"); + this.bgBase.apply(".bg-white"); + + // Header + this.textContent.apply(".navbar-light .navbar-nav .nav-link"); + this.textAccent.apply(".navbar-nav .nav-link.active"); + this.textContent.apply(".primary-navigation .navigation .nav-link"); + + // dashboard + this.bgBase.apply(".card-body"); +}; diff --git a/src/class/MyLibrary/index.ts b/src/class/MyLibrary/index.ts index 4c204bd..3389947 100644 --- a/src/class/MyLibrary/index.ts +++ b/src/class/MyLibrary/index.ts @@ -3,7 +3,7 @@ import { GundaiWebSite } from "../UnivWebsite"; export const MyLibrary = new GundaiWebSite("mylibrary"); -MyLibrary.enableRainbow = function () { +MyLibrary.rainbow.enable = function () { if (location.pathname == "/portal/portal/selectLogin/") { //document.getElementById("explanation") ChangeQueryInnerHTML( @@ -13,11 +13,11 @@ MyLibrary.enableRainbow = function () { ChangeQueryInnerHTML("#ssoLoginTitle", "全学ゲーミングアカウントでログイン"); // フッターをレインボー - this.rainbowBg.apply("#footer"); + this.bg.apply("#footer"); document.getElementById("footer")!.id = ""; } // ヘッダーとタイトルをレインボー - this.rainbowBg.apply("#header", "h2"); - this.rainbowText.apply("#lblTitle", "#mainTitle"); + this.bg.apply("#header", "h2"); + this.text.apply("#lblTitle", "#mainTitle"); }; diff --git a/src/class/SSO/index.ts b/src/class/SSO/index.ts index 7a71e29..53f36db 100644 --- a/src/class/SSO/index.ts +++ b/src/class/SSO/index.ts @@ -5,7 +5,7 @@ import changeQueryInnerHTML from "../../utils/changeQueryInnerHTML"; import { GundaiWebSite } from "../UnivWebsite"; export const SSO = new GundaiWebSite("sso"); -SSO.enableRainbow = () => { - SSO.rainbowBg.apply(".header_column", ".input_form", ".input_column"); +SSO.rainbow.enable = function () { + this.bg.apply(".header_column", ".input_form", ".input_column"); changeQueryInnerHTML(".product", "群馬大学ゲーミングサインオンシステム"); }; diff --git a/src/class/StorageTool/index.ts b/src/class/StorageTool/index.ts index 33dc4c2..79bf2de 100644 --- a/src/class/StorageTool/index.ts +++ b/src/class/StorageTool/index.ts @@ -1,5 +1,7 @@ import IsTrue from "../../utils/isTrue"; +type Keys = "dark" | "rainbow" | "enabled-hidden" | "show-hidden-option" | "installed"; + export class StorageTool { id: string; constructor(id: string) { @@ -11,7 +13,7 @@ export class StorageTool { } // eslint-disable-next-line @typescript-eslint/no-explicit-any - async set(key: string, value: any) { + async set(key: Keys, value: any) { let newData = { [key]: value }; const storage = StorageTool.getChromeStorage(); if (!storage) { @@ -24,7 +26,7 @@ export class StorageTool { storage.set({ [this.id]: newData }); } - async getBool(key: string) { + async getBool(key: Keys) { const storage = StorageTool.getChromeStorage(); if (!storage) { console.error("Storage is not supported"); @@ -35,7 +37,7 @@ export class StorageTool { return IsTrue(rawdata); } - async get(key: string) { + async get(key: Keys) { const storage = StorageTool.getChromeStorage(); if (!storage) { console.error("Storage is not supported"); diff --git a/src/class/UnivWebsite/index.ts b/src/class/UnivWebsite/index.ts index cb35c2a..f40fd42 100644 --- a/src/class/UnivWebsite/index.ts +++ b/src/class/UnivWebsite/index.ts @@ -1,15 +1,11 @@ // 無駄とは人生である。無駄を極めよ。無駄を愛せ。無駄を生きろ。 // 無駄を以て物を成す者は、無駄を以て物を滅ぼす者に勝る。x -import { addClass, Elements, removeClass } from "../../utils/addClass"; +import isTrue from "../../utils/isTrue"; +import { DarkApplicator, HiddenApplicator, RainbowApplicator } from "../ClassApplicator"; import { StorageTool } from "../StorageTool"; //import Storage from "../../utils/Storage"; -const rainbowBg = "rainbow-bg"; -const rainbowText = "rainbow-text"; -const rainbowBgShadow = "rainbow-bg-shadow"; -const rainbowTextShadow = "rainbow-text-shadow"; - // UnivWebSiteはゲーミング化するウェブサイトを定義したクラス // 型変数とAdditionalInfoプロパティによって任意の情報を追加できる export class UnivWebsite { @@ -17,72 +13,73 @@ export class UnivWebsite { additionalInfo: T; // 型変数使うとかっこいいよね storage: StorageTool; - rainbowText: Rainbow; - rainbowBg: Rainbow; - - rainbowTextShadow: Rainbow; - rainbowBgShadow: Rainbow; + rainbow: RainbowApplicator; + dark: DarkApplicator; + hidden: HiddenApplicator; constructor(id: string) { this.id = id; this.additionalInfo = {} as T; this.storage = new StorageTool(id); - this.rainbowText = new Rainbow([rainbowText]); - this.rainbowBg = new Rainbow([rainbowBg]); - this.rainbowTextShadow = new Rainbow([rainbowText, rainbowTextShadow]); - this.rainbowBgShadow = new Rainbow([rainbowBg, rainbowBgShadow]); - - this.enableRainbow.bind(this); - this.enableHidden.bind(this); - this.disableRainbow.bind(this); - this.disableHidden.bind(this); + this.rainbow = new RainbowApplicator(); + this.dark = new DarkApplicator(); + this.hidden = new HiddenApplicator(); } - // これらのメソッドは継承先でオーバーライドする - enableRainbow() {} - enableHidden() {} - disableRainbow() {} - disableHidden() {} - - // 上記の関数を実行するためのラッパー - enable() { - // CSSのためにHTML要素にデータ属性を追加 - document.documentElement.dataset.gaming_gundai = "true"; - this.storage.set("enabled", "true"); - this.enableRainbow(); + async isRainbowEnabled() { + const isRainbowEnabled = await this.storage.get("rainbow"); + return isTrue(isRainbowEnabled); + } - new StorageTool("other").getBool("enabled-hidden").then((enabled) => { - if (enabled) this.enableHidden(); - }); + async isDarkEnabled() { + const isDarkEnabled = await this.storage.get("dark"); + return isTrue(isDarkEnabled); } - disable() { - // CSSのためにHTML要素にデータ属性を追加 - document.documentElement.dataset.gaming_gundai = "false"; - this.storage.set("enabled", "false"); - this.disableRainbow(); - //this.DisableHidden(); + + async isHiddenEnabled() { + const otherStorage = new StorageTool("other"); + const isHiddenEnabled = await otherStorage.getBool("enabled-hidden"); + return isTrue(isHiddenEnabled); } -} -export class GundaiWebSite extends UnivWebsite {} + static async load(site: UnivWebsite) { + const isRainbowEnabled = await site.isRainbowEnabled(); + if (isRainbowEnabled) { + // CSSのためにHTML要素にデータ属性を追加 + document.documentElement.dataset.gaming_gundai = "true"; + site.storage.set("rainbow", "true"); + site.rainbow.enable(); + } else { + // CSSのためにHTML要素にデータ属性を追加 + document.documentElement.dataset.gaming_gundai = "false"; + site.storage.set("rainbow", "false"); + site.rainbow.disable(); + } -export class Rainbow { - base: string[]; - classes: string[]; - constructor(base: string[]) { - this.base = base; - this.classes = []; - } + const isDarkEnabled = await site.isDarkEnabled(); + if (isDarkEnabled) { + document.documentElement.dataset.gaming_gundai_dark = "true"; + site.storage.set("dark", "true"); + site.dark.enable(); + } else { + document.documentElement.dataset.gaming_gundai_dark = "false"; + site.storage.set("dark", "false"); + site.dark.disable(); + } - apply(...elements: Elements[]) { - addClass(elements, [...this.base, ...this.classes]); - } - remove(...elements: Elements[]) { - removeClass(elements, [...this.base, ...this.classes]); - } - selector() { - if (this.classes.length === 0) return `.${this.base}`; - else return `.${this.base}.${this.classes.join(".")}`; + const isHiddenEnabled = await site.isHiddenEnabled(); + const otherStorage = new StorageTool("other"); + if (isHiddenEnabled) { + document.documentElement.dataset.gaming_gundai_hidden = "true"; + otherStorage.set("enabled-hidden", "true"); + site.hidden.enable(); + } else { + document.documentElement.dataset.gaming_gundai_hidden = "false"; + site.storage.set("enabled-hidden", "false"); + site.hidden.disable(); + } } } + +export class GundaiWebSite extends UnivWebsite {} diff --git a/src/components/SwitchItem.tsx b/src/components/SwitchItem.tsx index 809c7ec..b8e547d 100644 --- a/src/components/SwitchItem.tsx +++ b/src/components/SwitchItem.tsx @@ -6,13 +6,14 @@ import { useCallback, useEffect, useState } from "react"; import { WebSites } from "../class"; import IsTrue from "../utils/isTrue"; import { FrontConfig } from "./config"; +import { Category } from "./type"; -export function SwitchItem({ config, className }: { config: FrontConfig; className?: string }) { +export function SwitchItem({ config, className, category }: { config: FrontConfig; className?: string; category: Category }) { const [enabled, setEnabled] = useState(false); console.log(`Render SwitchItem with ${config.name}`); useEffect(() => { - WebSites[config.id].storage.get("enabled").then((value) => { + WebSites[config.id].storage.get(category).then((value) => { setEnabled(IsTrue(value)); }); }, []); @@ -20,8 +21,7 @@ export function SwitchItem({ config, className }: { config: FrontConfig; classNa const genericChangeHandle = useCallback(() => { return (e: React.ChangeEvent) => { setEnabled(e.target.checked); - WebSites[config.id].storage.set("enabled", e.target.checked.toString()); - chrome.runtime.sendMessage("reload"); + WebSites[config.id].storage.set(category, e.target.checked.toString()); }; }, []); diff --git a/src/components/Switches.tsx b/src/components/Switches.tsx index a44731c..a95441a 100644 --- a/src/components/Switches.tsx +++ b/src/components/Switches.tsx @@ -1,11 +1,12 @@ import { FrontConfigs } from "./config"; import { SwitchItem } from "./SwitchItem"; +import { Category } from "./type"; -export function Switches({ className }: { className?: string }) { +export function Switches({ className, category }: { className?: string; category: Category }) { return ( <> {FrontConfigs.map((config) => { - return ; + return ; })} ); diff --git a/src/components/type.ts b/src/components/type.ts new file mode 100644 index 0000000..3303d3b --- /dev/null +++ b/src/components/type.ts @@ -0,0 +1 @@ +export type Category = "rainbow" | "dark"; diff --git a/src/options/pages/Top.tsx b/src/options/pages/Top.tsx index 54c8ed5..51e5473 100644 --- a/src/options/pages/Top.tsx +++ b/src/options/pages/Top.tsx @@ -10,9 +10,15 @@ import IsTrue from "../../utils/isTrue"; export default function Top() { return ( <> - +
- + +
+
+ + +
+
diff --git a/src/popup/components/Main.tsx b/src/popup/components/Main.tsx index 8f31191..91e5d63 100644 --- a/src/popup/components/Main.tsx +++ b/src/popup/components/Main.tsx @@ -18,7 +18,7 @@ export default function Main(props: MainProps) { [], ); - const switches = ; + const switches = ; const hiddenMsg =

設定画面を表示中はポップアップを利用できません

; return ( diff --git a/src/scripts/content_common.ts b/src/scripts/content_common.ts index ee7978f..53d4dd6 100644 --- a/src/scripts/content_common.ts +++ b/src/scripts/content_common.ts @@ -1,4 +1,5 @@ import "/styles/gaming.scss"; +import "/styles/darkmode.scss"; chrome.runtime.onMessage.addListener((message) => { if (message === "reload") { diff --git a/src/scripts/content_moodle.ts b/src/scripts/content_moodle.ts index 6e791a2..7b5772d 100644 --- a/src/scripts/content_moodle.ts +++ b/src/scripts/content_moodle.ts @@ -3,17 +3,4 @@ import "/styles/moodle.scss"; import { Moodle } from "../class"; import loadGamingWebsite from "../utils/loadGamingWebsite"; -//window.addEventListener("load", async () => await runFuncIfEnabled(Moodle.EnableRainbow)); loadGamingWebsite(Moodle); - -// あとでリロード無しでゲーミングモード解除を実装する -/* -chrome.action.onClicked.addListener(async () => { - const isEnable = await isEnabled(); - if (isEnable) { - EnableRainbow(); - } else { - DisableRainbow(); - } -}); -*/ diff --git a/src/scripts/content_sso.ts b/src/scripts/content_sso.ts index 3bf50e1..cafefe4 100644 --- a/src/scripts/content_sso.ts +++ b/src/scripts/content_sso.ts @@ -3,6 +3,4 @@ import "/styles/sso.css"; import { SSO } from "../class"; import loadGamingWebsite from "../utils/loadGamingWebsite"; -//window.addEventListener("load", async () => await runFuncIfEnabled(SSO.EnableRainbow)); - loadGamingWebsite(SSO); diff --git a/src/styles/darkmode.scss b/src/styles/darkmode.scss new file mode 100644 index 0000000..ac6ac19 --- /dev/null +++ b/src/styles/darkmode.scss @@ -0,0 +1,41 @@ +[data-gaming_gundai_dark="true"] { + * { + --base: #1d232a; + --base-darker: #191e25; + --content: #a6acba; + --neutral: #29323c; + --accent: #21b2a5; + } + + .bg-base { + background-color: var(--base) !important; + } + .bg-base-darker { + background-color: var(--base-darker) !important; + } + .bg-content { + background-color: var(--content) !important; + } + .bg-neutral { + background-color: var(--neutral) !important; + } + .bg-accent { + background-color: var(--accent) !important; + } + + .text-base { + color: var(--base) !important; + } + .text-base-darker { + color: var(--base-darker) !important; + } + .text-content { + color: var(--content) !important; + } + .text-neutral { + color: var(--neutral) !important; + } + .text-accent { + color: var(--accent) !important; + } +} diff --git a/src/styles/gaming.scss b/src/styles/gaming.scss index 6567515..8d572e1 100644 --- a/src/styles/gaming.scss +++ b/src/styles/gaming.scss @@ -1,38 +1,40 @@ -@keyframes gaming { - 100% { - background-position-x: 200%; +[data-gaming_gundai="true"] { + @keyframes gaming { + 100% { + background-position-x: 200%; + } } -} -.rainbow-bg { - animation-duration: 0.7s; + .rainbow-bg { + animation-duration: 0.7s; - background: linear-gradient(to right, Magenta, yellow, Cyan, Magenta) 0% center/200%; - animation-name: gaming; - animation-timing-function: linear; - animation-iteration-count: infinite; - text-shadow: 0 0 2px white; -} + background: linear-gradient(to right, Magenta, yellow, Cyan, Magenta) 0% center/200%; + animation-name: gaming; + animation-timing-function: linear; + animation-iteration-count: infinite; + text-shadow: 0 0 2px white; + } -.rainbow-text { - animation-duration: 0.7s; + .rainbow-text { + animation-duration: 0.7s; - background: linear-gradient(to right, Magenta, yellow, Cyan, Magenta) 0% center/200%; - animation-name: gaming; - animation-timing-function: linear; - animation-iteration-count: infinite; + background: linear-gradient(to right, Magenta, yellow, Cyan, Magenta) 0% center/200%; + animation-name: gaming; + animation-timing-function: linear; + animation-iteration-count: infinite; - // For Text - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: bold; - color: transparent; -} + // For Text + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: bold; + color: transparent; + } -.rainbow-text-shadow { - text-shadow: 0px 0px 80px black; -} + .rainbow-text-shadow { + text-shadow: 0px 0px 80px black; + } -.rainbow-bg-shadow { - box-shadow: 0px 0px 40px white; + .rainbow-bg-shadow { + box-shadow: 0px 0px 40px white; + } } diff --git a/src/styles/moodle.scss b/src/styles/moodle.scss index ad36242..c2bbd30 100644 --- a/src/styles/moodle.scss +++ b/src/styles/moodle.scss @@ -1,4 +1,5 @@ @import "./gaming.scss"; +@import "./darkmode.scss"; [data-gaming_gundai="true"] { .menu-action-text, @@ -22,3 +23,25 @@ background-color: transparent !important; } } + +[data-gaming_gundai_dark="true"] { + #page.drawers .main-inner, + #region-main { + background-color: transparent !important; + } + + .bg-white { + background-color: var(--base) !important; + } + + .list-group-item, + .form-control { + @extend .bg-base; + } +} + +[data-gaming_gundai_dark="true"]:not([data-gaming_gundai="true"]) { + .logo { + filter: invert(1) grayscale(100%); + } +} diff --git a/src/utils/loadGamingWebsite.ts b/src/utils/loadGamingWebsite.ts index 46d728e..02d52fb 100644 --- a/src/utils/loadGamingWebsite.ts +++ b/src/utils/loadGamingWebsite.ts @@ -1,15 +1,8 @@ import { UnivWebsite } from "../class/UnivWebsite"; -import isTrue from "./isTrue"; -//import RunFuncIfEnabled from "./RunFuncIfEnabled"; // ウィンドウが読み込まれたらGundaiWebsiteのEnableRainbowを実行する export default function loadGamingWebsite(website: UnivWebsite) { window.addEventListener("load", async () => { - const isEnabled = await website.storage.get("enabled"); - if (isTrue(isEnabled)) { - website.enable(); - } else { - website.disable(); - } + UnivWebsite.load(website); }); } diff --git a/tsconfig.json b/tsconfig.json index ac05d4d..0b76c0d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "ES2015", "module": "commonjs", "outDir": "dist", "strict": true,