mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-04-28 12:03:08 -07:00
f
This commit is contained in:
@@ -21,6 +21,7 @@ additional-js = [
|
|||||||
"theme/pagetoc.js",
|
"theme/pagetoc.js",
|
||||||
"theme/ht_searcher.js",
|
"theme/ht_searcher.js",
|
||||||
"theme/sponsor.js",
|
"theme/sponsor.js",
|
||||||
|
"theme/motion.js",
|
||||||
"theme/ai.js"
|
"theme/ai.js"
|
||||||
]
|
]
|
||||||
no-section-label = true
|
no-section-label = true
|
||||||
|
|||||||
@@ -70,6 +70,49 @@ body {
|
|||||||
animation: float-particle 16s infinite;
|
animation: float-particle 16s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.motion-paused .bg-animation,
|
||||||
|
html.motion-paused .grid-overlay,
|
||||||
|
html.motion-paused .particle,
|
||||||
|
html.motion-paused #ht-ai-btn {
|
||||||
|
animation-play-state: paused !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.motion-reduced .bg-animation,
|
||||||
|
html.motion-reduced .grid-overlay,
|
||||||
|
html.motion-reduced .particles {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.motion-reduced .particle,
|
||||||
|
html.motion-reduced #ht-ai-btn {
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.motion-reduced #ht-ai-btn {
|
||||||
|
background: linear-gradient(45deg, #b31328, #d42d3f) !important;
|
||||||
|
background-size: auto !important;
|
||||||
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.bg-animation,
|
||||||
|
.grid-overlay,
|
||||||
|
.particles {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.particle,
|
||||||
|
#ht-ai-btn {
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ht-ai-btn {
|
||||||
|
background: linear-gradient(45deg, #b31328, #d42d3f) !important;
|
||||||
|
background-size: auto !important;
|
||||||
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.3) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes bg-drift {
|
@keyframes bg-drift {
|
||||||
0% { transform: translate3d(0, 0, 0) scale(1); }
|
0% { transform: translate3d(0, 0, 0) scale(1); }
|
||||||
100% { transform: translate3d(-2%, 1%, 0) scale(1.04); }
|
100% { transform: translate3d(-2%, 1%, 0) scale(1.04); }
|
||||||
|
|||||||
187
theme/motion.js
Normal file
187
theme/motion.js
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
(function () {
|
||||||
|
var docEl = document.documentElement;
|
||||||
|
var REDUCED_CLASS = "motion-reduced";
|
||||||
|
var PAUSED_CLASS = "motion-paused";
|
||||||
|
var motionState = { mode: "normal", reason: "default" };
|
||||||
|
|
||||||
|
function setMode(mode, reason) {
|
||||||
|
var nextMode = mode === "reduced" ? "reduced" : "normal";
|
||||||
|
if (motionState.mode === nextMode && motionState.reason === reason) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
motionState.mode = nextMode;
|
||||||
|
motionState.reason = reason || motionState.reason;
|
||||||
|
docEl.classList.toggle(REDUCED_CLASS, nextMode === "reduced");
|
||||||
|
docEl.dataset.motionMode = nextMode;
|
||||||
|
window.__hacktricksMotion = {
|
||||||
|
mode: motionState.mode,
|
||||||
|
reason: motionState.reason,
|
||||||
|
shouldReduceMotion: function () {
|
||||||
|
return motionState.mode === "reduced";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.dispatchEvent(new CustomEvent("hacktricks:motionchange", {
|
||||||
|
detail: {
|
||||||
|
mode: motionState.mode,
|
||||||
|
reason: motionState.reason
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateVisibilityState() {
|
||||||
|
docEl.classList.toggle(PAUSED_CLASS, document.visibilityState === "hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMediaQuery() {
|
||||||
|
if (typeof window.matchMedia !== "function") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return window.matchMedia("(prefers-reduced-motion: reduce)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDeviceHints() {
|
||||||
|
var hints = {
|
||||||
|
lowCapability: false,
|
||||||
|
hardwareConcurrency: null,
|
||||||
|
deviceMemory: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof navigator.hardwareConcurrency === "number") {
|
||||||
|
hints.hardwareConcurrency = navigator.hardwareConcurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof navigator.deviceMemory === "number") {
|
||||||
|
hints.deviceMemory = navigator.deviceMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
hints.lowCapability =
|
||||||
|
(hints.hardwareConcurrency !== null && hints.hardwareConcurrency <= 4) ||
|
||||||
|
(hints.deviceMemory !== null && hints.deviceMemory <= 4);
|
||||||
|
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
function monitorAnimationHealth() {
|
||||||
|
if (
|
||||||
|
document.visibilityState === "hidden" ||
|
||||||
|
typeof window.requestAnimationFrame !== "function"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaQuery = getMediaQuery();
|
||||||
|
if (mediaQuery && mediaQuery.matches) {
|
||||||
|
setMode("reduced", "prefers-reduced-motion");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hints = getDeviceHints();
|
||||||
|
var perfState = {
|
||||||
|
frameCount: 0,
|
||||||
|
firstFrameAt: 0,
|
||||||
|
longTaskTime: 0,
|
||||||
|
worstFrameGap: 0
|
||||||
|
};
|
||||||
|
var observer = null;
|
||||||
|
|
||||||
|
if (typeof PerformanceObserver === "function") {
|
||||||
|
try {
|
||||||
|
observer = new PerformanceObserver(function (list) {
|
||||||
|
list.getEntries().forEach(function (entry) {
|
||||||
|
perfState.longTaskTime += entry.duration;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observer.observe({ type: "longtask", buffered: true });
|
||||||
|
} catch (error) {
|
||||||
|
observer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetDuration = 2500;
|
||||||
|
var fpsThreshold = hints.lowCapability ? 50 : 42;
|
||||||
|
var longTaskThreshold = hints.lowCapability ? 160 : 240;
|
||||||
|
var frameGapThreshold = hints.lowCapability ? 90 : 120;
|
||||||
|
var lastFrameAt = 0;
|
||||||
|
|
||||||
|
function finish(now) {
|
||||||
|
if (observer) {
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
var elapsed = now - perfState.firstFrameAt;
|
||||||
|
if (elapsed <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fps = (perfState.frameCount * 1000) / elapsed;
|
||||||
|
var shouldReduce =
|
||||||
|
fps < fpsThreshold ||
|
||||||
|
perfState.longTaskTime > longTaskThreshold ||
|
||||||
|
perfState.worstFrameGap > frameGapThreshold;
|
||||||
|
|
||||||
|
if (shouldReduce) {
|
||||||
|
setMode("reduced", "runtime-performance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sample(now) {
|
||||||
|
if (!perfState.firstFrameAt) {
|
||||||
|
perfState.firstFrameAt = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
perfState.frameCount += 1;
|
||||||
|
if (lastFrameAt) {
|
||||||
|
perfState.worstFrameGap = Math.max(
|
||||||
|
perfState.worstFrameGap,
|
||||||
|
now - lastFrameAt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lastFrameAt = now;
|
||||||
|
|
||||||
|
if (now - perfState.firstFrameAt >= targetDuration) {
|
||||||
|
finish(now);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaQuery = getMediaQuery();
|
||||||
|
if (mediaQuery && mediaQuery.matches) {
|
||||||
|
setMode("reduced", "prefers-reduced-motion");
|
||||||
|
} else {
|
||||||
|
setMode("normal", "default");
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
window.setTimeout(monitorAnimationHealth, 1200);
|
||||||
|
} else {
|
||||||
|
window.addEventListener("load", function () {
|
||||||
|
window.setTimeout(monitorAnimationHealth, 1200);
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaQuery) {
|
||||||
|
var handlePreferenceChange = function (event) {
|
||||||
|
if (event.matches) {
|
||||||
|
setMode("reduced", "prefers-reduced-motion");
|
||||||
|
} else if (motionState.reason === "prefers-reduced-motion") {
|
||||||
|
setMode("normal", "preference-restored");
|
||||||
|
window.setTimeout(monitorAnimationHealth, 600);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof mediaQuery.addEventListener === "function") {
|
||||||
|
mediaQuery.addEventListener("change", handlePreferenceChange);
|
||||||
|
} else if (typeof mediaQuery.addListener === "function") {
|
||||||
|
mediaQuery.addListener(handlePreferenceChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateVisibilityState();
|
||||||
|
document.addEventListener("visibilitychange", updateVisibilityState);
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user