complete animation

- adjust position of prompt and save button on MMRL
- complete ripple animation
- new checkbox animation
This commit is contained in:
KOWX712
2024-12-28 14:54:38 +08:00
parent 1861e43a81
commit 940d809ac5
10 changed files with 207 additions and 100 deletions

View File

@@ -32,7 +32,7 @@
<div class="language-dropdown">
<button class="language-button">
<i class="language-icon">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-155.5t86-127Q252-817 325-848.5T480-880q83 0 155.5 31.5t127 86q54.5 54.5 86 127T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127 86T480-80Zm0-82q26-36 45-75t31-83H404q12 44 31 83t45 75Zm-104-16q-18-33-31.5-68.5T322-320H204q29 50 72.5 87t99.5 55Zm208 0q56-18 99.5-55t72.5-87H638q-9 38-22.5 73.5T584-178ZM170-400h136q-3-20-4.5-39.5T300-480q0-21 1.5-40.5T306-560H170q-5 20-7.5 39.5T160-480q0 21 2.5 40.5T170-400Zm216 0h188q3-20 4.5-39.5T580-480q0-21-1.5-40.5T574-560H386q-3 20-4.5 39.5T380-480q0 21 1.5 40.5T386-400Zm268 0h136q5-20 7.5-39.5T800-480q0-21-2.5-40.5T790-560H654q3 20 4.5 39.5T660-480q0 21-1.5 40.5T654-400Zm-16-240h118q-29-50-72.5-87T584-782q18 33 31.5 68.5T638-640Zm-234 0h152q-12-44-31-83t-45-75q-26 36-45 75t-31 83Zm-200 0h118q9-38 22.5-73.5T376-782q-56 18-99.5 55T204-640Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="22px" viewBox="0 -960 960 960" width="22px"><path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-155.5t86-127Q252-817 325-848.5T480-880q83 0 155.5 31.5t127 86q54.5 54.5 86 127T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127 86T480-80Zm0-82q26-36 45-75t31-83H404q12 44 31 83t45 75Zm-104-16q-18-33-31.5-68.5T322-320H204q29 50 72.5 87t99.5 55Zm208 0q56-18 99.5-55t72.5-87H638q-9 38-22.5 73.5T584-178ZM170-400h136q-3-20-4.5-39.5T300-480q0-21 1.5-40.5T306-560H170q-5 20-7.5 39.5T160-480q0 21 2.5 40.5T170-400Zm216 0h188q3-20 4.5-39.5T580-480q0-21-1.5-40.5T574-560H386q-3 20-4.5 39.5T380-480q0 21 1.5 40.5T386-400Zm268 0h136q5-20 7.5-39.5T800-480q0-21-2.5-40.5T790-560H654q3 20 4.5 39.5T660-480q0 21-1.5 40.5T654-400Zm-16-240h118q-29-50-72.5-87T584-782q18 33 31.5 68.5T638-640Zm-234 0h152q-12-44-31-83t-45-75q-26 36-45 75t-31 83Zm-200 0h118q9-38 22.5-73.5T376-782q-56 18-99.5 55T204-640Z"/></svg>
</i>
</button>
<div class="language-menu"></div>
@@ -95,7 +95,14 @@
<div class="card" id="card">
<div class="content" data-package="">
<p class="name"></p>
<input type="checkbox" class="checkbox">
<div class="checkbox-wrapper">
<input type="checkbox" class="checkbox" id="checkbox1" disabled />
<label for="checkbox1" class="custom-checkbox">
<span class="tick-symbol">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -3 26 26" width="16px" height="16px" fill="#fff"><path d="M 22.566406 4.730469 L 20.773438 3.511719 C 20.277344 3.175781 19.597656 3.304688 19.265625 3.796875 L 10.476563 16.757813 L 6.4375 12.71875 C 6.015625 12.296875 5.328125 12.296875 4.90625 12.71875 L 3.371094 14.253906 C 2.949219 14.675781 2.949219 15.363281 3.371094 15.789063 L 9.582031 22 C 9.929688 22.347656 10.476563 22.613281 10.96875 22.613281 C 11.460938 22.613281 11.957031 22.304688 12.277344 21.839844 L 22.855469 6.234375 C 23.191406 5.742188 23.0625 5.066406 22.566406 4.730469 Z"/></svg>
</span>
</label>
</div>
</div>
</div>
</div>
@@ -165,7 +172,9 @@
<!-- BootHash Input Overlay -->
<div id="boot-hash-overlay" class="boot-hash-overlay"></div>
<div id="boot-hash-card" class="boot-hash-card">
<textarea id="boot-hash-input" class="input-box" placeholder="Paste your verified Boot Hash here" data-i18n="reset_vbmeta.boot_hash_input_placeholder"></textarea>
<div class="boot-hash-value">
<textarea id="boot-hash-input" class="input-box" placeholder="Paste your verified Boot Hash here" data-i18n="reset_vbmeta.boot_hash_input_placeholder"></textarea>
</div>
<div class="button-container">
<button id="boot-hash-save-button" class="boot-hash-save-button" data-i18n="reset_vbmeta.boot_hash_save_button"></button>
</div>

