2024-02-04 11:25:21 +00:00
|
|
|
import { For, Show, createSignal, lazy } from 'solid-js'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
import { MediaItem } from '~/types/mediaitem'
|
2023-07-01 13:05:59 +00:00
|
|
|
import { useLocalize } from '../../../context/localize'
|
2023-11-14 15:10:00 +00:00
|
|
|
import { getDescription } from '../../../utils/meta'
|
|
|
|
import { Icon } from '../../_shared/Icon'
|
|
|
|
import { Popover } from '../../_shared/Popover'
|
|
|
|
import { SharePopup, getShareUrl } from '../SharePopup'
|
|
|
|
|
|
|
|
import styles from './AudioPlayer.module.scss'
|
2023-07-01 13:05:59 +00:00
|
|
|
|
2023-11-18 14:10:02 +00:00
|
|
|
const SimplifiedEditor = lazy(() => import('../../Editor/SimplifiedEditor'))
|
|
|
|
const GrowingTextarea = lazy(() => import('../../_shared/GrowingTextarea/GrowingTextarea'))
|
|
|
|
|
2023-07-14 13:06:21 +00:00
|
|
|
type Props = {
|
2023-07-18 11:26:32 +00:00
|
|
|
media: MediaItem[]
|
|
|
|
currentTrackIndex: number
|
|
|
|
isPlaying: boolean
|
|
|
|
onPlayMedia: (trackIndex: number) => void
|
2023-07-14 13:06:21 +00:00
|
|
|
articleSlug?: string
|
|
|
|
body?: string
|
|
|
|
editorMode?: boolean
|
2023-07-18 11:26:32 +00:00
|
|
|
onMediaItemFieldChange?: (index: number, field: keyof MediaItem, value: string) => void
|
2024-06-24 17:50:27 +00:00
|
|
|
onChangeMediaIndex?: (direction: 'up' | 'down', index: number) => void
|
2023-07-14 13:06:21 +00:00
|
|
|
}
|
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const _getMediaTitle = (itm: MediaItem, idx: number) => `${idx}. ${itm.artist} - ${itm.title}`
|
2024-01-29 13:53:08 +00:00
|
|
|
|
2023-07-14 13:06:21 +00:00
|
|
|
export const PlayerPlaylist = (props: Props) => {
|
2023-07-01 13:05:59 +00:00
|
|
|
const { t } = useLocalize()
|
2023-07-14 13:06:21 +00:00
|
|
|
const [activeEditIndex, setActiveEditIndex] = createSignal(-1)
|
2023-07-01 13:05:59 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const toggleDropDown = (index: number) => {
|
2023-07-14 13:06:21 +00:00
|
|
|
setActiveEditIndex(activeEditIndex() === index ? -1 : index)
|
|
|
|
}
|
2023-07-18 11:26:32 +00:00
|
|
|
const handleMediaItemFieldChange = (field: keyof MediaItem, value: string) => {
|
2024-06-24 17:50:27 +00:00
|
|
|
props.onMediaItemFieldChange?.(activeEditIndex(), field, value)
|
2023-07-14 13:06:21 +00:00
|
|
|
}
|
2024-01-29 13:19:04 +00:00
|
|
|
|
2024-01-29 13:53:08 +00:00
|
|
|
const play = (index: number) => {
|
2024-03-20 11:59:07 +00:00
|
|
|
props.onPlayMedia(index)
|
2024-06-24 17:50:27 +00:00
|
|
|
//const mi = props.media[index]
|
|
|
|
//gtag('event', 'select_item', {
|
|
|
|
//item_list_id: props.articleSlug,
|
|
|
|
//item_list_name: getMediaTitle(mi, index),
|
|
|
|
//items: props.media.map((it, ix) => getMediaTitle(it, ix)),
|
|
|
|
//})
|
2024-01-29 13:19:04 +00:00
|
|
|
}
|
2023-07-01 13:05:59 +00:00
|
|
|
return (
|
|
|
|
<ul class={styles.playlist}>
|
2023-07-18 11:26:32 +00:00
|
|
|
<For each={props.media}>
|
|
|
|
{(mi, index) => (
|
2023-07-14 13:06:21 +00:00
|
|
|
<li>
|
|
|
|
<div class={styles.playlistItem}>
|
|
|
|
<button
|
|
|
|
class={styles.playlistItemPlayButton}
|
2024-01-29 13:19:04 +00:00
|
|
|
onClick={() => play(index())}
|
2023-07-14 13:06:21 +00:00
|
|
|
type="button"
|
|
|
|
aria-label="Play"
|
|
|
|
>
|
2023-07-18 11:26:32 +00:00
|
|
|
<Icon name={props.currentTrackIndex === index() && props.isPlaying ? 'pause' : 'play'} />
|
2023-07-14 13:06:21 +00:00
|
|
|
</button>
|
|
|
|
<div class={styles.playlistItemText}>
|
|
|
|
<Show
|
|
|
|
when={activeEditIndex() === index() && props.editorMode}
|
|
|
|
fallback={
|
|
|
|
<>
|
2024-01-18 08:44:01 +00:00
|
|
|
<div class={styles.title}>{mi.title || index()}</div>
|
|
|
|
<div class={styles.artist}>{mi.artist || ''}</div>
|
2023-07-14 13:06:21 +00:00
|
|
|
</>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
type="text"
|
2023-07-18 11:26:32 +00:00
|
|
|
value={mi.title}
|
2023-07-14 13:06:21 +00:00
|
|
|
class={styles.title}
|
|
|
|
placeholder={t('Song title')}
|
2023-07-18 11:26:32 +00:00
|
|
|
onChange={(e) => handleMediaItemFieldChange('title', e.target.value)}
|
2023-07-14 13:06:21 +00:00
|
|
|
/>
|
|
|
|
<input
|
|
|
|
type="text"
|
2023-07-18 11:26:32 +00:00
|
|
|
value={mi.artist}
|
2023-07-14 13:06:21 +00:00
|
|
|
class={styles.artist}
|
|
|
|
placeholder={t('Artist')}
|
2023-07-18 11:26:32 +00:00
|
|
|
onChange={(e) => handleMediaItemFieldChange('artist', e.target.value)}
|
2023-07-14 13:06:21 +00:00
|
|
|
/>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
<div class={styles.actions}>
|
2023-07-18 19:11:00 +00:00
|
|
|
<Show when={props.editorMode}>
|
|
|
|
<Popover content={t('Move up')}>
|
2024-06-24 17:50:27 +00:00
|
|
|
{(triggerRef: (el: HTMLElement) => void) => (
|
2023-07-18 19:11:00 +00:00
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
ref={triggerRef}
|
|
|
|
class={styles.action}
|
|
|
|
disabled={index() === 0}
|
2024-06-24 17:50:27 +00:00
|
|
|
onClick={() => props.onChangeMediaIndex?.('up', index())}
|
2023-07-18 19:11:00 +00:00
|
|
|
>
|
|
|
|
<Icon name="up-button" />
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</Popover>
|
|
|
|
<Popover content={t('Move down')}>
|
2024-06-24 17:50:27 +00:00
|
|
|
{(triggerRef: (el: HTMLElement) => void) => (
|
2023-07-18 19:11:00 +00:00
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
ref={triggerRef}
|
|
|
|
class={styles.action}
|
|
|
|
disabled={index() === props.media.length - 1}
|
2024-06-24 17:50:27 +00:00
|
|
|
onClick={() => props.onChangeMediaIndex?.('down', index())}
|
2023-07-18 19:11:00 +00:00
|
|
|
>
|
|
|
|
<Icon name="up-button" class={styles.moveIconDown} />
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</Popover>
|
|
|
|
</Show>
|
2023-07-18 11:26:32 +00:00
|
|
|
<Show when={(mi.lyrics || mi.body) && !props.editorMode}>
|
2023-07-14 13:06:21 +00:00
|
|
|
<Popover content={t('Show lyrics')}>
|
2024-06-24 17:50:27 +00:00
|
|
|
{(triggerRef: (el: HTMLElement) => void) => (
|
2023-07-14 13:06:21 +00:00
|
|
|
<button ref={triggerRef} type="button" onClick={() => toggleDropDown(index())}>
|
|
|
|
<Icon name="list" />
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</Popover>
|
|
|
|
</Show>
|
|
|
|
<Popover content={props.editorMode ? t('Edit') : t('Share')}>
|
2024-06-24 17:50:27 +00:00
|
|
|
{(triggerRef: (el: HTMLElement) => void) => (
|
2023-07-14 13:06:21 +00:00
|
|
|
<div ref={triggerRef}>
|
|
|
|
<Show
|
|
|
|
when={!props.editorMode}
|
|
|
|
fallback={
|
|
|
|
<button type="button" onClick={() => toggleDropDown(index())}>
|
|
|
|
<Icon name="pencil-stroke" />
|
|
|
|
</button>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<SharePopup
|
2023-07-18 11:26:32 +00:00
|
|
|
title={mi.title}
|
2024-06-24 17:50:27 +00:00
|
|
|
description={getDescription(props.body || '')}
|
|
|
|
imageUrl={mi.pic || ''}
|
2023-07-14 13:06:21 +00:00
|
|
|
shareUrl={getShareUrl({ pathname: `/${props.articleSlug}` })}
|
|
|
|
trigger={
|
|
|
|
<div>
|
|
|
|
<Icon name="share-media" />
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</Popover>
|
|
|
|
</div>
|
2023-07-01 13:05:59 +00:00
|
|
|
</div>
|
2023-07-14 13:06:21 +00:00
|
|
|
<Show when={activeEditIndex() === index()}>
|
|
|
|
<Show
|
|
|
|
when={props.editorMode}
|
|
|
|
fallback={
|
|
|
|
<div class={styles.descriptionBlock}>
|
2023-07-18 11:26:32 +00:00
|
|
|
<Show when={mi.body}>
|
2023-07-14 13:06:21 +00:00
|
|
|
<div class={styles.description}>
|
2023-11-13 17:14:58 +00:00
|
|
|
<div innerHTML={mi.body} />
|
2023-07-14 13:06:21 +00:00
|
|
|
</div>
|
|
|
|
</Show>
|
2023-07-18 11:26:32 +00:00
|
|
|
<Show when={mi.lyrics}>
|
2023-07-14 13:06:21 +00:00
|
|
|
<div class={styles.lyrics}>
|
2023-11-13 17:14:58 +00:00
|
|
|
<div innerHTML={mi.lyrics} />
|
2023-07-14 13:06:21 +00:00
|
|
|
</div>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<div class={styles.descriptionBlock}>
|
2023-07-24 08:58:07 +00:00
|
|
|
<SimplifiedEditor
|
|
|
|
initialContent={mi.body}
|
2023-08-16 13:11:58 +00:00
|
|
|
placeholder={`${t('Description')}...`}
|
2023-07-24 08:58:07 +00:00
|
|
|
smallHeight={true}
|
2023-08-17 10:36:27 +00:00
|
|
|
onChange={(value) => handleMediaItemFieldChange('body', value)}
|
2023-07-14 13:06:21 +00:00
|
|
|
/>
|
|
|
|
<GrowingTextarea
|
|
|
|
allowEnterKey={true}
|
|
|
|
class={styles.lyrics}
|
|
|
|
placeholder={t('Song lyrics')}
|
2023-07-18 11:26:32 +00:00
|
|
|
value={(value) => handleMediaItemFieldChange('lyrics', value)}
|
|
|
|
initialValue={mi.lyrics || ''}
|
2023-07-14 13:06:21 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Show>
|
|
|
|
</Show>
|
2023-07-01 13:05:59 +00:00
|
|
|
</li>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</ul>
|
|
|
|
)
|
|
|
|
}
|