|
@@ -1,3 +1,347 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { useStore } from "vuex";
|
|
|
+import { useRoute, useRouter } from "vue-router";
|
|
|
+import { ref, computed, onMounted, onBeforeUnmount } from "vue";
|
|
|
+import { Sortable } from "sortablejs-vue3";
|
|
|
+import Toast from "toasters";
|
|
|
+import keyboardShortcuts from "@/keyboardShortcuts";
|
|
|
+import ws from "@/ws";
|
|
|
+
|
|
|
+const store = useStore();
|
|
|
+const route = useRoute();
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const loggedIn = computed(() => store.state.user.auth.loggedIn);
|
|
|
+const userId = computed(() => store.state.user.auth.userId);
|
|
|
+const role = computed(() => store.state.user.auth.role);
|
|
|
+
|
|
|
+const { socket } = store.state.websockets;
|
|
|
+
|
|
|
+const stations = ref([]);
|
|
|
+const searchQuery = ref("");
|
|
|
+const siteSettings = ref({
|
|
|
+ logo_white: "",
|
|
|
+ sitename: "Musare",
|
|
|
+ registrationDisabled: false
|
|
|
+});
|
|
|
+const orderOfFavoriteStations = ref([]);
|
|
|
+const handledLoginRegisterRedirect = ref(false);
|
|
|
+const changeFavoriteOrderDebounceTimeout = ref();
|
|
|
+
|
|
|
+const isOwner = station => loggedIn.value && station.owner === userId.value;
|
|
|
+
|
|
|
+const isAdmin = () => loggedIn.value && role.value === "admin";
|
|
|
+
|
|
|
+const isOwnerOrAdmin = station => isOwner(station) || isAdmin();
|
|
|
+
|
|
|
+const isPlaying = station => typeof station.currentSong.title !== "undefined";
|
|
|
+
|
|
|
+const filteredStations = computed(() => {
|
|
|
+ const privacyOrder = ["public", "unlisted", "private"];
|
|
|
+ return stations.value
|
|
|
+ .filter(
|
|
|
+ station =>
|
|
|
+ JSON.stringify(Object.values(station)).indexOf(
|
|
|
+ searchQuery.value
|
|
|
+ ) !== -1
|
|
|
+ )
|
|
|
+ .sort(
|
|
|
+ (a, b) =>
|
|
|
+ isOwner(b) - isOwner(a) ||
|
|
|
+ isPlaying(b) - isPlaying(a) ||
|
|
|
+ a.paused - b.paused ||
|
|
|
+ privacyOrder.indexOf(a.privacy) -
|
|
|
+ privacyOrder.indexOf(b.privacy) ||
|
|
|
+ b.userCount - a.userCount
|
|
|
+ );
|
|
|
+});
|
|
|
+
|
|
|
+const dragOptions = computed(() => ({
|
|
|
+ animation: 200,
|
|
|
+ group: "favoriteStations",
|
|
|
+ disabled: false,
|
|
|
+ ghostClass: "draggable-list-ghost",
|
|
|
+ filter: ".ignore-elements",
|
|
|
+ fallbackTolerance: 50
|
|
|
+}));
|
|
|
+
|
|
|
+const favoriteStations = computed(() =>
|
|
|
+ filteredStations.value
|
|
|
+ .filter(station => station.isFavorited === true)
|
|
|
+ .sort(
|
|
|
+ (a, b) =>
|
|
|
+ orderOfFavoriteStations.value.indexOf(a._id) -
|
|
|
+ orderOfFavoriteStations.value.indexOf(b._id)
|
|
|
+ )
|
|
|
+);
|
|
|
+
|
|
|
+const openModal = payload =>
|
|
|
+ store.dispatch("modalVisibility/openModal", payload);
|
|
|
+
|
|
|
+const init = () => {
|
|
|
+ socket.dispatch(
|
|
|
+ "stations.index",
|
|
|
+ route.query.adminFilter === undefined,
|
|
|
+ res => {
|
|
|
+ stations.value = [];
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ res.data.stations.forEach(station => {
|
|
|
+ const modifiableStation = station;
|
|
|
+
|
|
|
+ if (!modifiableStation.currentSong)
|
|
|
+ modifiableStation.currentSong = {
|
|
|
+ thumbnail: "/assets/notes-transparent.png"
|
|
|
+ };
|
|
|
+
|
|
|
+ if (
|
|
|
+ modifiableStation.currentSong &&
|
|
|
+ !modifiableStation.currentSong.thumbnail
|
|
|
+ )
|
|
|
+ modifiableStation.currentSong.ytThumbnail = `https://img.youtube.com/vi/${station.currentSong.youtubeId}/mqdefault.jpg`;
|
|
|
+
|
|
|
+ stations.value.push(modifiableStation);
|
|
|
+ });
|
|
|
+
|
|
|
+ orderOfFavoriteStations.value = res.data.favorited;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ socket.dispatch("apis.joinRoom", "home");
|
|
|
+};
|
|
|
+
|
|
|
+const canRequest = (station, requireLogin = true) =>
|
|
|
+ station &&
|
|
|
+ (!requireLogin || loggedIn.value) &&
|
|
|
+ station.requests &&
|
|
|
+ station.requests.enabled &&
|
|
|
+ (station.requests.access === "user" ||
|
|
|
+ (station.requests.access === "owner" && isOwnerOrAdmin(station)));
|
|
|
+
|
|
|
+const favoriteStation = stationId => {
|
|
|
+ socket.dispatch("stations.favoriteStation", stationId, res => {
|
|
|
+ if (res.status === "success") {
|
|
|
+ new Toast("Successfully favorited station.");
|
|
|
+ } else new Toast(res.message);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const unfavoriteStation = stationId => {
|
|
|
+ socket.dispatch("stations.unfavoriteStation", stationId, res => {
|
|
|
+ if (res.status === "success") {
|
|
|
+ new Toast("Successfully unfavorited station.");
|
|
|
+ } else new Toast(res.message);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const changeFavoriteOrder = ({ oldIndex, newIndex }) => {
|
|
|
+ if (changeFavoriteOrderDebounceTimeout.value)
|
|
|
+ clearTimeout(changeFavoriteOrderDebounceTimeout.value);
|
|
|
+
|
|
|
+ changeFavoriteOrderDebounceTimeout.value = setTimeout(() => {
|
|
|
+ if (oldIndex === newIndex) return;
|
|
|
+ favoriteStations.value.splice(
|
|
|
+ newIndex,
|
|
|
+ 0,
|
|
|
+ favoriteStations.value.splice(oldIndex, 1)[0]
|
|
|
+ );
|
|
|
+
|
|
|
+ const recalculatedOrder = [];
|
|
|
+ favoriteStations.value.forEach(station =>
|
|
|
+ recalculatedOrder.push(station._id)
|
|
|
+ );
|
|
|
+
|
|
|
+ socket.dispatch(
|
|
|
+ "users.updateOrderOfFavoriteStations",
|
|
|
+ recalculatedOrder,
|
|
|
+ res => new Toast(res.message)
|
|
|
+ );
|
|
|
+ }, 100);
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ siteSettings.value = await lofig.get("siteSettings");
|
|
|
+
|
|
|
+ if (route.query.searchQuery) searchQuery.value = route.query.query;
|
|
|
+
|
|
|
+ if (
|
|
|
+ !loggedIn.value &&
|
|
|
+ route.redirectedFrom &&
|
|
|
+ (route.redirectedFrom.name === "login" ||
|
|
|
+ route.redirectedFrom.name === "register") &&
|
|
|
+ !handledLoginRegisterRedirect.value
|
|
|
+ ) {
|
|
|
+ // Makes sure the login/register modal isn't opened whenever the home page gets remounted due to a code change
|
|
|
+ handledLoginRegisterRedirect.value = true;
|
|
|
+ openModal(route.redirectedFrom.name);
|
|
|
+ }
|
|
|
+
|
|
|
+ ws.onConnect(init);
|
|
|
+
|
|
|
+ socket.on("event:station.created", res => {
|
|
|
+ const { station } = res.data;
|
|
|
+
|
|
|
+ if (stations.value.find(_station => _station._id === station._id)) {
|
|
|
+ stations.value.forEach(s => {
|
|
|
+ const _station = s;
|
|
|
+ if (_station._id === station._id) {
|
|
|
+ _station.privacy = station.privacy;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ if (!station.currentSong)
|
|
|
+ station.currentSong = {
|
|
|
+ thumbnail: "/assets/notes-transparent.png"
|
|
|
+ };
|
|
|
+ if (station.currentSong && !station.currentSong.thumbnail)
|
|
|
+ station.currentSong.ytThumbnail = `https://img.youtube.com/vi/${station.currentSong.youtubeId}/mqdefault.jpg`;
|
|
|
+ stations.value.push(station);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.deleted", res => {
|
|
|
+ const { stationId } = res.data;
|
|
|
+
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) {
|
|
|
+ const stationIndex = stations.value.indexOf(station);
|
|
|
+ stations.value.splice(stationIndex, 1);
|
|
|
+
|
|
|
+ if (station.isFavorited)
|
|
|
+ orderOfFavoriteStations.value =
|
|
|
+ orderOfFavoriteStations.value.filter(
|
|
|
+ favoritedId => favoritedId !== stationId
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.userCount.updated", res => {
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === res.data.stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) station.userCount = res.data.userCount;
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.updated", res => {
|
|
|
+ const stationIndex = stations.value
|
|
|
+ .map(station => station._id)
|
|
|
+ .indexOf(res.data.station._id);
|
|
|
+
|
|
|
+ if (stationIndex !== -1) {
|
|
|
+ stations.value[stationIndex] = {
|
|
|
+ ...stations.value[stationIndex],
|
|
|
+ ...res.data.station
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.nextSong", res => {
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === res.data.stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) {
|
|
|
+ let newSong = res.data.currentSong;
|
|
|
+
|
|
|
+ if (!newSong)
|
|
|
+ newSong = {
|
|
|
+ thumbnail: "/assets/notes-transparent.png"
|
|
|
+ };
|
|
|
+
|
|
|
+ station.currentSong = newSong;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.pause", res => {
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === res.data.stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) station.paused = true;
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:station.resume", res => {
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === res.data.stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) station.paused = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:user.station.favorited", res => {
|
|
|
+ const { stationId } = res.data;
|
|
|
+
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) {
|
|
|
+ station.isFavorited = true;
|
|
|
+ orderOfFavoriteStations.value.push(stationId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:user.station.unfavorited", res => {
|
|
|
+ const { stationId } = res.data;
|
|
|
+
|
|
|
+ const station = stations.value.find(
|
|
|
+ station => station._id === stationId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (station) {
|
|
|
+ station.isFavorited = false;
|
|
|
+ orderOfFavoriteStations.value =
|
|
|
+ orderOfFavoriteStations.value.filter(
|
|
|
+ favoritedId => favoritedId !== stationId
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ socket.on("event:user.orderOfFavoriteStations.updated", res => {
|
|
|
+ orderOfFavoriteStations.value = res.data.order;
|
|
|
+ });
|
|
|
+
|
|
|
+ // ctrl + alt + f
|
|
|
+ keyboardShortcuts.registerShortcut("home.toggleAdminFilter", {
|
|
|
+ keyCode: 70,
|
|
|
+ ctrl: true,
|
|
|
+ alt: true,
|
|
|
+ handler: () => {
|
|
|
+ if (isAdmin())
|
|
|
+ if (route.query.adminFilter === undefined)
|
|
|
+ router.push({
|
|
|
+ query: {
|
|
|
+ ...route.query,
|
|
|
+ adminFilter: null
|
|
|
+ }
|
|
|
+ });
|
|
|
+ else
|
|
|
+ router.push({
|
|
|
+ query: {
|
|
|
+ ...route.query,
|
|
|
+ adminFilter: undefined
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ socket.dispatch("apis.leaveRoom", "home", () => {});
|
|
|
+
|
|
|
+ const shortcutNames = ["home.toggleAdminFilter"];
|
|
|
+
|
|
|
+ shortcutNames.forEach(shortcutName => {
|
|
|
+ keyboardShortcuts.unregisterShortcut(shortcutName);
|
|
|
+ });
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
<template>
|
|
|
<div>
|
|
|
<page-metadata title="Home" />
|
|
@@ -46,11 +390,11 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <draggable
|
|
|
+ <sortable
|
|
|
item-key="_id"
|
|
|
- v-model="favoriteStations"
|
|
|
- v-bind="dragOptions"
|
|
|
- @change="changeFavoriteOrder"
|
|
|
+ :list="favoriteStations"
|
|
|
+ :options="dragOptions"
|
|
|
+ @update="changeFavoriteOrder"
|
|
|
>
|
|
|
<template #item="{ element }">
|
|
|
<router-link
|
|
@@ -265,7 +609,7 @@
|
|
|
</div>
|
|
|
</router-link>
|
|
|
</template>
|
|
|
- </draggable>
|
|
|
+ </sortable>
|
|
|
</div>
|
|
|
<div class="group bottom">
|
|
|
<div class="group-title">
|
|
@@ -514,365 +858,6 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
-<script>
|
|
|
-import { mapState, mapGetters, mapActions } from "vuex";
|
|
|
-import draggable from "vuedraggable";
|
|
|
-import Toast from "toasters";
|
|
|
-
|
|
|
-import ws from "@/ws";
|
|
|
-import keyboardShortcuts from "@/keyboardShortcuts";
|
|
|
-
|
|
|
-export default {
|
|
|
- components: {
|
|
|
- draggable
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- recaptcha: { key: "" },
|
|
|
- stations: [],
|
|
|
- favoriteStations: [],
|
|
|
- searchQuery: "",
|
|
|
- siteSettings: {
|
|
|
- logo_white: "",
|
|
|
- sitename: "Musare",
|
|
|
- registrationDisabled: false
|
|
|
- },
|
|
|
- orderOfFavoriteStations: [],
|
|
|
- handledLoginRegisterRedirect: false,
|
|
|
- editingStationId: null
|
|
|
- };
|
|
|
- },
|
|
|
- computed: {
|
|
|
- ...mapState({
|
|
|
- loggedIn: state => state.user.auth.loggedIn,
|
|
|
- userId: state => state.user.auth.userId,
|
|
|
- role: state => state.user.auth.role,
|
|
|
- modals: state => state.modalVisibility.modals
|
|
|
- }),
|
|
|
- ...mapGetters({
|
|
|
- socket: "websockets/getSocket"
|
|
|
- }),
|
|
|
- filteredStations() {
|
|
|
- const privacyOrder = ["public", "unlisted", "private"];
|
|
|
- return this.stations
|
|
|
- .filter(
|
|
|
- station =>
|
|
|
- JSON.stringify(Object.values(station)).indexOf(
|
|
|
- this.searchQuery
|
|
|
- ) !== -1
|
|
|
- )
|
|
|
- .sort(
|
|
|
- (a, b) =>
|
|
|
- this.isOwner(b) - this.isOwner(a) ||
|
|
|
- this.isPlaying(b) - this.isPlaying(a) ||
|
|
|
- a.paused - b.paused ||
|
|
|
- privacyOrder.indexOf(a.privacy) -
|
|
|
- privacyOrder.indexOf(b.privacy) ||
|
|
|
- b.userCount - a.userCount
|
|
|
- );
|
|
|
- },
|
|
|
- dragOptions() {
|
|
|
- return {
|
|
|
- animation: 200,
|
|
|
- group: "favoriteStations",
|
|
|
- disabled: false,
|
|
|
- ghostClass: "draggable-list-ghost",
|
|
|
- filter: ".ignore-elements",
|
|
|
- fallbackTolerance: 50
|
|
|
- };
|
|
|
- }
|
|
|
- },
|
|
|
- watch: {
|
|
|
- orderOfFavoriteStations: {
|
|
|
- deep: true,
|
|
|
- handler() {
|
|
|
- this.calculateFavoriteStations();
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- async mounted() {
|
|
|
- this.siteSettings = await lofig.get("siteSettings");
|
|
|
-
|
|
|
- if (this.$route.query.searchQuery)
|
|
|
- this.searchQuery = this.$route.query.query;
|
|
|
-
|
|
|
- if (
|
|
|
- !this.loggedIn &&
|
|
|
- this.$route.redirectedFrom &&
|
|
|
- (this.$route.redirectedFrom.name === "login" ||
|
|
|
- this.$route.redirectedFrom.name === "register") &&
|
|
|
- !this.handledLoginRegisterRedirect
|
|
|
- ) {
|
|
|
- // Makes sure the login/register modal isn't opened whenever the home page gets remounted due to a code change
|
|
|
- this.handledLoginRegisterRedirect = true;
|
|
|
- this.openModal(this.$route.redirectedFrom.name);
|
|
|
- }
|
|
|
-
|
|
|
- ws.onConnect(this.init);
|
|
|
-
|
|
|
- this.socket.on("event:station.created", res => {
|
|
|
- const { station } = res.data;
|
|
|
-
|
|
|
- if (this.stations.find(_station => _station._id === station._id)) {
|
|
|
- this.stations.forEach(s => {
|
|
|
- const _station = s;
|
|
|
- if (_station._id === station._id) {
|
|
|
- _station.privacy = station.privacy;
|
|
|
- }
|
|
|
- });
|
|
|
- } else {
|
|
|
- if (!station.currentSong)
|
|
|
- station.currentSong = {
|
|
|
- thumbnail: "/assets/notes-transparent.png"
|
|
|
- };
|
|
|
- if (station.currentSong && !station.currentSong.thumbnail)
|
|
|
- station.currentSong.ytThumbnail = `https://img.youtube.com/vi/${station.currentSong.youtubeId}/mqdefault.jpg`;
|
|
|
- this.stations.push(station);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.deleted", res => {
|
|
|
- const { stationId } = res.data;
|
|
|
-
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) {
|
|
|
- const stationIndex = this.stations.indexOf(station);
|
|
|
- this.stations.splice(stationIndex, 1);
|
|
|
-
|
|
|
- if (station.isFavorited)
|
|
|
- this.orderOfFavoriteStations =
|
|
|
- this.orderOfFavoriteStations.filter(
|
|
|
- favoritedId => favoritedId !== stationId
|
|
|
- );
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.userCount.updated", res => {
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === res.data.stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) station.userCount = res.data.userCount;
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.updated", res => {
|
|
|
- const stationIndex = this.stations
|
|
|
- .map(station => station._id)
|
|
|
- .indexOf(res.data.station._id);
|
|
|
-
|
|
|
- if (stationIndex !== -1) {
|
|
|
- this.stations[stationIndex] = {
|
|
|
- ...this.stations[stationIndex],
|
|
|
- ...res.data.station
|
|
|
- };
|
|
|
-
|
|
|
- this.calculateFavoriteStations();
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.nextSong", res => {
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === res.data.stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) {
|
|
|
- let newSong = res.data.currentSong;
|
|
|
-
|
|
|
- if (!newSong)
|
|
|
- newSong = {
|
|
|
- thumbnail: "/assets/notes-transparent.png"
|
|
|
- };
|
|
|
-
|
|
|
- station.currentSong = newSong;
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.pause", res => {
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === res.data.stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) station.paused = true;
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:station.resume", res => {
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === res.data.stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) station.paused = false;
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:user.station.favorited", res => {
|
|
|
- const { stationId } = res.data;
|
|
|
-
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) {
|
|
|
- station.isFavorited = true;
|
|
|
- this.orderOfFavoriteStations.push(stationId);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:user.station.unfavorited", res => {
|
|
|
- const { stationId } = res.data;
|
|
|
-
|
|
|
- const station = this.stations.find(
|
|
|
- station => station._id === stationId
|
|
|
- );
|
|
|
-
|
|
|
- if (station) {
|
|
|
- station.isFavorited = false;
|
|
|
- this.orderOfFavoriteStations =
|
|
|
- this.orderOfFavoriteStations.filter(
|
|
|
- favoritedId => favoritedId !== stationId
|
|
|
- );
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- this.socket.on("event:user.orderOfFavoriteStations.updated", res => {
|
|
|
- this.orderOfFavoriteStations = res.data.order;
|
|
|
- });
|
|
|
-
|
|
|
- // ctrl + alt + f
|
|
|
- keyboardShortcuts.registerShortcut("home.toggleAdminFilter", {
|
|
|
- keyCode: 70,
|
|
|
- ctrl: true,
|
|
|
- alt: true,
|
|
|
- handler: () => {
|
|
|
- if (this.isAdmin())
|
|
|
- if (this.$route.query.adminFilter === undefined)
|
|
|
- this.$router.push({
|
|
|
- query: {
|
|
|
- ...this.$route.query,
|
|
|
- adminFilter: null
|
|
|
- }
|
|
|
- });
|
|
|
- else
|
|
|
- this.$router.push({
|
|
|
- query: {
|
|
|
- ...this.$route.query,
|
|
|
- adminFilter: undefined
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- beforeUnmount() {
|
|
|
- this.socket.dispatch("apis.leaveRoom", "home", () => {});
|
|
|
-
|
|
|
- const shortcutNames = ["home.toggleAdminFilter"];
|
|
|
-
|
|
|
- shortcutNames.forEach(shortcutName => {
|
|
|
- keyboardShortcuts.unregisterShortcut(shortcutName);
|
|
|
- });
|
|
|
- },
|
|
|
- methods: {
|
|
|
- init() {
|
|
|
- this.socket.dispatch(
|
|
|
- "stations.index",
|
|
|
- this.$route.query.adminFilter === undefined,
|
|
|
- res => {
|
|
|
- this.stations = [];
|
|
|
-
|
|
|
- if (res.status === "success") {
|
|
|
- res.data.stations.forEach(station => {
|
|
|
- const modifiableStation = station;
|
|
|
-
|
|
|
- if (!modifiableStation.currentSong)
|
|
|
- modifiableStation.currentSong = {
|
|
|
- thumbnail: "/assets/notes-transparent.png"
|
|
|
- };
|
|
|
-
|
|
|
- if (
|
|
|
- modifiableStation.currentSong &&
|
|
|
- !modifiableStation.currentSong.thumbnail
|
|
|
- )
|
|
|
- modifiableStation.currentSong.ytThumbnail = `https://img.youtube.com/vi/${station.currentSong.youtubeId}/mqdefault.jpg`;
|
|
|
-
|
|
|
- this.stations.push(modifiableStation);
|
|
|
- });
|
|
|
-
|
|
|
- this.orderOfFavoriteStations = res.data.favorited;
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- this.socket.dispatch("apis.joinRoom", "home");
|
|
|
- },
|
|
|
- isOwner(station) {
|
|
|
- return this.loggedIn && station.owner === this.userId;
|
|
|
- },
|
|
|
- isAdmin() {
|
|
|
- return this.loggedIn && this.role === "admin";
|
|
|
- },
|
|
|
- isOwnerOrAdmin(station) {
|
|
|
- return this.isOwner(station) || this.isAdmin();
|
|
|
- },
|
|
|
- canRequest(station, requireLogin = true) {
|
|
|
- return (
|
|
|
- station &&
|
|
|
- (!requireLogin || this.loggedIn) &&
|
|
|
- station.requests &&
|
|
|
- station.requests.enabled &&
|
|
|
- (station.requests.access === "user" ||
|
|
|
- (station.requests.access === "owner" &&
|
|
|
- this.isOwnerOrAdmin(station)))
|
|
|
- );
|
|
|
- },
|
|
|
- isPlaying(station) {
|
|
|
- return typeof station.currentSong.title !== "undefined";
|
|
|
- },
|
|
|
- favoriteStation(stationId) {
|
|
|
- this.socket.dispatch("stations.favoriteStation", stationId, res => {
|
|
|
- if (res.status === "success") {
|
|
|
- new Toast("Successfully favorited station.");
|
|
|
- } else new Toast(res.message);
|
|
|
- });
|
|
|
- },
|
|
|
- unfavoriteStation(stationId) {
|
|
|
- this.socket.dispatch(
|
|
|
- "stations.unfavoriteStation",
|
|
|
- stationId,
|
|
|
- res => {
|
|
|
- if (res.status === "success") {
|
|
|
- new Toast("Successfully unfavorited station.");
|
|
|
- } else new Toast(res.message);
|
|
|
- }
|
|
|
- );
|
|
|
- },
|
|
|
- calculateFavoriteStations() {
|
|
|
- this.favoriteStations = this.filteredStations
|
|
|
- .filter(station => station.isFavorited === true)
|
|
|
- .sort(
|
|
|
- (a, b) =>
|
|
|
- this.orderOfFavoriteStations.indexOf(a._id) -
|
|
|
- this.orderOfFavoriteStations.indexOf(b._id)
|
|
|
- );
|
|
|
- },
|
|
|
- changeFavoriteOrder() {
|
|
|
- const recalculatedOrder = [];
|
|
|
- this.favoriteStations.forEach(station =>
|
|
|
- recalculatedOrder.push(station._id)
|
|
|
- );
|
|
|
-
|
|
|
- this.socket.dispatch(
|
|
|
- "users.updateOrderOfFavoriteStations",
|
|
|
- recalculatedOrder,
|
|
|
- res => new Toast(res.message)
|
|
|
- );
|
|
|
- },
|
|
|
- ...mapActions("modalVisibility", ["openModal"]),
|
|
|
- ...mapActions("station", ["updateIfStationIsFavorited"])
|
|
|
- }
|
|
|
-};
|
|
|
-</script>
|
|
|
-
|
|
|
<style lang="less">
|
|
|
.christmas-mode .home-page {
|
|
|
.header .overlay {
|