mirror of
https://github.com/TeamPiped/Piped.git
synced 2026-03-28 03:16:58 +00:00
132 lines
4.1 KiB
Vue
132 lines
4.1 KiB
Vue
<template>
|
|
<ModalComponent>
|
|
<div class="min-w-max flex flex-col">
|
|
<h2 v-t="'actions.export_history'" class="mb-4 text-center text-xl font-bold" />
|
|
<form>
|
|
<div>
|
|
<label v-t="'actions.file_format'" class="mr-2" for="export-format" />
|
|
<select id="export-format" v-model="exportAs" class="select">
|
|
<option
|
|
v-for="option in exportOptions"
|
|
:key="option"
|
|
:value="option"
|
|
v-text="formatField(option)"
|
|
/>
|
|
</select>
|
|
</div>
|
|
<div v-if="exportAs === 'history'">
|
|
<label v-for="field in fields" :key="field" class="flex items-center gap-2">
|
|
<input
|
|
v-model="selectedFields"
|
|
class="checkbox"
|
|
type="checkbox"
|
|
:value="field"
|
|
:disabled="field === 'videoId'"
|
|
/>
|
|
<span v-text="formatField(field)" />
|
|
</label>
|
|
</div>
|
|
</form>
|
|
<button class="btn mt-4" @click="handleExport" v-text="$t('actions.export')" />
|
|
</div>
|
|
</ModalComponent>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from "vue";
|
|
import ModalComponent from "./ModalComponent.vue";
|
|
import { download } from "@/composables/useMisc.js";
|
|
|
|
const exportOptions = ["playlist", "history"];
|
|
const exportAs = ref("playlist");
|
|
const fields = ["videoId", "title", "uploaderName", "uploaderUrl", "duration", "thumbnail", "watchedAt", "currentTime"];
|
|
const selectedFields = ref([
|
|
"videoId",
|
|
"title",
|
|
"uploaderName",
|
|
"uploaderUrl",
|
|
"duration",
|
|
"thumbnail",
|
|
"watchedAt",
|
|
"currentTime",
|
|
]);
|
|
|
|
let exportVideos = [];
|
|
|
|
async function fetchAllVideos() {
|
|
if (window.db) {
|
|
var tx = window.db.transaction("watch_history", "readonly");
|
|
var store = tx.objectStore("watch_history");
|
|
const request = store.getAll();
|
|
return new Promise((resolve, reject) => {
|
|
((request.onsuccess = e => {
|
|
const videos = e.target.result;
|
|
exportVideos = videos;
|
|
resolve();
|
|
}),
|
|
(request.onerror = e => {
|
|
reject(e);
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
|
|
function handleExport() {
|
|
if (exportAs.value === "playlist") {
|
|
fetchAllVideos()
|
|
.then(() => {
|
|
exportAsPlaylist();
|
|
})
|
|
.catch(e => {
|
|
console.error(e);
|
|
});
|
|
} else if (exportAs.value === "history") {
|
|
fetchAllVideos()
|
|
.then(() => {
|
|
exportAsHistory();
|
|
})
|
|
.catch(e => {
|
|
console.error(e);
|
|
});
|
|
}
|
|
}
|
|
|
|
function exportAsPlaylist() {
|
|
const dateStr = new Date().toISOString().split(".")[0];
|
|
let json = {
|
|
format: "Piped",
|
|
version: 1,
|
|
playlists: [
|
|
{
|
|
name: `Piped History ${dateStr}`,
|
|
type: "history",
|
|
visibility: "private",
|
|
videos: exportVideos.map(video => "https://youtube.com" + video.url),
|
|
},
|
|
],
|
|
};
|
|
download(JSON.stringify(json), `piped_history_${dateStr}.json`, "application/json");
|
|
}
|
|
|
|
function exportAsHistory() {
|
|
const dateStr = new Date().toISOString().split(".")[0];
|
|
let json = {
|
|
format: "Piped",
|
|
version: 1,
|
|
watchHistory: exportVideos.map(video => {
|
|
let obj = {};
|
|
selectedFields.value.forEach(field => {
|
|
obj[field] = video[field];
|
|
});
|
|
return obj;
|
|
}),
|
|
};
|
|
download(JSON.stringify(json), `piped_history_${dateStr}.json`, "application/json");
|
|
}
|
|
|
|
function formatField(field) {
|
|
// camelCase to Title Case
|
|
return field.replace(/([A-Z])/g, " $1").replace(/^./, str => str.toUpperCase());
|
|
}
|
|
</script>
|