Skip to content

Commit

Permalink
feat: add loading indicator on Search and Streams
Browse files Browse the repository at this point in the history
  • Loading branch information
tymmesyde committed Mar 18, 2023
1 parent 99a09e7 commit afda51b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 7 deletions.
27 changes: 27 additions & 0 deletions src/components/ui/Loading.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div class="loading">
<ion-icon name="sync-outline" class="icon spin"></ion-icon>
</div>
</template>

<script setup>
</script>

<style lang="scss" scoped>
.loading {
position: relative;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
.icon {
font-size: 4rem;
color: $text-color;
--ionicon-stroke-width: 20px;
}
}
</style>
22 changes: 19 additions & 3 deletions src/views/Search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
</div>

<TextInput large v-model="search" placeholder="Parasite, Fight Club, ..."/>
<Segments :segments="types" v-model="type" v-show="search">
<Segments :segments="types" v-model="type" v-show="!loading && search">
<template #segment="{ segment }">
{{ $t(`views.search.segments.${segment}`) }}
</template>
</Segments>
</div>


<Loading class="loading" v-show="loading" />

<List class="list" :items="results[type]" itemKey="id" @click="goToStream($event)">
<template #left="{ item }">
<div class="poster" :style="`background-image: url(${item.poster})`">
Expand All @@ -39,7 +41,9 @@ import Title from '@/components/ui/Title.vue';
import TextInput from '@/components/ui/TextInput.vue';
import Segments from '@/components/ui/Segments.vue';
import List from '@/components/ui/List.vue';
import Loading from '@/components/ui/Loading.vue';
const loading = ref(false);
const search = ref('');
const type = ref('movies');
const types = ['movies', 'series'];
Expand All @@ -50,8 +54,8 @@ const results = ref({
let debouncer = null;
watch(search, (value) => {
loading.value = true;
clearTimeout(debouncer);
debouncer = setTimeout(async () => {
if (value.length) {
results.value.movies = await StremioService.searchMovies(value);
Expand All @@ -60,6 +64,7 @@ watch(search, (value) => {
movies: [],
series: []
};
loading.value = false;
}, 250);
});
Expand All @@ -70,6 +75,8 @@ const goToStream = ({ type, imdb_id }) => {

<style lang="scss" scoped>
.search {
position: relative;
.header {
z-index: 97;
top: 0;
Expand All @@ -87,7 +94,16 @@ const goToStream = ({ type, imdb_id }) => {
}
}
.loading {
z-index: 0;
position: absolute;
height: 12rem;
}
.list {
position: relative;
z-index: 0;
.item {
.poster {
display: grid;
Expand Down
5 changes: 4 additions & 1 deletion src/views/Stream/Stream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
</List>
</div>

<Streams :streams="streams" @streamClick="createRoom"/>
<Streams :streams="streams" :loading="loading" @streamClick="createRoom" />

<Button large class="addons-button" icon="cube-outline" @click="isAddonsMenuOpen = true">
{{ t('views.stream.streams.button') }}
Expand All @@ -72,6 +72,7 @@ import Streams from './Streams/Streams.vue';
const { t } = useI18n();
const loading = ref(false);
const meta = ref({});
const seasons = ref([]);
const selectedSeason = ref(1);
Expand All @@ -88,6 +89,7 @@ const episodes = computed(() => meta.value && meta.value.videos && meta.value.vi
let loadStreamsDebouncer = null;
const loadStreams = () => {
loading.value = true;
clearTimeout(loadStreamsDebouncer);
loadStreamsDebouncer = setTimeout(async () => {
const { id, type } = router.currentRoute.value.params;
Expand All @@ -96,6 +98,7 @@ const loadStreams = () => {
if (installedAddons)
streams.value = await AddonService.getStreams(installedAddons, type, id);
}
loading.value = false;
}, 250);
};
Expand Down
14 changes: 11 additions & 3 deletions src/views/Stream/Streams/Streams.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
</template>
</Segments>

<div class="no-streams" v-show="!filteredStreams.length">
<div class="no-streams" v-show="!props.loading && !filteredStreams.length">
<div>
<ion-icon name="sad"></ion-icon>
<p>{{ t(`views.stream.streams.error`) }}</p>
</div>
</div>

<List class="list" :items="filteredStreams" @click="streamClick" v-show="filteredStreams.length">
<Loading class="loading" v-show="props.loading" />

<List class="list" :items="filteredStreams" @click="streamClick" v-show="!props.loading && filteredStreams.length">
<template #left="{ item }">
<div class="icon">
<img v-bind:src="item.icon" alt="">
Expand Down Expand Up @@ -49,11 +51,13 @@ import { useI18n } from 'vue-i18n';
import Title from '@/components/ui/Title.vue';
import Segments from '@/components/ui/Segments.vue';
import List from '@/components/ui/List.vue';
import Loading from '@/components/ui/Loading.vue';
const { t } = useI18n();
const props = defineProps({
streams: Array
streams: Array,
loading: Boolean,
});
const emit = defineEmits(['streamClick']);
Expand Down Expand Up @@ -110,6 +114,10 @@ const streamClick = (stream) => {
}
}
.loading {
height: 200px;
}
.list {
/deep/ .item {
align-items: flex-start;
Expand Down

0 comments on commit afda51b

Please sign in to comment.