scroller: inverted logic

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/653/head
Varun Patil 2023-05-04 19:28:51 -07:00
parent 636183918c
commit d465f996e2
3 changed files with 36 additions and 14 deletions

View File

@ -20,8 +20,9 @@
<span class="cursor st" ref="cursorSt" :style="{ transform: `translateY(${cursorY}px)` }"> </span> <span class="cursor st" ref="cursorSt" :style="{ transform: `translateY(${cursorY}px)` }"> </span>
<span <span
ref="hoverCursor"
class="cursor hv" class="cursor hv"
:style="{ transform: `translateY(${hoverCursorY}px)` }" :style="{ transform: `translateY(calc(${hoverCursorY}px - 100%))` }"
@touchmove.prevent="touchmove" @touchmove.prevent="touchmove"
@touchstart.passive="interactstart" @touchstart.passive="interactstart"
@touchend.passive="interactend" @touchend.passive="interactend"
@ -66,7 +67,7 @@ export default defineComponent({
required: true, required: true,
}, },
/** Total height */ /** Total height */
height: { fullHeight: {
type: Number, type: Number,
required: true, required: true,
}, },
@ -87,6 +88,8 @@ export default defineComponent({
lastAdjustHeight: 0, lastAdjustHeight: 0,
/** Height of the entire photo view */ /** Height of the entire photo view */
recyclerHeight: 100, recyclerHeight: 100,
/** Space to leave at the top (for the hover cursor) */
topPadding: 0,
/** Rect of scroller */ /** Rect of scroller */
scrollerRect: null as DOMRect | null, scrollerRect: null as DOMRect | null,
/** Computed ticks */ /** Computed ticks */
@ -132,6 +135,11 @@ export default defineComponent({
return tick; return tick;
}); });
}, },
/** Height of usable area */
height(): number {
return this.fullHeight - this.topPadding;
},
}, },
methods: { methods: {
@ -188,7 +196,7 @@ export default defineComponent({
// Move hover cursor to same position unless hovering // Move hover cursor to same position unless hovering
// Regardless, we need this call because the internal mapping might have changed // Regardless, we need this call because the internal mapping might have changed
if ((<HTMLElement>this.$refs.scroller).matches(':hover')) { if (!utils.isMobile() && (<HTMLElement>this.$refs.scroller).matches(':hover')) {
this.moveHoverCursor(this.hoverCursorY); this.moveHoverCursor(this.hoverCursorY);
} else { } else {
this.moveHoverCursor(rtop); this.moveHoverCursor(rtop);
@ -279,6 +287,9 @@ export default defineComponent({
this.recyclerHeight = this.recycler?.$refs.wrapper.clientHeight ?? 0; this.recyclerHeight = this.recycler?.$refs.wrapper.clientHeight ?? 0;
const extraY = this.recyclerBefore?.clientHeight ?? 0; const extraY = this.recyclerBefore?.clientHeight ?? 0;
// Exclude hover cursor height
this.topPadding = (<HTMLSpanElement>this.$refs.hoverCursor)?.clientHeight ?? 0;
// Start with the first tick. Walk over all rows counting the // Start with the first tick. Walk over all rows counting the
// y position. When you hit a row with the tick, update y and // y position. When you hit a row with the tick, update y and
// top values and move to the next tick. // top values and move to the next tick.
@ -343,7 +354,9 @@ export default defineComponent({
if (!tick.isMonth) continue; if (!tick.isMonth) continue;
// You can't see these anyway, why bother? // You can't see these anyway, why bother?
if (tick.top < minGap || tick.top > this.height - minGap) continue; const minTop = this.topPadding + minGap;
const maxTop = this.fullHeight - minGap;
if (tick.top < minTop || tick.top > maxTop) continue;
// Will overlap with the previous tick. Skip anyway. // Will overlap with the previous tick. Skip anyway.
if (tick.top - prevShow < minGap) continue; if (tick.top - prevShow < minGap) continue;
@ -380,12 +393,14 @@ export default defineComponent({
}, },
setTicksTop(total: number) { setTicksTop(total: number) {
const isMobile = globalThis.windowInnerWidth <= 768; // On mobile, move the ticks up by half the height of the cursor
const padding = isMobile ? 20 : 0; // so that the cursor is centered on the tick instead (on desktop, it's at the bottom)
const displayPadding = utils.isMobile() ? -20 : 0;
// Set topF (float) and top (rounded) values
for (const tick of this.ticks) { for (const tick of this.ticks) {
tick.topF = this.height * (tick.count / total); tick.topF = this.topPadding + this.height * (tick.count / total);
tick.top = utils.roundHalf(tick.topF) + padding; tick.top = utils.roundHalf(tick.topF) + displayPadding;
} }
}, },
@ -432,7 +447,6 @@ export default defineComponent({
/** Binary search and get coords surrounding position */ /** Binary search and get coords surrounding position */
getCoords(y: number, field: 'topF' | 'y') { getCoords(y: number, field: 'topF' | 'y') {
// Top of first and second ticks
let top1 = 0, let top1 = 0,
top2 = 0, top2 = 0,
y1 = 0, y1 = 0,
@ -441,7 +455,7 @@ export default defineComponent({
// Get index of previous tick // Get index of previous tick
let idx = utils.binarySearch(this.ticks, y, field); let idx = utils.binarySearch(this.ticks, y, field);
if (idx <= 0) { if (idx <= 0) {
top1 = 0; top1 = this.topPadding;
top2 = this.ticks[0].topF; top2 = this.ticks[0].topF;
y1 = 0; y1 = 0;
y2 = this.ticks[0].y; y2 = this.ticks[0].y;
@ -492,7 +506,7 @@ export default defineComponent({
touchmove(event: any) { touchmove(event: any) {
if (!this.scrollerRect) return; if (!this.scrollerRect) return;
let y = event.targetTouches[0].pageY - this.scrollerRect.top; let y = event.targetTouches[0].pageY - this.scrollerRect.top;
y = Math.max(0, y - 20); // middle of touch finger y = Math.max(this.topPadding, y + 20); // middle of touch finger
this.moveto(y, true); this.moveto(y, true);
}, },
@ -594,14 +608,15 @@ export default defineComponent({
&.hv { &.hv {
background-color: var(--color-main-background); background-color: var(--color-main-background);
padding: 2px 5px; padding: 1px 5px;
border-top: 2px solid var(--color-primary); border-bottom: 2px solid var(--color-primary);
border-radius: 2px; border-radius: 2px;
width: auto; width: auto;
white-space: nowrap; white-space: nowrap;
z-index: 100; z-index: 100;
font-size: 0.95em; font-size: 0.95em;
font-weight: 600; font-weight: 600;
height: calc(1.2em + 10px);
> .icon { > .icon {
display: none; display: none;

View File

@ -77,7 +77,7 @@
<ScrollerManager <ScrollerManager
ref="scrollerManager" ref="scrollerManager"
:rows="list" :rows="list"
:height="scrollerHeight" :fullHeight="scrollerHeight"
:recycler="$refs.recycler" :recycler="$refs.recycler"
:recyclerBefore="$refs.recyclerBefore" :recyclerBefore="$refs.recyclerBefore"
@interactend="loadScrollView()" @interactend="loadScrollView()"

View File

@ -3,6 +3,13 @@ import { API } from '../API';
import { constants } from './const'; import { constants } from './const';
import * as nativex from '../../native'; import * as nativex from '../../native';
/**
* Check if width <= 768px
*/
export function isMobile() {
return globalThis.windowInnerWidth <= 768;
}
/** Get preview URL from photo object */ /** Get preview URL from photo object */
export function getPreviewUrl(photo: IPhoto, square: boolean, size: number | [number, number] | 'screen') { export function getPreviewUrl(photo: IPhoto, square: boolean, size: number | [number, number] | 'screen') {
// Native preview // Native preview