v1.5
This commit is contained in:
parent
632cd3a0c8
commit
fb8a786f8c
@ -8,6 +8,8 @@ A simple, versatile language processing interface for websites.
|
||||
- Adjust opacity of responses
|
||||
- Hidden
|
||||
- Only visible to those who know where to look
|
||||
- Exam mode
|
||||
- Make text selection hard to see to avoid detection
|
||||
|
||||
## Usage
|
||||
After installing the extensions, selecting text and pressing `Ctrl+Space` will display the answer above the selected text in the configured opacity. To hide the answer, press `Ctrl+Space` again without selecting any text.
|
||||
|
@ -1,10 +1,11 @@
|
||||
// Constants
|
||||
// contents
|
||||
const DEFAULT_SETTINGS = {
|
||||
apiUrl: "https://api.elia.network",
|
||||
apiKey: "sk-TvFhtxHAPXEcmRtyva-ctA",
|
||||
textOpacity: 10,
|
||||
model: "llama3.2-90b",
|
||||
background: false,
|
||||
examModeStates: {},
|
||||
};
|
||||
|
||||
const MAX_CONTEXT_LENGTH = 6000;
|
||||
|
@ -18,7 +18,14 @@
|
||||
"js": ["content.js"]
|
||||
}
|
||||
],
|
||||
"permissions": ["activeTab", "storage", "*://api.elia.network/*"],
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"storage",
|
||||
"*://api.elia.network/*",
|
||||
"scripting",
|
||||
"tabs",
|
||||
"<all_urls>"
|
||||
],
|
||||
"commands": {
|
||||
"print-selection": {
|
||||
"suggested_key": {
|
||||
|
@ -163,6 +163,33 @@
|
||||
background: var(--primary-hover);
|
||||
}
|
||||
|
||||
.exam-mode-button {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.exam-mode-button:hover {
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
.exam-mode-button.active {
|
||||
background: #065f46;
|
||||
border-color: #059669;
|
||||
}
|
||||
|
||||
.exam-mode-button.active:hover {
|
||||
background: #047857;
|
||||
}
|
||||
|
||||
#status {
|
||||
margin-top: 12px;
|
||||
padding: 8px 12px;
|
||||
@ -181,7 +208,6 @@
|
||||
color: #fef2f2;
|
||||
}
|
||||
|
||||
/* Scrollbar Styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
@ -204,7 +230,7 @@
|
||||
<body>
|
||||
<div class="header">
|
||||
<h2>CAS</h2>
|
||||
<span class="version-badge">v1.4</span>
|
||||
<span class="version-badge">v1.5</span>
|
||||
</div>
|
||||
|
||||
<form id="settingsForm">
|
||||
@ -266,6 +292,8 @@
|
||||
<button type="submit" class="save-button">Save Settings</button>
|
||||
</form>
|
||||
|
||||
<button id="examMode" class="exam-mode-button">Enable Exam Mode</button>
|
||||
|
||||
<div id="status"></div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
|
200
src/popup.js
200
src/popup.js
@ -4,14 +4,128 @@ const DEFAULT_SETTINGS = {
|
||||
textOpacity: 10,
|
||||
model: "llama3.2-90b",
|
||||
background: false,
|
||||
examModeStates: {},
|
||||
};
|
||||
|
||||
// Load settings when the popup opens
|
||||
// track for each tab
|
||||
const tabStates = new Map();
|
||||
|
||||
async function updateExamModeState(tabId, enabled) {
|
||||
try {
|
||||
const data = await browser.storage.sync.get("settings");
|
||||
const settings = { ...DEFAULT_SETTINGS, ...data.settings };
|
||||
|
||||
settings.examModeStates = {
|
||||
...settings.examModeStates,
|
||||
[tabId]: enabled,
|
||||
};
|
||||
|
||||
await browser.storage.sync.set({ settings });
|
||||
} catch (error) {
|
||||
console.error("Error updating exam mode state:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// scriptinjector
|
||||
async function injectExamModeScript(enabled) {
|
||||
try {
|
||||
const tabs = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
const tabId = tabs[0].id;
|
||||
|
||||
// update for this tab
|
||||
tabStates.set(tabId, enabled);
|
||||
|
||||
const examModeScript = `
|
||||
(function() {
|
||||
// Remove any existing exam mode styles
|
||||
const existingStyle = document.getElementById('exam-mode-style');
|
||||
if (existingStyle) {
|
||||
existingStyle.remove();
|
||||
}
|
||||
|
||||
// If enabled, add the new style
|
||||
if (${enabled}) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'exam-mode-style';
|
||||
style.textContent = \`
|
||||
::selection {
|
||||
background-color: rgba(0, 0, 255, 0.05) !important;
|
||||
}
|
||||
::-moz-selection {
|
||||
background-color: rgba(0, 0, 255, 0.05) !important;
|
||||
}
|
||||
\`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
return true;
|
||||
})();
|
||||
`;
|
||||
|
||||
// inject ;3
|
||||
await browser.tabs.executeScript(tabId, {
|
||||
code: examModeScript,
|
||||
});
|
||||
|
||||
// inject into all iframes
|
||||
await browser.tabs.executeScript(tabId, {
|
||||
code: examModeScript,
|
||||
allFrames: true,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error injecting exam mode script:", error);
|
||||
if (error.message.includes("non-structured-clonable data")) {
|
||||
return true;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
try {
|
||||
const data = await browser.storage.sync.get("settings");
|
||||
const settings = { ...DEFAULT_SETTINGS, ...data.settings };
|
||||
|
||||
// get exam mode status for this tab
|
||||
const tabs = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
const tabId = tabs[0].id;
|
||||
const tabExamMode = settings.examModeStates[tabId] || false;
|
||||
|
||||
return { ...settings, examMode: tabExamMode };
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
return DEFAULT_SETTINGS;
|
||||
}
|
||||
}
|
||||
|
||||
// exam mode status
|
||||
function updateExamModeButton(enabled) {
|
||||
const button = document.getElementById("examMode");
|
||||
button.textContent = enabled ? "Disable Exam Mode" : "Enable Exam Mode";
|
||||
button.classList.toggle("active", enabled);
|
||||
}
|
||||
|
||||
function showStatus(message, type) {
|
||||
const status = document.getElementById("status");
|
||||
status.textContent = message;
|
||||
status.className = type;
|
||||
status.style.display = "block";
|
||||
setTimeout(() => {
|
||||
status.style.display = "none";
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
try {
|
||||
const settings = await loadSettings();
|
||||
|
||||
// Populate form fields
|
||||
// load settings into the form
|
||||
document.getElementById("apiUrl").value = settings.apiUrl;
|
||||
document.getElementById("model").value = settings.model;
|
||||
document.getElementById("apiKey").value = settings.apiKey;
|
||||
@ -19,23 +133,59 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
document.getElementById("opacityValue").textContent =
|
||||
`${settings.textOpacity}%`;
|
||||
document.getElementById("background").checked = settings.background;
|
||||
|
||||
// update button state
|
||||
updateExamModeButton(settings.examMode);
|
||||
|
||||
// if exam mode is enabled, inject the script
|
||||
if (settings.examMode) {
|
||||
await injectExamModeScript(true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
showStatus("Error loading settings", "error");
|
||||
}
|
||||
});
|
||||
|
||||
// Handle opacity slider changes
|
||||
// handle opacity slider
|
||||
document.getElementById("textOpacity").addEventListener("input", (e) => {
|
||||
document.getElementById("opacityValue").textContent = `${e.target.value}%`;
|
||||
});
|
||||
|
||||
// Handle form submission
|
||||
document.getElementById("examMode").addEventListener("click", async () => {
|
||||
try {
|
||||
const tabs = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
const tabId = tabs[0].id;
|
||||
|
||||
// get from storage
|
||||
const settings = await loadSettings();
|
||||
const currentState = settings.examMode;
|
||||
const newExamMode = !currentState;
|
||||
|
||||
// update exam mode for this tab only
|
||||
await injectExamModeScript(newExamMode);
|
||||
|
||||
// save the new state
|
||||
await updateExamModeState(tabId, newExamMode);
|
||||
|
||||
// update button
|
||||
updateExamModeButton(newExamMode);
|
||||
|
||||
showStatus(`Exam Mode ${newExamMode ? "enabled" : "disabled"}`, "success");
|
||||
} catch (error) {
|
||||
console.error("Error toggling exam mode:", error);
|
||||
showStatus("Error toggling exam mode", "error");
|
||||
}
|
||||
});
|
||||
|
||||
// form submission handler
|
||||
document
|
||||
.getElementById("settingsForm")
|
||||
.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const settings = {
|
||||
apiUrl: document.getElementById("apiUrl").value,
|
||||
apiKey: document.getElementById("apiKey").value,
|
||||
@ -43,7 +193,6 @@ document
|
||||
textOpacity: parseInt(document.getElementById("textOpacity").value),
|
||||
background: document.getElementById("background").checked,
|
||||
};
|
||||
|
||||
try {
|
||||
await browser.storage.sync.set({ settings });
|
||||
showStatus("Settings saved successfully!", "success");
|
||||
@ -53,30 +202,27 @@ document
|
||||
}
|
||||
});
|
||||
|
||||
// Load settings from storage or use defaults
|
||||
async function loadSettings() {
|
||||
browser.tabs.onActivated.addListener(async (activeInfo) => {
|
||||
const tabId = activeInfo.tabId;
|
||||
const tabExamMode = tabStates.get(tabId) || false;
|
||||
updateExamModeButton(tabExamMode);
|
||||
});
|
||||
|
||||
browser.tabs.onRemoved.addListener(async (tabId) => {
|
||||
try {
|
||||
const data = await browser.storage.sync.get("settings");
|
||||
return { ...DEFAULT_SETTINGS, ...data.settings };
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
return DEFAULT_SETTINGS;
|
||||
const settings = { ...DEFAULT_SETTINGS, ...data.settings };
|
||||
|
||||
if (settings.examModeStates[tabId]) {
|
||||
delete settings.examModeStates[tabId];
|
||||
await browser.storage.sync.set({ settings });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error cleaning up exam mode state:", error);
|
||||
}
|
||||
});
|
||||
|
||||
// Show status message
|
||||
function showStatus(message, type) {
|
||||
const status = document.getElementById("status");
|
||||
status.textContent = message;
|
||||
status.className = type;
|
||||
status.style.display = "block";
|
||||
|
||||
setTimeout(() => {
|
||||
status.style.display = "none";
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Handle errors
|
||||
// errorhandler
|
||||
window.addEventListener("error", (event) => {
|
||||
console.error("Error:", event.error);
|
||||
showStatus("An error occurred", "error");
|
||||
|
Loading…
Reference in New Issue
Block a user