Update efy branch from master

This commit is contained in:
dragos-efy
2023-09-06 00:59:52 +03:00
41 changed files with 1310 additions and 1026 deletions

View File

@@ -1,8 +1,8 @@
<template>
<ModalComponent>
<ModalComponent @close="$emit('close')">
<h4 v-t="'actions.select_playlist'" class="mb-2" />
<select class="select w-full mb-2" v-model="selectedPlaylist">
<option v-for="playlist in playlists" :value="playlist.id" :key="playlist.id" v-text="playlist.name" />
<select v-model="selectedPlaylist" class="select w-full mb-2">
<option v-for="playlist in playlists" :key="playlist.id" :value="playlist.id" v-text="playlist.name" />
</select>
<div class="flex justify-end">
<button ref="addButton" v-t="'actions.create_playlist'" class="btn" @click="onCreatePlaylist" />

View File

@@ -4,8 +4,15 @@
<button v-t="'actions.create_playlist'" class="btn mr-2" @click="onCreatePlaylist" />
<div class="flex">
<button v-if="playlists.length > 0" v-t="'actions.export_to_json'" @click="exportPlaylists" />
<input id="fileSelector" ref="fileSelector" type="file" class="display-none" @change="importPlaylists" />
<label for="fileSelector" v-t="'actions.import_from_json'" class="btn ml-2" role="button" />
<input
id="fileSelector"
ref="fileSelector"
type="file"
class="display-none"
multiple="multiple"
@change="importPlaylists"
/>
<label v-t="'actions.import_from_json_csv'" for="fileSelector" class="btn ml-2" role="button" />
</div>
</div>

View File

@@ -1,10 +1,26 @@
<template>
<div class="flex justify-between w-full">
<div class="flex">
<button class="btn mr-2">
<router-link to="/import" v-t="'actions.import_from_json'" />
</button>
<button v-t="'actions.export_to_json'" class="btn" @click="exportHandler" />
<!-- import / export section -->
<div class="w-full flex justify-between">
<div class="flex gap-2">
<router-link v-t="'actions.import_from_json_csv'" to="/import" role="button" />
<button v-t="'actions.export_to_json'" @click="exportHandler" />
<input
id="fileSelector"
ref="fileSelector"
type="file"
class="display-none"
multiple="multiple"
@change="importGroupsHandler"
/>
<label
for="fileSelector"
role="button"
v-text="`${$t('actions.import_from_json')} (${$t('titles.channel_groups')})`"
/>
<button
@click="exportGroupsHandler"
v-text="`${$t('actions.export_to_json')} (${$t('titles.channel_groups')})`"
/>
</div>
<i18n-t keypath="subscriptions.subscribed_channels_count">{{ subscriptions.length }}</i18n-t>
</div>
@@ -13,7 +29,7 @@
<button
v-for="group in channelGroups"
:key="group.groupName"
class="btn mx-1 w-max"
class="mx-1 w-max"
:class="{ selected: selectedGroup === group }"
@click="selectGroup(group)"
>
@@ -239,6 +255,24 @@ export default {
: this.selectedGroup.channels.concat(channelId);
this.createOrUpdateChannelGroup(this.selectedGroup);
},
async importGroupsHandler() {
const files = this.$refs.fileSelector.files;
for (let file of files) {
const groups = JSON.parse(await file.text()).groups;
for (let group of groups) {
this.createOrUpdateChannelGroup(group);
this.channelGroups.push(group);
}
}
},
exportGroupsHandler() {
const json = {
format: "Piped",
version: 1,
groups: this.channelGroups.slice(1),
};
this.download(JSON.stringify(json), "channel_groups.json", "application/json");
},
},
};
</script>

View File

