mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
Compare commits
48 Commits
v3.3.0-beta
...
v3.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
| cd4dc73897 | |||
| d748eece8a | |||
| 37dab0f5a7 | |||
| 842a132c7f | |||
| b36426a94b | |||
| 9659f9aae2 | |||
| b205c0f832 | |||
| f99e76c723 | |||
| 4680e9879d | |||
| cfdea6a116 | |||
| 31954dcbce | |||
| 444cb14e8a | |||
| 856ef62306 | |||
| 5335bba04c | |||
| 611fcef12b | |||
| 6e4fe64789 | |||
| 545a999c46 | |||
| b6dbcfeb69 | |||
| 5bc3d22214 | |||
| be44e86290 | |||
| a78993fffc | |||
| a8ff2213bd | |||
| 7519312282 | |||
| 8b9ad39e8e | |||
| 182597efce | |||
| 4d38af402f | |||
| e19020066a | |||
| ee76b4d9d2 | |||
| 47014bc77f | |||
| 3dc7396f7a | |||
| f70c032f06 | |||
| 5d97ab3da6 | |||
| 5549de571d | |||
| 8bad8d5b34 | |||
| f97276082e | |||
| 4a9048ac62 | |||
| a2dac4d84d | |||
| ddd1bbe847 | |||
| 0873a33da2 | |||
| f9c2f5876f | |||
| dfef312ddc | |||
| 629c98ce0e | |||
| 3279775a99 | |||
| 97089e5134 | |||
| fed198108a | |||
| 76ed27e82d | |||
| cc88d8c984 | |||
| c6b4bdcbc9 |
@@ -11,30 +11,36 @@
|
|||||||
<a target="_blank" href="https://discord.gg/YzmbnCDkat"><img src="https://github.com/SethBurkart123/EvenBetterSEQTA/assets/108050083/23055730-b16e-44c0-9bef-221d8545af92" width="240" style="border-radius:10%;" /></a>
|
<a target="_blank" href="https://discord.gg/YzmbnCDkat"><img src="https://github.com/SethBurkart123/EvenBetterSEQTA/assets/108050083/23055730-b16e-44c0-9bef-221d8545af92" width="240" style="border-radius:10%;" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
- [Features](#features)
|
|
||||||
- [Getting Started](#getting-started)
|
|
||||||
|
|
||||||
## Release Videos
|
|
||||||
<video autoplay loop muted controls="false" width="33%" src="https://github.com/SethBurkart123/EvenBetterSEQTA/assets/108050083/3084644a-edbc-40e5-b1ad-1fdea4f0ca18"></video>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img src="https://img.shields.io/chrome-web-store/users/afdgaoaclhkhemfkkkonemoapeinchel" />
|
<img src="https://img.shields.io/chrome-web-store/users/afdgaoaclhkhemfkkkonemoapeinchel" />
|
||||||
<img src="https://img.shields.io/chrome-web-store/rating/afdgaoaclhkhemfkkkonemoapeinchel" />
|
<img src="https://img.shields.io/chrome-web-store/rating/afdgaoaclhkhemfkkkonemoapeinchel" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
- [Features](#features)
|
||||||
|
- [Creating Custom Themes](#creating-custom-themes)
|
||||||
|
- [Getting Started](#getting-started)
|
||||||
|
- [Running Development](#running-development)
|
||||||
|
- [Building for production](#building-for-production)
|
||||||
|
- [Folder Structure](#folder-structure)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [Credits](#credits)
|
||||||
|
- [Star History](#star-history)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Dark mode
|
- Dark mode
|
||||||
- Custom Background
|
- Custom Background/Themes
|
||||||
- Improved Styling/CSS
|
- Improved Styling/CSS
|
||||||
- Improved look for SEQTA Learn
|
- Improved look for SEQTA Learn
|
||||||
- Custom Home Page including:
|
- Custom Home Page including:
|
||||||
- Daily Lessons
|
- Daily Lessons
|
||||||
- Shortcuts
|
- Shortcuts
|
||||||
- Easier Access Notices
|
- Easier Access Notices
|
||||||
|
- Assessments
|
||||||
- Options to remove certain items from the side menu
|
- Options to remove certain items from the side menu
|
||||||
|
- Fully customisable themes and an offical theme store
|
||||||
- Notification for next lesson (sent 5 minutes before end of the lesson)
|
- Notification for next lesson (sent 5 minutes before end of the lesson)
|
||||||
- Browser Support
|
- Browser Support
|
||||||
- Chrome Supported
|
- Chrome Supported
|
||||||
@@ -42,9 +48,21 @@
|
|||||||
- Brave Supported
|
- Brave Supported
|
||||||
- Opera Supported
|
- Opera Supported
|
||||||
- Vivaldi Supported
|
- Vivaldi Supported
|
||||||
- Firefox (Experimental - available [here](https://addons.mozilla.org/en-US/firefox/addon/betterseqta-plus/))
|
- Firefox (Experimental - available [here](https://addons.mozilla.org/en-US/firefox/addon/betterseqta-plus/)
|
||||||
- Safari (Experimental - only available via compilation)
|
- Safari (Experimental - only available via compilation)
|
||||||
|
|
||||||
|
## Creating Custom Themes
|
||||||
|
|
||||||
|
If you are looking to create custom themes, I would recommend you start at the official documentation [here](https://betterseqta.gitbook.io/betterseqta-docs). You can see some premade examples along with a compilation script that can be used to allow for CSS frameworks and libraries such as SCSS to be used [here](https://github.com/SethBurkart123/BetterSEQTA-theme-generator).
|
||||||
|
|
||||||
|
Don't worry- if you get stuck feel free to ask around in the discord. We're open and happy to help out! Happy creating :)
|
||||||
|
|
||||||
|
## Creating Custom Themes
|
||||||
|
|
||||||
|
If you are looking to create custom themes, I would recommend you start at the official documentation [here](https://betterseqta.gitbook.io/betterseqta-docs). You can see some premade examples along with a compilation script that can be used to allow for CSS frameworks and libraries such as SCSS to be used [here](https://github.com/SethBurkart123/BetterSEQTA-theme-generator).
|
||||||
|
|
||||||
|
Don't worry- if you get stuck feel free to ask around in the discord. We're open and happy to help out! Happy creating :)
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
1. Clone the repository
|
1. Clone the repository
|
||||||
@@ -93,7 +111,7 @@ npm run build
|
|||||||
3. Package it up (optional)
|
3. Package it up (optional)
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run package # this requires 7zip to be installed in order to work
|
npm run package # This requires 7-Zip to be installed in order to work
|
||||||
```
|
```
|
||||||
|
|
||||||
## Folder Structure
|
## Folder Structure
|
||||||
@@ -106,15 +124,13 @@ The folder structure is as follows:
|
|||||||
|
|
||||||
- The `dist` folder is where the compiled code ends up, this is the folder what you need to load into chrome as an unpacked extension for development.
|
- The `dist` folder is where the compiled code ends up, this is the folder what you need to load into chrome as an unpacked extension for development.
|
||||||
|
|
||||||
- The `safari` folder is an Xcode project, building it for MacOS does work, IOS needs a few modifications to the manifest to work, but I have managed to get it working. It will give an error, to fix this you need to regenerate it, you can delete the safari folder and then run the command `xcrun safari-web-extension-converter <extension-folder>/dist` and it will automatically generate the xcode project where you are.
|
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
<a href="https://github.com/betterseqta/betterseqta-plus/graphs/contributors">
|
<a href="https://github.com/betterseqta/betterseqta-plus/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=betterseqta/betterseqta-plus" />
|
<img src="https://contrib.rocks/image?repo=betterseqta/betterseqta-plus" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
Want to contribute? [Click Here!](https://github.com/BetterSEQTA/BetterSEQTA-Plus/contribute.md)
|
Want to contribute? [Click Here!](https://github.com/BetterSEQTA/BetterSEQTA-Plus/blob/main/contribute.md)
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
This extension was initially developed by [Nulkem](https://github.com/Nulkem/betterseqta), was ported to manifest V3 by [MEGA-Dawg68](https://github.com/MEGA-Dawg68) and is currently under active development by [SethBurkart123](https://github.com/SethBurkart123) and [Crazypersonalph](https://github.com/Crazypersonalph)
|
This extension was initially developed by [Nulkem](https://github.com/Nulkem/betterseqta), was ported to manifest V3 by [MEGA-Dawg68](https://github.com/MEGA-Dawg68) and is currently under active development by [SethBurkart123](https://github.com/SethBurkart123) and [Crazypersonalph](https://github.com/Crazypersonalph)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"64": "src/resources/icons/icon-64.png"
|
"64": "src/resources/icons/icon-64.png"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"permissions": ["tabs", "notifications", "storage", "activeTab", "scripting"],
|
"permissions": ["tabs", "notifications", "storage", "activeTab"],
|
||||||
"host_permissions": ["<all_urls>"],
|
"host_permissions": ["<all_urls>"],
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["src/background.ts"]
|
"scripts": ["src/background.ts"]
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
"64": "src/resources/icons/icon-64.png"
|
"64": "src/resources/icons/icon-64.png"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"permissions": ["tabs", "notifications", "storage", "scripting"],
|
"permissions": ["tabs", "notifications", "storage"],
|
||||||
"host_permissions": ["https://newsapi.org/", "*://*/*"],
|
"host_permissions": ["https://newsapi.org/", "*://*/*"],
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "src/background.ts"
|
"service_worker": "src/background.ts"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "betterseqtaplus",
|
"name": "betterseqtaplus",
|
||||||
"version": "3.2.6",
|
"version": "3.3.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development, and incorporate a plethora of new features!",
|
"description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development, and incorporate a plethora of new features!",
|
||||||
"browserslist": "> 0.5%, last 2 versions, not dead",
|
"browserslist": "> 0.5%, last 2 versions, not dead",
|
||||||
|
|||||||
+80
-36
@@ -1,32 +1,40 @@
|
|||||||
|
// Third-party libraries
|
||||||
|
import Color from 'color'
|
||||||
|
import Sortable from 'sortablejs'
|
||||||
|
import browser from 'webextension-polyfill'
|
||||||
import { animate, spring, stagger } from 'motion'
|
import { animate, spring, stagger } from 'motion'
|
||||||
import loading, { AppendLoadingSymbol } from './seqta/ui/Loading'
|
|
||||||
|
|
||||||
|
// Internal utilities and functions
|
||||||
|
import { delay } from './seqta/utils/delay'
|
||||||
|
import stringToHTML from './seqta/utils/stringToHTML'
|
||||||
|
import { MessageHandler } from './seqta/utils/listeners/MessageListener'
|
||||||
|
import { initializeSettingsState, settingsState } from './seqta/utils/listeners/SettingsState'
|
||||||
|
import { StorageChangeHandler } from './seqta/utils/listeners/StorageChanges'
|
||||||
|
import { eventManager } from './seqta/utils/listeners/EventManager'
|
||||||
|
|
||||||
|
// UI and theme management
|
||||||
|
import loading, { AppendLoadingSymbol } from './seqta/ui/Loading'
|
||||||
|
import { enableCurrentTheme } from './seqta/ui/themes/enableCurrent'
|
||||||
|
import { updateAllColors } from './seqta/ui/colors/Manager'
|
||||||
|
import { SettingsResizer } from './seqta/ui/SettingsResizer'
|
||||||
|
import { AddBetterSEQTAElements } from './seqta/ui/AddBetterSEQTAElements'
|
||||||
|
|
||||||
|
// JSON content
|
||||||
|
import MenuitemSVGKey from './seqta/content/MenuItemSVGKey.json'
|
||||||
|
import ShortcutLinks from './seqta/content/links.json'
|
||||||
|
|
||||||
|
// Icons and fonts
|
||||||
import IconFamily from './resources/fonts/IconFamily.woff'
|
import IconFamily from './resources/fonts/IconFamily.woff'
|
||||||
import LogoLight from './resources/icons/betterseqta-light-icon.png'
|
import LogoLight from './resources/icons/betterseqta-light-icon.png'
|
||||||
import LogoLightOutline from './resources/icons/betterseqta-light-outline.png'
|
import LogoLightOutline from './resources/icons/betterseqta-light-outline.png'
|
||||||
import icon48 from './resources/icons/icon-48.png?base64'
|
import icon48 from './resources/icons/icon-48.png?base64'
|
||||||
|
|
||||||
import Color from 'color'
|
|
||||||
import MenuitemSVGKey from './seqta/content/MenuItemSVGKey.json'
|
|
||||||
import { MessageHandler } from './seqta/utils/listeners/MessageListener'
|
|
||||||
import ShortcutLinks from './seqta/content/links.json'
|
|
||||||
import Sortable from 'sortablejs'
|
|
||||||
import assessmentsicon from './seqta/icons/assessmentsIcon'
|
import assessmentsicon from './seqta/icons/assessmentsIcon'
|
||||||
import browser from 'webextension-polyfill'
|
|
||||||
import coursesicon from './seqta/icons/coursesIcon'
|
import coursesicon from './seqta/icons/coursesIcon'
|
||||||
import { delay } from "./seqta/utils/delay"
|
|
||||||
import { enableCurrentTheme } from "./seqta/ui/themes/enableCurrent";
|
// Stylesheets
|
||||||
import iframeCSS from "./css/iframe.scss?raw"
|
import iframeCSS from './css/iframe.scss?raw'
|
||||||
import injectedCSS from './css/injected.scss?inline'
|
import injectedCSS from './css/injected.scss?inline'
|
||||||
import stringToHTML from './seqta/utils/stringToHTML'
|
|
||||||
import { updateAllColors } from './seqta/ui/colors/Manager'
|
|
||||||
import { SettingsResizer } from "./seqta/ui/SettingsResizer";
|
|
||||||
import documentLoadCSS from './css/documentload.scss?inline'
|
import documentLoadCSS from './css/documentload.scss?inline'
|
||||||
import { injectYouTubeVideo } from './seqta/ui/VideoLoader'
|
|
||||||
import { initializeSettingsState, settingsState } from './seqta/utils/listeners/SettingsState'
|
|
||||||
import { StorageChangeHandler } from './seqta/utils/listeners/StorageChanges'
|
|
||||||
import { AddBetterSEQTAElements } from './seqta/ui/AddBetterSEQTAElements'
|
|
||||||
import { eventManager } from './seqta/utils/listeners/EventManager'
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@@ -133,9 +141,16 @@ export function OpenWhatsNewPopup() {
|
|||||||
let imagecont = document.createElement('div')
|
let imagecont = document.createElement('div')
|
||||||
imagecont.classList.add('whatsnewImgContainer')
|
imagecont.classList.add('whatsnewImgContainer')
|
||||||
|
|
||||||
let div = document.createElement('div')
|
let video = document.createElement('video')
|
||||||
div.classList.add('whatsnewImg')
|
let source = document.createElement('source')
|
||||||
imagecont.appendChild(div)
|
// Perhaps we host this on a server and then grab it instead of having it locally?
|
||||||
|
source.setAttribute('src', 'https://raw.githubusercontent.com/BetterSEQTA/BetterSEQTA-Plus/main/src/resources/update-video.webm')
|
||||||
|
video.autoplay = true
|
||||||
|
video.muted = true
|
||||||
|
video.loop = true
|
||||||
|
video.appendChild(source)
|
||||||
|
video.classList.add('whatsnewImg')
|
||||||
|
imagecont.appendChild(video)
|
||||||
|
|
||||||
let textcontainer = document.createElement('div')
|
let textcontainer = document.createElement('div')
|
||||||
textcontainer.classList.add('whatsnewTextContainer')
|
textcontainer.classList.add('whatsnewTextContainer')
|
||||||
@@ -145,7 +160,19 @@ export function OpenWhatsNewPopup() {
|
|||||||
<div class="whatsnewTextContainer" style="height: 50%;overflow-y: scroll;">
|
<div class="whatsnewTextContainer" style="height: 50%;overflow-y: scroll;">
|
||||||
|
|
||||||
<h1>3.3.0 - Overhauled Theming System</h1>
|
<h1>3.3.0 - Overhauled Theming System</h1>
|
||||||
<li>Find and create awesome themes! <span style="background: var(--background-secondary); color: var(--text-primary); padding: 2px 4px; border-radius: 4px; font-size: 12px; font-weight: 600;">Beta</span></li>
|
<li>Added a theme store!</li>
|
||||||
|
<li>Added the new theme creator!</li>
|
||||||
|
<li>Fixed Notices not working on home page</li>
|
||||||
|
<li>Fixed dark/light button labels inverted</li>
|
||||||
|
<li>Switched to GitHub for hosting the update video</li>
|
||||||
|
<li>Fixed an issue where the settings menu wouldn't change theme</li>
|
||||||
|
<li>Fixed custom shortcuts not allowing ports to be used</li>
|
||||||
|
<li>Fixed occasional flashing when using animations</li>
|
||||||
|
<li>Fixed loading of the tab icon</li>
|
||||||
|
<li>Made animations toggle apply to settings</li>
|
||||||
|
<li>Small styling improvements</li>
|
||||||
|
<li>Other minor bug fixes</li>
|
||||||
|
|
||||||
|
|
||||||
<h1>3.2.7 - Minor Improvements</h1>
|
<h1>3.2.7 - Minor Improvements</h1>
|
||||||
<li>Improved performance!</li>
|
<li>Improved performance!</li>
|
||||||
@@ -285,10 +312,6 @@ export function OpenWhatsNewPopup() {
|
|||||||
let bkelement = document.getElementById('whatsnewbk')
|
let bkelement = document.getElementById('whatsnewbk')
|
||||||
let popup = document.getElementsByClassName('whatsnewContainer')[0]
|
let popup = document.getElementsByClassName('whatsnewContainer')[0]
|
||||||
|
|
||||||
injectYouTubeVideo(
|
|
||||||
'JdDA45GYEUc', 'PLSlFV-9e6dvyvZJFPCtBMb3LSp-LGbrbI', document.querySelector('.whatsnewImg')!, true, true, '100%', '100%'
|
|
||||||
)
|
|
||||||
|
|
||||||
if (settingsState.animations) {
|
if (settingsState.animations) {
|
||||||
animate(
|
animate(
|
||||||
[popup, bkelement as HTMLElement],
|
[popup, bkelement as HTMLElement],
|
||||||
@@ -484,7 +507,7 @@ async function updateIframesWithDarkMode(): Promise<void> {
|
|||||||
}, (element) => {
|
}, (element) => {
|
||||||
const iframe = element as HTMLIFrameElement;
|
const iframe = element as HTMLIFrameElement;
|
||||||
try {
|
try {
|
||||||
applyDarkModeToIframe(iframe, cssLink, settingsState.DarkMode);
|
applyDarkModeToIframe(iframe, cssLink);
|
||||||
|
|
||||||
if (element.classList.contains('cke_wysiwyg_frame')) {
|
if (element.classList.contains('cke_wysiwyg_frame')) {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -498,18 +521,20 @@ async function updateIframesWithDarkMode(): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDarkModeToIframe(iframe: HTMLIFrameElement, cssLink: HTMLStyleElement, DarkMode: boolean): void {
|
function applyDarkModeToIframe(iframe: HTMLIFrameElement, cssLink: HTMLStyleElement): void {
|
||||||
const iframeDocument = iframe.contentDocument;
|
const iframeDocument = iframe.contentDocument;
|
||||||
if (!iframeDocument) return;
|
if (!iframeDocument) return;
|
||||||
|
|
||||||
if (iframeDocument.readyState !== 'complete') {
|
if (iframeDocument.readyState !== 'complete') {
|
||||||
iframe.onload = () => {
|
iframe.onload = () => {
|
||||||
applyDarkModeToIframe(iframe, cssLink, DarkMode);
|
applyDarkModeToIframe(iframe, cssLink);
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DarkMode) iframeDocument.documentElement.classList.add('dark');
|
if (settingsState.DarkMode) {
|
||||||
|
iframeDocument.documentElement.classList.add('dark')
|
||||||
|
}
|
||||||
|
|
||||||
const head = iframeDocument.head;
|
const head = iframeDocument.head;
|
||||||
if (head && !head.innerHTML.includes('iframecss')) {
|
if (head && !head.innerHTML.includes('iframecss')) {
|
||||||
@@ -603,10 +628,15 @@ async function handleSublink(sublink: string | undefined): Promise<void> {
|
|||||||
handleMessages(document.querySelector('.messages')!)
|
handleMessages(document.querySelector('.messages')!)
|
||||||
await handleDefault()
|
await handleDefault()
|
||||||
break;
|
break;
|
||||||
default:
|
case 'dashboard':
|
||||||
await handleDefault();
|
handleDashboard(document.querySelector('.dashboard')!)
|
||||||
|
await handleDefault()
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
default:
|
||||||
|
await handleDefault()
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleTimetable(): Promise<void> {
|
async function handleTimetable(): Promise<void> {
|
||||||
@@ -649,6 +679,12 @@ async function handleMessages(node: Element): Promise<void> {
|
|||||||
|
|
||||||
if (!settingsState.animations) return;
|
if (!settingsState.animations) return;
|
||||||
|
|
||||||
|
// Hides messages on page load
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.classList.add('messageHider')
|
||||||
|
style.innerHTML = '[data-message]{opacity: 0 !important;}'
|
||||||
|
document.head.append(style)
|
||||||
|
|
||||||
await waitForElm('[data-message]', true, 10);
|
await waitForElm('[data-message]', true, 10);
|
||||||
const messages = Array.from(document.querySelectorAll('[data-message]')).slice(0, 35);
|
const messages = Array.from(document.querySelectorAll('[data-message]')).slice(0, 35);
|
||||||
animate(
|
animate(
|
||||||
@@ -660,12 +696,19 @@ async function handleMessages(node: Element): Promise<void> {
|
|||||||
easing: [.22, .03, .26, 1]
|
easing: [.22, .03, .26, 1]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
document.head.querySelector('style.messageHider')?.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDashboard(node: Element): Promise<void> {
|
async function handleDashboard(node: Element): Promise<void> {
|
||||||
if (!(node instanceof HTMLElement)) return;
|
if (!(node instanceof HTMLElement)) return;
|
||||||
if (!settingsState.animations) return;
|
if (!settingsState.animations) return;
|
||||||
|
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.classList.add('dashboardHider')
|
||||||
|
style.innerHTML = '.dashboard{opacity: 0 !important;}'
|
||||||
|
document.head.append(style)
|
||||||
|
|
||||||
await waitForElm('.dashlet', true, 10);
|
await waitForElm('.dashlet', true, 10);
|
||||||
animate(
|
animate(
|
||||||
'.dashboard > *',
|
'.dashboard > *',
|
||||||
@@ -676,6 +719,8 @@ async function handleDashboard(node: Element): Promise<void> {
|
|||||||
easing: [.22, .03, .26, 1]
|
easing: [.22, .03, .26, 1]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
document.head.querySelector('style.dashboardHider')?.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDocuments(node: Element): Promise<void> {
|
async function handleDocuments(node: Element): Promise<void> {
|
||||||
@@ -2280,8 +2325,7 @@ function processNotices(responseText: any, labelArray: any) {
|
|||||||
let colour = notice.colour;
|
let colour = notice.colour;
|
||||||
if (typeof colour === 'string') {
|
if (typeof colour === 'string') {
|
||||||
const rgb = GetThresholdOfColor(colour);
|
const rgb = GetThresholdOfColor(colour);
|
||||||
const DarkModeResult = settingsState.DarkMode;
|
if (rgb < 100 && settingsState.DarkMode) {
|
||||||
if (rgb < 100 && DarkModeResult) {
|
|
||||||
colour = undefined;
|
colour = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-11
@@ -1,6 +1,5 @@
|
|||||||
import browser from 'webextension-polyfill'
|
import browser from 'webextension-polyfill'
|
||||||
import { SettingsState } from "./types/storage";
|
import { SettingsState } from "./types/storage";
|
||||||
import { applyYoutubeStyles } from './seqta/ui/VideoLoader';
|
|
||||||
|
|
||||||
export const openDB = () => {
|
export const openDB = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -117,16 +116,6 @@ browser.runtime.onMessage.addListener((request: any, _sender: any, sendResponse:
|
|||||||
|
|
||||||
GetNews(sendResponse, url);
|
GetNews(sendResponse, url);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 'youtubeIframe':
|
|
||||||
const { hideControls } = request;
|
|
||||||
|
|
||||||
browser.scripting.executeScript({
|
|
||||||
target: { tabId: _sender.tab.id, allFrames: true },
|
|
||||||
func: applyYoutubeStyles,
|
|
||||||
args: [hideControls]
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log('Unknown request type');
|
console.log('Unknown request type');
|
||||||
@@ -283,6 +272,7 @@ async function UpdateCurrentValues() {
|
|||||||
browser.runtime.onInstalled.addListener(function (event) {
|
browser.runtime.onInstalled.addListener(function (event) {
|
||||||
browser.storage.local.remove(['justupdated']);
|
browser.storage.local.remove(['justupdated']);
|
||||||
browser.storage.local.remove(['data']);
|
browser.storage.local.remove(['data']);
|
||||||
|
|
||||||
UpdateCurrentValues();
|
UpdateCurrentValues();
|
||||||
if ( event.reason == 'install', event.reason == 'update' ) {
|
if ( event.reason == 'install', event.reason == 'update' ) {
|
||||||
browser.storage.local.set({ justupdated: true });
|
browser.storage.local.set({ justupdated: true });
|
||||||
|
|||||||
+36
-37
@@ -159,7 +159,13 @@ html {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legacy-root button:active, .legacy-root a:active {
|
.cke_panel {
|
||||||
|
border-radius: 16px !important;
|
||||||
|
margin-top: 8px !important;
|
||||||
|
background: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legacy-root button:active, .legacy-root a:active:not(.cke_combo_button) {
|
||||||
background-image: unset !important;
|
background-image: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,13 +549,13 @@ td.colourBar {
|
|||||||
}
|
}
|
||||||
#toolbar .search {
|
#toolbar .search {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
/* Provides space for the icon */
|
|
||||||
}
|
}
|
||||||
#toolbar span:has(.search)::before {
|
#toolbar span:has(.search)::before {
|
||||||
content: "\eca5";
|
content: "\eca5";
|
||||||
/* Unicode for the search icon */
|
/* Unicode for the search icon */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 8px;
|
left: 8px;
|
||||||
|
z-index: 10;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
@@ -616,10 +622,6 @@ ul.buttonChecklist {
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
ol > [data-message] {
|
|
||||||
padding-left: 8px !important;
|
|
||||||
padding-right: 4px !important;
|
|
||||||
}
|
|
||||||
ol > [data-label] {
|
ol > [data-label] {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
@@ -1035,6 +1037,7 @@ div > ol:has(.uiFileHandlerWrapper) {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
border-radius: 16px;
|
||||||
border-bottom-left-radius: 15px;
|
border-bottom-left-radius: 15px;
|
||||||
border-bottom-right-radius: 15px;
|
border-bottom-right-radius: 15px;
|
||||||
}
|
}
|
||||||
@@ -1050,11 +1053,9 @@ div > ol:has(.uiFileHandlerWrapper) {
|
|||||||
}
|
}
|
||||||
.notice {
|
.notice {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 95%;
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 0px auto 7px;
|
|
||||||
background: var(--background-primary);
|
background: var(--background-primary);
|
||||||
transition: 200ms;
|
transition: 200ms;
|
||||||
box-shadow: inset 0px 5px 20px 1px rgba(0, 0, 0, 0.3);
|
box-shadow: inset 0px 5px 20px 1px rgba(0, 0, 0, 0.3);
|
||||||
@@ -1454,11 +1455,6 @@ div > ol:has(.uiFileHandlerWrapper) {
|
|||||||
height: 180px;
|
height: 180px;
|
||||||
background: var(--background-primary);
|
background: var(--background-primary);
|
||||||
}
|
}
|
||||||
.cke_panel {
|
|
||||||
border-radius: 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
background: unset;
|
|
||||||
}
|
|
||||||
.Avatar__Avatar___gE5kx.Avatar__staff___4gVLs {
|
.Avatar__Avatar___gE5kx.Avatar__staff___4gVLs {
|
||||||
--person-colour: var(--better-light);
|
--person-colour: var(--better-light);
|
||||||
background: var(--person-colour, var(--navy));
|
background: var(--person-colour, var(--navy));
|
||||||
@@ -1571,7 +1567,7 @@ div,
|
|||||||
ol,
|
ol,
|
||||||
ul {
|
ul {
|
||||||
scrollbar-width: thin !important;
|
scrollbar-width: thin !important;
|
||||||
scrollbar-color: var(--better-light) var(--better-sub) !important;
|
scrollbar-color: var(--better-light) var(--better-sub);
|
||||||
}
|
}
|
||||||
.connectedNotificationsWrapper > div > button {
|
.connectedNotificationsWrapper > div > button {
|
||||||
color: var(--text-primary) !important;
|
color: var(--text-primary) !important;
|
||||||
@@ -1656,6 +1652,22 @@ ul {
|
|||||||
.MenuButton__MenuPanel___2q42B {
|
.MenuButton__MenuPanel___2q42B {
|
||||||
background: var(--background-primary);
|
background: var(--background-primary);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: clip;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
padding: 0 !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
> h2 {
|
||||||
|
padding-bottom: 1px;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.dailycal > .header {
|
.dailycal > .header {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
@@ -1718,6 +1730,11 @@ div.entry.class[style*="width: 46.5%"] {
|
|||||||
margin-top: 4px !important;
|
margin-top: 4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uiFile {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
.dark .title a.uiFile {
|
.dark .title a.uiFile {
|
||||||
color: #06b4fc !important;
|
color: #06b4fc !important;
|
||||||
}
|
}
|
||||||
@@ -1869,13 +1886,15 @@ div.bar.flat {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.cke_toolbox {
|
.cke_toolbox {
|
||||||
|
padding: 0 !important;
|
||||||
|
padding-left: 8px !important;
|
||||||
background: unset !important;
|
background: unset !important;
|
||||||
gap: 4px;
|
gap: 0 8px;
|
||||||
}
|
}
|
||||||
.cke_toolbox > .cke_toolbar > .cke_toolgroup {
|
.cke_toolbox > .cke_toolbar > .cke_toolgroup {
|
||||||
margin: 0;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
#cke_1_top a:hover {
|
#cke_1_top a:hover:not(.cke_combo_button) {
|
||||||
background: #5a5a5a;
|
background: #5a5a5a;
|
||||||
}
|
}
|
||||||
.legacy-root button.depressed,
|
.legacy-root button.depressed,
|
||||||
@@ -2884,32 +2903,12 @@ li.MessageList__unread___3imtO {
|
|||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
.whatsnewImg {
|
.whatsnewImg {
|
||||||
background-color: black;
|
|
||||||
pointer-events: none !important;
|
|
||||||
margin: 8px auto;
|
margin: 8px auto;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
|
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
}
|
}
|
||||||
.whatsnewImg > iframe {
|
|
||||||
aspect-ratio: 16/9.823;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 16px;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
animation: fade-in 0.5s forwards;
|
|
||||||
animation-delay: 0.8s !important;
|
|
||||||
}
|
|
||||||
@keyframes fade-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.whatsnewTextContainer {
|
.whatsnewTextContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ export const SettingsContextProvider: React.FC<{ children: ReactNode }> = ({ chi
|
|||||||
transparencyEffects: false,
|
transparencyEffects: false,
|
||||||
selectedTheme: '',
|
selectedTheme: '',
|
||||||
animations: true,
|
animations: true,
|
||||||
defaultPage: 'home'
|
defaultPage: 'home',
|
||||||
|
devMode: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const [showPicker, setShowPicker] = useState<boolean>(false);
|
const [showPicker, setShowPicker] = useState<boolean>(false);
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
import React, { memo, useEffect, useRef, useState } from 'react';
|
import React, { memo, useEffect, useRef, useState } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import type { TabbedContainerProps } from '../types/TabbedContainerProps';
|
import type { TabbedContainerProps } from '../types/TabbedContainerProps';
|
||||||
|
import { useSettingsContext } from '../SettingsContext';
|
||||||
|
|
||||||
const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
|
const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
|
||||||
|
const { settingsState } = useSettingsContext();
|
||||||
const [activeTab, setActiveTab] = useState(0);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
const [hoveredTab, setHoveredTab] = useState<number | null>(null);
|
const [hoveredTab, setHoveredTab] = useState<number | null>(null);
|
||||||
const [tabWidth, setTabWidth] = useState(0);
|
const [tabWidth, setTabWidth] = useState(0);
|
||||||
const [position, setPosition] = useState(0);
|
const [position, setPosition] = useState(0);
|
||||||
const positionRef = useRef(position);
|
const positionRef = useRef(position);
|
||||||
|
|
||||||
|
// Function to handle message
|
||||||
// Function to handle message
|
const handleMessage = (event: MessageEvent) => {
|
||||||
const handleMessage = (event: MessageEvent) => {
|
if (event.data === "popupClosed") {
|
||||||
if (event.data === "popupClosed") {
|
setActiveTab(0);
|
||||||
setActiveTab(0);
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Add event listener for 'message' event
|
||||||
|
window.addEventListener("message", handleMessage);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("message", handleMessage);
|
||||||
};
|
};
|
||||||
|
}, []);
|
||||||
useEffect(() => {
|
|
||||||
// Add event listener for 'message' event
|
|
||||||
window.addEventListener("message", handleMessage);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("message", handleMessage);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newPosition = -activeTab * 100;
|
const newPosition = -activeTab * 100;
|
||||||
@@ -36,7 +36,7 @@ const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
|
|||||||
|
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
|
||||||
const springTransition = { type: 'spring', stiffness: 250, damping: 25 };
|
const springTransition = settingsState.animations ? { type: 'spring', stiffness: 250, damping: 25 } : { duration: 0 };
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (containerRef.current) {
|
if (containerRef.current) {
|
||||||
@@ -85,8 +85,8 @@ const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
|
|||||||
className='flex'
|
className='flex'
|
||||||
>
|
>
|
||||||
{tabs.map((tab, index) => (
|
{tabs.map((tab, index) => (
|
||||||
<div key={index} className={`absolute h-[100vh] focus-visible:outline-none overflow-y-scroll w-full pb-40 transition-opacity duration-300 ${activeTab === index ? 'opacity-100' : 'opacity-0'}`}
|
<div key={index} className={`absolute h-[100vh] focus-visible:outline-none overflow-y-scroll w-full pb-40 ${ settingsState.animations ? 'transition-opacity duration-300' : ''} ${activeTab === index ? 'opacity-100' : 'opacity-0'}`}
|
||||||
style={{left: `${index * 100}%`}}>
|
style={{left: `${index * 100}%`}}>
|
||||||
{tab.content}
|
{tab.content}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -96,4 +96,4 @@ const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(TabbedContainer);
|
export default memo(TabbedContainer);
|
||||||
@@ -53,9 +53,9 @@ const useSettingsState = ({ settingsState, setSettingsState }: SettingsProps) =>
|
|||||||
for (const [key, { newValue }] of Object.entries(changes)) {
|
for (const [key, { newValue }] of Object.entries(changes)) {
|
||||||
if (key === "DarkMode") {
|
if (key === "DarkMode") {
|
||||||
if (key === "DarkMode" && newValue) {
|
if (key === "DarkMode" && newValue) {
|
||||||
document.body.classList.add('dark');
|
document.documentElement.classList.add('dark');
|
||||||
} else {
|
} else {
|
||||||
document.body.classList.remove('dark');
|
document.documentElement.classList.remove('dark');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ root.render(
|
|||||||
<div className="grid w-full h-screen text-center place-content-center dark:text-white">
|
<div className="grid w-full h-screen text-center place-content-center dark:text-white">
|
||||||
<h1 className="text-2xl font-bold">An error occurred 😭😭😭</h1>
|
<h1 className="text-2xl font-bold">An error occurred 😭😭😭</h1>
|
||||||
<p className="text-lg">Try clicking this button and see if it helps...</p>
|
<p className="text-lg">Try clicking this button and see if it helps...</p>
|
||||||
<button className='flex gap-2 p-2 px-4 mx-auto mt-4 text-white rounded-lg bg-zinc-100 dark:bg-zinc-800/20 outline outline-white/20 w-fit' onClick={() => window.location.reload()}>
|
<button className='flex gap-2 p-2 px-4 mx-auto mt-4 rounded-lg dark:text-white bg-zinc-100 dark:bg-zinc-800/20 outline outline-white/20 w-fit' onClick={() => window.location.reload()}>
|
||||||
<svg height="18" width="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
|
<svg height="18" width="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g fill="#F7F7F7">
|
<g fill="currentColor">
|
||||||
<path d="M9.03,12.22c-.293-.293-.768-.293-1.061,0s-.293,.768,0,1.061l1.208,1.208c-.059,.002-.118,.012-.178,.012-3.032,0-5.5-2.467-5.5-5.5,0-1.616,.706-3.143,1.938-4.191,.315-.269,.354-.742,.085-1.057s-.74-.353-1.058-.085c-1.567,1.333-2.466,3.277-2.466,5.333,0,3.76,2.983,6.829,6.704,6.985l-.735,.735c-.293,.293-.293,.768,0,1.061,.146,.146,.338,.22,.53,.22s.384-.073,.53-.22l2.25-2.25c.293-.293,.293-.768,0-1.061l-2.25-2.25Z" fill="#F7F7F7"/>
|
<path d="M9.03,12.22c-.293-.293-.768-.293-1.061,0s-.293,.768,0,1.061l1.208,1.208c-.059,.002-.118,.012-.178,.012-3.032,0-5.5-2.467-5.5-5.5,0-1.616,.706-3.143,1.938-4.191,.315-.269,.354-.742,.085-1.057s-.74-.353-1.058-.085c-1.567,1.333-2.466,3.277-2.466,5.333,0,3.76,2.983,6.829,6.704,6.985l-.735,.735c-.293,.293-.293,.768,0,1.061,.146,.146,.338,.22,.53,.22s.384-.073,.53-.22l2.25-2.25c.293-.293,.293-.768,0-1.061l-2.25-2.25Z" fill="currentColor"/>
|
||||||
<path d="M9.296,2.015l.735-.735c.293-.293,.293-.768,0-1.061s-.768-.293-1.061,0l-2.25,2.25c-.293,.293-.293,.768,0,1.061l2.25,2.25c.146,.146,.338,.22,.53,.22s.384-.073,.53-.22c.293-.293,.293-.768,0-1.061l-1.208-1.208c.059-.002,.118-.012,.177-.012,3.032,0,5.5,2.467,5.5,5.5,0,1.616-.706,3.143-1.938,4.191-.315,.269-.354,.742-.085,1.057,.148,.174,.359,.264,.571,.264,.172,0,.345-.059,.486-.179,1.567-1.333,2.466-3.277,2.466-5.333,0-3.76-2.983-6.829-6.704-6.985Z" fill="#F7F7F7"/>
|
<path d="M9.296,2.015l.735-.735c.293-.293,.293-.768,0-1.061s-.768-.293-1.061,0l-2.25,2.25c-.293,.293-.293,.768,0,1.061l2.25,2.25c.146,.146,.338,.22,.53,.22s.384-.073,.53-.22c.293-.293,.293-.768,0-1.061l-1.208-1.208c.059-.002,.118-.012,.177-.012,3.032,0,5.5,2.467,5.5,5.5,0,1.616-.706,3.143-1.938,4.191-.315,.269-.354,.742-.085,1.057,.148,.174,.359,.264,.571,.264,.172,0,.345-.059,.486-.179,1.567-1.333,2.466-3.277,2.466-5.333,0-3.76-2.983-6.829-6.704-6.985Z" fill="currentColor"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
Reload
|
Reload
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const SettingsPage = ({ standalone }: SettingsPage) => {
|
|||||||
<button onClick={() => browser.runtime.sendMessage({ type: 'currentTab', info: 'OpenChangelog' })} className="absolute w-8 h-8 text-lg rounded-xl font-IconFamily top-1 right-1 bg-zinc-100 dark:bg-zinc-700"></button>
|
<button onClick={() => browser.runtime.sendMessage({ type: 'currentTab', info: 'OpenChangelog' })} className="absolute w-8 h-8 text-lg rounded-xl font-IconFamily top-1 right-1 bg-zinc-100 dark:bg-zinc-700"></button>
|
||||||
</div>
|
</div>
|
||||||
<Picker />
|
<Picker />
|
||||||
<TabbedContainer tabs={tabs} />
|
<TabbedContainer tabs={tabs} animations={false} />
|
||||||
</div>
|
</div>
|
||||||
</SettingsContextProvider>
|
</SettingsContextProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const Shortcuts = memo(() => {
|
|||||||
const isValidTitle = useCallback((title: string) => title.trim() !== "", []);
|
const isValidTitle = useCallback((title: string) => title.trim() !== "", []);
|
||||||
|
|
||||||
const isValidURL = useCallback((url: string) => {
|
const isValidURL = useCallback((url: string) => {
|
||||||
const pattern = new RegExp("^(https?:\\/\\/)?[\\w.-]+[\\w.-]+(/[\\w.-]*)*$", "i");
|
const pattern = new RegExp("^(https?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\-]+)*(?::\\d+)?(/[\\w\\-./]*)*$", "i");
|
||||||
return pattern.test(url);
|
return pattern.test(url);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -144,4 +144,4 @@ const Shortcuts = memo(() => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Shortcuts;
|
export default Shortcuts;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ const Store = () => {
|
|||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
className="w-full max-w-xl h-[95%] p-8 pt-5 bg-white rounded-t-2xl dark:bg-zinc-800 overflow-scroll"
|
className="w-full max-w-xl h-[95%] p-4 bg-white rounded-t-2xl dark:bg-zinc-800 overflow-scroll"
|
||||||
exit={{ y: "100vh" }}
|
exit={{ y: "100vh" }}
|
||||||
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
|
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
|
||||||
variants={containerVariants}
|
variants={containerVariants}
|
||||||
@@ -219,7 +219,7 @@ const Store = () => {
|
|||||||
<motion.h2 className="mb-4 text-2xl font-bold" variants={textVariants}>
|
<motion.h2 className="mb-4 text-2xl font-bold" variants={textVariants}>
|
||||||
{displayTheme.name}
|
{displayTheme.name}
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
<motion.img src={displayTheme.coverImage} alt="Theme Cover" className="object-cover w-full mb-4 rounded-md" variants={textVariants} />
|
<motion.img src={displayTheme.marqueeImage} alt="Theme Cover" className="object-cover w-full mb-4 rounded-md" variants={textVariants} />
|
||||||
<motion.p className="mb-4 text-gray-700 dark:text-gray-300" variants={textVariants}>
|
<motion.p className="mb-4 text-gray-700 dark:text-gray-300" variants={textVariants}>
|
||||||
{displayTheme.description}
|
{displayTheme.description}
|
||||||
</motion.p>
|
</motion.p>
|
||||||
@@ -259,16 +259,9 @@ const Store = () => {
|
|||||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
{gridThemes.filter(theme => theme.id !== displayTheme.id).sort((a, b) => a.name.localeCompare(displayTheme.name) - b.name.localeCompare(displayTheme.name)).map((theme, index) => (
|
{gridThemes.filter(theme => theme.id !== displayTheme.id).sort((a, b) => a.name.localeCompare(displayTheme.name) - b.name.localeCompare(displayTheme.name)).map((theme, index) => (
|
||||||
<motion.div key={index} onClick={() => { setDisplayTheme(null); setDisplayTheme(theme); }} className='w-full cursor-pointer' variants={textVariants}>
|
<motion.div key={index} onClick={() => { setDisplayTheme(null); setDisplayTheme(theme); }} className='w-full cursor-pointer' variants={textVariants}>
|
||||||
<div
|
<div className="bg-gray-50 w-full transition-all hover:scale-105 duration-500 relative group group/card flex flex-col hover:shadow-2xl dark:hover:shadow-white/[0.1] hover:shadow-white/[0.8] dark:bg-zinc-800 dark:border-white/[0.1] h-auto rounded-xl overflow-clip border">
|
||||||
className="w-full overflow-clip rounded-xl transition-all duration-300 relative group/card flex flex-col hover:shadow-xl dark:hover:shadow-white/[0.1] hover:shadow-white/[0.8] h-auto"
|
<div className="absolute z-10 mb-1 text-xl font-bold text-white transition-all duration-500 group-hover:-translate-y-0.5 bottom-1 left-3">
|
||||||
>
|
{theme.name}
|
||||||
<div className='absolute bottom-0 left-0 z-10 p-2'>
|
|
||||||
<h6 className="text-xl font-bold text-neutral-600 dark:text-white">
|
|
||||||
{theme.name}
|
|
||||||
</h6>
|
|
||||||
<p className="max-w-sm text-sm text-neutral-500 dark:text-neutral-200">
|
|
||||||
{theme.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='absolute bottom-0 z-0 w-full h-3/4 bg-gradient-to-t from-black/80 to-transparent' />
|
<div className='absolute bottom-0 z-0 w-full h-3/4 bg-gradient-to-t from-black/80 to-transparent' />
|
||||||
<img src={theme.coverImage} alt="Theme Preview" className="object-cover w-full h-48" />
|
<img src={theme.coverImage} alt="Theme Preview" className="object-cover w-full h-48" />
|
||||||
@@ -304,52 +297,28 @@ const Store = () => {
|
|||||||
<div className="grid grid-cols-1 gap-4 py-12 mx-auto sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid grid-cols-1 gap-4 py-12 mx-auto sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{filteredThemes.map((theme, index) => (
|
{filteredThemes.map((theme, index) => (
|
||||||
<div onClick={() => setDisplayTheme(theme)} key={index} className='w-full cursor-pointer'>
|
<div onClick={() => setDisplayTheme(theme)} key={index} className='w-full cursor-pointer'>
|
||||||
<div className="bg-gray-50 w-full transition-all duration-300 relative group/card flex flex-col hover:shadow-2xl dark:hover:shadow-white/[0.1] hover:shadow-white/[0.8] dark:bg-zinc-800 dark:border-white/[0.1] h-auto rounded-xl p-6 border">
|
<div className="bg-gray-50 w-full transition-all hover:scale-105 duration-500 relative group group/card flex flex-col hover:shadow-2xl dark:hover:shadow-white/[0.1] hover:shadow-white/[0.8] dark:bg-zinc-800 dark:border-white/[0.1] h-auto rounded-xl overflow-clip border">
|
||||||
<div>
|
<div className="absolute z-10 mb-1 text-xl font-bold text-white transition-all duration-500 group-hover:-translate-y-0.5 bottom-1 left-3">
|
||||||
|
{theme.name}
|
||||||
<div className="mb-1 text-xl font-bold text-neutral-600 dark:text-white">
|
|
||||||
{theme.name}
|
|
||||||
</div>
|
|
||||||
<p className="max-w-sm mb-4 text-sm text-neutral-500 dark:text-neutral-300">
|
|
||||||
{theme.description}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className='absolute bottom-0 z-0 w-full h-3/4 bg-gradient-to-t from-black/80 to-transparent' />
|
||||||
<div
|
<div
|
||||||
className='w-full'>
|
className='w-full'>
|
||||||
<img src={theme.coverImage} alt="Theme Preview" className="object-cover w-full h-48 rounded-md" />
|
<img src={theme.coverImage} alt="Theme Preview" className="object-cover w-full h-48 rounded-md" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
{
|
|
||||||
currentThemes.includes(theme.id) ?
|
|
||||||
<button
|
|
||||||
onClick={() => removeTheme(theme.id)}
|
|
||||||
className="flex px-4 py-2 mt-4 ml-auto transition rounded-full dark:text-white bg-zinc-300 dark:bg-zinc-700 dark:hover:bg-zinc-600/50 hover:bg-zinc-200 focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:ring-offset-2">
|
|
||||||
{ installingThemes.includes(theme.id) ?
|
|
||||||
<>
|
|
||||||
<SpinnerIcon className="w-4 h-4 mr-2" />
|
|
||||||
Removing...
|
|
||||||
</> :
|
|
||||||
<> Remove </>
|
|
||||||
}
|
|
||||||
</button> :
|
|
||||||
<button
|
|
||||||
onClick={() => downloadTheme(theme.id)}
|
|
||||||
className="flex px-4 py-2 mt-4 ml-auto transition rounded-full dark:text-white bg-zinc-300 dark:bg-zinc-700 dark:hover:bg-zinc-600/50 hover:bg-zinc-200 focus:outline-none focus:ring-2 focus:ring-zinc-800 focus:ring-offset-2">
|
|
||||||
{ installingThemes.includes(theme.id) ?
|
|
||||||
<>
|
|
||||||
<SpinnerIcon className="w-4 h-4 mr-2" />
|
|
||||||
Installing...
|
|
||||||
</> :
|
|
||||||
<> Install </>
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
<a href="https://betterseqta.gitbook.io/betterseqta-docs" className='w-full cursor-pointer'>
|
||||||
|
<div className="bg-zinc-50 h-48 w-full transition-all hover:scale-105 duration-500 relative justify-center items-center group group/card flex flex-col hover:shadow-2xl dark:hover:shadow-white/[0.1] hover:shadow-white/[0.8] dark:bg-zinc-800 dark:border-white/[0.1] rounded-xl overflow-clip border">
|
||||||
|
<div className="text-2xl font-IconFamily">{'\uecb3'}</div>
|
||||||
|
<div className="text-xl font-bold text-center transition-all duration-500 dark:text-white">
|
||||||
|
Got a Theme Idea?
|
||||||
|
<p className="text-lg font-light subtitle">Transform it into a stunning theme!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{filteredThemes.length == 0 && !loading && (
|
{filteredThemes.length == 0 && !loading && (
|
||||||
<div className="flex flex-col items-center justify-center w-full text-center h-96">
|
<div className="flex flex-col items-center justify-center w-full text-center h-96">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import ColorPicker from 'react-best-gradient-color-picker';
|
|||||||
import Accordion from '../components/Accordian';
|
import Accordion from '../components/Accordian';
|
||||||
import Switch from '../components/Switch';
|
import Switch from '../components/Switch';
|
||||||
import { sendThemeUpdate } from '../hooks/ThemeManagment';
|
import { sendThemeUpdate } from '../hooks/ThemeManagment';
|
||||||
import { PlusIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
import { MoonIcon, PlusIcon, SunIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { CustomTheme, CustomThemeBase64 } from '../types/CustomThemes';
|
import { CustomTheme, CustomThemeBase64 } from '../types/CustomThemes';
|
||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
@@ -23,6 +23,7 @@ function ThemeCreator() {
|
|||||||
coverImage: null,
|
coverImage: null,
|
||||||
isEditable: true,
|
isEditable: true,
|
||||||
hideThemeName: false,
|
hideThemeName: false,
|
||||||
|
forceDark: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -159,6 +160,12 @@ function ThemeCreator() {
|
|||||||
<div className='w-full min-h-[100vh] bg-zinc-100 dark:bg-zinc-800 dark:text-white transition duration-30'>
|
<div className='w-full min-h-[100vh] bg-zinc-100 dark:bg-zinc-800 dark:text-white transition duration-30'>
|
||||||
<div className='flex flex-col p-2'>
|
<div className='flex flex-col p-2'>
|
||||||
<h1 className='text-xl font-semibold'>Theme Creator</h1>
|
<h1 className='text-xl font-semibold'>Theme Creator</h1>
|
||||||
|
<a href="https://betterseqta.gitbook.io/betterseqta-docs" target="_blank" className='text-sm font-light text-zinc-500 dark:text-zinc-400'>
|
||||||
|
<span className="no-underline font-IconFamily pr-0.5">{'\ueb44'}</span>
|
||||||
|
<span className="underline">
|
||||||
|
Need help? Check out the docs!
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
@@ -243,6 +250,29 @@ function ThemeCreator() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Divider /> */}
|
<Divider /> */}
|
||||||
|
|
||||||
|
<div className='flex items-center justify-between'>
|
||||||
|
<div>
|
||||||
|
<div className='pr-2 text-sm font-semibold'>Force Theme</div>
|
||||||
|
<div className='pr-2 text-[11px]'>Force users to use either dark or light mode</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Switch state={theme.forceDark == undefined ? false : true} onChange={value => setTheme({ ...theme, forceDark: value ? false : undefined })} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ theme.forceDark != undefined &&
|
||||||
|
<div className='flex items-center justify-between pt-4'>
|
||||||
|
<div>
|
||||||
|
<div className='pr-2 text-sm font-semibold'>Force {theme.forceDark ? 'Dark' : 'Light'} Mode</div>
|
||||||
|
<div className='pr-2 text-[11px]'>Force users to use {theme.forceDark ? 'dark' : 'light'} mode</div>
|
||||||
|
</div>
|
||||||
|
<button className='flex items-center justify-center p-2 transition rounded-lg bg-zinc-100 dark:bg-zinc-700' onClick={() => setTheme({ ...theme, forceDark: !theme.forceDark })}>
|
||||||
|
{theme.forceDark ? <MoonIcon className='w-6 h-6' /> : <SunIcon className='w-6 h-6' />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
<Accordion defaultOpened title='Default Theme Colour'>
|
<Accordion defaultOpened title='Default Theme Colour'>
|
||||||
<div className='p-2 mt-2 bg-white rounded-lg w-fit dark:bg-zinc-900'>
|
<div className='p-2 mt-2 bg-white rounded-lg w-fit dark:bg-zinc-900'>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type CustomTheme = {
|
|||||||
hideThemeName: boolean;
|
hideThemeName: boolean;
|
||||||
webURL?: string;
|
webURL?: string;
|
||||||
selectedColor?: string;
|
selectedColor?: string;
|
||||||
|
forceDark?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DownloadedTheme = CustomTheme & {
|
export type DownloadedTheme = CustomTheme & {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export interface Tab {
|
|||||||
}
|
}
|
||||||
export interface TabbedContainerProps {
|
export interface TabbedContainerProps {
|
||||||
tabs: Tab[];
|
tabs: Tab[];
|
||||||
|
animations?: boolean;
|
||||||
}
|
}
|
||||||
declare const TabbedContainer: React.FC<TabbedContainerProps>;
|
declare const TabbedContainer: React.FC<TabbedContainerProps>;
|
||||||
export default TabbedContainer;
|
export default TabbedContainer;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -4,6 +4,7 @@ import { appendBackgroundToUI } from "./ImageBackgrounds";
|
|||||||
import stringToHTML from "../utils/stringToHTML";
|
import stringToHTML from "../utils/stringToHTML";
|
||||||
import { settingsState } from "../utils/listeners/SettingsState";
|
import { settingsState } from "../utils/listeners/SettingsState";
|
||||||
import { updateAllColors } from "./colors/Manager";
|
import { updateAllColors } from "./colors/Manager";
|
||||||
|
import { delay } from "../utils/delay";
|
||||||
|
|
||||||
export async function AddBetterSEQTAElements() {
|
export async function AddBetterSEQTAElements() {
|
||||||
if (settingsState.onoff) {
|
if (settingsState.onoff) {
|
||||||
@@ -220,8 +221,8 @@ async function createSettingsButton() {
|
|||||||
ContentDiv!.append(SettingsButton.firstChild!);
|
ContentDiv!.append(SettingsButton.firstChild!);
|
||||||
}
|
}
|
||||||
|
|
||||||
function GetLightDarkModeString(darkMode: boolean) {
|
function GetLightDarkModeString() {
|
||||||
if (darkMode) {
|
if (settingsState.DarkMode) {
|
||||||
return 'Switch to light theme'
|
return 'Switch to light theme'
|
||||||
} else {
|
} else {
|
||||||
return 'Switch to dark theme'
|
return 'Switch to dark theme'
|
||||||
@@ -229,7 +230,7 @@ function GetLightDarkModeString(darkMode: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function addDarkLightToggle() {
|
async function addDarkLightToggle() {
|
||||||
const tooltipString = GetLightDarkModeString(settingsState.DarkMode);
|
const tooltipString = GetLightDarkModeString();
|
||||||
const svgContent = settingsState.DarkMode ?
|
const svgContent = settingsState.DarkMode ?
|
||||||
/* html */`<defs><clipPath id="__lottie_element_80"><rect width="24" height="24" x="0" y="0"></rect></clipPath></defs><g clip-path="url(#__lottie_element_80)"><g style="display: block;" transform="matrix(1,0,0,1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,-4 C-2.2100000381469727,-4 -4,-2.2100000381469727 -4,0 C-4,2.2100000381469727 -2.2100000381469727,4 0,4 C2.2100000381469727,4 4,2.2100000381469727 4,0 C4,-2.2100000381469727 2.2100000381469727,-4 0,-4z"></path></g></g><g style="display: block;" transform="matrix(1,0,0,1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,6 C-3.309999942779541,6 -6,3.309999942779541 -6,0 C-6,-3.309999942779541 -3.309999942779541,-6 0,-6 C3.309999942779541,-6 6,-3.309999942779541 6,0 C6,3.309999942779541 3.309999942779541,6 0,6z M8,-3.309999942779541 C8,-3.309999942779541 8,-8 8,-8 C8,-8 3.309999942779541,-8 3.309999942779541,-8 C3.309999942779541,-8 0,-11.3100004196167 0,-11.3100004196167 C0,-11.3100004196167 -3.309999942779541,-8 -3.309999942779541,-8 C-3.309999942779541,-8 -8,-8 -8,-8 C-8,-8 -8,-3.309999942779541 -8,-3.309999942779541 C-8,-3.309999942779541 -11.3100004196167,0 -11.3100004196167,0 C-11.3100004196167,0 -8,3.309999942779541 -8,3.309999942779541 C-8,3.309999942779541 -8,8 -8,8 C-8,8 -3.309999942779541,8 -3.309999942779541,8 C-3.309999942779541,8 0,11.3100004196167 0,11.3100004196167 C0,11.3100004196167 3.309999942779541,8 3.309999942779541,8 C3.309999942779541,8 8,8 8,8 C8,8 8,3.309999942779541 8,3.309999942779541 C8,3.309999942779541 11.3100004196167,0 11.3100004196167,0 C11.3100004196167,0 8,-3.309999942779541 8,-3.309999942779541z"></path></g></g></g>` :
|
/* html */`<defs><clipPath id="__lottie_element_80"><rect width="24" height="24" x="0" y="0"></rect></clipPath></defs><g clip-path="url(#__lottie_element_80)"><g style="display: block;" transform="matrix(1,0,0,1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,-4 C-2.2100000381469727,-4 -4,-2.2100000381469727 -4,0 C-4,2.2100000381469727 -2.2100000381469727,4 0,4 C2.2100000381469727,4 4,2.2100000381469727 4,0 C4,-2.2100000381469727 2.2100000381469727,-4 0,-4z"></path></g></g><g style="display: block;" transform="matrix(1,0,0,1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,6 C-3.309999942779541,6 -6,3.309999942779541 -6,0 C-6,-3.309999942779541 -3.309999942779541,-6 0,-6 C3.309999942779541,-6 6,-3.309999942779541 6,0 C6,3.309999942779541 3.309999942779541,6 0,6z M8,-3.309999942779541 C8,-3.309999942779541 8,-8 8,-8 C8,-8 3.309999942779541,-8 3.309999942779541,-8 C3.309999942779541,-8 0,-11.3100004196167 0,-11.3100004196167 C0,-11.3100004196167 -3.309999942779541,-8 -3.309999942779541,-8 C-3.309999942779541,-8 -8,-8 -8,-8 C-8,-8 -8,-3.309999942779541 -8,-3.309999942779541 C-8,-3.309999942779541 -11.3100004196167,0 -11.3100004196167,0 C-11.3100004196167,0 -8,3.309999942779541 -8,3.309999942779541 C-8,3.309999942779541 -8,8 -8,8 C-8,8 -3.309999942779541,8 -3.309999942779541,8 C-3.309999942779541,8 0,11.3100004196167 0,11.3100004196167 C0,11.3100004196167 3.309999942779541,8 3.309999942779541,8 C3.309999942779541,8 8,8 8,8 C8,8 8,3.309999942779541 8,3.309999942779541 C8,3.309999942779541 11.3100004196167,0 11.3100004196167,0 C11.3100004196167,0 8,-3.309999942779541 8,-3.309999942779541z"></path></g></g></g>` :
|
||||||
/* html */`<defs><clipPath id="__lottie_element_263"><rect width="24" height="24" x="0" y="0"></rect></clipPath></defs><g clip-path="url(#__lottie_element_263)"><g style="display: block;" transform="matrix(1.5,0,0,1.5,7,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,-4 C-2.2100000381469727,-4 -1.2920000553131104,-2.2100000381469727 -1.2920000553131104,0 C-1.2920000553131104,2.2100000381469727 -2.2100000381469727,4 0,4 C2.2100000381469727,4 4,2.2100000381469727 4,0 C4,-2.2100000381469727 2.2100000381469727,-4 0,-4z"></path></g></g><g style="display: block;" transform="matrix(-1,0,0,-1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,6 C-3.309999942779541,6 -6,3.309999942779541 -6,0 C-6,-3.309999942779541 -3.309999942779541,-6 0,-6 C3.309999942779541,-6 6,-3.309999942779541 6,0 C6,3.309999942779541 3.309999942779541,6 0,6z M8,-3.309999942779541 C8,-3.309999942779541 8,-8 8,-8 C8,-8 3.309999942779541,-8 3.309999942779541,-8 C3.309999942779541,-8 0,-11.3100004196167 0,-11.3100004196167 C0,-11.3100004196167 -3.309999942779541,-8 -3.309999942779541,-8 C-3.309999942779541,-8 -8,-8 -8,-8 C-8,-8 -8,-3.309999942779541 -8,-3.309999942779541 C-8,-3.309999942779541 -11.3100004196167,0 -11.3100004196167,0 C-11.3100004196167,0 -8,3.309999942779541 -8,3.309999942779541 C-8,3.309999942779541 -8,8 -8,8 C-8,8 -3.309999942779541,8 -3.309999942779541,8 C-3.309999942779541,8 0,11.3100004196167 0,11.3100004196167 C0,11.3100004196167 3.309999942779541,8 3.309999942779541,8 C3.309999942779541,8 8,8 8,8 C8,8 8,3.309999942779541 8,3.309999942779541 C8,3.309999942779541 11.3100004196167,0 11.3100004196167,0 C11.3100004196167,0 8,-3.309999942779541 8,-3.309999942779541z"></path></g></g></g>`;
|
/* html */`<defs><clipPath id="__lottie_element_263"><rect width="24" height="24" x="0" y="0"></rect></clipPath></defs><g clip-path="url(#__lottie_element_263)"><g style="display: block;" transform="matrix(1.5,0,0,1.5,7,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,-4 C-2.2100000381469727,-4 -1.2920000553131104,-2.2100000381469727 -1.2920000553131104,0 C-1.2920000553131104,2.2100000381469727 -2.2100000381469727,4 0,4 C2.2100000381469727,4 4,2.2100000381469727 4,0 C4,-2.2100000381469727 2.2100000381469727,-4 0,-4z"></path></g></g><g style="display: block;" transform="matrix(-1,0,0,-1,12,12)" opacity="1"><g opacity="1" transform="matrix(1,0,0,1,0,0)"><path fill-opacity="1" d=" M0,6 C-3.309999942779541,6 -6,3.309999942779541 -6,0 C-6,-3.309999942779541 -3.309999942779541,-6 0,-6 C3.309999942779541,-6 6,-3.309999942779541 6,0 C6,3.309999942779541 3.309999942779541,6 0,6z M8,-3.309999942779541 C8,-3.309999942779541 8,-8 8,-8 C8,-8 3.309999942779541,-8 3.309999942779541,-8 C3.309999942779541,-8 0,-11.3100004196167 0,-11.3100004196167 C0,-11.3100004196167 -3.309999942779541,-8 -3.309999942779541,-8 C-3.309999942779541,-8 -8,-8 -8,-8 C-8,-8 -8,-3.309999942779541 -8,-3.309999942779541 C-8,-3.309999942779541 -11.3100004196167,0 -11.3100004196167,0 C-11.3100004196167,0 -8,3.309999942779541 -8,3.309999942779541 C-8,3.309999942779541 -8,8 -8,8 C-8,8 -3.309999942779541,8 -3.309999942779541,8 C-3.309999942779541,8 0,11.3100004196167 0,11.3100004196167 C0,11.3100004196167 3.309999942779541,8 3.309999942779541,8 C3.309999942779541,8 8,8 8,8 C8,8 8,3.309999942779541 8,3.309999942779541 C8,3.309999942779541 11.3100004196167,0 11.3100004196167,0 C11.3100004196167,0 8,-3.309999942779541 8,-3.309999942779541z"></path></g></g></g>`;
|
||||||
@@ -247,12 +248,23 @@ async function addDarkLightToggle() {
|
|||||||
updateAllColors();
|
updateAllColors();
|
||||||
|
|
||||||
document.getElementById('LightDarkModeButton')!.addEventListener('click', async () => {
|
document.getElementById('LightDarkModeButton')!.addEventListener('click', async () => {
|
||||||
|
const darklightText = document.getElementById('darklighttooliptext');
|
||||||
|
|
||||||
|
if (settingsState.originalDarkMode != undefined && settingsState.selectedTheme) {
|
||||||
|
darklightText!.innerText = 'Locked by current theme';
|
||||||
|
|
||||||
|
await delay(1000)
|
||||||
|
|
||||||
|
darklightText!.innerText = GetLightDarkModeString();
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
settingsState.DarkMode = !settingsState.DarkMode;
|
settingsState.DarkMode = !settingsState.DarkMode;
|
||||||
|
|
||||||
updateAllColors();
|
updateAllColors();
|
||||||
|
|
||||||
const darklightText = document.getElementById('darklighttooliptext');
|
darklightText!.innerText = GetLightDarkModeString();
|
||||||
darklightText!.innerText = GetLightDarkModeString(!settingsState.DarkMode);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
import Browser from "webextension-polyfill";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects a YouTube iframe into the specified element.
|
|
||||||
*
|
|
||||||
* @param videoId - The YouTube video ID to embed.
|
|
||||||
* @param playlistId - The YouTube playlist ID to allow embed to loop.
|
|
||||||
* @param mountElement - The element to mount the iframe to.
|
|
||||||
* @param hideControls - Whether to hide the YouTube player controls.
|
|
||||||
* @param mute - Whether to mute the video.
|
|
||||||
* @param width - The width of the iframe.
|
|
||||||
* @param height - The height of the iframe.
|
|
||||||
*/
|
|
||||||
export function injectYouTubeVideo(videoId: string, playlistId: string, mountElement: HTMLElement, hideControls: boolean, mute: boolean, width: string, height: string): void {
|
|
||||||
const controlsParam = hideControls ? 'controls=0' : 'controls=1';
|
|
||||||
const autoplayParam = 'autoplay=1';
|
|
||||||
const muteParam = mute ? 'mute=1' : 'mute=0';
|
|
||||||
const listParams = playlistId ? `list=${playlistId}&` : '';
|
|
||||||
|
|
||||||
const iframeSrc = `https://www.youtube.com/embed/${videoId}?${listParams}${autoplayParam}&${controlsParam}&${muteParam}&loop=1`;
|
|
||||||
const iframe = document.createElement('iframe');
|
|
||||||
|
|
||||||
iframe.width = width;
|
|
||||||
iframe.height = height;
|
|
||||||
iframe.src = iframeSrc;
|
|
||||||
iframe.frameBorder = '0';
|
|
||||||
iframe.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture';
|
|
||||||
iframe.allowFullscreen = true;
|
|
||||||
|
|
||||||
iframe.onload = () => {
|
|
||||||
Browser.runtime.sendMessage({ type: 'youtubeIframe', hideControls });
|
|
||||||
};
|
|
||||||
|
|
||||||
mountElement.innerHTML = ''; // Clear any existing content
|
|
||||||
mountElement.appendChild(iframe);
|
|
||||||
|
|
||||||
/* if (hideControls) {
|
|
||||||
applyCustomStylesToIframe(iframe);
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to inject CSS styles into the iframe.
|
|
||||||
*
|
|
||||||
* @param hideControls - Whether to hide the YouTube player controls.
|
|
||||||
*/
|
|
||||||
export function applyYoutubeStyles(hideControls: boolean) {
|
|
||||||
if (window.location == window.parent.location) return;
|
|
||||||
if (!window.location.href.includes('youtube.com/embed/')) return;
|
|
||||||
|
|
||||||
if (hideControls) {
|
|
||||||
const hideControlsCss = `
|
|
||||||
.ytp-gradient-top,
|
|
||||||
.ytp-chrome-bottom,
|
|
||||||
.ytp-chrome-top,
|
|
||||||
.ytp-chrome-top-buttons,
|
|
||||||
.ytp-pause-overlay,
|
|
||||||
.ytp-watermark {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const hideControlsStyle = document.createElement('style');
|
|
||||||
hideControlsStyle.textContent = hideControlsCss;
|
|
||||||
document.head.appendChild(hideControlsStyle);
|
|
||||||
|
|
||||||
const f =() => {
|
|
||||||
const btn = document.querySelector('.ytp-ad-skip-button') as HTMLButtonElement | null;
|
|
||||||
const adText = document.querySelector('.ytp-ad-text');
|
|
||||||
const v = document.querySelector('video')!;
|
|
||||||
if(adText){
|
|
||||||
v.currentTime = v.duration
|
|
||||||
}
|
|
||||||
if(btn){
|
|
||||||
v.currentTime = v.duration
|
|
||||||
btn.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setInterval(f, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -58,15 +58,15 @@ export function updateAllColors() {
|
|||||||
|
|
||||||
for (let i = 0; i < alliframes.length; i++) {
|
for (let i = 0; i < alliframes.length; i++) {
|
||||||
const element = alliframes[i];
|
const element = alliframes[i];
|
||||||
|
|
||||||
if (element.getAttribute('excludeDarkCheck') == 'true') {
|
if (element.getAttribute('excludeDarkCheck') == 'true') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingsState.DarkMode) {
|
if (settingsState.DarkMode) {
|
||||||
element.contentDocument?.body.classList.add('dark');
|
element.contentDocument?.documentElement.classList.add('dark');
|
||||||
} else {
|
} else {
|
||||||
element.contentDocument?.body.classList.remove('dark');
|
element.contentDocument?.documentElement.classList.remove('dark');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,14 @@ import { settingsState } from '../../utils/listeners/SettingsState';
|
|||||||
export const UpdateThemePreview = async (updatedTheme: CustomThemeBase64 /* Omit<CustomTheme, 'CustomImages'> & { CustomImages: Omit<CustomImage, 'blob'>[] } */) => {
|
export const UpdateThemePreview = async (updatedTheme: CustomThemeBase64 /* Omit<CustomTheme, 'CustomImages'> & { CustomImages: Omit<CustomImage, 'blob'>[] } */) => {
|
||||||
const { CustomCSS, CustomImages, defaultColour } = updatedTheme;
|
const { CustomCSS, CustomImages, defaultColour } = updatedTheme;
|
||||||
|
|
||||||
|
if (updatedTheme.forceDark != undefined) {
|
||||||
|
if (updatedTheme.forceDark) {
|
||||||
|
settingsState.DarkMode = true;
|
||||||
|
} else {
|
||||||
|
settingsState.DarkMode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update image data
|
// Update image data
|
||||||
const currentImageIds = Object.keys(imageData);
|
const currentImageIds = Object.keys(imageData);
|
||||||
const updatedImageIds = CustomImages.map((image) => image.id);
|
const updatedImageIds = CustomImages.map((image) => image.id);
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { CustomImage, CustomTheme } from '../../../interface/types/CustomThemes';
|
import { CustomImage, CustomTheme } from '../../../interface/types/CustomThemes';
|
||||||
|
import { settingsState } from '../../utils/listeners/SettingsState';
|
||||||
import { applyCustomCSS } from './Themes';
|
import { applyCustomCSS } from './Themes';
|
||||||
|
|
||||||
|
|
||||||
export const applyTheme = async (theme: CustomTheme) => {
|
export const applyTheme = async (theme: CustomTheme, reEnable?: boolean) => {
|
||||||
let CustomCSS = '';
|
let CustomCSS = '';
|
||||||
let CustomImages: CustomImage[] = [];
|
let CustomImages: CustomImage[] = [];
|
||||||
|
|
||||||
if (theme?.CustomCSS) CustomCSS = theme.CustomCSS;
|
if (theme?.CustomCSS) CustomCSS = theme.CustomCSS;
|
||||||
if (theme?.CustomImages) CustomImages = theme.CustomImages;
|
if (theme?.CustomImages) CustomImages = theme.CustomImages;
|
||||||
|
if (theme?.forceDark != undefined) {
|
||||||
|
if (!reEnable) settingsState.originalDarkMode = settingsState.DarkMode
|
||||||
|
|
||||||
|
settingsState.DarkMode = theme.forceDark
|
||||||
|
}
|
||||||
|
|
||||||
// Apply custom CSS
|
// Apply custom CSS
|
||||||
applyCustomCSS(CustomCSS);
|
applyCustomCSS(CustomCSS);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const enableCurrentTheme = async () => {
|
|||||||
if (settingsState.selectedTheme) {
|
if (settingsState.selectedTheme) {
|
||||||
const theme = await localforage.getItem(settingsState.selectedTheme) as CustomTheme;
|
const theme = await localforage.getItem(settingsState.selectedTheme) as CustomTheme;
|
||||||
if (theme) {
|
if (theme) {
|
||||||
await applyTheme(theme);
|
await applyTheme(theme, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ export const removeTheme = async (theme: CustomTheme) => {
|
|||||||
if (settingsState.originalSelectedColor !== '') {
|
if (settingsState.originalSelectedColor !== '') {
|
||||||
settingsState.selectedColor = settingsState.originalSelectedColor
|
settingsState.selectedColor = settingsState.originalSelectedColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsState.originalDarkMode !== undefined) {
|
||||||
|
settingsState.DarkMode = settingsState.originalDarkMode
|
||||||
|
settingsState.originalDarkMode = undefined
|
||||||
|
}
|
||||||
|
|
||||||
// Remove custom images
|
// Remove custom images
|
||||||
const customImageVariables = theme.CustomImages.map((image) => image.variableName);
|
const customImageVariables = theme.CustomImages.map((image) => image.variableName);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class StorageManager {
|
|||||||
return Reflect.get(target.data, prop);
|
return Reflect.get(target.data, prop);
|
||||||
},
|
},
|
||||||
set: (target, prop: keyof SettingsState, value) => {
|
set: (target, prop: keyof SettingsState, value) => {
|
||||||
console.log(target)
|
|
||||||
Reflect.set(target.data, prop, value);
|
Reflect.set(target.data, prop, value);
|
||||||
target.saveToStorage();
|
target.saveToStorage();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export interface SettingsState {
|
|||||||
animations: boolean;
|
animations: boolean;
|
||||||
defaultPage: string;
|
defaultPage: string;
|
||||||
devMode?: boolean;
|
devMode?: boolean;
|
||||||
|
originalDarkMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ToggleItem {
|
interface ToggleItem {
|
||||||
|
|||||||
Reference in New Issue
Block a user