mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
experimental: full support for background photos and videos
This commit is contained in:
@@ -13,7 +13,6 @@ const useSettingsState = ({ settingsState, setSettingsState }: SettingsProps) =>
|
|||||||
|
|
||||||
// get the current settings state
|
// get the current settings state
|
||||||
chrome.storage.local.get(function(result: MainConfig) {
|
chrome.storage.local.get(function(result: MainConfig) {
|
||||||
console.log(result);
|
|
||||||
setSettingsState({
|
setSettingsState({
|
||||||
notificationCollector: result.notificationcollector,
|
notificationCollector: result.notificationcollector,
|
||||||
lessonAlerts: result.lessonalert,
|
lessonAlerts: result.lessonalert,
|
||||||
@@ -43,7 +42,6 @@ const useSettingsState = ({ settingsState, setSettingsState }: SettingsProps) =>
|
|||||||
}), []);
|
}), []);
|
||||||
|
|
||||||
const storageChangeListener = (changes: chrome.storage.StorageChange) => {
|
const storageChangeListener = (changes: chrome.storage.StorageChange) => {
|
||||||
console.log(settingsState);
|
|
||||||
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) {
|
||||||
|
|||||||
@@ -47,12 +47,15 @@ const readData = async () => {
|
|||||||
|
|
||||||
const Themes: React.FC = () => {
|
const Themes: React.FC = () => {
|
||||||
const [imageSrc, setImageSrc] = useState<string | null>(null);
|
const [imageSrc, setImageSrc] = useState<string | null>(null);
|
||||||
|
const [videoSrc, setVideoSrc] = useState<string | null>(null);
|
||||||
|
|
||||||
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
const fileType = 'image';
|
const fileType = file.type.split('/')[0];
|
||||||
|
console.log(fileType);
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
reader.onload = async () => {
|
reader.onload = async () => {
|
||||||
@@ -61,11 +64,7 @@ const Themes: React.FC = () => {
|
|||||||
setImageSrc(dataURL as string);
|
setImageSrc(dataURL as string);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fileType === 'image') {
|
reader.readAsDataURL(file);
|
||||||
reader.readAsDataURL(file);
|
|
||||||
} else {
|
|
||||||
// Handle video file
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -73,6 +72,8 @@ const Themes: React.FC = () => {
|
|||||||
const data = await readData();
|
const data = await readData();
|
||||||
if (data?.type === 'image') {
|
if (data?.type === 'image') {
|
||||||
setImageSrc(data.data);
|
setImageSrc(data.data);
|
||||||
|
} else if (data?.type === 'video') {
|
||||||
|
setVideoSrc(data.data);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -85,6 +86,7 @@ const Themes: React.FC = () => {
|
|||||||
|
|
||||||
<input type="file" onChange={handleFileChange} />
|
<input type="file" onChange={handleFileChange} />
|
||||||
{imageSrc && <img src={imageSrc} alt="Uploaded content" />}
|
{imageSrc && <img src={imageSrc} alt="Uploaded content" />}
|
||||||
|
{videoSrc && <video src={videoSrc} autoPlay loop muted />}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold">Themes</h2>
|
<h2 className="text-lg font-bold">Themes</h2>
|
||||||
|
|||||||
+2
-1
@@ -1157,7 +1157,6 @@ function ReplaceMenuSVG(element, svg) {
|
|||||||
|
|
||||||
function AddBetterSEQTAElements(toggle) {
|
function AddBetterSEQTAElements(toggle) {
|
||||||
var code = document.getElementsByClassName("code")[0];
|
var code = document.getElementsByClassName("code")[0];
|
||||||
appendBackgroundToUI();
|
|
||||||
// Replaces students code with the version of BetterSEQTA
|
// Replaces students code with the version of BetterSEQTA
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
if (!code.innerHTML.includes("BetterSEQTA")) {
|
if (!code.innerHTML.includes("BetterSEQTA")) {
|
||||||
@@ -1324,8 +1323,10 @@ function AddBetterSEQTAElements(toggle) {
|
|||||||
SendNewsPage();
|
SendNewsPage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appendBackgroundToUI();
|
||||||
CallExtensionSettings();
|
CallExtensionSettings();
|
||||||
|
|
||||||
// If betterSEQTA+ is enabled, run the code
|
// If betterSEQTA+ is enabled, run the code
|
||||||
|
|||||||
+82
-29
@@ -1,6 +1,67 @@
|
|||||||
/*global chrome*/
|
/*global chrome*/
|
||||||
|
|
||||||
import { readData, writeData } from "./seqta/utils/IndexedDB.js";
|
export const openDB = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const request = indexedDB.open("MyDatabase", 1);
|
||||||
|
|
||||||
|
request.onupgradeneeded = (event) => {
|
||||||
|
const db = event.target.result;
|
||||||
|
db.createObjectStore("backgrounds", { keyPath: "id" });
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onsuccess = () => {
|
||||||
|
resolve(request.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = (event) => {
|
||||||
|
reject("Error opening database: " + event.target.errorCode);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const writeData = async (type, data) => {
|
||||||
|
console.log("Reading Data");
|
||||||
|
const db = await openDB();
|
||||||
|
console.log("Opened DB");
|
||||||
|
|
||||||
|
const tx = db.transaction("backgrounds", "readwrite");
|
||||||
|
const store = tx.objectStore("backgrounds");
|
||||||
|
const request = await store.put({ id: "customBackground", type, data });
|
||||||
|
|
||||||
|
console.log("Data written successfully");
|
||||||
|
|
||||||
|
return request.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const readData = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
openDB()
|
||||||
|
.then(db => {
|
||||||
|
console.log("Database, typeof", typeof db, "Is: ", db);
|
||||||
|
const tx = db.transaction("backgrounds", "readonly");
|
||||||
|
const store = tx.objectStore("backgrounds");
|
||||||
|
console.log("Current store: ", store);
|
||||||
|
|
||||||
|
// Retrieve the custom background
|
||||||
|
const getRequest = store.get("customBackground");
|
||||||
|
|
||||||
|
// Attach success and error event handlers
|
||||||
|
getRequest.onsuccess = function(event) {
|
||||||
|
console.log("CustomBackground", event.target.result);
|
||||||
|
resolve(event.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
getRequest.onerror = function(event) {
|
||||||
|
console.error("An error occurred:", event);
|
||||||
|
reject(event);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("An error occurred:", error);
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function ReloadSEQTAPages() {
|
function ReloadSEQTAPages() {
|
||||||
chrome.tabs.query({}, function (tabs) {
|
chrome.tabs.query({}, function (tabs) {
|
||||||
@@ -12,28 +73,6 @@ function ReloadSEQTAPages() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to handle IndexedDB actions
|
|
||||||
const handleIndexedDBActions = (request) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
console.log("request");
|
|
||||||
if (request.action === "save") {
|
|
||||||
writeData(request.data.type, request.data.data)
|
|
||||||
.then(() => {
|
|
||||||
resolve({ message: "Data saved successfully" });
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
} else if (request.action === "read") {
|
|
||||||
readData()
|
|
||||||
.then(data => {
|
|
||||||
resolve(data);
|
|
||||||
})
|
|
||||||
.catch(reject);
|
|
||||||
} else {
|
|
||||||
reject(new Error("Invalid action type"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper function to handle setting permissions
|
// Helper function to handle setting permissions
|
||||||
const handleAddPermissions = () => {
|
const handleAddPermissions = () => {
|
||||||
if (typeof chrome.declarativeContent !== "undefined") {
|
if (typeof chrome.declarativeContent !== "undefined") {
|
||||||
@@ -59,20 +98,17 @@ const handleAddPermissions = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Main message listener
|
// Main message listener
|
||||||
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
console.log("Message received in background script", request);
|
console.log("Message received in background script", request);
|
||||||
|
|
||||||
sendResponse({ type: "success" });
|
|
||||||
switch (request.type) {
|
switch (request.type) {
|
||||||
case "reloadTabs":
|
case "reloadTabs":
|
||||||
ReloadSEQTAPages();
|
ReloadSEQTAPages();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "IndexedDB":
|
case "IndexedDB":
|
||||||
handleIndexedDBActions(request, sendResponse);
|
HandleIntexedDB(request, sendResponse);
|
||||||
return true; // This keeps the message channel open for async sendResponse
|
return true;
|
||||||
// eslint-disable-next-line no-unreachable
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "githubTab":
|
case "githubTab":
|
||||||
chrome.tabs.create({ url: "github.com/SethBurkart123/EvenBetterSEQTA" });
|
chrome.tabs.create({ url: "github.com/SethBurkart123/EvenBetterSEQTA" });
|
||||||
@@ -98,6 +134,21 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function HandleIntexedDB(request, sendResponse) {
|
||||||
|
switch (request.action) {
|
||||||
|
case "write":
|
||||||
|
writeData(request.data.type, request.data.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "read":
|
||||||
|
readData().then((data) => {
|
||||||
|
console.log("Sending data: ", data);
|
||||||
|
sendResponse(data);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
function GetNews(sendResponse) {
|
function GetNews(sendResponse) {
|
||||||
// Gets the current date
|
// Gets the current date
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
@@ -116,6 +167,7 @@ function GetNews(sendResponse) {
|
|||||||
|
|
||||||
let url = `https://newsapi.org/v2/everything?domains=abc.net.au&from=${from}&apiKey=17c0da766ba347c89d094449504e3080`;
|
let url = `https://newsapi.org/v2/everything?domains=abc.net.au&from=${from}&apiKey=17c0da766ba347c89d094449504e3080`;
|
||||||
|
|
||||||
|
console.log("Fetching news from " + url);
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then((result) => result.json())
|
.then((result) => result.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -123,6 +175,7 @@ function GetNews(sendResponse) {
|
|||||||
url += "%00";
|
url += "%00";
|
||||||
GetNews();
|
GetNews();
|
||||||
} else {
|
} else {
|
||||||
|
console.log(response);
|
||||||
sendResponse({ news: response });
|
sendResponse({ news: response });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,600");
|
@import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,600");
|
||||||
@import "./injected/popup.css";
|
@import "./injected/popup.css";
|
||||||
|
@import "./injected/sidebar-animation.css";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
background: var(--better-main) !important;
|
background: var(--better-main) !important;
|
||||||
|
|||||||
@@ -25,4 +25,5 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/* #menu ul.noscroll li {
|
||||||
|
transform: translateX(-10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#menu li.active>.sub {
|
||||||
|
transform: translateX(0);
|
||||||
|
} */
|
||||||
+69
-29
@@ -1,37 +1,77 @@
|
|||||||
/* global chrome */
|
/* global chrome */
|
||||||
|
/* function isValidBase64(str) {
|
||||||
|
const len = str.length;
|
||||||
|
if (len % 4 !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
if (!(/[A-Za-z0-9+/=]/.test(str[i]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function base64ToArrayBuffer(base64) {
|
||||||
|
console.log(base64);
|
||||||
|
if (!isValidBase64(base64)) {
|
||||||
|
console.error("Invalid base64 string");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const binaryString = atob(base64);
|
||||||
|
const len = binaryString.length;
|
||||||
|
const bytes = new Uint8Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
bytes[i] = binaryString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return bytes.buffer;
|
||||||
|
} */
|
||||||
|
|
||||||
export async function appendBackgroundToUI() {
|
export async function appendBackgroundToUI() {
|
||||||
try {
|
const response = await new Promise((resolve, reject) => {
|
||||||
const response = await new Promise((resolve, reject) => {
|
chrome.runtime.sendMessage({ type: "IndexedDB", action: "read", fileName: "customBackground" }, (response) => {
|
||||||
chrome.runtime.sendMessage({ type: "IndexedDB" }, (response) => {
|
if (chrome.runtime.lastError) {
|
||||||
if (chrome.runtime.lastError) {
|
return reject(chrome.runtime.lastError);
|
||||||
return reject(chrome.runtime.lastError);
|
}
|
||||||
}
|
resolve(response);
|
||||||
resolve(response);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
console.log("response:", response);
|
});
|
||||||
} catch (error) {
|
console.log("response:", response);
|
||||||
console.log("Error:", error);
|
|
||||||
|
let data = response.data; // response.data is the image base64 string
|
||||||
|
let type = response.type; // response.type is the image type [ video | image ]
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
// check if it is video from its base64 string
|
||||||
|
const mount = document.getElementById("container");
|
||||||
|
console.log("Starting to append background");
|
||||||
|
let backgroundElement;
|
||||||
|
if (type === "video") {
|
||||||
|
/* const arrayBuffer = base64ToArrayBuffer(data);
|
||||||
|
const blob = new Blob([arrayBuffer], { type: "video/mp4" });
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
console.log("blobUrl:", blobUrl); */
|
||||||
|
|
||||||
|
backgroundElement = document.createElement("video");
|
||||||
|
backgroundElement.src = data;
|
||||||
|
backgroundElement.autoplay = true;
|
||||||
|
backgroundElement.loop = true;
|
||||||
|
backgroundElement.muted = true;
|
||||||
|
backgroundElement.classList.add("imageBackground");
|
||||||
|
mount.appendChild(backgroundElement);
|
||||||
|
|
||||||
|
const videoElement = document.getElementsByClassName("imageBackground")[0];
|
||||||
|
setTimeout(() => {
|
||||||
|
videoElement.play();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
backgroundElement = document.createElement("img");
|
||||||
|
backgroundElement.src = data;
|
||||||
|
backgroundElement.alt = "Custom Background";
|
||||||
|
backgroundElement.classList.add("imageBackground");
|
||||||
|
mount.appendChild(backgroundElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mount = document.getElementById("container");
|
|
||||||
console.log("Starting to append background");
|
|
||||||
let data;
|
|
||||||
const response = await chrome.runtime.sendMessage({ type: "IndexedDB" });
|
|
||||||
data = response;
|
|
||||||
const imgElement = document.createElement("img");
|
|
||||||
imgElement.src = data;
|
|
||||||
imgElement.alt = "Uploaded Image";
|
|
||||||
imgElement.classList.add("imageBackground");
|
|
||||||
mount.appendChild(imgElement);
|
|
||||||
|
|
||||||
/* if (data) {
|
|
||||||
continue
|
|
||||||
} else if (data?.type === "video") {
|
|
||||||
// Handle video
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appendBackgroundToUI();
|
appendBackgroundToUI();
|
||||||
|
|||||||
@@ -1,29 +1,26 @@
|
|||||||
// IndexedDB utility functions
|
export const openDB = async () => {
|
||||||
export const openDB = () => {
|
const request = indexedDB.open("MyDatabase", 1);
|
||||||
return new Promise<IDBDatabase>((resolve, reject) => {
|
|
||||||
const request = indexedDB.open("MyDatabase", 1);
|
|
||||||
|
|
||||||
request.onerror = () => reject(request.error);
|
request.onupgradeneeded = async (event) => {
|
||||||
request.onsuccess = () => resolve(request.result);
|
const db = event.target.result;
|
||||||
|
await db.createObjectStore("backgrounds", { keyPath: "id" });
|
||||||
|
};
|
||||||
|
|
||||||
request.onupgradeneeded = (event) => {
|
return request;
|
||||||
const db = (event.target).result;
|
|
||||||
db.createObjectStore("backgrounds", { keyPath: "id" });
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const writeData = async (type, data) => {
|
export const writeData = async (type, data) => {
|
||||||
return new Promise((resolve, reject) => {
|
console.log("Reading Data");
|
||||||
openDB().then(db => {
|
const db = await openDB();
|
||||||
const tx = db.transaction("backgrounds", "readwrite");
|
console.log("Opened DB");
|
||||||
const store = tx.objectStore("backgrounds");
|
|
||||||
const request = store.put({ id: "customBackground", type, data });
|
|
||||||
|
|
||||||
tx.oncomplete = () => resolve(request.result);
|
const tx = db.transaction("backgrounds", "readwrite");
|
||||||
tx.onerror = () => reject(tx.error);
|
const store = tx.objectStore("backgrounds");
|
||||||
}).catch(reject);
|
const request = await store.put({ id: "customBackground", type, data });
|
||||||
});
|
|
||||||
|
console.log("Data written successfully");
|
||||||
|
|
||||||
|
return request.result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readData = async () => {
|
export const readData = async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user