media-audio-view
This commit is contained in:
parent
9b4cede871
commit
d0a165c3f4
|
@ -1,4 +1,6 @@
|
||||||
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg" width="512px" height="512px" viewBox="0 0 512 512">
|
||||||
<path d="M13 6C13 7.65685 11.6569 9 10 9C8.34315 9 7 7.65685 7 6C7 4.34315 8.34315 3 10 3C11.6569 3 13 4.34315 13 6Z" fill="#141414"/>
|
<path
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.7784 6.5C16.6611 8.44191 13.9671 11 10 11C6.03294 11 3.33893 8.44191 2.22163 6.5C3.33893 4.55809 6.03294 2 10 2C13.9671 2 16.6611 4.55809 17.7784 6.5ZM10 13C15.5228 13 19 9 20 6.5C19 4 15.5228 0 10 0C4.47715 0 1 4 0 6.5C1 9 4.47715 13 10 13Z" fill="#141414"/>
|
d="M255.66,112c-77.94,0-157.89,45.11-220.83,135.33a16,16,0,0,0-.27,17.77C82.92,340.8,161.8,400,255.66,400,348.5,400,429,340.62,477.45,264.75a16.14,16.14,0,0,0,0-17.47C428.89,172.28,347.8,112,255.66,112Z"
|
||||||
|
style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px" />
|
||||||
|
<circle cx="256" cy="256" r="80" style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 532 B |
|
@ -2,8 +2,8 @@ import { capitalize, formatDate } from '../../utils'
|
||||||
import './Full.scss'
|
import './Full.scss'
|
||||||
import { Icon } from '../_shared/Icon'
|
import { Icon } from '../_shared/Icon'
|
||||||
import { AuthorCard } from '../Author/Card'
|
import { AuthorCard } from '../Author/Card'
|
||||||
import { createMemo, createSignal, For, onMount, Show } from 'solid-js'
|
import { createMemo, createSignal, For, Match, onMount, Show, Switch } from 'solid-js'
|
||||||
import type { Author, Reaction, Shout } from '../../graphql/types.gen'
|
import type { Author, Shout } from '../../graphql/types.gen'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
import MD from './MD'
|
import MD from './MD'
|
||||||
import { SharePopup } from './SharePopup'
|
import { SharePopup } from './SharePopup'
|
||||||
|
@ -12,11 +12,50 @@ import styles from '../../styles/Article.module.scss'
|
||||||
import RatingControl from './RatingControl'
|
import RatingControl from './RatingControl'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { CommentsTree } from './CommentsTree'
|
import { CommentsTree } from './CommentsTree'
|
||||||
|
import { useSession } from '../../context/session'
|
||||||
|
|
||||||
interface ArticleProps {
|
interface ArticleProps {
|
||||||
article: Shout
|
article: Shout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MediaItem {
|
||||||
|
url?: string
|
||||||
|
pic?: string
|
||||||
|
title?: string
|
||||||
|
body?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const MediaView = (props: { media: MediaItem; kind: Shout['layout'] }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Switch
|
||||||
|
fallback={
|
||||||
|
<picture>
|
||||||
|
<source src={props.media.url} />
|
||||||
|
</picture>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Match when={props.kind === 'audio'}>
|
||||||
|
<div>
|
||||||
|
<h5>{props.media.title}</h5>
|
||||||
|
<audio controls>
|
||||||
|
<source src={props.media.url} />
|
||||||
|
</audio>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.kind === 'video'}>
|
||||||
|
<video controls>
|
||||||
|
<source src={props.media.url} />
|
||||||
|
</video>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const FullArticle = (props: ArticleProps) => {
|
export const FullArticle = (props: ArticleProps) => {
|
||||||
|
const { session } = useSession()
|
||||||
const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt)))
|
const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt)))
|
||||||
const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false)
|
const [isSharePopupVisible, setIsSharePopupVisible] = createSignal(false)
|
||||||
|
|
||||||
|
@ -39,6 +78,20 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const canEdit = () => props.article.authors?.some((a) => a.slug === session()?.user?.slug)
|
||||||
|
|
||||||
|
const bookmark = (ev) => {
|
||||||
|
// TODO: implement bookmark clicked
|
||||||
|
ev.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = createMemo(() => props.article.body)
|
||||||
|
const media = createMemo(() => {
|
||||||
|
const mi = JSON.parse(props.article.media || '[]')
|
||||||
|
console.debug(mi)
|
||||||
|
return mi
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="shout wide-container">
|
<div class="shout wide-container">
|
||||||
<article class="col-md-6 shift-content">
|
<article class="col-md-6 shift-content">
|
||||||
|
@ -65,13 +118,24 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
<div class={styles.shoutCover} style={{ 'background-image': `url('${props.article.cover}')` }} />
|
<div class={styles.shoutCover} style={{ 'background-image': `url('${props.article.cover}')` }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={Boolean(props.article.body)}>
|
<Show when={media()}>
|
||||||
|
<div class="media-items">
|
||||||
|
<For each={media() || []}>
|
||||||
|
{(m: MediaItem) => (
|
||||||
|
<div class={styles.shoutMediaBody}>
|
||||||
|
<MediaView media={m} kind={props.article.layout} />
|
||||||
|
<Show when={m?.body}>
|
||||||
|
<div innerHTML={m.body} />
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
<Show when={body()}>
|
||||||
<div class={styles.shoutBody}>
|
<div class={styles.shoutBody}>
|
||||||
<Show
|
<Show when={!body().startsWith('<')} fallback={<div innerHTML={body()} />}>
|
||||||
when={!props.article.body.startsWith('<')}
|
<MD body={body()} />
|
||||||
fallback={<div innerHTML={props.article.body} />}
|
|
||||||
>
|
|
||||||
<MD body={props.article.body} />
|
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
@ -83,16 +147,18 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
<RatingControl rating={props.article.stat?.rating} class={styles.ratingControl} />
|
<RatingControl rating={props.article.stat?.rating} class={styles.ratingControl} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Show when={props.article.stat?.viewed}>
|
||||||
|
<div class={clsx(styles.shoutStatsItem)}>
|
||||||
|
<Icon name="eye" class={styles.icon} />
|
||||||
|
<sup>{props.article.stat?.viewed}</sup>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<div class={styles.shoutStatsItem}>
|
<div class={styles.shoutStatsItem}>
|
||||||
<Icon name="comment" class={styles.icon} />
|
<Icon name="comment" class={styles.icon} />
|
||||||
{props.article.stat?.commented || ''}
|
{props.article.stat?.commented || ''}
|
||||||
</div>
|
</div>
|
||||||
{/*FIXME*/}
|
|
||||||
{/*<div class={styles.shoutStatsItem}>*/}
|
|
||||||
{/* <a href="#bookmark" onClick={() => console.log(props.article.slug, 'articles')}>*/}
|
|
||||||
{/* <Icon name={'bookmark' + (bookmarked() ? '' : '-x')} />*/}
|
|
||||||
{/* </a>*/}
|
|
||||||
{/*</div>*/}
|
|
||||||
<div class={styles.shoutStatsItem}>
|
<div class={styles.shoutStatsItem}>
|
||||||
<SharePopup
|
<SharePopup
|
||||||
onVisibilityChange={(isVisible) => {
|
onVisibilityChange={(isVisible) => {
|
||||||
|
@ -102,36 +168,32 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
trigger={<Icon name="share-new" class={styles.icon} />}
|
trigger={<Icon name="share-new" class={styles.icon} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.shoutStatsItem}>
|
|
||||||
|
<div class={styles.shoutStatsItem} onClick={bookmark}>
|
||||||
<Icon name="bookmark" class={styles.icon} />
|
<Icon name="bookmark" class={styles.icon} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*FIXME*/}
|
<Show when={canEdit()}>
|
||||||
{/*<Show when={canEdit()}>*/}
|
<div class={styles.shoutStatsItem}>
|
||||||
{/* <div class={styles.shoutStatsItem}>*/}
|
<a href="/edit">
|
||||||
{/* <a href="/edit">*/}
|
<Icon name="edit" />
|
||||||
{/* <Icon name="edit" />*/}
|
{t('Edit')}
|
||||||
{/* {t('Edit')}*/}
|
</a>
|
||||||
{/* </a>*/}
|
</div>
|
||||||
{/* </div>*/}
|
</Show>
|
||||||
{/*</Show>*/}
|
|
||||||
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalData)}>
|
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalData)}>
|
||||||
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalDataItem)}>
|
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalDataItem)}>
|
||||||
{formattedDate()}
|
{formattedDate()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={props.article.stat?.viewed}>
|
|
||||||
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalDataItem)}>
|
|
||||||
<Icon name="view" class={styles.icon} />
|
|
||||||
{props.article.stat?.viewed}
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={styles.help}>
|
<div class={styles.help}>
|
||||||
<button class="button">Соучаствовать</button>
|
<Show when={session()?.token}>
|
||||||
<button class="button button--light">Пригласить к участию</button>
|
<button class="button">{t('Cooperate')}</button>
|
||||||
|
</Show>
|
||||||
|
<Show when={canEdit()}>
|
||||||
|
<button class="button button--light">{t('Invite to collab')}</button>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={styles.topicsList}>
|
<div class={styles.topicsList}>
|
||||||
|
|
|
@ -49,6 +49,7 @@ export const HomeView = (props: HomeProps) => {
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) {
|
if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) {
|
||||||
const { hasMore } = await loadShouts({
|
const { hasMore } = await loadShouts({
|
||||||
|
filters: { visibility: 'public' },
|
||||||
limit: CLIENT_LOAD_ARTICLES_COUNT,
|
limit: CLIENT_LOAD_ARTICLES_COUNT,
|
||||||
offset: sortedArticles().length
|
offset: sortedArticles().length
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,6 +10,7 @@ export default gql`
|
||||||
layout
|
layout
|
||||||
cover
|
cover
|
||||||
body
|
body
|
||||||
|
media
|
||||||
# community
|
# community
|
||||||
mainTopic
|
mainTopic
|
||||||
topics {
|
topics {
|
|
@ -58,6 +58,17 @@ img {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shoutMediaBody {
|
||||||
|
display: block;
|
||||||
|
audio {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.shoutAuthor,
|
.shoutAuthor,
|
||||||
.shoutDate {
|
.shoutDate {
|
||||||
@include font-size(1.5rem);
|
@include font-size(1.5rem);
|
||||||
|
|
|
@ -39,7 +39,7 @@ import reactionsLoadBy from '../graphql/query/reactions-load-by'
|
||||||
import { REACTIONS_AMOUNT_PER_PAGE } from '../stores/zine/reactions'
|
import { REACTIONS_AMOUNT_PER_PAGE } from '../stores/zine/reactions'
|
||||||
import authorsLoadBy from '../graphql/query/authors-load-by'
|
import authorsLoadBy from '../graphql/query/authors-load-by'
|
||||||
import shoutsLoadBy from '../graphql/query/articles-load-by'
|
import shoutsLoadBy from '../graphql/query/articles-load-by'
|
||||||
import shoutLoad from '../graphql/query/articles-load'
|
import shoutLoad from '../graphql/query/article-load'
|
||||||
import loadRecipients from '../graphql/query/chat-recipients'
|
import loadRecipients from '../graphql/query/chat-recipients'
|
||||||
import createMessage from '../graphql/mutation/create-chat-message'
|
import createMessage from '../graphql/mutation/create-chat-message'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user