mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-06-11 23:46:53 +02:00
Set up TotpLooper & Dots components
This commit is contained in:
parent
c389378dc3
commit
ed1a653b37
4
resources/js_vue3/assets/app.scss
vendored
4
resources/js_vue3/assets/app.scss
vendored
@ -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;
|
||||
// }
|
||||
|
49
resources/js_vue3/components/Dots.vue
Normal file
49
resources/js_vue3/components/Dots.vue
Normal 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>
|
121
resources/js_vue3/components/TotpLooper.vue
Normal file
121
resources/js_vue3/components/TotpLooper.vue
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user