Skip to content

Commit

Permalink
Merge pull request #24 from alkrauss48/issue-23/feat/looping
Browse files Browse the repository at this point in the history
Implements front-end looping via query param
  • Loading branch information
alkrauss48 authored May 24, 2024
2 parents 7279c83 + c241279 commit 84f488d
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 7 deletions.
2 changes: 2 additions & 0 deletions app/Http/Middleware/HandleInertiaRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ public function share(Request $request): array
{
$index = intval(request()->input('index'));
$progress = request()->input('progress');
$loop = intval(request()->input('loop'));

return [
...parent::share($request),
'index' => $index,
'progress' => $progress,
'loop' => $loop,
'auth' => [
'user' => $request->user(),
],
Expand Down
40 changes: 35 additions & 5 deletions resources/js/Components/SlideView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import Keys from '@/constants/keys.ts';
import dataStore from '@/store/dataStore.ts'
import slideStore from '@/store/slideStore.ts'
const content = computed(() => {
return dataStore.data[slideStore.index];
});
let loopInterval: null | ReturnType<typeof setInterval> = null;
let fontLoadInterval: null | ReturnType<typeof setInterval> = null;
const fontLoaded = ref(false);
const FONT = '16px Montserrat';
const content = computed(() => {
return dataStore.data[slideStore.index];
});
const showProgressLabel = computed<boolean>(() => {
return slideStore.progress === ProgressType.Label;
});
Expand All @@ -35,6 +36,14 @@ const buildQueryParams = () : QueryParams => {
return query;
};
const checkAndClearLoopInterval = () : void => {
if (!loopInterval) {
return;
}
clearInterval(Number(loopInterval));
};
const incrementContent = (count: number) : void => {
slideStore.increment(count);
Expand All @@ -58,6 +67,10 @@ const bindKeyDown = (event: KeyboardEvent): void => {
}
}
if (Keys.ALL_APP_KEYS.includes(key)) {
checkAndClearLoopInterval();
}
if (Keys.INCREMENTORS.includes(key)) {
incrementContent(1);
} else if (Keys.DECREMENTORS.includes(key)) {
Expand Down Expand Up @@ -86,8 +99,25 @@ onMounted(() => {
fontLoaded.value = true;
clearInterval(Number(fontLoadInterval));
}, 50);
if (!slideStore.canLoop()) {
return;
}
loopInterval = setInterval(() => {
if (slideStore.isEnd()) {
incrementContent(-1 * dataStore.data.length);
return;
}
incrementContent(1)
}, slideStore.loop * 1000);
});
onUnmounted(() => {
window.removeEventListener('keydown', bindKeyDown);
checkAndClearLoopInterval();
});
onUnmounted(() => window.removeEventListener('keydown', bindKeyDown));
</script>

<template>
Expand Down
2 changes: 2 additions & 0 deletions resources/js/Pages/Slides.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import slideStore from '@/store/slideStore.ts'
const props = defineProps<{
index?: number,
loop?: number,
progress?: ProgressType,
slides?: string
content?: string
}>();
const processQueryParams = (): void => {
slideStore.index = props.index ?? 0;
slideStore.loop = props.loop ?? 0;
slideStore.progress = props.progress ?? ProgressType.Bar;
};
Expand Down
10 changes: 10 additions & 0 deletions resources/js/constants/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export const LARGE_DECREMENTORS = [
'B',
];

export const ALL_APP_KEYS = [
...INCREMENTORS,
...DECREMENTORS,
...LARGE_INCREMENTORS,
...LARGE_DECREMENTORS,
DOLLAR_SIGN,
ZERO,
];

export default {
ENTER,
SPACE,
Expand All @@ -43,4 +52,5 @@ export default {
DECREMENTORS,
LARGE_INCREMENTORS,
LARGE_DECREMENTORS,
ALL_APP_KEYS
};
13 changes: 13 additions & 0 deletions resources/js/store/slideStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dataStore from './dataStore.ts'

const slideStore = reactive({
index: 0,
loop: 0,
progress: ProgressType.Bar,

getNewIndex(count: number) : number {
Expand All @@ -29,6 +30,18 @@ const slideStore = reactive({
slideStore.index = newIndex;
},

isEnd() : boolean {
return this.index === dataStore.data.length - 1;
},

canLoop() : boolean {
if (this.loop < 2) {
return false;
}

return true;
},

reset() {
this.index = 0;
this.progress = ProgressType.Bar;
Expand Down
53 changes: 53 additions & 0 deletions resources/js/test/components/SlideView.loop.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { mount, VueWrapper } from '@vue/test-utils'

import SlideView from '@/Components/SlideView.vue'
import Keys from '@/constants/keys.ts';
import ProgressType from '@/enums/progressType.ts'
import dataStore from '@/store/dataStore.ts'
import slideStore from '@/store/slideStore.ts'

// Incrementors

const mountWrapper = () : VueWrapper<any> => {
dataStore.data = ['foo', 'bar', 'baz', 'foo', 'bar', 'baz', 'foo', 'bar'];
slideStore.index = 1;
slideStore.loop = 5;
slideStore.progress = ProgressType.Bar;

return mount(SlideView);
};

test('loopInterval is not null with valid loop set', async () => {
const wrapper = mountWrapper();

expect(wrapper.vm.loopInterval).not.toBe(null);
});

test('loopInterval is cleared with valid loop set', async () => {
const wrapper = mountWrapper();
const spy = vi.spyOn(global, 'clearInterval');

wrapper.vm.checkAndClearLoopInterval();

expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.lastCall?.[0]).toBe(Number(wrapper.vm.loopInterval));
});

test('loopInterval is cleared on valid key press', async () => {
const wrapper = mountWrapper();
const spy = vi.spyOn(global, 'clearInterval');

wrapper.vm.bindKeyDown({ key: Keys.ENTER });

expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.lastCall?.[0]).toBe(Number(wrapper.vm.loopInterval));
});

test('loopInterval is not cleared on invalid key press', async () => {
const wrapper = mountWrapper();
const spy = vi.spyOn(global, 'clearInterval');

wrapper.vm.bindKeyDown({ key: 'x' });

expect(spy).toHaveBeenCalledTimes(0);
});
32 changes: 30 additions & 2 deletions resources/js/test/store/slideStore.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import ProgressType from '@/enums/progressType.ts'
import dataStore from '@/store/dataStore.ts'
import slideStore from '@/store/slideStore.ts'

afterEach(() => {
slideStore.reset()
})
dataStore.reset();
slideStore.reset();
});

test('gets the right initial values', async () => {
expect(slideStore.index).toBe(0);
Expand All @@ -30,3 +32,29 @@ test('will not change slide store if no new index', async () => {

expect(slideStore.index).toBe(0);
});

test('returns true for isEnd if slide index is at the end', async () => {
dataStore.data = ['a', 'b', 'c'];
slideStore.index = 2;

expect(slideStore.isEnd()).toBe(true);
});

test('returns false for isEnd if slide index is not at the end', async () => {
dataStore.data = ['a', 'b', 'c'];
slideStore.index = 1;

expect(slideStore.isEnd()).toBe(false);
});

test('returns true for canLoop if loop value is valid', async () => {
slideStore.loop = 5;

expect(slideStore.canLoop()).toBe(true);
});

test('returns false for canLoop if loop value is invalid', async () => {
slideStore.loop = 1;

expect(slideStore.canLoop()).toBe(false);
});

0 comments on commit 84f488d

Please sign in to comment.