timeline: revert loading icon move
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/653/merge
parent
a7e7f80745
commit
90003614b7
|
@ -6,7 +6,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent, type PropType } from 'vue';
|
||||||
|
|
||||||
const SWIPE_PX = 250;
|
const SWIPE_PX = 250;
|
||||||
|
|
||||||
|
@ -14,37 +14,56 @@ export default defineComponent({
|
||||||
name: 'SwipeRefresh',
|
name: 'SwipeRefresh',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
refresh: {
|
||||||
|
type: Function as PropType<() => Promise<any>>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
allowSwipe: {
|
allowSwipe: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
loading: {
|
state: {
|
||||||
type: Boolean,
|
type: Number,
|
||||||
default: false,
|
default: Math.random(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: {
|
|
||||||
refresh: () => true,
|
|
||||||
},
|
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
/** Is active interaction */
|
||||||
on: false,
|
on: false,
|
||||||
|
/** Start touch Y coordinate */
|
||||||
start: 0,
|
start: 0,
|
||||||
|
/** End touch Y coordinate */
|
||||||
end: 0,
|
end: 0,
|
||||||
updateFrame: 0,
|
/** Percentage progress to show in swiping */
|
||||||
progress: 0,
|
progress: 0,
|
||||||
|
/** Next update frame reference */
|
||||||
|
updateFrame: 0,
|
||||||
|
|
||||||
|
// Loading animation state
|
||||||
|
loading: false,
|
||||||
animate: false,
|
animate: false,
|
||||||
wasSwiped: true,
|
wasSwiped: true,
|
||||||
firstcycle: 0,
|
firstcycle: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
emits: [],
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.animate = this.loading; // start if needed
|
this.animate = this.loading; // start if needed
|
||||||
},
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
state() {
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
|
||||||
loading() {
|
loading() {
|
||||||
this.wasSwiped = this.progress >= 100;
|
this.wasSwiped = this.progress >= 100;
|
||||||
if (!this.wasSwiped) {
|
if (!this.wasSwiped) {
|
||||||
|
@ -93,6 +112,21 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
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) */
|
/** Start gesture on container (passive) */
|
||||||
touchstart(event: TouchEvent) {
|
touchstart(event: TouchEvent) {
|
||||||
if (!this.allowSwipe) return;
|
if (!this.allowSwipe) return;
|
||||||
|
@ -104,12 +138,12 @@ export default defineComponent({
|
||||||
|
|
||||||
/** Execute gesture on container (passive) */
|
/** Execute gesture on container (passive) */
|
||||||
touchmove(event: TouchEvent) {
|
touchmove(event: TouchEvent) {
|
||||||
if (!this.allowSwipe) return;
|
if (!this.allowSwipe || !this.on) return;
|
||||||
const touch = event.touches[0];
|
const touch = event.touches[0];
|
||||||
this.end = touch.clientY;
|
this.end = touch.clientY;
|
||||||
|
|
||||||
// Update progress only once per frame
|
// Update progress only once per frame
|
||||||
this.updateFrame ||= requestAnimationFrame(() => {
|
this.updateFrame ||= window.requestAnimationFrame(async () => {
|
||||||
this.updateFrame = 0;
|
this.updateFrame = 0;
|
||||||
|
|
||||||
// Compute percentage of swipe
|
// Compute percentage of swipe
|
||||||
|
@ -118,8 +152,16 @@ export default defineComponent({
|
||||||
|
|
||||||
// Execute action on threshold
|
// Execute action on threshold
|
||||||
if (this.progress >= 100) {
|
if (this.progress >= 100) {
|
||||||
this.$emit('refresh');
|
|
||||||
this.on = false;
|
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% {
|
49.99% {
|
||||||
background-image: $progress-outside;
|
background-image: $progress-outside;
|
||||||
background-size: 12000% 12000%;
|
background-size: 11000% 11000%;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
background-image: $progress-inside;
|
background-image: $progress-inside;
|
||||||
|
@ -178,7 +220,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
background-image: $progress-inside;
|
background-image: $progress-inside;
|
||||||
background-size: 12000% 12000%;
|
background-size: 11000% 11000%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
<SwipeRefresh
|
<SwipeRefresh
|
||||||
class="container no-user-select"
|
class="container no-user-select"
|
||||||
ref="container"
|
ref="container"
|
||||||
|
:refresh="softRefreshSync"
|
||||||
:allowSwipe="allowSwipe"
|
:allowSwipe="allowSwipe"
|
||||||
@refresh="softRefresh"
|
:state="state"
|
||||||
:loading="loading > 0"
|
|
||||||
>
|
>
|
||||||
|
<!-- Loading indicator -->
|
||||||
|
<XLoadingIcon class="loading-icon centered" v-if="loading" />
|
||||||
|
|
||||||
<!-- Static top matter -->
|
<!-- Static top matter -->
|
||||||
<TopMatter ref="topmatter" />
|
<TopMatter ref="topmatter" />
|
||||||
|
|
||||||
|
@ -275,7 +278,7 @@ export default defineComponent({
|
||||||
|
|
||||||
// Do a soft refresh if the query changes
|
// Do a soft refresh if the query changes
|
||||||
else if (JSON.stringify(from.query) !== JSON.stringify(to.query)) {
|
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
|
// Check if viewer is supposed to be open
|
||||||
|
@ -370,14 +373,19 @@ export default defineComponent({
|
||||||
* when changing the configuration
|
* when changing the configuration
|
||||||
*/
|
*/
|
||||||
softRefresh() {
|
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).
|
* 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
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ export default defineComponent({
|
||||||
|
|
||||||
.loading-icon {
|
.loading-icon {
|
||||||
z-index: 100000; // above everything
|
z-index: 100000; // above everything
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
.higher {
|
.higher {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
Loading…
Reference in New Issue