add more info for claim-preview-tile aria label
This commit is contained in:
parent
7c8c43d3a7
commit
60c5d3bf67
5 changed files with 66 additions and 26 deletions
|
@ -2054,5 +2054,7 @@
|
||||||
"Item removed from Watch Later": "Item removed from Watch Later",
|
"Item removed from Watch Later": "Item removed from Watch Later",
|
||||||
"Skip Navigation": "Skip Navigation",
|
"Skip Navigation": "Skip Navigation",
|
||||||
"In Favorites": "In Favorites",
|
"In Favorites": "In Favorites",
|
||||||
|
"%title% by %channelTitle%, %mediaDuration%": "%title% by %channelTitle%, %mediaDuration%",
|
||||||
|
"%title% by %channelTitle%": "%title% by %channelTitle%",
|
||||||
"--end--": "--end--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +14,28 @@ import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
||||||
import { selectShowMatureContent } from 'redux/selectors/settings';
|
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import ClaimPreviewTile from './view';
|
import ClaimPreviewTile from './view';
|
||||||
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => {
|
||||||
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
|
const claim = props.uri && makeSelectClaimForUri(props.uri)(state);
|
||||||
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
|
const media = claim && claim.value && (claim.value.video || claim.value.audio);
|
||||||
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
|
const mediaDuration = media && media.duration && formatMediaDuration(media.duration, { screenReader: true });
|
||||||
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
|
|
||||||
title: props.uri && makeSelectTitleForUri(props.uri)(state),
|
return {
|
||||||
blackListedOutpoints: selectBlackListedOutpoints(state),
|
claim,
|
||||||
filteredOutpoints: selectFilteredOutpoints(state),
|
mediaDuration,
|
||||||
blockedChannelUris: selectMutedChannels(state),
|
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
|
||||||
showMature: selectShowMatureContent(state),
|
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
|
||||||
isMature: makeSelectClaimIsNsfw(props.uri)(state),
|
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
|
||||||
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
|
title: props.uri && makeSelectTitleForUri(props.uri)(state),
|
||||||
});
|
blackListedOutpoints: selectBlackListedOutpoints(state),
|
||||||
|
filteredOutpoints: selectFilteredOutpoints(state),
|
||||||
|
blockedChannelUris: selectMutedChannels(state),
|
||||||
|
showMature: selectShowMatureContent(state),
|
||||||
|
isMature: makeSelectClaimIsNsfw(props.uri)(state),
|
||||||
|
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
resolveUri: (uri) => dispatch(doResolveUri(uri)),
|
resolveUri: (uri) => dispatch(doResolveUri(uri)),
|
||||||
|
|
|
@ -21,6 +21,7 @@ import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
|
mediaDuration?: string,
|
||||||
resolveUri: (string) => void,
|
resolveUri: (string) => void,
|
||||||
isResolvingUri: boolean,
|
isResolvingUri: boolean,
|
||||||
history: { push: (string) => void },
|
history: { push: (string) => void },
|
||||||
|
@ -72,6 +73,7 @@ function ClaimPreviewTile(props: Props) {
|
||||||
showNoSourceClaims,
|
showNoSourceClaims,
|
||||||
isLivestream,
|
isLivestream,
|
||||||
collectionId,
|
collectionId,
|
||||||
|
mediaDuration,
|
||||||
} = props;
|
} = props;
|
||||||
const isRepost = claim && claim.repost_channel_url;
|
const isRepost = claim && claim.repost_channel_url;
|
||||||
const isCollection = claim && claim.value_type === 'collection';
|
const isCollection = claim && claim.value_type === 'collection';
|
||||||
|
@ -114,6 +116,18 @@ function ClaimPreviewTile(props: Props) {
|
||||||
|
|
||||||
const signingChannel = claim && claim.signing_channel;
|
const signingChannel = claim && claim.signing_channel;
|
||||||
const channelUri = !isChannel ? signingChannel && signingChannel.permanent_url : claim && claim.permanent_url;
|
const channelUri = !isChannel ? signingChannel && signingChannel.permanent_url : claim && claim.permanent_url;
|
||||||
|
const channelTitle = signingChannel && (signingChannel.value.title || signingChannel.name);
|
||||||
|
|
||||||
|
// Aria-label value for claim preview
|
||||||
|
let ariaLabelData = title;
|
||||||
|
|
||||||
|
if (!isChannel && channelTitle) {
|
||||||
|
if (mediaDuration) {
|
||||||
|
ariaLabelData = __('%title% by %channelTitle%, %mediaDuration%', { title, channelTitle, mediaDuration });
|
||||||
|
} else {
|
||||||
|
ariaLabelData = __('%title% by %channelTitle%', { title, channelTitle });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleClick(e) {
|
function handleClick(e) {
|
||||||
if (navigateUrl) {
|
if (navigateUrl) {
|
||||||
|
@ -226,7 +240,7 @@ function ClaimPreviewTile(props: Props) {
|
||||||
</FileThumbnail>
|
</FileThumbnail>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<div className="claim-tile__header">
|
<div className="claim-tile__header">
|
||||||
<NavLink {...navLinkProps}>
|
<NavLink aria-label={ariaLabelData} {...navLinkProps}>
|
||||||
<h2 className="claim-tile__title">
|
<h2 className="claim-tile__title">
|
||||||
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
|
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
|
||||||
{isChannel && (
|
{isChannel && (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
type Props = {
|
type Props = {
|
||||||
claim: ?StreamClaim,
|
claim: ?StreamClaim,
|
||||||
className?: string,
|
className?: string,
|
||||||
|
@ -9,19 +9,11 @@ type Props = {
|
||||||
function VideoDuration(props: Props) {
|
function VideoDuration(props: Props) {
|
||||||
const { claim, className } = props;
|
const { claim, className } = props;
|
||||||
|
|
||||||
const video = claim && claim.value && (claim.value.video || claim.value.audio);
|
const media = claim && claim.value && (claim.value.video || claim.value.audio);
|
||||||
let duration;
|
let duration;
|
||||||
if (video && video.duration) {
|
if (media && media.duration) {
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
let date = new Date(null);
|
duration = formatMediaDuration(media.duration);
|
||||||
date.setSeconds(video.duration);
|
|
||||||
let timeString = date.toISOString().substr(11, 8);
|
|
||||||
|
|
||||||
if (timeString.startsWith('00:')) {
|
|
||||||
timeString = timeString.substr(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
duration = timeString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return duration ? <span className={className}>{duration}</span> : null;
|
return duration ? <span className={className}>{duration}</span> : null;
|
||||||
|
|
24
ui/util/formatMediaDuration.js
Normal file
24
ui/util/formatMediaDuration.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
export default function formatMediaDuration(duration = 0, config) {
|
||||||
|
const options = {
|
||||||
|
screenReader: false,
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optimize for screen readers
|
||||||
|
if (options.screenReader) {
|
||||||
|
return moment.utc(moment.duration(duration, 'seconds').asMilliseconds()).format('HH:mm:ss');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal format
|
||||||
|
let date = new Date(null);
|
||||||
|
date.setSeconds(duration);
|
||||||
|
|
||||||
|
let timeString = date.toISOString().substr(11, 8);
|
||||||
|
if (timeString.startsWith('00:')) {
|
||||||
|
timeString = timeString.substr(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeString;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue