timeline: move loading to swipe

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/653/merge
Varun Patil 2023-11-01 14:25:50 -07:00
parent 910cb4ada0
commit 59ec7119ea
2 changed files with 106 additions and 13 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<div @touchstart.passive="touchstart" @touchmove.passive="touchmove" @touchend.passive="touchend"> <div @touchstart.passive="touchstart" @touchmove.passive="touchmove" @touchend.passive="touchend">
<div v-if="on && progress" class="swipe-progress" :style="{ background: gradient }"></div> <div v-show="show" class="swipe-progress" :style="{ background: gradient }" :class="{ animate }"></div>
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
@ -18,6 +18,11 @@ export default defineComponent({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
loading: {
type: Boolean,
default: false,
},
}, },
emits: { emits: {
@ -30,15 +35,50 @@ export default defineComponent({
end: 0, end: 0,
updateFrame: 0, updateFrame: 0,
progress: 0, progress: 0,
animate: false,
firstcycle: 0,
}), }),
mounted() {
this.animate = this.loading; // start if needed
},
watch: {
loading() {
if (this.loading) {
if (!this.animate) {
// Let the animation run for at least half cycle
this.firstcycle = window.setTimeout(() => {
this.firstcycle = 0;
this.animate = this.loading;
}, 750);
}
this.animate = this.loading;
} else {
if (!this.firstcycle) {
console.log('stop');
this.animate = this.loading;
}
}
},
},
computed: { computed: {
show() {
return (this.on && this.progress) || this.animate;
},
gradient() { gradient() {
const start = 50 - this.progress / 2; if (this.animate) {
const end = 50 + this.progress / 2; // CSS animation below
const out = 'transparent'; return undefined;
const progress = 'var(--color-primary)'; }
return `linear-gradient(to right, ${out} ${start}%, ${progress} ${start}%, ${progress} ${end}%, ${out} ${end}%)`;
// Pull down progress
const p = this.progress;
const outer = 'transparent';
const inner = 'var(--color-primary)';
return `radial-gradient(circle at center, ${inner} 0, ${inner} ${p}%, ${outer} ${p}%, ${outer} 100%)`;
}, },
}, },
@ -89,9 +129,49 @@ export default defineComponent({
top: 0; top: 0;
width: 100%; width: 100%;
height: 3px; height: 3px;
pointer-events: none;
html.native & { html.native & {
top: 2px; top: 2px;
} }
&.animate {
$progress-inside: radial-gradient(
circle at center,
transparent 0%,
transparent 1%,
var(--color-primary) 1%,
var(--color-primary) 100%
);
$progress-outside: radial-gradient(
circle at center,
var(--color-primary) 0%,
var(--color-primary) 1%,
transparent 1%,
transparent 100%
);
animation: swipe-loading 1.5s ease infinite;
background-position: center;
@keyframes swipe-loading {
0% {
background-image: $progress-inside;
background-size: 100% 100%;
}
49.99% {
background-image: $progress-inside;
background-size: 12000% 12000%;
}
50% {
background-image: $progress-outside;
background-size: 100% 100%;
}
100% {
background-image: $progress-outside;
background-size: 12000% 12000%;
}
}
}
} }
</style> </style>

View File

@ -1,8 +1,11 @@
<template> <template>
<SwipeRefresh class="container no-user-select" ref="container" :allowSwipe="allowSwipe" @refresh="softRefresh"> <SwipeRefresh
<!-- Loading indicator --> class="container no-user-select"
<XLoadingIcon class="loading-icon centered" v-if="loading" /> ref="container"
:allowSwipe="allowSwipe"
@refresh="softRefresh"
:loading="loading > 0"
>
<!-- Static top matter --> <!-- Static top matter -->
<TopMatter ref="topmatter" /> <TopMatter ref="topmatter" />
@ -371,18 +374,28 @@ export default defineComponent({
}, },
/** /**
* Fetch and re-process days (can be awaited). * Fetch and re-process days (can be awaited if sync).
* Do not pass this function as a callback directly. * Do not pass this function as a callback directly.
*/ */
async softRefreshInternal(sync: boolean) { async softRefreshInternal(sync: boolean) {
this.refs.selectionManager.clear(); this.refs.selectionManager.clear();
this.fetchDayQueue = []; // reset queue this.fetchDayQueue = []; // reset queue
// Fetch days and reset loading
this.updateLoading(1);
const doFetch = async () => {
try {
await this.fetchDays(true);
} finally {
this.updateLoading(-1);
}
};
// Fetch days // Fetch days
if (sync) { if (sync) {
await this.fetchDays(true); doFetch();
} else { } else {
utils.setRenewingTimeout(this, '_softRefreshInternalTimer', () => this.fetchDays(true), 30); utils.setRenewingTimeout(this, '_softRefreshInternalTimer', doFetch, 30);
} }
}, },