Merge pull request #2192 from Bnyro/loading-indicators

Loading indicators
This commit is contained in:
Bnyro 2023-03-14 19:25:53 +01:00 committed by GitHub
commit b3b9feb6ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 17 deletions

View file

@ -1,7 +1,7 @@
<template> <template>
<ErrorHandler v-if="channel && channel.error" :message="channel.message" :error="channel.error" /> <ErrorHandler v-if="channel && channel.error" :message="channel.message" :error="channel.error" />
<div v-if="channel" v-show="!channel.error"> <LoadingIndicatorPage :show-content="channel != null && !channel.error">
<div class="flex justify-center place-items-center"> <div class="flex justify-center place-items-center">
<img height="48" width="48" class="rounded-full m-1" :src="channel.avatarUrl" /> <img height="48" width="48" class="rounded-full m-1" :src="channel.avatarUrl" />
<h1 v-text="channel.name" /> <h1 v-text="channel.name" />
@ -61,19 +61,21 @@
hide-channel hide-channel
/> />
</div> </div>
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
import ErrorHandler from "./ErrorHandler.vue"; import ErrorHandler from "./ErrorHandler.vue";
import ContentItem from "./ContentItem.vue"; import ContentItem from "./ContentItem.vue";
import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue"; import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
export default { export default {
components: { components: {
ErrorHandler, ErrorHandler,
ContentItem, ContentItem,
WatchOnYouTubeButton, WatchOnYouTubeButton,
LoadingIndicatorPage,
}, },
data() { data() {
return { return {

View file

@ -24,27 +24,29 @@
<hr /> <hr />
<div class="video-grid"> <LoadingIndicatorPage :show-content="videosStore != null" class="video-grid">
<template v-for="video in videos" :key="video.url"> <template v-for="video in videos" :key="video.url">
<VideoItem v-if="shouldShowVideo(video)" :is-feed="true" :item="video" /> <VideoItem v-if="shouldShowVideo(video)" :is-feed="true" :item="video" />
</template> </template>
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
import VideoItem from "./VideoItem.vue"; import VideoItem from "./VideoItem.vue";
import SortingSelector from "./SortingSelector.vue"; import SortingSelector from "./SortingSelector.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
export default { export default {
components: { components: {
VideoItem, VideoItem,
SortingSelector, SortingSelector,
LoadingIndicatorPage,
}, },
data() { data() {
return { return {
currentVideoCount: 0, currentVideoCount: 0,
videoStep: 100, videoStep: 100,
videosStore: [], videosStore: null,
videos: [], videos: [],
availableFilters: ["all", "shorts", "videos"], availableFilters: ["all", "shorts", "videos"],
selectedFilter: "all", selectedFilter: "all",

View file

@ -0,0 +1,55 @@
<template>
<div v-if="!showContent" class="flex min-h-[75vh] w-full justify-center items-center">
<span id="spinner" />
</div>
<div v-else>
<slot />
</div>
</template>
<style>
#spinner:after {
--spinner-color: #000;
}
.dark #spinner:after {
--spinner-color: #fff;
}
#spinner {
display: inline-block;
width: 70px;
height: 70px;
}
#spinner:after {
content: " ";
display: block;
width: 54px;
height: 54px;
margin: 8px;
border-radius: 50%;
border: 4px solid var(--spinner-color);
border-color: var(--spinner-color) transparent var(--spinner-color) transparent;
animation: spinner 1.2s linear infinite;
}
@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<script>
export default {
props: {
showContent: {
type: Boolean,
required: true,
},
},
};
</script>

View file

@ -1,7 +1,7 @@
<template> <template>
<ErrorHandler v-if="playlist && playlist.error" :message="playlist.message" :error="playlist.error" /> <ErrorHandler v-if="playlist && playlist.error" :message="playlist.message" :error="playlist.error" />
<div v-if="playlist" v-show="!playlist.error"> <LoadingIndicatorPage :show-content="playlist" v-show="!playlist.error">
<h1 class="text-center my-4" v-text="playlist.name" /> <h1 class="text-center my-4" v-text="playlist.name" />
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
@ -46,11 +46,12 @@
width="168" width="168"
/> />
</div> </div>
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
import ErrorHandler from "./ErrorHandler.vue"; import ErrorHandler from "./ErrorHandler.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
import VideoItem from "./VideoItem.vue"; import VideoItem from "./VideoItem.vue";
import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue"; import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue";
@ -59,6 +60,7 @@ export default {
ErrorHandler, ErrorHandler,
VideoItem, VideoItem,
WatchOnYouTubeButton, WatchOnYouTubeButton,
LoadingIndicatorPage,
}, },
data() { data() {
return { return {

View file

@ -18,19 +18,21 @@
</i18n-t> </i18n-t>
</div> </div>
<div v-if="results" class="video-grid"> <LoadingIndicatorPage :show-content="results != null && results.items?.length" class="video-grid">
<template v-for="result in results.items" :key="result.url"> <template v-for="result in results.items" :key="result.url">
<ContentItem :item="result" height="94" width="168" /> <ContentItem :item="result" height="94" width="168" />
</template> </template>
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
import ContentItem from "./ContentItem.vue"; import ContentItem from "./ContentItem.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
export default { export default {
components: { components: {
ContentItem, ContentItem,
LoadingIndicatorPage,
}, },
data() { data() {
return { return {

View file

@ -3,17 +3,19 @@
<hr /> <hr />
<div class="video-grid"> <LoadingIndicatorPage :show-content="videos.length != 0" class="video-grid">
<VideoItem v-for="video in videos" :key="video.url" :item="video" height="118" width="210" /> <VideoItem v-for="video in videos" :key="video.url" :item="video" height="118" width="210" />
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
import VideoItem from "./VideoItem.vue"; import VideoItem from "./VideoItem.vue";
export default { export default {
components: { components: {
VideoItem, VideoItem,
LoadingIndicatorPage,
}, },
data() { data() {
return { return {

View file

@ -12,7 +12,7 @@
/> />
</div> </div>
<div v-if="video && !isEmbed" class="w-full"> <LoadingIndicatorPage :show-content="video && !isEmbed" class="w-full">
<ErrorHandler v-if="video && video.error" :message="video.message" :error="video.error" /> <ErrorHandler v-if="video && video.error" :message="video.message" :error="video.error" />
<div v-show="!video.error"> <div v-show="!video.error">
@ -217,7 +217,7 @@
<hr class="sm:hidden" /> <hr class="sm:hidden" />
</div> </div>
</div> </div>
</div> </LoadingIndicatorPage>
</template> </template>
<script> <script>
@ -230,6 +230,7 @@ import PlaylistAddModal from "./PlaylistAddModal.vue";
import ShareModal from "./ShareModal.vue"; import ShareModal from "./ShareModal.vue";
import PlaylistVideos from "./PlaylistVideos.vue"; import PlaylistVideos from "./PlaylistVideos.vue";
import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue"; import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue";
import LoadingIndicatorPage from "./LoadingIndicatorPage.vue";
export default { export default {
name: "App", name: "App",
@ -243,13 +244,12 @@ export default {
ShareModal, ShareModal,
PlaylistVideos, PlaylistVideos,
WatchOnYouTubeButton, WatchOnYouTubeButton,
LoadingIndicatorPage,
}, },
data() { data() {
const smallViewQuery = window.matchMedia("(max-width: 640px)"); const smallViewQuery = window.matchMedia("(max-width: 640px)");
return { return {
video: { video: null,
title: "Loading...",
},
playlistId: null, playlistId: null,
playlist: null, playlist: null,
index: null, index: null,
@ -351,7 +351,7 @@ export default {
this.showDesc = !this.getPreferenceBoolean("minimizeDescription", false); this.showDesc = !this.getPreferenceBoolean("minimizeDescription", false);
this.showRecs = !this.getPreferenceBoolean("minimizeRecommendations", false); this.showRecs = !this.getPreferenceBoolean("minimizeRecommendations", false);
this.showChapters = !this.getPreferenceBoolean("minimizeChapters", false); this.showChapters = !this.getPreferenceBoolean("minimizeChapters", false);
if (this.video.duration) { if (this.video?.duration) {
document.title = this.video.title + " - Piped"; document.title = this.video.title + " - Piped";
this.$refs.videoPlayer.loadVideo(); this.$refs.videoPlayer.loadVideo();
} }