mirror of
				https://github.com/TeamPiped/Piped.git
				synced 2024-08-14 23:57:27 +00:00 
			
		
		
		
	add countdown until next video
This commit is contained in:
		
							parent
							
								
									2134e82efe
								
							
						
					
					
						commit
						e46cbadc51
					
				
					 4 changed files with 119 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -45,6 +45,16 @@
 | 
			
		|||
            @change="onChange($event)"
 | 
			
		||||
        />
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="chkAutoPlayNextCountdown">
 | 
			
		||||
        <strong v-t="'actions.autoplay_next_countdown'" />
 | 
			
		||||
        <input
 | 
			
		||||
            id="chkAutoPlayNextCountdown"
 | 
			
		||||
            v-model="autoPlayNextCountdown"
 | 
			
		||||
            class="input w-24"
 | 
			
		||||
            type="number"
 | 
			
		||||
            @change="onChange($event)"
 | 
			
		||||
        />
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="chkAudioOnly">
 | 
			
		||||
        <strong v-t="'actions.audio_only'" />
 | 
			
		||||
        <input id="chkAudioOnly" v-model="listen" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
| 
						 | 
				
			
			@ -346,6 +356,7 @@ export default {
 | 
			
		|||
            minSegmentLength: 0,
 | 
			
		||||
            selectedTheme: "dark",
 | 
			
		||||
            autoPlayVideo: true,
 | 
			
		||||
            autoPlayNextCountdown: 5,
 | 
			
		||||
            listen: false,
 | 
			
		||||
            resolutions: [144, 240, 360, 480, 720, 1080, 1440, 2160, 4320],
 | 
			
		||||
            defaultQuality: 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -461,6 +472,7 @@ export default {
 | 
			
		|||
            this.minSegmentLength = Math.max(this.getPreferenceNumber("minSegmentLength", 0), 0);
 | 
			
		||||
            this.selectedTheme = this.getPreferenceString("theme", "dark");
 | 
			
		||||
            this.autoPlayVideo = this.getPreferenceBoolean("playerAutoPlay", true);
 | 
			
		||||
            this.autoPlayNextCountdown = this.getPreferenceNumber("autoPlayNextCountdown", 5);
 | 
			
		||||
            this.listen = this.getPreferenceBoolean("listen", false);
 | 
			
		||||
            this.defaultQuality = Number(localStorage.getItem("quality"));
 | 
			
		||||
            this.bufferingGoal = Math.max(Number(localStorage.getItem("bufferGoal")), 10);
 | 
			
		||||
| 
						 | 
				
			
			@ -515,6 +527,7 @@ export default {
 | 
			
		|||
                localStorage.setItem("minSegmentLength", this.minSegmentLength);
 | 
			
		||||
                localStorage.setItem("theme", this.selectedTheme);
 | 
			
		||||
                localStorage.setItem("playerAutoPlay", this.autoPlayVideo);
 | 
			
		||||
                localStorage.setItem("autoPlayNextCountdown", this.autoPlayNextCountdown);
 | 
			
		||||
                localStorage.setItem("listen", this.listen);
 | 
			
		||||
                localStorage.setItem("quality", this.defaultQuality);
 | 
			
		||||
                localStorage.setItem("bufferGoal", this.bufferingGoal);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								src/components/ToastComponent.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/components/ToastComponent.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div class="toast">
 | 
			
		||||
        <slot />
 | 
			
		||||
        <button @click="dismiss" v-t="'actions.dismiss'" />
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
    methods: {
 | 
			
		||||
        dismiss() {
 | 
			
		||||
            this.$emit("dismissed");
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.toast {
 | 
			
		||||
    @apply bg-dark-900/80 text-white flex flex-col justify-center fixed top-12 right-12 p-4 min-w-max shadow rounded duration-200 z-9999;
 | 
			
		||||
}
 | 
			
		||||
.toast button {
 | 
			
		||||
    @apply underline;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -4,8 +4,6 @@
 | 
			
		|||
            ref="videoPlayer"
 | 
			
		||||
            :video="video"
 | 
			
		||||
            :sponsors="sponsors"
 | 
			
		||||
            :playlist="playlist"
 | 
			
		||||
            :index="index"
 | 
			
		||||
            :selected-auto-play="false"
 | 
			
		||||
            :selected-auto-loop="selectedAutoLoop"
 | 
			
		||||
            :is-embed="isEmbed"
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +12,11 @@
 | 
			
		|||
 | 
			
		||||
    <div v-if="video && !isEmbed" class="w-full">
 | 
			
		||||
        <ErrorHandler v-if="video && video.error" :message="video.message" :error="video.error" />
 | 
			
		||||
        <Transition>
 | 
			
		||||
            <ToastComponent v-if="shouldShowToast" @dismissed="dismiss">
 | 
			
		||||
                <i18n-t keypath="info.next_video_countdown">{{ counter }}</i18n-t>
 | 
			
		||||
            </ToastComponent>
 | 
			
		||||
        </Transition>
 | 
			
		||||
 | 
			
		||||
        <div v-show="!video.error">
 | 
			
		||||
            <div :class="isMobile ? 'flex-col' : 'flex'">
 | 
			
		||||
| 
						 | 
				
			
			@ -21,11 +24,10 @@
 | 
			
		|||
                    ref="videoPlayer"
 | 
			
		||||
                    :video="video"
 | 
			
		||||
                    :sponsors="sponsors"
 | 
			
		||||
                    :playlist="playlist"
 | 
			
		||||
                    :index="index"
 | 
			
		||||
                    :selected-auto-play="selectedAutoPlay"
 | 
			
		||||
                    :selected-auto-loop="selectedAutoLoop"
 | 
			
		||||
                    @timeupdate="onTimeUpdate"
 | 
			
		||||
                    @ended="onVideoEnded"
 | 
			
		||||
                />
 | 
			
		||||
                <ChaptersBar
 | 
			
		||||
                    :mobileLayout="isMobile"
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +232,7 @@ import PlaylistAddModal from "./PlaylistAddModal.vue";
 | 
			
		|||
import ShareModal from "./ShareModal.vue";
 | 
			
		||||
import PlaylistVideos from "./PlaylistVideos.vue";
 | 
			
		||||
import WatchOnYouTubeButton from "./WatchOnYouTubeButton.vue";
 | 
			
		||||
import ToastComponent from "./ToastComponent.vue";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    name: "App",
 | 
			
		||||
| 
						 | 
				
			
			@ -243,6 +246,7 @@ export default {
 | 
			
		|||
        ShareModal,
 | 
			
		||||
        PlaylistVideos,
 | 
			
		||||
        WatchOnYouTubeButton,
 | 
			
		||||
        ToastComponent,
 | 
			
		||||
    },
 | 
			
		||||
    data() {
 | 
			
		||||
        const smallViewQuery = window.matchMedia("(max-width: 640px)");
 | 
			
		||||
| 
						 | 
				
			
			@ -270,6 +274,9 @@ export default {
 | 
			
		|||
            showShareModal: false,
 | 
			
		||||
            isMobile: true,
 | 
			
		||||
            currentTime: 0,
 | 
			
		||||
            shouldShowToast: false,
 | 
			
		||||
            timeoutCounter: null,
 | 
			
		||||
            counter: 0,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
| 
						 | 
				
			
			@ -291,6 +298,9 @@ export default {
 | 
			
		|||
                year: "numeric",
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        defaultCounter(_this) {
 | 
			
		||||
            return _this.getPreferenceNumber("autoPlayNextCountdown", 5);
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    mounted() {
 | 
			
		||||
        // check screen size
 | 
			
		||||
| 
						 | 
				
			
			@ -560,6 +570,68 @@ export default {
 | 
			
		|||
        onTimeUpdate(time) {
 | 
			
		||||
            this.currentTime = time;
 | 
			
		||||
        },
 | 
			
		||||
        onVideoEnded() {
 | 
			
		||||
            if (
 | 
			
		||||
                !this.selectedAutoLoop &&
 | 
			
		||||
                this.selectedAutoPlay &&
 | 
			
		||||
                (this.playlist?.relatedStreams?.length > 0 || this.video.relatedStreams.length > 0)
 | 
			
		||||
            ) {
 | 
			
		||||
                this.showToast();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        showToast() {
 | 
			
		||||
            this.counter = this.defaultCounter;
 | 
			
		||||
            if (this.counter < 1) {
 | 
			
		||||
                this.navigateNext();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.timeoutCounter) clearInterval(this.timeoutCounter);
 | 
			
		||||
            this.timeoutCounter = setInterval(() => {
 | 
			
		||||
                this.counter--;
 | 
			
		||||
                if (this.counter === 0) {
 | 
			
		||||
                    this.dismiss();
 | 
			
		||||
                    this.navigateNext();
 | 
			
		||||
                }
 | 
			
		||||
            }, 1000);
 | 
			
		||||
            this.shouldShowToast = true;
 | 
			
		||||
        },
 | 
			
		||||
        dismiss() {
 | 
			
		||||
            clearInterval(this.timeoutCounter);
 | 
			
		||||
            this.shouldShowToast = false;
 | 
			
		||||
        },
 | 
			
		||||
        navigateNext() {
 | 
			
		||||
            const params = this.$route.query;
 | 
			
		||||
            let url = this.playlist?.relatedStreams?.[this.index]?.url ?? this.video.relatedStreams[0].url;
 | 
			
		||||
            const searchParams = new URLSearchParams();
 | 
			
		||||
            for (var param in params)
 | 
			
		||||
                switch (param) {
 | 
			
		||||
                    case "v":
 | 
			
		||||
                    case "t":
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "index":
 | 
			
		||||
                        if (this.index < this.playlist.relatedStreams.length) searchParams.set("index", this.index + 1);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "list":
 | 
			
		||||
                        if (this.index < this.playlist.relatedStreams.length) searchParams.set("list", params.list);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        searchParams.set(param, params[param]);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            // save the fullscreen state
 | 
			
		||||
            searchParams.set("fullscreen", this.$refs.videoPlayer.$ui.getControls().isFullScreenEnabled());
 | 
			
		||||
            const paramStr = searchParams.toString();
 | 
			
		||||
            if (paramStr.length > 0) url += "&" + paramStr;
 | 
			
		||||
            this.$router.push(url);
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.v-enter-from,
 | 
			
		||||
.v-leave-to {
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    transform: translateX(100%) scale(0.5);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@
 | 
			
		|||
        "dark": "Dark",
 | 
			
		||||
        "light": "Light",
 | 
			
		||||
        "autoplay_video": "Autoplay Video",
 | 
			
		||||
        "autoplay_next_countdown": "Default Countdown until next video (in seconds)",
 | 
			
		||||
        "audio_only": "Audio Only",
 | 
			
		||||
        "default_quality": "Default Quality",
 | 
			
		||||
        "buffering_goal": "Buffering Goal (in seconds)",
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +128,8 @@
 | 
			
		|||
        "no_valid_playlists": "The file doesn't contain valid playlists!",
 | 
			
		||||
        "with_playlist": "Share with playlist",
 | 
			
		||||
        "bookmark_playlist": "Bookmark",
 | 
			
		||||
        "playlist_bookmarked": "Bookmarked"
 | 
			
		||||
        "playlist_bookmarked": "Bookmarked",
 | 
			
		||||
        "dismiss": "Dismiss"
 | 
			
		||||
    },
 | 
			
		||||
    "comment": {
 | 
			
		||||
        "pinned_by": "Pinned by {author}",
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +182,7 @@
 | 
			
		|||
        "copied": "Copied!",
 | 
			
		||||
        "cannot_copy": "Can't copy!",
 | 
			
		||||
        "local_storage": "This action requires localStorage, are cookies enabled?",
 | 
			
		||||
        "register_no_email_note": "Using an e-mail as username is not recommended. Proceed anyways?"
 | 
			
		||||
        "register_no_email_note": "Using an e-mail as username is not recommended. Proceed anyways?",
 | 
			
		||||
        "next_video_countdown": "Playing next video in {0}s"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue