Files
AstralRinth/theseus_gui/src/components/modrinth-loading-indicator.js
Geometrically ee0c91aa80 Performance improvements (#114)
* Performance improvements

* run fmt

* optimize creation modal

* remove print, fix mod loader editing

* Fix library update

* update extract loading bar

* Update theseus_gui/src-tauri/src/api/metadata.rs

Co-authored-by: triphora <emma@modrinth.com>

* fix cli

---------

Co-authored-by: triphora <emma@modrinth.com>
2023-05-11 18:11:15 -07:00

135 lines
2.7 KiB
JavaScript

import { computed, defineComponent, h, onBeforeUnmount, ref, watch } from 'vue'
import { useLoading } from '@/store/state.js'
export default defineComponent({
props: {
throttle: {
type: Number,
default: 50,
},
duration: {
type: Number,
default: 500,
},
height: {
type: Number,
default: 3,
},
color: {
type: [String, Boolean],
default:
'repeating-linear-gradient(to right, var(--color-brand) 0%, var(--color-brand) 100%)',
},
offsetWidth: {
type: String,
default: '208px',
},
offsetHeight: {
type: String,
default: '52px',
},
},
setup(props, { slots }) {
const indicator = useLoadingIndicator({
duration: props.duration,
throttle: props.throttle,
})
onBeforeUnmount(() => indicator.clear)
const loading = useLoading()
watch(loading, (newValue) => {
if (newValue.loading) {
indicator.start()
} else {
indicator.finish()
}
})
return () =>
h(
'div',
{
style: {
position: 'fixed',
top: props.offsetHeight,
right: 0,
left: props.offsetWidth,
pointerEvents: 'none',
width: `calc((100vw - ${props.offsetWidth}) * ${indicator.progress.value / 100})`,
height: `${props.height}px`,
opacity: indicator.isLoading.value ? 1 : 0,
background: props.color || undefined,
backgroundSize: `${(100 / indicator.progress.value) * 100}% auto`,
transition: 'width 0.1s, height 0.4s, opacity 0.4s',
zIndex: 6,
},
},
slots
)
},
})
function useLoadingIndicator(opts) {
const progress = ref(0)
const isLoading = ref(false)
const step = computed(() => 10000 / opts.duration)
let _timer = null
let _throttle = null
function start() {
clear()
progress.value = 0
if (opts.throttle) {
_throttle = setTimeout(() => {
isLoading.value = true
_startTimer()
}, opts.throttle)
} else {
isLoading.value = true
_startTimer()
}
}
function finish() {
progress.value = 100
_hide()
}
function clear() {
clearInterval(_timer)
clearTimeout(_throttle)
_timer = null
_throttle = null
}
function _increase(num) {
progress.value = Math.min(100, progress.value + num)
}
function _hide() {
clear()
setTimeout(() => {
isLoading.value = false
setTimeout(() => {
progress.value = 0
}, 400)
}, 500)
}
function _startTimer() {
_timer = setInterval(() => {
_increase(step.value)
}, 100)
}
return {
progress,
isLoading,
start,
finish,
clear,
}
}