View File

@@ -1,4 +1,4 @@
import { execCommand } from './main.js';
import { execCommand, linkRedirect } from './main.js';
const telegramLink = document.getElementById('telegram');
const githubLink = document.getElementById('github');
@@ -38,17 +38,9 @@ document.getElementById("about").addEventListener("click", () => {
});
// Event listener for link redirect
telegramLink.addEventListener('click', async () => {
try {
await execCommand('am start -a android.intent.action.VIEW -d https://t.me/kowchannel');
} catch (error) {
console.error('Error opening Telegram link:', error);
}
telegramLink.addEventListener('click', function() {
linkRedirect('https://t.me/kowchannel');
});
githubLink.addEventListener('click', async () => {
try {
await execCommand('am start -a android.intent.action.VIEW -d https://github.com/KOWX712/Tricky-Addon-Update-Target-List');
} catch (error) {
console.error('Error opening GitHub link:', error);
}
githubLink.addEventListener('click', function() {
linkRedirect('https://github.com/KOWX712/Tricky-Addon-Update-Target-List');
});

View File

@@ -86,7 +86,7 @@ export async function fetchAppList() {
} catch (error) {
console.error("Failed to fetch or render app list with names:", error);
}
floatingBtn.style.transform = "translateY(-120px)";
floatingBtn.style.transform = 'translateY(0)';
toggleableCheckbox();
if (appListContainer.firstChild !== updateCard) {
appListContainer.insertBefore(updateCard, appListContainer.firstChild);
@@ -119,9 +119,7 @@ function toggleableCheckbox() {
const content = card.querySelector(".content");
const checkbox = content.querySelector(".checkbox");
content.addEventListener("click", (event) => {
if (event.target !== checkbox) {
checkbox.checked = !checkbox.checked;
}
checkbox.checked = !checkbox.checked;
});
});
}

View File

@@ -12,13 +12,14 @@ export const noConnection = document.querySelector('.no-connection');
// Loading, Save and Prompt Elements
const loadingIndicator = document.querySelector('.loading');
const prompt = document.getElementById('prompt');
const floatingCard = document.querySelector('.floating-card');
export const floatingBtn = document.querySelector('.floating-btn');
export const basePath = "set-path";
export const appsWithExclamation = [];
export const appsWithQuestion = [];
const ADDITIONAL_APPS = [ "com.google.android.gms", "io.github.vvb2060.keyattestation", "io.github.vvb2060.mahoshojo", "icu.nullptr.nativetest" ];
const rippleClasses = ['.language-option', '.menu-button', '.menu-options li', '.search-card', '.card', '.update-card', '.link-icon', '.floating-btn', '.uninstall-container'];
const rippleClasses = ['.language-option', '.menu-button', '.menu-options li', '.search-card', '.card', '.update-card', '.link-icon', '.floating-btn', '.uninstall-container', '.boot-hash-save-button', '.boot-hash-value'];
// Variables
let e = 0;
@@ -41,7 +42,7 @@ async function refreshAppList() {
isRefreshing = true;
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(0)';
hideFloatingBtn();
searchInput.value = '';
clearBtn.style.display = "none";
appListContainer.innerHTML = '';
@@ -89,15 +90,27 @@ export function showPrompt(key, isSuccess = true) {
clearTimeout(window.promptTimeout);
}
setTimeout(() => {
prompt.classList.add('visible');
prompt.classList.remove('hidden');
if (typeof ksu !== 'undefined' && ksu.mmrl) {
prompt.style.transform = 'translateY(calc((var(--window-inset-bottom) + 60%) * -1))';
} else {
prompt.style.transform = 'translateY(-60%)';
}
window.promptTimeout = setTimeout(() => {
prompt.classList.remove('visible');
prompt.classList.add('hidden');
prompt.style.transform = 'translateY(100%)';
}, 3000);
}, 200);
}
// Function to redirect link on external browser
export async function linkRedirect(link) {
try {
await execCommand(`am start -a android.intent.action.VIEW -d ${link}`);
} catch (error) {
toast('error!');
console.error('Error redirect link:', error);
}
}
// Save configure and preserve ! and ? in target.txt
document.getElementById("save").addEventListener("click", async () => {
const selectedApps = Array.from(appListContainer.querySelectorAll(".checkbox:checked"))
@@ -155,6 +168,16 @@ function adjustHeaderForMMRL() {
const insetTopValue = parseInt(insetTop, 10);
searchMenuContainer.style.top = `${insetTopValue + 40}px`;
headerBlock.style.display = 'block';
floatingCard.style.bottom = 'calc(var(--window-inset-bottom) + 50px)';
}
}
// Funtion to adapt floating button hide in MMRL
function hideFloatingBtn() {
if (typeof ksu !== 'undefined' && ksu.mmrl) {
floatingBtn.style.transform = 'translateY(calc(var(--window-inset-bottom) + 120px))';
} else {
floatingBtn.style.transform = 'translateY(120px)';
}
}
@@ -162,26 +185,55 @@ function adjustHeaderForMMRL() {
function applyRippleEffect() {
rippleClasses.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
element.addEventListener("click", function(event) {
element.addEventListener("pointerdown", function (event) {
if (isScrolling) return;
const ripple = document.createElement("span");
ripple.classList.add("ripple");
// Calculate ripple size and position
const rect = element.getBoundingClientRect();
const width = rect.width;
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
let duration = 0.3 + (width / 800) * 0.5;
// Determine animation duration
let duration = 0.2 + (width / 800) * 0.5;
duration = Math.min(0.8, Math.max(0.2, duration));
// Set ripple styles
ripple.style.width = ripple.style.height = `${size}px`;
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
ripple.style.animationDuration = `${duration}s`;
ripple.style.transition = `opacity ${duration}s ease`;
// Adaptive color
const computedStyle = window.getComputedStyle(element);
const bgColor = computedStyle.backgroundColor || "rgba(0, 0, 0, 0)";
const textColor = computedStyle.color;
const isDarkColor = (color) => {
const rgb = color.match(/\d+/g);
if (!rgb) return false;
const [r, g, b] = rgb.map(Number);
return (r * 0.299 + g * 0.587 + b * 0.114) < 128; // Luma formula
};
ripple.style.backgroundColor = isDarkColor(bgColor) ? "rgba(255, 255, 255, 0.2)" : "";
// Append ripple and handle cleanup
element.appendChild(ripple);
ripple.addEventListener("animationend", () => {
ripple.remove();
});
const handlePointerUp = () => {
ripple.classList.add("end");
setTimeout(() => {
ripple.classList.remove("end");
ripple.remove();
}, duration * 1000);
element.removeEventListener("pointerup", handlePointerUp);
element.removeEventListener("pointercancel", handlePointerUp);
};
element.addEventListener("pointerup", handlePointerUp);
element.addEventListener("pointercancel", handlePointerUp);
});
});
});
@@ -189,19 +241,26 @@ function applyRippleEffect() {
// Scroll event
let lastScrollY = window.scrollY;
let isScrolling = false;
let scrollTimeout;
const scrollThreshold = 40;
window.addEventListener('scroll', () => {
isScrolling = true;
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
isScrolling = false;
}, 200);
if (isRefreshing) return;
if (window.scrollY > lastScrollY && window.scrollY > scrollThreshold) {
title.style.transform = 'translateY(-80px)';
headerBlock.style.transform = 'translateY(-80px)';
searchMenuContainer.style.transform = 'translateY(-40px)';
floatingBtn.style.transform = 'translateY(0)';
hideFloatingBtn();
} else if (window.scrollY < lastScrollY) {
headerBlock.style.transform = 'translateY(0)';
title.style.transform = 'translateY(0)';
searchMenuContainer.style.transform = 'translateY(0)';
floatingBtn.style.transform = 'translateY(-120px)';
floatingBtn.style.transform = 'translateY(0)';
}
lastScrollY = window.scrollY;
});
@@ -254,4 +313,9 @@ export async function execCommand(command) {
reject(error);
}
});
}
// Function to toast message
export function toast(message) {
ksu.toast(message);
}

