diff --git a/module/action.sh b/module/action.sh index 0aa1c79..6d69128 100644 --- a/module/action.sh +++ b/module/action.sh @@ -5,6 +5,14 @@ MODDIR=/data/adb/modules/playintegrityfix version=$(grep "^version=" $MODDIR/module.prop | sed 's/version=//g') FORCE_PREVIEW=1 +# lets try to use tmpfs for processing +TEMPDIR="$MODDIR/temp" #fallback +[ -w /sbin ] && TEMPDIR="/sbin/playintegrityfix" +[ -w /debug_ramdisk ] && TEMPDIR="/debug_ramdisk/playintegrityfix" +[ -w /dev ] && TEMPDIR="/dev/playintegrityfix" +mkdir -p "$TEMPDIR" +cd "$TEMPDIR" + echo "[+] PlayIntegrityFix $version" echo "[+] $(basename "$0")" printf "\n\n" @@ -20,6 +28,8 @@ sleep_pause() { download_fail() { dl_domain=$(echo "$1" | awk -F[/:] '{print $4}') echo "$1" | grep -q "\.zip$" && return + # Clean up on download fail + rm -rf "$TEMPDIR" ping -c 1 -W 5 "$dl_domain" > /dev/null 2>&1 || { echo "[!] Unable to connect to $dl_domain, please check your internet connection and try again" sleep_pause @@ -52,14 +62,6 @@ set_random_beta() { PRODUCT=$(echo "$PRODUCT_LIST" | sed -n "$((rand_index + 1))p") } -# lets try to use tmpfs for processing -TEMPDIR="$MODDIR/temp" #fallback -[ -w /sbin ] && TEMPDIR="/sbin/playintegrityfix" -[ -w /debug_ramdisk ] && TEMPDIR="/debug_ramdisk/playintegrityfix" -[ -w /dev ] && TEMPDIR="/dev/playintegrityfix" -mkdir -p "$TEMPDIR" -cd "$TEMPDIR" - # Get latest Pixel Beta information download https://developer.android.com/about/versions PIXEL_VERSIONS_HTML BETA_URL=$(grep -o 'https://developer.android.com/about/versions/.*[0-9]"' PIXEL_VERSIONS_HTML | sort -ru | cut -d\" -f1 | head -n1) @@ -93,6 +95,12 @@ echo "$MODEL ($PRODUCT)" FINGERPRINT="$(strings PIXEL_ZIP_METADATA | grep -am1 'post-build=' | cut -d= -f2)" SECURITY_PATCH="$(strings PIXEL_ZIP_METADATA | grep -am1 'security-patch-level=' | cut -d= -f2)" +# Validate required field to prevent empty pif.json +if [ -z "$FINGERPRINT" ] || [ -z "$SECURITY_PATCH" ]; then + # link to download pixel rom metadata that skipped connection check due to ulimit + download_fail "https://dl.google.com" +fi + echo "- Dumping values to pif.json ..." cat < { @@ -34,14 +35,12 @@ function applyButtonEventListeners() { console.error('Failed to switch fingerprint type:', error); } }); + clearButton.addEventListener('click', () => { - const output = document.querySelector('.output-terminal-content'); - output.innerHTML = ''; + terminal.innerHTML = ''; currentFontSize = 14; updateFontSize(currentFontSize); }); - - const terminal = document.querySelector('.output-terminal-content'); terminal.addEventListener('touchstart', (e) => { if (e.touches.length === 2) { @@ -49,7 +48,6 @@ function applyButtonEventListeners() { initialPinchDistance = getDistance(e.touches[0], e.touches[1]); } }, { passive: false }); - terminal.addEventListener('touchmove', (e) => { if (e.touches.length === 2) { e.preventDefault(); @@ -66,7 +64,6 @@ function applyButtonEventListeners() { initialPinchDistance = currentDistance; } }, { passive: false }); - terminal.addEventListener('touchend', () => { initialPinchDistance = null; }); @@ -147,11 +144,29 @@ async function runAction() { actionRunning = false; } -// Function to apply ripple effect +/** + * Simulate MD3 ripple animation + * Usage: class="ripple-element" style="position: relative; overflow: hidden;" + * Note: Require background-color to work properly + * @return {void} + */ function applyRippleEffect() { document.querySelectorAll('.ripple-element').forEach(element => { if (element.dataset.rippleListener !== "true") { - element.addEventListener("pointerdown", function (event) { + element.addEventListener("pointerdown", async (event) => { + // Pointer up event + 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); + const ripple = document.createElement("span"); ripple.classList.add("ripple"); @@ -176,7 +191,6 @@ function applyRippleEffect() { // 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; @@ -185,19 +199,8 @@ function applyRippleEffect() { }; ripple.style.backgroundColor = isDarkColor(bgColor) ? "rgba(255, 255, 255, 0.2)" : ""; - // Append ripple and handle cleanup + // Append ripple element.appendChild(ripple); - 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); }); element.dataset.rippleListener = "true"; } @@ -213,27 +216,6 @@ async function checkMMRL() { } catch (error) { console.log("Error setting status bars theme:", error) } - - // Request API permission, supported version: 33045+ - try { - $playintegrityfix.requestAdvancedKernelSUAPI(); - } catch (error) { - console.log("Error requesting API:", error); - } - try { - await execCommand("whoami"); - } catch (error) { - appendToOutput(""); - appendToOutput("[!] Please allow permission in MMRL settings"); - appendToOutput("[-] Settings"); - appendToOutput("[-] Security"); - appendToOutput("[-] Allow JavaScript API"); - appendToOutput("[-] Play Integrity Fix"); - appendToOutput("[-] Enable Allow Advanced KernelSU API"); - appendToOutput(""); - } - } else { - console.log("Not running in MMRL environment."); } } diff --git a/module/webroot/styles.css b/module/webroot/styles.css index b79458d..d33ff34 100644 --- a/module/webroot/styles.css +++ b/module/webroot/styles.css @@ -1,23 +1,61 @@ -@font-face { - font-family: 'Mono'; - src: url('assets/RobotoMono-Regular.ttf') format('truetype'); - font-weight: normal; - font-style: normal; +@import url('https://mui.kernelsu.org/mmrl/insets.css'); +@import url('https://mui.kernelsu.org/mmrl/colors.css'); + +:root { + /* window inset */ + --top-inset: var(--window-inset-top, 0px); + --bottom-inset: var(--window-inset-bottom, 0px); + + /* Background colors */ + --bg-primary: var(--background, #EDEDED); + --bg-secondary: var(--tonalSurface, #fff); + --bg-input: var(--surfaceBright, #F5F5F5); + + /* Text colors */ + --text-constant: var(--onSurface, #000); + --text-primary: var(--onSurface, #000); + --text-muted: #757575; + + /* Border colors */ + --border-color: var(--outlineVariant, #ccc); + + /* Button colors */ + --btn-primary: var(--primary, #007bff); + --btn-primary-text: var(--onPrimary, #fff); +} + +@media (prefers-color-scheme: dark) { + :root { + /* Background colors */ + --bg-primary: var(--background, #151515); + --bg-secondary: var(--tonalSurface, #292929); + --bg-input: var(--surfaceBright, #1b1b1b); + + /* Text colors */ + --text-constant: var(--onSurface, #eee);; + --text-primary: var(--onSurface, #eee); + --text-muted: #C2C2C2; + + /* Border colors */ + --border-color: var(--outlineVariant, #636363); + } } body { - background-color: #F5F5F5; - padding-top: var(--window-inset-top); - padding-bottom: var(--window-inset-bottom); + color: var(--text-primary); + background-color: var(--bg-primary); + padding-top: var(--top-inset); + padding-bottom: var(--bottom-inset); + margin: 0; } .content { - padding-bottom: 10px; + padding-bottom: 30px; display: flex; flex-direction: column; align-items: center; - height: 90vh; - gap: 15px; + height: calc(100vh - var(--top-inset) - var(--bottom-inset)); + box-sizing: border-box; } .header { @@ -28,22 +66,23 @@ body { width: calc(85vw + 30px); max-width: 800px; flex-shrink: 0; - background-color: #fff; + background-color: var(--bg-secondary); border: none; border-radius: 15px; box-sizing: border-box; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.2); overflow: hidden; } .toggle-list { display: flex; align-items: center; - background-color: #fff; - padding: 10px 20px; + background-color: var(--bg-secondary); + min-height: 25px; + padding: 8px 20px; white-space: nowrap; text-align: left; - border-bottom: 1px solid #ccc; + border-bottom: 1px solid var(--border-color);; position: relative; overflow: hidden; } @@ -81,7 +120,7 @@ body { left: 0; right: 0; bottom: 0; - background-color: #ccc; + background-color: var(--border-color); -webkit-transition: .4s; transition: .4s; } @@ -93,19 +132,20 @@ body { width: 19px; left: 3px; bottom: 3px; - background-color: white; + background-color: var(--text-muted); transition: .4s; } input:checked+.slider { - background-color: #007bff; + background-color: var(--btn-primary); } input:focus+.slider { - box-shadow: 0 0 1px #007bff; + box-shadow: 0 0 1px var(--btn-primary); } input:checked+.slider:before { + background-color: var(--btn-primary-text); transform: translateX(15px); } @@ -121,10 +161,11 @@ input:checked+.slider:before { width: calc(85vw + 30px); max-width: 800px; flex-grow: 1; - background-color: #fff; + background-color: var(--bg-input); box-sizing: border-box; border-radius: 15px; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.2); + margin-top: 15px; overflow: hidden; } @@ -133,27 +174,27 @@ input:checked+.slider:before { padding: 5px 15px; font-size: 14px; justify-content: space-between; - background-color: #E0E0E0; - color: #333; + background-color: var(--bg-secondary); + color: var(--text-muted); user-select: none; } .clear-terminal { display: flex; align-items: center; -} -.clear-terminal svg { - fill: #333; + svg { + fill: var(--text-muted);; + } } .output-terminal-content { - font-family: 'Mono'; + font-family: monospace; font-size: 14px; padding: 10px; width: calc(100% - 20px); height: calc(100% - 50px); - overflow-y: scroll; + overflow-y: auto; } .output-content { @@ -188,37 +229,4 @@ input:checked+.slider:before { to { transform: scale(3); } -} - -@media (prefers-color-scheme: dark) { - body { - background-color: #121212; - color: #fff; - } - - .toggle-list, - .button-box, - .output-terminal-header { - background-color: #343434; - } - - .output-terminal-header { - color: #ccc; - } - - .clear-terminal svg { - fill: #ccc; - } - - .output-terminal { - background-color: #232323; - } - - .toggle-list { - border-bottom: 1px solid #6E6E6E; - } - - .slider { - background-color: #6E6E6E; - } } \ No newline at end of file