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",
|
||||
"Skip Navigation": "Skip Navigation",
|
||||
"In Favorites": "In Favorites",
|
||||
"%title% by %channelTitle%, %mediaDuration%": "%title% by %channelTitle%, %mediaDuration%",
|
||||
"%title% by %channelTitle%": "%title% by %channelTitle%",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -14,9 +14,16 @@ import { selectMutedChannels } from 'redux/selectors/blocked';
|
|||
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
||||
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||
import ClaimPreviewTile from './view';
|
||||
import formatMediaDuration from 'util/formatMediaDuration';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
|
||||
const select = (state, props) => {
|
||||
const claim = props.uri && makeSelectClaimForUri(props.uri)(state);
|
||||
const media = claim && claim.value && (claim.value.video || claim.value.audio);
|
||||
const mediaDuration = media && media.duration && formatMediaDuration(media.duration, { screenReader: true });
|
||||
|
||||
return {
|
||||
claim,
|
||||
mediaDuration,
|
||||
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
|
||||
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
|
||||
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
|
||||
|
@ -27,7 +34,8 @@ const select = (state, props) => ({
|
|||
showMature: selectShowMatureContent(state),
|
||||
isMature: makeSelectClaimIsNsfw(props.uri)(state),
|
||||
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const perform = (dispatch) => ({
|
||||
resolveUri: (uri) => dispatch(doResolveUri(uri)),
|
||||
|
|
|
@ -21,6 +21,7 @@ import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
|
|||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim,
|
||||
mediaDuration?: string,
|
||||
resolveUri: (string) => void,
|
||||
isResolvingUri: boolean,
|
||||
history: { push: (string) => void },
|
||||
|
@ -72,6 +73,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
showNoSourceClaims,
|
||||
isLivestream,
|
||||
collectionId,
|
||||
mediaDuration,
|
||||
} = props;
|
||||
const isRepost = claim && claim.repost_channel_url;
|
||||
const isCollection = claim && claim.value_type === 'collection';
|
||||
|
@ -114,6 +116,18 @@ function ClaimPreviewTile(props: Props) {
|
|||
|
||||
const signingChannel = claim && claim.signing_channel;
|
||||
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) {
|
||||
if (navigateUrl) {
|
||||
|
@ -226,7 +240,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
</FileThumbnail>
|
||||
</NavLink>
|
||||
<div className="claim-tile__header">
|
||||
<NavLink {...navLinkProps}>
|
||||
<NavLink aria-label={ariaLabelData} {...navLinkProps}>
|
||||
<h2 className="claim-tile__title">
|
||||
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
|
||||
{isChannel && (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
|
||||
import formatMediaDuration from 'util/formatMediaDuration';
|
||||
type Props = {
|
||||
claim: ?StreamClaim,
|
||||
className?: string,
|
||||
|
@ -9,19 +9,11 @@ type Props = {
|
|||
function VideoDuration(props: 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;
|
||||
if (video && video.duration) {
|
||||
if (media && media.duration) {
|
||||
// $FlowFixMe
|
||||
let date = new Date(null);
|
||||
date.setSeconds(video.duration);
|
||||
let timeString = date.toISOString().substr(11, 8);
|
||||
|
||||
if (timeString.startsWith('00:')) {
|
||||
timeString = timeString.substr(3);
|
||||
}
|
||||
|
||||
duration = timeString;
|
||||
duration = formatMediaDuration(media.duration);
|
||||
}
|
||||
|
||||
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…
Reference in a new issue