Skip to content
Open
63 changes: 27 additions & 36 deletions src/components/ListviewItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,39 @@
@menu.stop="onMenu"
>
<template #prepend>
<div v-if="showCheckboxes" class="media-thumb listitem-media-thumb">
<v-checkbox
<div v-if="showCheckboxes" class="flex items-center space-x-2 checkbox">
<Checkbox
:id="`listviewitem-checkbox-${item.item_id}`"
:model-value="isSelected"
@click.stop
@update:model-value="
(x: boolean | null) => {
if (x != null) emit('select', item, x);
(x: boolean | 'indeterminate') => {
if (x != 'indeterminate') emit('select', item, x);
}
"
/>
<label :for="`listviewitem-checkbox-${item.item_id}`">
<ListviewItemTitle
:display-name="displayName"
:item="item"
:show-checkboxes="showCheckboxes"
:is-playing="isPlaying"
/>
</label>
</div>
<div v-else class="media-thumb listitem-media-thumb">
<MediaItemThumb size="50" :item="isAvailable ? item : undefined" />
</div>
</template>

<!-- title -->
<template #title>
<span v-if="item.media_type == MediaType.FOLDER">
<span>{{ getBrowseFolderName(item as BrowseFolder, t) }}</span>
</span>
<span v-else :class="{ 'is-playing': isPlaying }">
{{ displayName }}
<span v-if="'version' in item && item.version"
>({{ item.version }})</span
>
<span
v-if="
item.media_type == MediaType.TRACK && item.metadata?.release_date
"
>
({{ new Date(item.metadata.release_date).getFullYear() }})</span
>
</span>
<!-- explicit icon -->
<v-tooltip v-if="item && item.metadata" location="bottom">
<template #activator="{ props }">
<v-icon
v-if="parseBool(item.metadata.explicit || false)"
v-bind="props"
icon="mdi-alpha-e-box"
width="35"
/>
</template>
<span>{{ $t("tooltip.explicit") }}</span>
</v-tooltip>
<template v-if="!showCheckboxes" #title>
<ListviewItemTitle
:display-name="displayName"
:item="item"
:show-checkboxes="showCheckboxes"
:is-playing="isPlaying"
/>
</template>

<!-- subtitle -->
Expand Down Expand Up @@ -219,19 +206,16 @@ import NowPlayingBadge from "@/components/NowPlayingBadge.vue";
import {
formatDuration,
getArtistsString,
getBrowseFolderName,
getGenreDisplayName,
handleMediaItemClick,
handleMenuBtnClick,
handlePlayBtnClick,
parseBool,
truncateString,
} from "@/helpers/utils";
import {
AlbumType,
ContentType,
MediaType,
type BrowseFolder,
type MediaItemType,
} from "@/plugins/api/interfaces";
import { getBreakpointValue } from "@/plugins/breakpoint";
Expand All @@ -242,6 +226,9 @@ import MediaItemThumb from "./MediaItemThumb.vue";
import ProviderIcon from "./ProviderIcon.vue";
import { iconHiRes } from "./QualityDetailsBtn.vue";

import ListviewItemTitle from "./ListviewItemTitle.vue";
import { Checkbox } from "@/components/ui/checkbox";

// properties
export interface Props {
item: MediaItemType;
Expand Down Expand Up @@ -361,6 +348,10 @@ const onPlayClick = function (evt: PointerEvent) {
</script>

<style scoped>
.checkbox {
margin-bottom: 0.1em;
}

.unavailable {
opacity: 0.3;
}
Expand Down
85 changes: 85 additions & 0 deletions src/components/ListviewItemTitle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<template>
<span v-if="item.media_type == MediaType.FOLDER" class="checkbox-label">
<span>{{ getBrowseFolderName(item as BrowseFolder, t) }}</span>
</span>
<span v-else :class="{ 'is-playing': isPlaying }" class="checkbox-label">
{{ displayName }}
<span v-if="'version' in item && item.version"> ({{ item.version }}) </span>
<span
v-if="item.media_type == MediaType.TRACK && item.metadata?.release_date"
>
({{ new Date(item.metadata.release_date).getFullYear() }})
</span>
</span>
<!-- explicit icon -->
<template
v-if="item && item.metadata && parseBool(item.metadata.explicit || false)"
>
<TooltipProvider>
<Tooltip>
<TooltipTrigger as-child>
<span
:aria-label="t('tooltip.explicit')"
role="button"
tabindex="0"
>
<v-icon
:class="{ 'explicit-icon-margin-left': showCheckboxes }"
icon="mdi-alpha-e-box"
width="35"
/>
</span>
</TooltipTrigger>
<TooltipContent>
<span>{{ $t("tooltip.explicit") }}</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</template>
</template>

<script setup lang="ts">
import { getBrowseFolderName, parseBool } from "@/helpers/utils";
import {
MediaType,
type BrowseFolder,
type MediaItemType,
} from "@/plugins/api/interfaces";
import { useI18n } from "vue-i18n";

import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";

// properties
export interface Props {
displayName: string;
item: MediaItemType;
showCheckboxes: boolean;
isPlaying: boolean;
}

// global refs
const { t } = useI18n();

withDefaults(defineProps<Props>(), {
displayName: "",
showCheckboxes: false,
isPlaying: false,
});
</script>

<style scoped>
.checkbox-label {
font-weight: 500;
}

/* When checkbox is displayed, explicit icon will be shown to the right of the title.
This adds a bit of spacing between the title and the explicit icon. */
.explicit-icon-margin-left {
margin-left: 0.1em;
}
</style>
Loading