@@ -25,6 +25,11 @@
<span v-t="'actions.skip_segment'" />
<i class="material-icons-round">skip_next</i>
</button>
<span
v-if="error > 0"
v-t="{ path: 'player.failed', args: [error] }"
class="absolute top-8 rounded bg-black/80 p-2 text-lg backdrop-blur-sm"
/>
</div>
</template>
@@ -67,6 +72,7 @@ export default {
isHoveringTimebar: false,
currentTime: 0,
seekbarPadding: 2,
error: 0,
};
},
computed: {
@@ -510,6 +516,9 @@ export default {
manifest: {
disableVideo: disableVideo,
},
streaming: {
segmentPrefetchLimit: 10,
},
});
const quality = this.getPreferenceNumber("quality", 0);
@@ -517,73 +526,79 @@ export default {
quality > 0 && (this.video.audioStreams.length > 0 || this.video.livestream) && !disableVideo;
if (qualityConds) this.$player.configure("abr.enabled", false);
player.load(uri, 0, mime).then(() => {
const isSafari = window.navigator?.vendor?.includes("Apple");
player
.load(uri, 0, mime)
.then(() => {
const isSafari = window.navigator?.vendor?.includes("Apple");
if (!isSafari) {
// Set the audio language
const prefLang = this.getPreferenceString("hl", "en").substr(0, 2);
var lang = "en";
for (var l in player.getAudioLanguages()) {
if (l == prefLang) {
lang = l;
return;
}
}
player.selectAudioLanguage(lang);
}
if (qualityConds) {
var leastDiff = Number.MAX_VALUE;
var bestStream = null;
var bestAudio = 0;
const tracks = player
.getVariantTracks()
.filter(track => track.language == lang || track.language == "und");
// Choose the best audio stream
if (quality >= 480)
tracks.forEach(track => {
const audioBandwidth = track.audioBandwidth;
if (audioBandwidth > bestAudio) bestAudio = audioBandwidth;
});
// Find best matching stream based on resolution and bitrate
tracks
.sort((a, b) => a.bandwidth - b.bandwidth)
.forEach(stream => {
if (stream.audioBandwidth < bestAudio) return;
const diff = Math.abs(quality - stream.height);
if (diff < leastDiff) {
leastDiff = diff;
bestStream = stream;
if (!isSafari) {
// Set the audio language
const prefLang = this.getPreferenceString("hl", "en").substr(0, 2);
var lang = "en";
for (var l in player.getAudioLanguages()) {
if (l == prefLang) {
lang = l;
return;
}
});
}
player.selectAudioLanguage(lang);
}
player.selectVariantTrack(bestStream);
}
if (qualityConds) {
var leastDiff = Number.MAX_VALUE;
var bestStream = null;
this.video.subtitles.map(subtitle => {
player.addTextTrackAsync(
subtitle.url,
subtitle.code,
"subtitles",
subtitle.mimeType,
null,
subtitle.name,
);
var bestAudio = 0;
const tracks = player
.getVariantTracks()
.filter(track => track.language == lang || track.language == "und");
// Choose the best audio stream
if (quality >= 480)
tracks.forEach(track => {
const audioBandwidth = track.audioBandwidth;
if (audioBandwidth > bestAudio) bestAudio = audioBandwidth;
});
// Find best matching stream based on resolution and bitrate
tracks
.sort((a, b) => a.bandwidth - b.bandwidth)
.forEach(stream => {
if (stream.audioBandwidth < bestAudio) return;
const diff = Math.abs(quality - stream.height);
if (diff < leastDiff) {
leastDiff = diff;
bestStream = stream;
}
});
player.selectVariantTrack(bestStream);
}
this.video.subtitles.map(subtitle => {
player.addTextTrackAsync(
subtitle.url,
subtitle.code,
"subtitles",
subtitle.mimeType,
null,
subtitle.name,
);
});
videoEl.volume = this.getPreferenceNumber("volume", 1);
const rate = this.getPreferenceNumber("rate", 1);
videoEl.playbackRate = rate;
videoEl.defaultPlaybackRate = rate;
const autoDisplayCaptions = this.getPreferenceBoolean("autoDisplayCaptions", false);
this.$player.setTextTrackVisibility(autoDisplayCaptions);
})
.catch(e => {
console.error(e);
this.error = e.code;
});
videoEl.volume = this.getPreferenceNumber("volume", 1);
const rate = this.getPreferenceNumber("rate", 1);
videoEl.playbackRate = rate;
videoEl.defaultPlaybackRate = rate;
const autoDisplayCaptions = this.getPreferenceBoolean("autoDisplayCaptions", false);
this.$player.setTextTrackVisibility(autoDisplayCaptions);
});
// expand the player to fullscreen when the fullscreen query equals true
if (this.$route.query.fullscreen === "true" && !this.$ui.getControls().isFullScreenEnabled())

View File

@@ -90,10 +90,15 @@
@click="subscribeHandler"
/>
<!-- Playlist Add button -->
<button v-if="authenticated" class="btn" @click="showModal = !showModal">
<button class="btn flex items-center" @click="showModal = !showModal">
{{ $t("actions.add_to_playlist") }}<font-awesome-icon class="ml-1" icon="circle-plus" />
</button>
<PlaylistAddModal v-if="showModal" :video-id="getVideoId()" @close="showModal = !showModal" />
<PlaylistAddModal
v-if="showModal"
:video-id="getVideoId()"
:video-info="video"
@close="showModal = !showModal"
/>
<!-- Share Dialog -->
<ShareModal
v-if="showShareModal"
@@ -133,6 +138,9 @@
>
<font-awesome-icon class="mx-1.5" icon="rss" />
</a>
<button class="btn flex items-center gap-1 <md:hidden" @click="downloadCurrentFrame">
<i class="i-fa6-solid:download" />{{ $t("actions.download_frame") }}
</button>
</div>
</div>
@@ -674,6 +682,21 @@ export default {
if (paramStr.length > 0) url += "&" + paramStr;
this.$router.push(url);
},
downloadCurrentFrame() {
const video = document.querySelector("video");
const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const context = canvas.getContext("2d");
context.drawImage(video, 0, 0, canvas.width, canvas.height);
let link = document.createElement("a");
const currentTime = Math.round(video.currentTime * 1000) / 1000;
link.download = `${this.video.title}_${currentTime}s.png`;
link.href = canvas.toDataURL();
link.click();
},
},
};
</script>