Add support for playlist bookmarks

This commit is contained in:
Bnyro 2023-01-06 19:30:28 +01:00
parent 11b3037775
commit d84580cf4f
5 changed files with 77 additions and 13 deletions

View File

@ -40,12 +40,13 @@ export default {
darkModePreference.addEventListener("change", () => { darkModePreference.addEventListener("change", () => {
this.setTheme(); this.setTheme();
}); });
if (this.getPreferenceBoolean("watchHistory", false))
if ("indexedDB" in window) { if ("indexedDB" in window) {
const request = indexedDB.open("piped-db", 2); const request = indexedDB.open("piped-db", 3);
request.onupgradeneeded = ev => { request.onupgradeneeded = ev => {
const db = request.result; const db = request.result;
console.log("Upgrading object store."); console.log("Upgrading object store.");
if (this.getPreferenceBoolean("watchHistory", false)) {
if (!db.objectStoreNames.contains("watch_history")) { if (!db.objectStoreNames.contains("watch_history")) {
const store = db.createObjectStore("watch_history", { keyPath: "videoId" }); const store = db.createObjectStore("watch_history", { keyPath: "videoId" });
store.createIndex("video_id_idx", "videoId", { unique: true }); store.createIndex("video_id_idx", "videoId", { unique: true });
@ -55,11 +56,17 @@ export default {
const store = request.transaction.objectStore("watch_history"); const store = request.transaction.objectStore("watch_history");
store.createIndex("watchedAt", "watchedAt", { unique: false }); store.createIndex("watchedAt", "watchedAt", { unique: false });
} }
}; }
request.onsuccess = e => { if (!db.objectStoreNames.contains("playlist_bookmarks")) {
window.db = e.target.result; const store = db.createObjectStore("playlist_bookmarks", { keyPath: "playlistId" });
}; store.createIndex("playlist_id_idx", "playlistId", { unique: true });
} else console.log("This browser doesn't support IndexedDB"); store.createIndex("id_idx", "id", { unique: true, autoIncrement: true });
}
};
request.onsuccess = e => {
window.db = e.target.result;
};
} else console.log("This browser doesn't support IndexedDB");
const App = this; const App = this;

View File

@ -14,6 +14,9 @@
<div> <div>
<strong v-text="`${playlist.videos} ${$t('video.videos')}`" /> <strong v-text="`${playlist.videos} ${$t('video.videos')}`" />
<br /> <br />
<button class="btn mr-1" v-if="!isPipedPlaylist" @click="bookmarkPlaylist">
{{ $t("actions.bookmark_playlist") }}<font-awesome-icon class="ml-3" icon="bookmark" />
</button>
<button class="btn mr-1" v-if="authenticated && !isPipedPlaylist" @click="clonePlaylist"> <button class="btn mr-1" v-if="authenticated && !isPipedPlaylist" @click="clonePlaylist">
{{ $t("actions.clone_playlist") }}<font-awesome-icon class="ml-3" icon="clone" /> {{ $t("actions.clone_playlist") }}<font-awesome-icon class="ml-3" icon="clone" />
</button> </button>
@ -144,6 +147,23 @@ export default {
}); });
this.download(data, this.playlist.name + ".txt", "text/plain"); this.download(data, this.playlist.name + ".txt", "text/plain");
}, },
async bookmarkPlaylist() {
if (!this.playlist) return;
if (window.db) {
const playlistId = this.$route.query.list;
var tx = window.db.transaction("playlist_bookmarks", "readwrite");
var store = tx.objectStore("playlist_bookmarks");
store.put({
playlistId: playlistId,
name: this.playlist.name,
uploader: this.playlist.uploader,
uploaderUrl: this.playlist.uploaderUrl,
thumbnail: this.playlist.thumbnailUrl,
uploaderAvatar: this.playlist.uploaderAvatar,
videos: this.playlist.videos,
});
}
},
}, },
}; };
</script> </script>

View File

@ -39,6 +39,25 @@
</div> </div>
</div> </div>
<br /> <br />
<div v-if="bookmarks" class="video-grid">
<router-link v-for="playlist in bookmarks" :key="playlist.id" :to="`/playlist?list=${playlist.id}`">
<img class="w-full" :src="playlist.thumbnail" alt="thumbnail" />
<div class="relative text-sm">
<span class="thumbnail-overlay thumbnail-right" v-text="`${playlist.videos} ${$t('video.videos')}`" />
</div>
<p
style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical"
class="my-2 overflow-hidden flex link"
:title="playlist.name"
v-text="playlist.name"
/>
<div class="flex">
<img class="rounded-full" src="" alt="" />
</div>
</router-link>
</div>
<br />
</template> </template>
<script> <script>
@ -46,11 +65,12 @@ export default {
data() { data() {
return { return {
playlists: [], playlists: [],
bookmarks: [],
}; };
}, },
mounted() { mounted() {
if (this.authenticated) this.fetchPlaylists(); if (this.authenticated) this.fetchPlaylists();
else this.$router.push("/login"); this.loadPlaylistBookmarks();
}, },
activated() { activated() {
document.title = this.$t("titles.playlists") + " - Piped"; document.title = this.$t("titles.playlists") + " - Piped";
@ -201,6 +221,20 @@ export default {
}, },
}); });
}, },
async loadPlaylistBookmarks() {
if (!window.db) return;
var tx = window.db.transaction("playlist_bookmarks", "readonly");
var store = tx.objectStore("playlist_bookmarks");
const cursorRequest = store.openCursor();
cursorRequest.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const bookmark = cursor.value;
this.bookmarks.push(bookmark);
cursor.continue();
}
};
},
}, },
}; };
</script> </script>

View File

@ -120,7 +120,8 @@
"instance_donations": "Instance donations", "instance_donations": "Instance donations",
"reply_count": "{count} replies", "reply_count": "{count} replies",
"no_valid_playlists": "The file doesn't contain valid playlists!", "no_valid_playlists": "The file doesn't contain valid playlists!",
"with_playlist": "Share with playlist" "with_playlist": "Share with playlist",
"bookmark_playlist": "Bookmark"
}, },
"comment": { "comment": {
"pinned_by": "Pinned by {author}", "pinned_by": "Pinned by {author}",

View File

@ -20,6 +20,7 @@ import {
faBook, faBook,
faServer, faServer,
faDonate, faDonate,
faBookmark,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { faGithub, faBitcoin, faYoutube } from "@fortawesome/free-brands-svg-icons"; import { faGithub, faBitcoin, faYoutube } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
@ -46,6 +47,7 @@ library.add(
faBook, faBook,
faServer, faServer,
faDonate, faDonate,
faBookmark,
); );
import router from "@/router/router.js"; import router from "@/router/router.js";