View File

@@ -53,14 +53,17 @@
#module_name_line1 {
font-size: 26px;
user-select: none;
}
#module_name_line2 {
font-size: 22px;
user-select: none;
}
#authored {
font-size: 14px;
user-select: none;
}
#disclaimer {
@@ -70,6 +73,7 @@
#acknowledgment {
font-weight: bold;
font-size: 18px;
user-select: none;
}
.link-icon {
@@ -95,6 +99,7 @@
background-color: #38A7ED;
color: #fff;
fill: #fff;
user-select: none;
}
#github {
@@ -103,6 +108,7 @@
background-color: #606060;
color: #fff;
fill: #fff;
user-select: none;
}
#link-text {

View File

@@ -67,11 +67,66 @@
max-width: calc(100% - 30px);
overflow-wrap: break-word;
word-break: break-word;
user-select: none;
}
.checkbox-wrapper {
position: relative;
display: inline-block;
width: 20px;
height: 20px;
margin-left: auto;
}
.checkbox {
margin-left: auto;
transform: scale(1.15);
opacity: 0;
position: absolute;
width: 0;
height: 0;
}
.custom-checkbox {
position: relative;
display: inline-block;
width: 100%;
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;
}
.tick-symbol {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
opacity: 0;
transition: transform 0.2s ease-out, opacity 0.3s ease;
}
.checkbox:checked + .custom-checkbox {
border-color: #007bff;
background-color: #007bff;
transition: border-color 0.1s ease;
animation: border-bounce 0.3s ease-out;
}
.checkbox:checked + .custom-checkbox .tick-symbol {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
@keyframes border-bounce {
0% {
transform: scale(1);
}
50% {
transform: scale(0.8);
}
100% {
transform: scale(1);
}
}
@media (prefers-color-scheme: dark) {

View File

@@ -42,15 +42,30 @@
opacity: 1;
}
.input-box {
width: calc(100% - 20px);
.boot-hash-value {
width: 100%;
height: 100px;
resize: none;
padding: 9px;
font-size: 16px;
background-color: #FFF;
border: 1px solid #ccc;
border-radius: 10px;
box-sizing: border-box;
position: relative;
overflow: hidden;
}
.input-box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 10px;
font-size: 16px;
border-radius: 9px;
box-sizing: border-box;
background-color: transparent;
outline-color: #007bff;
}
.button-container {
@@ -67,11 +82,9 @@
background-color: #007bff;
color: white;
margin-left: auto;
transition: background-color 0.2s ease;
}
.boot-hash-save-button:active {
background-color: #003d80;
position: relative;
overflow: hidden;
user-select: none;
}
@media (prefers-color-scheme: dark) {
@@ -81,6 +94,9 @@
.input-box {
color: #fff;
}
.boot-hash-value {
background-color: #343434;
border: 1px solid #6E6E6E;
}

View File

@@ -12,7 +12,7 @@ body {
display: flex;
justify-content: center;
position: fixed;
bottom: -70px;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
@@ -30,9 +30,10 @@ body {
padding: 10px 20px;
font-size: 20px;
font-weight: bold;
transition: transform 0.3s ease-in-out, background-color 0.2s ease;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
border-radius: 50px 50px;
overflow: hidden;
user-select: none;
}
.prompt {
@@ -49,49 +50,13 @@ body {
width: auto;
max-width: calc(100% - 40px);
transform: translateY(100%);
transition: transform 0.5s ease;
}
.prompt.visible {
animation: YbounceIn 0.4s forwards;
}
.prompt.hidden {
animation: YbounceOut 0.4s forwards;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.prompt.error {
background-color: #f44336;
}
@keyframes YbounceIn {
0% {
transform: translateY(100%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(-60%);
}
}
@keyframes YbounceOut {
0% {
transform: translateY(-60%);
}
50% {
transform: translateY(-80%);
}
100% {
transform: translateY(100%);
}
}
.loading {
position: fixed;
top: 0;
@@ -130,6 +95,7 @@ body {
background-color: #CE0000;
white-space: nowrap;
overflow: hidden;
user-select: none;
}
.uninstall-container i {
@@ -150,15 +116,19 @@ body {
position: absolute;
border-radius: 50%;
transform: scale(0);
animation: ripple-animation ease-out;
opacity: 1;
animation: ripple-animation ease-out forwards;
pointer-events: none;
background: rgba(0, 0, 0, 0.2);
}
.ripple.end {
opacity: 0;
}
@keyframes ripple-animation {
to {
transform: scale(4);
opacity: 0;
transform: scale(3);
}
}
@@ -167,9 +137,4 @@ body {
background-color: #121212;
color: #fff;
}
.ripple {
background: rgba(255, 255, 255, 0.2);
}
}

View File

@@ -8,12 +8,13 @@
width: calc(100% - 10px);
max-width: 1100px;
background-color: #F5F5F5;
transition: transform 0.3s ease;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
z-index: 1100;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
user-select: none;
}
.header-block {
@@ -24,7 +25,7 @@
left: 0;
width: 100%;
z-index: 1100;
transition: transform 0.3s ease;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
height: var(--window-inset-top);
}
@@ -74,7 +75,7 @@
max-height: calc(100vh - 50px);
overflow-y: auto;
transform: translateY(-10px);
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.language-menu.show {
@@ -97,6 +98,7 @@
transition: background-color 0.2s ease;
position: relative;
overflow: hidden;
user-select: none;
}
.language-option:last-child {
@@ -133,7 +135,7 @@
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
transition: opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.help-overlay.show {
@@ -174,6 +176,7 @@
.help-content p {
font-size: 26px;
user-select: none;
}
.help-content ul {

View File

@@ -6,7 +6,7 @@
width: calc(100% - 20px);
max-width: 1100px;
z-index: 1000;
transition: transform 0.3s ease;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
margin-left: auto;
margin-right: auto;
left: 0;
@@ -86,7 +86,7 @@
display: inline-block;
fill: #000;
transform: rotate(0deg);
transition: transform 0.2s ease;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.menu-icon.menu-open {
@@ -108,10 +108,10 @@
max-height: calc(100vh - 120px);
overflow-y: auto;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transform: translateX(120%);
transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease;
transition: all 0.4s cubic-bezier(0.22, 1, 0.36, 1);
user-select: none;
}
#select-denylist {
@@ -120,7 +120,6 @@
.menu-options.visible {
display: block;
opacity: 1;
visibility: visible;
transform: translateX(0);
}