+
+
+
+
diff --git a/module/webui/scripts/applist.js b/module/webui/scripts/applist.js
index 141ba55..65363c8 100644
--- a/module/webui/scripts/applist.js
+++ b/module/webui/scripts/applist.js
@@ -1,6 +1,7 @@
-import { basePath, execCommand, floatingBtn, appsWithExclamation, appsWithQuestion } from './main.js';
+import { basePath, execCommand, floatingBtn, appsWithExclamation, appsWithQuestion, toast } from './main.js';
const appTemplate = document.getElementById('app-template').content;
+const modeOverlay = document.querySelector('.mode-overlay');
export const appListContainer = document.getElementById('apps-list');
export const updateCard = document.getElementById('update-card');
@@ -13,6 +14,7 @@ export async function fetchAppList() {
targetList = processTargetList(targetFileContent);
console.log("Current target list:", targetList);
} catch (error) {
+ toast("Failed to read target.txt!");
console.error("Failed to read target.txt file:", error);
}
@@ -35,7 +37,7 @@ export async function fetchAppList() {
console.warn("Applist file not found or could not be loaded. Skipping applist lookup.");
}
- const result = await execCommand("pm list packages -3");
+ const result = await execCommand('pm list packages -3; pm path com.google.android.gms >/dev/null 2>&1 && echo "package:com.google.android.gms"');
const appEntries = result
.split("\n")
.map(line => {
@@ -76,6 +78,26 @@ export async function fetchAppList() {
const appElement = document.importNode(appTemplate, true);
const contentElement = appElement.querySelector(".content");
contentElement.setAttribute("data-package", packageName);
+
+ // Set unique names for radio button groups
+ const radioButtons = appElement.querySelectorAll('input[type="radio"]');
+ radioButtons.forEach((radio) => {
+ radio.name = `mode-radio-${packageName}`;
+ });
+
+ // Preselect the radio button based on the package name
+ const generateRadio = appElement.querySelector('#generate-mode');
+ const hackRadio = appElement.querySelector('#hack-mode');
+ const normalRadio = appElement.querySelector('#normal-mode');
+
+ if (appsWithExclamation.includes(packageName)) {
+ generateRadio.checked = true;
+ } else if (appsWithQuestion.includes(packageName)) {
+ hackRadio.checked = true;
+ } else {
+ normalRadio.checked = true;
+ }
+
const nameElement = appElement.querySelector(".name");
nameElement.innerHTML = `${appName || "Unknown App"}
${packageName}`; const checkbox = appElement.querySelector(".checkbox"); @@ -84,6 +106,7 @@ export async function fetchAppList() { }); console.log("App list with names and packages rendered successfully."); } catch (error) { + toast("Failed to fetch app list!"); console.error("Failed to fetch or render app list with names:", error); } floatingBtn.style.transform = 'translateY(0)'; @@ -91,6 +114,10 @@ export async function fetchAppList() { if (appListContainer.firstChild !== updateCard) { appListContainer.insertBefore(updateCard, appListContainer.firstChild); } + const checkboxes = appListContainer.querySelectorAll(".checkbox"); + setupRadioButtonListeners(); + setupCardHoldListener(); + updateCheckboxColor(); } // Function to save app with ! and ? then process target list @@ -122,4 +149,112 @@ function toggleableCheckbox() { checkbox.checked = !checkbox.checked; }); }); +} + +// Add eventlistener to mode button +function setupRadioButtonListeners() { + const radioButtons = appListContainer.querySelectorAll('input[type="radio"]'); + radioButtons.forEach((radioButton) => { + radioButton.addEventListener('change', (event) => { + const card = radioButton.closest(".card"); + const packageName = card.querySelector(".content").getAttribute("data-package"); + if (radioButton.id === 'generate-mode') { + if (!appsWithExclamation.includes(packageName)) { + appsWithExclamation.push(packageName); + } + const indexInQuestion = appsWithQuestion.indexOf(packageName); + if (indexInQuestion > -1) { + appsWithQuestion.splice(indexInQuestion, 1); + } + } else if (radioButton.id === 'hack-mode') { + if (!appsWithQuestion.includes(packageName)) { + appsWithQuestion.push(packageName); + } + const indexInExclamation = appsWithExclamation.indexOf(packageName); + if (indexInExclamation > -1) { + appsWithExclamation.splice(indexInExclamation, 1); + } + } else if (radioButton.id === 'normal-mode') { + const indexInExclamation = appsWithExclamation.indexOf(packageName); + if (indexInExclamation > -1) { + appsWithExclamation.splice(indexInExclamation, 1); + } + const indexInQuestion = appsWithQuestion.indexOf(packageName); + if (indexInQuestion > -1) { + appsWithQuestion.splice(indexInQuestion, 1); + } + } + updateCheckboxColor(); + console.log("Updated appsWithExclamation:", appsWithExclamation); + console.log("Updated appsWithQuestion:", appsWithQuestion); + }); + }); +} + +// Hold to open menu +function setupCardHoldListener() { + let holdTimeout; + function showMode(card) { + const modeElement = card.querySelector(".mode"); + if (modeElement) { + modeElement.style.display = "flex"; + modeOverlay.style.display = "flex"; + setTimeout(() => { + modeElement.classList.add('show'); + }, 10); + } + } + function hideAllModes() { + const allModeElements = appListContainer.querySelectorAll(".mode"); + allModeElements.forEach((modeElement) => { + modeElement.classList.remove('show'); + modeOverlay.style.display = "none"; + setTimeout(() => { + modeElement.style.display = "none"; + }, 200); + }); + } + + const cards = appListContainer.querySelectorAll(".card"); + cards.forEach((card) => { + card.addEventListener("pointerdown", () => { + const checkbox = card.querySelector(".checkbox"); + if (checkbox && checkbox.checked) { + holdTimeout = setTimeout(() => { + showMode(card); + }, 500); + } + }); + card.addEventListener("pointerup", () => clearTimeout(holdTimeout)); + card.addEventListener("pointercancel", () => clearTimeout(holdTimeout)); + }); + + // Close on click/scroll + document.addEventListener("click", (event) => { + if (!event.target.closest(".mode") || modeOverlay.contains(event.target)) { + hideAllModes(); + } else if (event.target.closest(".status-indicator")) { + setTimeout(() => { + hideAllModes(); + }, 200); + } + }); + window.addEventListener("scroll", hideAllModes); +} + +// Function to update card borders color +function updateCheckboxColor() { + const cards = appListContainer.querySelectorAll(".card"); + cards.forEach((card) => { + const packageName = card.querySelector(".content").getAttribute("data-package"); + const checkbox = card.querySelector(".checkbox"); + checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack"); + if (appsWithExclamation.includes(packageName)) { + checkbox.classList.add("checkbox-checked-generate"); + } else if (appsWithQuestion.includes(packageName)) { + checkbox.classList.add("checkbox-checked-hack"); + } else if (checkbox.checked) { + checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack"); + } + }); } \ No newline at end of file diff --git a/module/webui/scripts/language.js b/module/webui/scripts/language.js index 86fa773..4c586ca 100644 --- a/module/webui/scripts/language.js +++ b/module/webui/scripts/language.js @@ -1,4 +1,4 @@ -import { basePath, execCommand } from './main.js'; +import { basePath, execCommand, toast } from './main.js'; const languageButton = document.querySelector('.language-button'); const languageMenu = document.querySelector('.language-menu'); @@ -16,6 +16,7 @@ export async function initializeAvailableLanguages() { availableLanguages = multiLang.trim().split('\n'); generateLanguageMenu(); } catch (error) { + toast("Failed to get available langauge!"); console.error('Failed to fetch available languages:', error); availableLanguages = ['en-US']; } @@ -41,6 +42,7 @@ export async function loadTranslations(lang) { translations = await response.json(); applyTranslations(); } catch (error) { + toast(`Failed to load translation for ${lang}!`); console.error(`Error loading translations for ${lang}:`, error); if (lang !== 'en-US') { console.log("Falling back to English."); diff --git a/module/webui/scripts/main.js b/module/webui/scripts/main.js index 7ec252c..3da9ec6 100644 --- a/module/webui/scripts/main.js +++ b/module/webui/scripts/main.js @@ -33,7 +33,7 @@ async function getModuleVersion() { moduleVersion.textContent = version; } catch (error) { console.error("Failed to read version from module.prop:", error); - updateVersion("Error reading version from module.prop"); + updateVersion("Error"); } } @@ -55,6 +55,7 @@ async function refreshAppList() { updateCheck(); await execCommand(`[ -f ${basePath}common/tmp/exclude-list ] && rm -f "${basePath}common/tmp/exclude-list"`); } catch (error) { + toast("Failed!"); console.error("Error occurred:", error); } } @@ -77,6 +78,7 @@ async function checkMagisk() { console.log("not running on Magisk, leaving denylist element hidden."); } } catch (error) { + toast("Failed to check Magisk!"); console.error("Error while checking denylist conditions:", error); } } @@ -106,7 +108,7 @@ export async function linkRedirect(link) { try { await execCommand(`am start -a android.intent.action.VIEW -d ${link}`); } catch (error) { - toast('error!'); + toast("Failed!"); console.error('Error redirect link:', error); } } @@ -199,7 +201,7 @@ function applyRippleEffect() { const y = event.clientY - rect.top - size / 2; // Determine animation duration - let duration = 0.2 + (width / 800) * 0.5; + let duration = 0.2 + (width / 800) * 0.4; duration = Math.min(0.8, Math.max(0.2, duration)); // Set ripple styles @@ -289,6 +291,7 @@ updateCard.addEventListener('click', async () => { try { await execCommand('am start -a android.intent.action.VIEW -d https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest'); } catch (error) { + toast("Failed!"); console.error('Error opening GitHub Release link:', error); } }); diff --git a/module/webui/scripts/menu_option.js b/module/webui/scripts/menu_option.js index 2ef7366..b6cdcc0 100644 --- a/module/webui/scripts/menu_option.js +++ b/module/webui/scripts/menu_option.js @@ -1,4 +1,4 @@ -import { basePath, execCommand, showPrompt } from './main.js'; +import { basePath, execCommand, showPrompt, toast } from './main.js'; // Function to check or uncheck all app function toggleCheckboxes(shouldCheck) { @@ -32,6 +32,7 @@ document.getElementById("select-denylist").addEventListener("click", async () => }); console.log("Denylist apps selected successfully."); } catch (error) { + toast("Failed to read DenyList!"); console.error("Failed to select Denylist apps:", error); } }); @@ -65,6 +66,7 @@ document.getElementById("deselect-unnecessary").addEventListener("click", async }); console.log("Unnecessary apps deselected successfully."); } catch (error) { + toast("Failed!"); console.error("Failed to deselect unnecessary apps:", error); } }); diff --git a/module/webui/styles/applist.css b/module/webui/styles/applist.css index 65c742c..67b9aba 100644 --- a/module/webui/styles/applist.css +++ b/module/webui/styles/applist.css @@ -46,7 +46,7 @@ margin: 0 auto; margin-bottom: 10px; outline: none; - padding: 12px; + padding: 10px; width: calc(100% - 30px); max-width: 900px; transition: background-color 0.2s ease; @@ -58,6 +58,83 @@ display: flex; justify-content: space-between; align-items: center; + position: relative; +} + +.mode { + display: none; + flex-direction: row; + gap: 10px; + padding: 10px; + position: absolute; + left: 0; + right: 0; + margin: auto; + width: fit-content; + background-color: #B1B1B1; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + border: 1px solid #ccc; + border-radius: 12px; + opacity: 0; + transform: scale(0); + transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1); + z-index: 1200; +} + +.mode.show { + opacity: 1; + transform: scale(1); +} + +.mode-overlay { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: none; + z-index: 1100; +} + +.mode-switch { + position: relative; + display: inline-block; +} + +.mode-input { + opacity: 0; + position: absolute; + width: 0; + height: 0; +} + +.status-indicator { + display: flex; + justify-content: center; + align-items: center; + width: 30px; + height: 30px; + border-radius: 7px; + box-sizing: border-box; + transition: border-color 0.2s ease; + border: 3px solid transparent; +} + +#normal-indicator { + background-color: #007bff; +} + +#hack-indicator { + background-color: #FF8400; +} + +#generate-indicator { + background-color: #6C00FF; +} + +.mode-input[type="radio"]:checked ~ .mode-icon .status-indicator { + border-color: #fff; } .name { @@ -92,8 +169,8 @@ height: 100%; border: 2px solid #ccc; border-radius: 4px; - transition: border-color 1s ease, transform 0.3s ease, background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1); box-sizing: border-box; + transition: border-color 1s ease, transform 0.3s ease, background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1); } .tick-symbol { @@ -109,7 +186,21 @@ border-color: #007bff; background-color: #007bff; transition: border-color 0.1s ease; - animation: border-bounce 0.3s ease-out; + animation: checked-bounce 0.3s ease-out; +} + +.checkbox-checked-generate:checked + .custom-checkbox { + border-color: #6C00FF; + background-color: #6C00FF; +} + +.checkbox-checked-hack:checked + .custom-checkbox { + border-color: #FF8400; + background-color: #FF8400; +} + +.checkbox:not(:checked) + .custom-checkbox { + animation: unchecked-bounce 0.3s ease-out; } .checkbox:checked + .custom-checkbox .tick-symbol { @@ -117,7 +208,19 @@ opacity: 1; } -@keyframes border-bounce { +@keyframes checked-bounce { + 0% { + transform: scale(1); + } + 50% { + transform: scale(0.8); + } + 100% { + transform: scale(1); + } +} + +@keyframes unchecked-bounce { 0% { transform: scale(1); } @@ -137,4 +240,9 @@ .update-card { background-color: #4D4D4D; } + + .mode { + background-color: #343434; + border: 1px solid #6E6E6E; + } } \ No newline at end of file diff --git a/module/webui/styles/global.css b/module/webui/styles/global.css index cb2b333..5c4b559 100644 --- a/module/webui/styles/global.css +++ b/module/webui/styles/global.css @@ -15,7 +15,7 @@ body { bottom: 50px; left: 50%; transform: translateX(-50%); - z-index: 3; + z-index: 10; } .floating-btn {
${packageName}`; const checkbox = appElement.querySelector(".checkbox"); @@ -84,6 +106,7 @@ export async function fetchAppList() { }); console.log("App list with names and packages rendered successfully."); } catch (error) { + toast("Failed to fetch app list!"); console.error("Failed to fetch or render app list with names:", error); } floatingBtn.style.transform = 'translateY(0)'; @@ -91,6 +114,10 @@ export async function fetchAppList() { if (appListContainer.firstChild !== updateCard) { appListContainer.insertBefore(updateCard, appListContainer.firstChild); } + const checkboxes = appListContainer.querySelectorAll(".checkbox"); + setupRadioButtonListeners(); + setupCardHoldListener(); + updateCheckboxColor(); } // Function to save app with ! and ? then process target list @@ -122,4 +149,112 @@ function toggleableCheckbox() { checkbox.checked = !checkbox.checked; }); }); +} + +// Add eventlistener to mode button +function setupRadioButtonListeners() { + const radioButtons = appListContainer.querySelectorAll('input[type="radio"]'); + radioButtons.forEach((radioButton) => { + radioButton.addEventListener('change', (event) => { + const card = radioButton.closest(".card"); + const packageName = card.querySelector(".content").getAttribute("data-package"); + if (radioButton.id === 'generate-mode') { + if (!appsWithExclamation.includes(packageName)) { + appsWithExclamation.push(packageName); + } + const indexInQuestion = appsWithQuestion.indexOf(packageName); + if (indexInQuestion > -1) { + appsWithQuestion.splice(indexInQuestion, 1); + } + } else if (radioButton.id === 'hack-mode') { + if (!appsWithQuestion.includes(packageName)) { + appsWithQuestion.push(packageName); + } + const indexInExclamation = appsWithExclamation.indexOf(packageName); + if (indexInExclamation > -1) { + appsWithExclamation.splice(indexInExclamation, 1); + } + } else if (radioButton.id === 'normal-mode') { + const indexInExclamation = appsWithExclamation.indexOf(packageName); + if (indexInExclamation > -1) { + appsWithExclamation.splice(indexInExclamation, 1); + } + const indexInQuestion = appsWithQuestion.indexOf(packageName); + if (indexInQuestion > -1) { + appsWithQuestion.splice(indexInQuestion, 1); + } + } + updateCheckboxColor(); + console.log("Updated appsWithExclamation:", appsWithExclamation); + console.log("Updated appsWithQuestion:", appsWithQuestion); + }); + }); +} + +// Hold to open menu +function setupCardHoldListener() { + let holdTimeout; + function showMode(card) { + const modeElement = card.querySelector(".mode"); + if (modeElement) { + modeElement.style.display = "flex"; + modeOverlay.style.display = "flex"; + setTimeout(() => { + modeElement.classList.add('show'); + }, 10); + } + } + function hideAllModes() { + const allModeElements = appListContainer.querySelectorAll(".mode"); + allModeElements.forEach((modeElement) => { + modeElement.classList.remove('show'); + modeOverlay.style.display = "none"; + setTimeout(() => { + modeElement.style.display = "none"; + }, 200); + }); + } + + const cards = appListContainer.querySelectorAll(".card"); + cards.forEach((card) => { + card.addEventListener("pointerdown", () => { + const checkbox = card.querySelector(".checkbox"); + if (checkbox && checkbox.checked) { + holdTimeout = setTimeout(() => { + showMode(card); + }, 500); + } + }); + card.addEventListener("pointerup", () => clearTimeout(holdTimeout)); + card.addEventListener("pointercancel", () => clearTimeout(holdTimeout)); + }); + + // Close on click/scroll + document.addEventListener("click", (event) => { + if (!event.target.closest(".mode") || modeOverlay.contains(event.target)) { + hideAllModes(); + } else if (event.target.closest(".status-indicator")) { + setTimeout(() => { + hideAllModes(); + }, 200); + } + }); + window.addEventListener("scroll", hideAllModes); +} + +// Function to update card borders color +function updateCheckboxColor() { + const cards = appListContainer.querySelectorAll(".card"); + cards.forEach((card) => { + const packageName = card.querySelector(".content").getAttribute("data-package"); + const checkbox = card.querySelector(".checkbox"); + checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack"); + if (appsWithExclamation.includes(packageName)) { + checkbox.classList.add("checkbox-checked-generate"); + } else if (appsWithQuestion.includes(packageName)) { + checkbox.classList.add("checkbox-checked-hack"); + } else if (checkbox.checked) { + checkbox.classList.remove("checkbox-checked-generate", "checkbox-checked-hack"); + } + }); } \ No newline at end of file diff --git a/module/webui/scripts/language.js b/module/webui/scripts/language.js index 86fa773..4c586ca 100644 --- a/module/webui/scripts/language.js +++ b/module/webui/scripts/language.js @@ -1,4 +1,4 @@ -import { basePath, execCommand } from './main.js'; +import { basePath, execCommand, toast } from './main.js'; const languageButton = document.querySelector('.language-button'); const languageMenu = document.querySelector('.language-menu'); @@ -16,6 +16,7 @@ export async function initializeAvailableLanguages() { availableLanguages = multiLang.trim().split('\n'); generateLanguageMenu(); } catch (error) { + toast("Failed to get available langauge!"); console.error('Failed to fetch available languages:', error); availableLanguages = ['en-US']; } @@ -41,6 +42,7 @@ export async function loadTranslations(lang) { translations = await response.json(); applyTranslations(); } catch (error) { + toast(`Failed to load translation for ${lang}!`); console.error(`Error loading translations for ${lang}:`, error); if (lang !== 'en-US') { console.log("Falling back to English."); diff --git a/module/webui/scripts/main.js b/module/webui/scripts/main.js index 7ec252c..3da9ec6 100644 --- a/module/webui/scripts/main.js +++ b/module/webui/scripts/main.js @@ -33,7 +33,7 @@ async function getModuleVersion() { moduleVersion.textContent = version; } catch (error) { console.error("Failed to read version from module.prop:", error); - updateVersion("Error reading version from module.prop"); + updateVersion("Error"); } } @@ -55,6 +55,7 @@ async function refreshAppList() { updateCheck(); await execCommand(`[ -f ${basePath}common/tmp/exclude-list ] && rm -f "${basePath}common/tmp/exclude-list"`); } catch (error) { + toast("Failed!"); console.error("Error occurred:", error); } } @@ -77,6 +78,7 @@ async function checkMagisk() { console.log("not running on Magisk, leaving denylist element hidden."); } } catch (error) { + toast("Failed to check Magisk!"); console.error("Error while checking denylist conditions:", error); } } @@ -106,7 +108,7 @@ export async function linkRedirect(link) { try { await execCommand(`am start -a android.intent.action.VIEW -d ${link}`); } catch (error) { - toast('error!'); + toast("Failed!"); console.error('Error redirect link:', error); } } @@ -199,7 +201,7 @@ function applyRippleEffect() { const y = event.clientY - rect.top - size / 2; // Determine animation duration - let duration = 0.2 + (width / 800) * 0.5; + let duration = 0.2 + (width / 800) * 0.4; duration = Math.min(0.8, Math.max(0.2, duration)); // Set ripple styles @@ -289,6 +291,7 @@ updateCard.addEventListener('click', async () => { try { await execCommand('am start -a android.intent.action.VIEW -d https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest'); } catch (error) { + toast("Failed!"); console.error('Error opening GitHub Release link:', error); } }); diff --git a/module/webui/scripts/menu_option.js b/module/webui/scripts/menu_option.js index 2ef7366..b6cdcc0 100644 --- a/module/webui/scripts/menu_option.js +++ b/module/webui/scripts/menu_option.js @@ -1,4 +1,4 @@ -import { basePath, execCommand, showPrompt } from './main.js'; +import { basePath, execCommand, showPrompt, toast } from './main.js'; // Function to check or uncheck all app function toggleCheckboxes(shouldCheck) { @@ -32,6 +32,7 @@ document.getElementById("select-denylist").addEventListener("click", async () => }); console.log("Denylist apps selected successfully."); } catch (error) { + toast("Failed to read DenyList!"); console.error("Failed to select Denylist apps:", error); } }); @@ -65,6 +66,7 @@ document.getElementById("deselect-unnecessary").addEventListener("click", async }); console.log("Unnecessary apps deselected successfully."); } catch (error) { + toast("Failed!"); console.error("Failed to deselect unnecessary apps:", error); } }); diff --git a/module/webui/styles/applist.css b/module/webui/styles/applist.css index 65c742c..67b9aba 100644 --- a/module/webui/styles/applist.css +++ b/module/webui/styles/applist.css @@ -46,7 +46,7 @@ margin: 0 auto; margin-bottom: 10px; outline: none; - padding: 12px; + padding: 10px; width: calc(100% - 30px); max-width: 900px; transition: background-color 0.2s ease; @@ -58,6 +58,83 @@ display: flex; justify-content: space-between; align-items: center; + position: relative; +} + +.mode { + display: none; + flex-direction: row; + gap: 10px; + padding: 10px; + position: absolute; + left: 0; + right: 0; + margin: auto; + width: fit-content; + background-color: #B1B1B1; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + border: 1px solid #ccc; + border-radius: 12px; + opacity: 0; + transform: scale(0); + transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1); + z-index: 1200; +} + +.mode.show { + opacity: 1; + transform: scale(1); +} + +.mode-overlay { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: none; + z-index: 1100; +} + +.mode-switch { + position: relative; + display: inline-block; +} + +.mode-input { + opacity: 0; + position: absolute; + width: 0; + height: 0; +} + +.status-indicator { + display: flex; + justify-content: center; + align-items: center; + width: 30px; + height: 30px; + border-radius: 7px; + box-sizing: border-box; + transition: border-color 0.2s ease; + border: 3px solid transparent; +} + +#normal-indicator { + background-color: #007bff; +} + +#hack-indicator { + background-color: #FF8400; +} + +#generate-indicator { + background-color: #6C00FF; +} + +.mode-input[type="radio"]:checked ~ .mode-icon .status-indicator { + border-color: #fff; } .name { @@ -92,8 +169,8 @@ height: 100%; border: 2px solid #ccc; border-radius: 4px; - transition: border-color 1s ease, transform 0.3s ease, background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1); box-sizing: border-box; + transition: border-color 1s ease, transform 0.3s ease, background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1); } .tick-symbol { @@ -109,7 +186,21 @@ border-color: #007bff; background-color: #007bff; transition: border-color 0.1s ease; - animation: border-bounce 0.3s ease-out; + animation: checked-bounce 0.3s ease-out; +} + +.checkbox-checked-generate:checked + .custom-checkbox { + border-color: #6C00FF; + background-color: #6C00FF; +} + +.checkbox-checked-hack:checked + .custom-checkbox { + border-color: #FF8400; + background-color: #FF8400; +} + +.checkbox:not(:checked) + .custom-checkbox { + animation: unchecked-bounce 0.3s ease-out; } .checkbox:checked + .custom-checkbox .tick-symbol { @@ -117,7 +208,19 @@ opacity: 1; } -@keyframes border-bounce { +@keyframes checked-bounce { + 0% { + transform: scale(1); + } + 50% { + transform: scale(0.8); + } + 100% { + transform: scale(1); + } +} + +@keyframes unchecked-bounce { 0% { transform: scale(1); } @@ -137,4 +240,9 @@ .update-card { background-color: #4D4D4D; } + + .mode { + background-color: #343434; + border: 1px solid #6E6E6E; + } } \ No newline at end of file diff --git a/module/webui/styles/global.css b/module/webui/styles/global.css index cb2b333..5c4b559 100644 --- a/module/webui/styles/global.css +++ b/module/webui/styles/global.css @@ -15,7 +15,7 @@ body { bottom: 50px; left: 50%; transform: translateX(-50%); - z-index: 3; + z-index: 10; } .floating-btn {