mediacms/frontend/src/static/js/components/media-actions/MediaShareOptions.jsx

333 wiersze
9.9 KiB
JavaScript

import React, { useRef, useState, useEffect } from 'react';
import { ShareOptionsContext } from '../../utils/contexts/';
import { PageStore, MediaPageStore } from '../../utils/stores/';
import { PageActions, MediaPageActions } from '../../utils/actions/';
import ItemsInlineSlider from '../item-list/includes/itemLists/ItemsInlineSlider';
import { CircleIconButton } from '../_shared/';
function shareOptionsList() {
const socialMedia = ShareOptionsContext._currentValue;
const mediaUrl = MediaPageStore.get('media-url');
const mediaTitle = MediaPageStore.get('media-data').title;
const ret = {};
let i = 0;
while (i < socialMedia.length) {
switch (socialMedia[i]) {
case 'embed':
if ('video' === MediaPageStore.get('media-data').media_type) {
ret[socialMedia[i]] = {};
}
break;
case 'email':
ret[socialMedia[i]] = {
title: 'Email',
shareUrl: 'mailto:?body=' + mediaUrl,
};
break;
case 'fb':
ret[socialMedia[i]] = {
title: 'Facebook',
shareUrl: 'https://www.facebook.com/sharer.php?u=' + mediaUrl,
};
break;
case 'tw':
ret[socialMedia[i]] = {
title: 'Twitter',
shareUrl: 'https://twitter.com/intent/tweet?url=' + mediaUrl,
};
break;
case 'reddit':
ret[socialMedia[i]] = {
title: 'reddit',
shareUrl: 'https://reddit.com/submit?url=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'tumblr':
ret[socialMedia[i]] = {
title: 'Tumblr',
shareUrl: 'https://www.tumblr.com/widgets/share/tool?canonicalUrl=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'pinterest':
ret[socialMedia[i]] = {
title: 'Pinterest',
shareUrl: 'http://pinterest.com/pin/create/link/?url=' + mediaUrl,
};
break;
case 'vk':
ret[socialMedia[i]] = {
title: 'ВКонтакте',
shareUrl: 'http://vk.com/share.php?url=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'linkedin':
ret[socialMedia[i]] = {
title: 'LinkedIn',
shareUrl: 'https://www.linkedin.com/shareArticle?mini=true&url=' + mediaUrl,
};
break;
case 'mix':
ret[socialMedia[i]] = {
title: 'Mix',
shareUrl: 'https://mix.com/add?url=' + mediaUrl,
};
break;
case 'whatsapp':
ret[socialMedia[i]] = {
title: 'WhatsApp',
shareUrl: 'whatsapp://send?text=' + mediaUrl,
};
break;
case 'telegram':
ret[socialMedia[i]] = {
title: 'Telegram',
shareUrl: 'https://t.me/share/url?url=' + mediaUrl + '&text=' + mediaTitle,
};
break;
}
i += 1;
}
return ret;
}
function ShareOptions() {
const shareOptions = shareOptionsList();
const compList = [];
for (let k in shareOptions) {
if (shareOptions.hasOwnProperty(k)) {
if (k === 'embed') {
compList.push(
<div key={'share-' + k} className={'sh-option share-' + k + '-opt'}>
<button className="sh-option change-page" data-page-id="shareEmbed">
<span>
<i className="material-icons">code</i>
</span>
<span>Embed</span>
</button>
</div>
);
} else if (k === 'whatsapp') {
compList.push(
<div key={'share-' + k} className={'sh-option share-' + k}>
<a
href={shareOptions[k].shareUrl}
title=""
target="_blank"
data-action="share/whatsapp/share"
rel="noreferrer"
>
<span></span>
<span>{shareOptions[k].title}</span>
</a>
</div>
);
} else if (k === 'email') {
compList.push(
<div key="share-email" className="sh-option share-email">
<a href={shareOptions[k].shareUrl} title="">
<span>
<i className="material-icons">email</i>
</span>
<span>{shareOptions[k].title}</span>
</a>
</div>
);
} else {
compList.push(
<div key={'share-' + k} className={'sh-option share-' + k}>
<a href={shareOptions[k].shareUrl} title="" target="_blank" rel="noreferrer">
<span></span>
<span>{shareOptions[k].title}</span>
</a>
</div>
);
}
}
}
return compList;
}
function NextSlideButton({ onClick }) {
return (
<span className="next-slide">
<CircleIconButton buttonShadow={true} onClick={onClick}>
<i className="material-icons">keyboard_arrow_right</i>
</CircleIconButton>
</span>
);
}
function PreviousSlideButton({ onClick }) {
return (
<span className="previous-slide">
<CircleIconButton buttonShadow={true} onClick={onClick}>
<i className="material-icons">keyboard_arrow_left</i>
</CircleIconButton>
</span>
);
}
function updateDimensions() {
return {
maxFormContentHeight: window.innerHeight - (56 + 4 * 24 + 44),
maxPopupWidth: 518 > window.innerWidth - 2 * 40 ? window.innerWidth - 2 * 40 : null,
};
}
function getTimestamp() {
const videoPlayer = document.getElementsByTagName("video");
return videoPlayer[0]?.currentTime;
}
function ToHHMMSS (timeInt) {
let sec_num = parseInt(timeInt, 10);
let hours = Math.floor(sec_num / 3600);
let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
let seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours >= 1 ? hours + ':' + minutes + ':' + seconds : minutes + ':' + seconds;
}
export function MediaShareOptions(props) {
const containerRef = useRef(null);
const shareOptionsInnerRef = useRef(null);
const mediaUrl = MediaPageStore.get('media-url');
const [inlineSlider, setInlineSlider] = useState(null);
const [sliderButtonsVisible, setSliderButtonsVisible] = useState({ prev: false, next: false });
const [dimensions, setDimensions] = useState(updateDimensions());
const [shareOptions] = useState(ShareOptions());
const [timestamp, setTimestamp] = useState(0);
const [formattedTimestamp, setFormattedTimestamp] = useState(0);
const [startAtSelected, setStartAtSelected] = useState(false);
const [shareMediaLink, setShareMediaLink] = useState(mediaUrl);
function onWindowResize() {
setDimensions(updateDimensions());
}
function onClickCopyMediaLink() {
MediaPageActions.copyShareLink(containerRef.current.querySelector('.copy-field input'));
}
function onCompleteCopyMediaLink() {
// FIXME: Without delay throws conflict error [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
setTimeout(function () {
PageActions.addNotification('Link copied to clipboard', 'clipboardLinkCopy');
}, 100);
}
function updateSlider() {
inlineSlider.scrollToCurrentSlide();
updateSliderButtonsView();
}
function updateSliderButtonsView() {
setSliderButtonsVisible({
prev: inlineSlider.hasPreviousSlide(),
next: inlineSlider.hasNextSlide(),
});
}
function updateStartAtCheckbox() {
setStartAtSelected(!startAtSelected);
updateShareMediaLink();
}
function updateShareMediaLink()
{
const newLink = startAtSelected ? mediaUrl : mediaUrl + "&t=" + Math.trunc(timestamp);
setShareMediaLink(newLink);
}
function nextSlide() {
inlineSlider.nextSlide();
updateSlider();
}
function prevSlide() {
inlineSlider.previousSlide();
updateSlider();
}
useEffect(() => {
setInlineSlider(new ItemsInlineSlider(shareOptionsInnerRef.current, '.sh-option'));
}, [shareOptions]);
useEffect(() => {
if (inlineSlider) {
inlineSlider.updateDataStateOnResize(shareOptions.length, true, true);
updateSlider();
}
}, [dimensions, inlineSlider]);
useEffect(() => {
PageStore.on('window_resize', onWindowResize);
MediaPageStore.on('copied_media_link', onCompleteCopyMediaLink);
const localTimestamp = getTimestamp();
setTimestamp(localTimestamp);
setFormattedTimestamp(ToHHMMSS(localTimestamp));
return () => {
PageStore.removeListener('window_resize', onWindowResize);
MediaPageStore.removeListener('copied_media_link', onCompleteCopyMediaLink);
setInlineSlider(null);
};
}, []);
return (
<div
ref={containerRef}
style={null !== dimensions.maxPopupWidth ? { maxWidth: dimensions.maxPopupWidth + 'px' } : null}
>
<div
className="scrollable-content"
style={null !== dimensions.maxFormContentHeight ? { maxHeight: dimensions.maxFormContentHeight + 'px' } : null}
>
<div className="share-popup-title">Share media</div>
{shareOptions.length ? (
<div className="share-options">
{sliderButtonsVisible.prev ? <PreviousSlideButton onClick={prevSlide} /> : null}
<div ref={shareOptionsInnerRef} className="share-options-inner">
{shareOptions}
</div>
{sliderButtonsVisible.next ? <NextSlideButton onClick={nextSlide} /> : null}
</div>
) : null}
</div>
<div className="copy-field">
<div>
<input type="text" readOnly value={shareMediaLink} />
<button onClick={onClickCopyMediaLink}>COPY</button>
</div>
</div>
<div className="start-at">
<label>
<input
type="checkbox"
name="start-at-checkbox"
id="id-start-at-checkbox"
checked={startAtSelected}
onChange={updateStartAtCheckbox}
/>
Start at {formattedTimestamp}
</label>
</div>
</div>
);
}