timeline: revert loading icon move

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/653/merge
Varun Patil 2023-11-02 12:12:30 -07:00
parent a7e7f80745
commit 90003614b7
3 changed files with 70 additions and 19 deletions

View File

@ -6,7 +6,7 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, type PropType } from 'vue';
const SWIPE_PX = 250;
@ -14,37 +14,56 @@ export default defineComponent({
name: 'SwipeRefresh',
props: {
refresh: {
type: Function as PropType<() => Promise<any>>,
required: true,
},
allowSwipe: {
type: Boolean,
default: true,
},
loading: {
type: Boolean,
default: false,
state: {
type: Number,
default: Math.random(),
},
},
emits: {
refresh: () => true,
},
data: () => ({
/** Is active interaction */
on: false,
/** Start touch Y coordinate */
start: 0,
/** End touch Y coordinate */
end: 0,
updateFrame: 0,
/** Percentage progress to show in swiping */
progress: 0,
/** Next update frame reference */
updateFrame: 0,
// Loading animation state
loading: false,
animate: false,
wasSwiped: true,
firstcycle: 0,
}),
emits: [],
mounted() {
this.animate = this.loading; // start if needed
},
beforeDestroy() {
this.reset();
},
watch: {
state() {
this.reset();
},
loading() {
this.wasSwiped = this.progress >= 100;
if (!this.wasSwiped) {
@ -93,6 +112,21 @@ export default defineComponent({
},
methods: {
reset() {
// Clear events
window.cancelAnimationFrame(this.updateFrame);
window.clearTimeout(this.firstcycle);
// Reset state
this.on = false;
this.progress = 0;
this.updateFrame = 0;
this.loading = false;
this.animate = false;
this.wasSwiped = true;
this.firstcycle = 0;
},
/** Start gesture on container (passive) */
touchstart(event: TouchEvent) {
if (!this.allowSwipe) return;
@ -104,12 +138,12 @@ export default defineComponent({
/** Execute gesture on container (passive) */
touchmove(event: TouchEvent) {
if (!this.allowSwipe) return;
if (!this.allowSwipe || !this.on) return;
const touch = event.touches[0];
this.end = touch.clientY;
// Update progress only once per frame
this.updateFrame ||= requestAnimationFrame(() => {
this.updateFrame ||= window.requestAnimationFrame(async () => {
this.updateFrame = 0;
// Compute percentage of swipe
@ -118,8 +152,16 @@ export default defineComponent({
// Execute action on threshold
if (this.progress >= 100) {
this.$emit('refresh');
this.on = false;
const state = this.state;
try {
this.loading = true;
await this.refresh();
} finally {
if (this.state === state) {
this.loading = false;
}
}
}
});
},
@ -170,7 +212,7 @@ export default defineComponent({
}
49.99% {
background-image: $progress-outside;
background-size: 12000% 12000%;
background-size: 11000% 11000%;
}
50% {
background-image: $progress-inside;
@ -178,7 +220,7 @@ export default defineComponent({
}
100% {
background-image: $progress-inside;
background-size: 12000% 12000%;
background-size: 11000% 11000%;
}
}
}

View File

@ -2,10 +2,13 @@
<SwipeRefresh
class="container no-user-select"
ref="container"
:refresh="softRefreshSync"
:allowSwipe="allowSwipe"
@refresh="softRefresh"
:loading="loading > 0"
:state="state"
>
<!-- Loading indicator -->
<XLoadingIcon class="loading-icon centered" v-if="loading" />
<!-- Static top matter -->
<TopMatter ref="topmatter" />
@ -275,7 +278,7 @@ export default defineComponent({
// Do a soft refresh if the query changes
else if (JSON.stringify(from.query) !== JSON.stringify(to.query)) {
await this.softRefreshInternal(true);
await this.softRefreshSync();
}
// Check if viewer is supposed to be open
@ -370,14 +373,19 @@ export default defineComponent({
* when changing the configuration
*/
softRefresh() {
this.softRefreshInternal(false);
this._softRefreshInternal(false);
},
/** Fetch and re-process days (sync can be awaited) */
async softRefreshSync() {
await this._softRefreshInternal(true);
},
/**
* Fetch and re-process days (can be awaited if sync).
* Do not pass this function as a callback directly.
*/
async softRefreshInternal(sync: boolean) {
async _softRefreshInternal(sync: boolean) {
this.refs.selectionManager.clear();
this.fetchDayQueue = []; // reset queue

View File

@ -31,6 +31,7 @@ export default defineComponent({
.loading-icon {
z-index: 100000; // above everything
pointer-events: none;
.higher {
position: relative;