浏览代码

feat: Add youtube search item component

Owen Diffey 2 天之前
父节点
当前提交
e535afa82e
共有 1 个文件被更改,包括 175 次插入0 次删除
  1. 175 0
      frontend/src/pages/NewStation/Components/YoutubeSearchItem.vue

+ 175 - 0
frontend/src/pages/NewStation/Components/YoutubeSearchItem.vue

@@ -0,0 +1,175 @@
+<script lang="ts" setup>
+import { defineAsyncComponent, ref } from "vue";
+import { useModalsStore } from "@/stores/modals";
+
+const AddToPlaylistDropdown = defineAsyncComponent(
+	() => import("@/pages/NewStation/Components/AddToPlaylistDropdown.vue")
+);
+const Button = defineAsyncComponent(
+	() => import("@/pages/NewStation/Components/Button.vue")
+);
+const DropdownList = defineAsyncComponent(
+	() => import("@/pages/NewStation/Components/DropdownList.vue")
+);
+const DropdownListItem = defineAsyncComponent(
+	() => import("@/pages/NewStation/Components/DropdownListItem.vue")
+);
+const SongThumbnail = defineAsyncComponent(
+	() => import("@/components/SongThumbnail.vue")
+);
+
+const props = defineProps<{
+	item: {
+		id: string;
+		url: string;
+		title: string;
+		thumbnail: string;
+		channelId: string;
+		channelTitle: string;
+		isAddedToQueue: boolean;
+	};
+}>();
+
+const { openModal } = useModalsStore();
+
+const actions = ref();
+
+const expandActions = () => {
+	actions.value.expand();
+};
+
+const collapseActions = () => {
+	actions.value.collapse();
+};
+
+const view = () => {
+	collapseActions();
+
+	openModal({
+		modal: "viewMedia",
+		props: { mediaSource: `youtube:${props.item.id}` }
+	});
+};
+
+defineExpose({
+	expandActions,
+	collapseActions
+});
+</script>
+
+<template>
+	<div class="youtube-search-item">
+		<SongThumbnail
+			:song="{
+				thumbnail: item.thumbnail,
+				youtubeId: item.id
+			}"
+		/>
+		<div class="youtube-search-item__content">
+			<p class="youtube-search-item__title" :title="item.title">
+				{{ item.title }}
+			</p>
+			<a
+				v-if="item.channelTitle && item.channelId"
+				class="youtube-search-item__channel"
+				:title="item.channelTitle"
+				:href="'https://youtube.com/channel/' + item.channelId"
+				target="_blank"
+			>
+				{{ item.channelTitle }}
+			</a>
+		</div>
+		<slot name="featuredAction" />
+		<DropdownList ref="actions">
+			<Button icon="more_horiz" square inverse title="Actions" />
+
+			<template #options>
+				<slot name="actions" />
+
+				<DropdownListItem>
+					<AddToPlaylistDropdown :media-source="`youtube:${item.id}`">
+						<button class="dropdown-list-item__action">
+							<span
+								class="material-icons dropdown-list-item__icon"
+								aria-hidden="true"
+							>
+								playlist_add
+							</span>
+							Add to playlist
+						</button>
+					</AddToPlaylistDropdown>
+				</DropdownListItem>
+				<DropdownListItem
+					icon="play_arrow"
+					label="View media"
+					@click="view"
+				/>
+			</template>
+		</DropdownList>
+	</div>
+</template>
+
+<style lang="less" scoped>
+.youtube-search-item {
+	display: flex;
+	align-items: center;
+	flex-shrink: 0;
+	height: 48px;
+	background-color: var(--white);
+	border-radius: 5px;
+	border: solid 1px var(--light-grey-1);
+	gap: 5px;
+	overflow: hidden;
+
+	:deep(.thumbnail) {
+		height: 48px;
+		min-width: 48px;
+		flex-shrink: 0;
+		margin: 0;
+	}
+
+	&__content {
+		display: flex;
+		flex-direction: column;
+		flex-grow: 1;
+		min-width: 0;
+		justify-content: center;
+	}
+
+	&__title {
+		font-size: 11.75px !important;
+		line-height: 14px;
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-box-orient: vertical;
+		-webkit-line-clamp: 2;
+		word-wrap: break-word;
+	}
+
+	&__channel {
+		display: inline-flex;
+		align-items: center;
+		align-self: start;
+		font-size: 10px !important;
+		font-weight: 500 !important;
+		line-height: 12px;
+		color: var(--dark-grey-1);
+		overflow: hidden;
+		text-overflow: ellipsis;
+		white-space: nowrap;
+	}
+
+	& > :deep(.dropdown-list__reference) {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		padding-right: 5px;
+	}
+
+	:deep(.dropdown-list-item > .dropdown-list__reference) {
+		display: flex;
+		flex-grow: 1;
+	}
+}
+</style>