Set up TotpLooper & Dots components

This commit is contained in:
Bubka 2023-10-19 11:40:19 +02:00
parent c389378dc3
commit ed1a653b37
3 changed files with 174 additions and 0 deletions

View File

@ -447,6 +447,10 @@ figure.no-icon {
/* green */
}
.dots.off li {
background: $black-bis;
}
// .dots li:nth-child(3n+2), .dots li:nth-child(3n+3) {
// display:none;
// }

View File

@ -0,0 +1,49 @@
<script setup>
const props = defineProps({
stepCount: {
type: Number,
default: 10
},
initialIndex: {
type: Number,
default: null
},
})
const activeDot = ref(0)
const isOff = computed(() => {
return activeDot.value == -1
})
/**
* Turns On dots
*/
function turnOn(index) {
activeDot.value = index < props.stepCount ? index + 1 : 1
}
/**
* Turns Off all dots
*/
function turnOff() {
activeDot.value = -1
}
onMounted(() => {
if (props.initialIndex != null) {
turnOn(props.initialIndex)
}
})
defineExpose({
turnOn,
turnOff
})
</script>
<template>
<ul class="dots" :class="{'off' : isOff}">
<li v-for="n in stepCount" :key="n" :data-is-active="n == activeDot ? true : null"></li>
</ul>
</template>

View File

@ -0,0 +1,121 @@
<script setup>
const props = defineProps({
step_count: {
type: Number,
default: 10
},
period : Number,
generated_at: Number,
autostart: {
type: Boolean,
default: true
},
})
const generatedAt = ref(null)
const remainingTimeout = ref(null)
const initialStepToNextStepTimeout = ref(null)
const stepToStepInterval = ref(null)
const stepIndex = ref(null)
// |<----period p----->|
// | | |
// |------- ··· ------------|--------|----------|---------->
// | | | |
// unix T0 Tp.start Tgen_at Tp.end
// | | |
// elapsedTimeInCurrentPeriod--|<------>| |
// (in ms) | | |
// | |
// | | || |
// | | |<-------->|--remainingTimeBeforeEndOfPeriod (for remainingTimeout)
// durationBetweenTwoSteps-->|-|< ||
// (for stepToStepInterval) | | >||<---durationFromInitialToNextStep (for initialStepToNextStepTimeout)
// |
// |
// stepIndex
const elapsedTimeInCurrentPeriod = computed(() => {
return generatedAt.value % props.period
})
const remainingTimeBeforeEndOfPeriod = computed(() => {
return props.period - elapsedTimeInCurrentPeriod.value
})
const durationBetweenTwoSteps = computed(() => {
return props.period / props.step_count
})
const initialStepIndex = computed(() => {
let relativePosition = (elapsedTimeInCurrentPeriod.value * props.step_count) / props.period
return (Math.floor(relativePosition) + 0)
})
const emit = defineEmits(['loop-started', 'loop-ended', 'stepped-up'])
/**
* Starts looping
*/
const startLoop = () => {
clearLooper()
generatedAt.value = props.generated_at
emit('loop-started', initialStepIndex.value)
stepIndex.value = initialStepIndex.value
// Main timeout that runs until the end of the period
remainingTimeout.value = setTimeout(function() {
clearLooper()
emit('loop-ended')
}, remainingTimeBeforeEndOfPeriod.value * 1000);
// During the remainingTimeout countdown we emit an event every durationBetweenTwoSteps seconds,
// except for the first next dot
let durationFromInitialToNextStep = (Math.ceil(elapsedTimeInCurrentPeriod.value / durationBetweenTwoSteps.value) * durationBetweenTwoSteps.value) - elapsedTimeInCurrentPeriod.value
initialStepToNextStepTimeout.value = setTimeout(function() {
if( durationFromInitialToNextStep > 0 ) {
stepIndex.value += 1
emit('stepped-up', stepIndex.value)
}
stepToStepInterval.value = setInterval(function() {
stepIndex.value += 1
emit('stepped-up', stepIndex.value)
}, durationBetweenTwoSteps.value * 1000)
}, durationFromInitialToNextStep * 1000)
}
/**
* Resets all timers and internal vars
*/
const clearLooper = () => {
clearTimeout(remainingTimeout.value)
clearTimeout(initialStepToNextStepTimeout.value)
clearInterval(stepToStepInterval.value)
stepIndex.value = generatedAt.value = null
}
onMounted(() => {
if (props.autostart == true) {
startLoop()
}
})
onUnmounted(() => {
clearLooper()
})
defineExpose({
startLoop,
clearLooper
})
</script>
<template>
<div>
</div>
</template>