aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author0neGal <mail@0negal.com>2024-06-19 23:24:47 +0200
committer0neGal <mail@0negal.com>2024-06-19 23:24:47 +0200
commitfce388b3d9b520459413988e190f916f334a8d48 (patch)
tree5605416c2550cda739a28f82c8531cf98beff673
parenta2c165b16a82799422547b124fde72bfbad40f0d (diff)
downloadViper-fce388b3d9b520459413988e190f916f334a8d48.tar.gz
Viper-fce388b3d9b520459413988e190f916f334a8d48.zip
proper gamepad element scrolling support
-rw-r--r--src/app/css/selection.css6
-rw-r--r--src/app/index.html6
-rw-r--r--src/app/js/navigate.js112
3 files changed, 116 insertions, 8 deletions
diff --git a/src/app/css/selection.css b/src/app/css/selection.css
index 04e1d5d..5b7d647 100644
--- a/src/app/css/selection.css
+++ b/src/app/css/selection.css
@@ -3,7 +3,7 @@
transition: 0.15s ease-in-out;
transition-property:
- opacity, border-radius,
+ opacity, border-radius, background,
transform, width, height, top, left;
position: fixed;
@@ -13,6 +13,10 @@
border-radius: calc(var(--padding) / 2);
}
+:has(.active-selection.scroll-selection) #selection {
+ background: rgba(255, 255, 255, 0.2);
+}
+
#selection.keyboard-selecting,
#selection.controller-selecting {
transform: scale(1.1);
diff --git a/src/app/index.html b/src/app/index.html
index 40b64a0..1f9f443 100644
--- a/src/app/index.html
+++ b/src/app/index.html
@@ -228,7 +228,7 @@
</button>
</div>
- <webview></webview>
+ <webview class="scroll-selection"></webview>
</div>
<nav class="gamesContainer">
@@ -252,7 +252,7 @@
<a id="setpath" href="#" onclick="gamepath.set()" class="disable-when-installing">%%gui.setpath%%</a>
</div>
</div>
- <div id="vpReleaseNotes" class="hidden section"></div>
+ <div id="vpReleaseNotes" class="scroll-selection hidden section"></div>
<div id="vpInfo" class="hidden section">
<h2>%%viper.info.links%%</h2>
<ul>
@@ -312,7 +312,7 @@
</div>
</div>
</div>
- <div id="nsRelease" class="hidden section"></div>
+ <div id="nsRelease" class="scroll-selection hidden section"></div>
</div>
</div>
diff --git a/src/app/js/navigate.js b/src/app/js/navigate.js
index d9744fa..9f2a19f 100644
--- a/src/app/js/navigate.js
+++ b/src/app/js/navigate.js
@@ -115,7 +115,8 @@ navigate.get_els = (div) => {
"button",
"select",
"textarea",
- "[onclick]"
+ "[onclick]",
+ ".scroll-selection"
])]
// this'll contain a filtered list of `els`
@@ -129,13 +130,31 @@ navigate.get_els = (div) => {
"#overlay",
".no-navigate",
"button.visual",
+ ".scroll-selection",
".popup:not(.shown)"
]
+ // ignore, even if `.closest()` matches, if its just matching on
+ // itself instead of a different element
+ let ignore_closest_self = [
+ ".scroll-selection"
+ ]
+
// check if `els[i].closest()` matches on any of the elements
// inside of `ignore_closest`
for (let ii = 0; ii < ignore_closest.length; ii++) {
- if (els[i].closest(ignore_closest[ii])) {
+ let closest = els[i].closest(ignore_closest[ii]);
+
+ // check if `.closest()` matches, but not on itself
+ if (closest) {
+ // ignore if `closest` is just `els[i]` and the selector
+ // is inside `ignore_closest_self`
+ if (closest == els[i] &&
+ ignore_closest_self.includes(ignore_closest[ii])) {
+
+ continue;
+ }
+
// it matches
continue filter;
}
@@ -221,7 +240,7 @@ navigate.default_selection = () => {
// this navigates `#selection` in the direction of `direction`
// this can be: up, down, left and right
-navigate.move = (direction) => {
+navigate.move = async (direction) => {
// get the `.active-selection` if there is one
let active = document.querySelector(".active-selection");
@@ -238,6 +257,91 @@ navigate.move = (direction) => {
}
}
+ // is the active selection one that should be scrollable?
+ if (active.classList.contains("scroll-selection")) {
+ // scroll the respective `direction` if `active` has any more
+ // scroll left in that direction
+
+ // short hand to easily scroll in `direction` by `amount` with
+ // smooth scrolling enabled
+ let scroll = (direction, amount) => {
+ // update the `#selection` element
+ navigate.selection();
+
+ // scroll inside `<webview>` if the active selection is one
+ if (active.tagName == "WEBVIEW") {
+ active.executeJavaScript(`
+ document.scrollingElement.scrollBy({
+ behavior: "smooth",
+ ${direction}: ${amount}
+ })
+ `)
+
+ return;
+ }
+
+ active.scrollBy({
+ behavior: "smooth",
+ [direction]: amount
+ })
+ }
+
+ // get values needed for determining if we should scroll the
+ // active selection, and by how much
+ let scroll_el = {
+ top: active.scrollTop,
+ left: active.scrollLeft,
+ width: active.scrollWidth,
+ height: active.scrollHeight,
+ bounds: {
+ width: active.clientWidth,
+ height: active.clientWidth
+ }
+ }
+
+ // get `scroll_el` from inside a `<webview>` if the active
+ // selection is one
+ if (active.tagName == "WEBVIEW") {
+ scroll_el = await active.executeJavaScript(`(() => {
+ return {
+ top: document.scrollingElement.scrollTop,
+ left: document.scrollingElement.scrollLeft,
+ width: document.scrollingElement.scrollWidth,
+ height: document.scrollingElement.scrollHeight,
+ bounds: {
+ width: document.scrollingElement.clientWidth,
+ height: document.scrollingElement.clientHeight
+ }
+ }
+ })()`)
+ }
+
+ // decrease to increase scroll length, and in reverse
+ let scroll_scale = 2;
+
+ if (direction == "up" && scroll_el.top > 0) {
+ return scroll("top", -scroll_el.bounds.height / scroll_scale);
+ }
+
+ if (direction == "down" &&
+ scroll_el.top <= scroll_el.height &&
+ scroll_el.height != scroll_el.bounds.height) {
+
+ return scroll("top", scroll_el.bounds.height / scroll_scale);
+ }
+
+ if (direction == "left" && scroll_el.left > 0) {
+ return scroll("left", -width / scroll_scale);
+ }
+
+ if (direction == "right" &&
+ scroll_el.left <= scroll_el.width &&
+ scroll_el.width != scroll_el.bounds.width) {
+
+ return scroll("left", scroll_el.bounds.width / scroll_scale);
+ }
+ }
+
// attempt to get the element in the `direction` requested
let move_to_el = navigate.get_relative_el(active, direction);
@@ -269,7 +373,7 @@ navigate.move = (direction) => {
// these elements cant be scrolled
let no_scroll_parents = [
".el .text",
- ".gamesContainer"
+ ".gamesContainer",
]
// run through unscrollable parent elements