* when there is no div for it, don't render CommentSubscription * Retrigger CI * Retrigger CI * don't write an error to the comment div if its gone This fixes an issue seen in tests, where the page transitioned while we were running the articlePage async handler, so the article-body element was gone (can't access dataset of null), and the error handler catch block tried to access the innerHTML of another getElementById. * Use existing found element `root` when setting the error message No need to find a new comment-subscription div to write the error to, we already named the one we're interested in at the beginning of the function
138 lines
4.2 KiB
JavaScript
138 lines
4.2 KiB
JavaScript
import { h, render } from 'preact';
|
|
import { Snackbar, addSnackbarItem } from '../Snackbar';
|
|
import { addFullScreenModeControl } from '../utilities/codeFullscreenModeSwitcher';
|
|
import { initializeDropdown } from '../utilities/dropdownUtils';
|
|
import { embedGists } from '../utilities/gist';
|
|
import { initializeUserSubscriptionLiquidTagContent } from '../liquidTags/userSubscriptionLiquidTag';
|
|
|
|
/* global Runtime */
|
|
|
|
const animatedImages = document.querySelectorAll('[data-animated="true"]');
|
|
if (animatedImages.length > 0) {
|
|
import('@utilities/animatedImageUtils').then(
|
|
({ initializePausableAnimatedImages }) => {
|
|
initializePausableAnimatedImages(animatedImages);
|
|
},
|
|
);
|
|
}
|
|
|
|
const fullscreenActionElements = document.getElementsByClassName(
|
|
'js-fullscreen-code-action',
|
|
);
|
|
|
|
if (fullscreenActionElements) {
|
|
addFullScreenModeControl(fullscreenActionElements);
|
|
}
|
|
|
|
// The Snackbar for the article page
|
|
const snackZone = document.getElementById('snack-zone');
|
|
if (snackZone) {
|
|
render(<Snackbar lifespan={3} />, snackZone);
|
|
}
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
top.addSnackbarItem = addSnackbarItem;
|
|
|
|
// Dropdown accessibility
|
|
function hideCopyLinkAnnouncerIfVisible() {
|
|
document.getElementById('article-copy-link-announcer').hidden = true;
|
|
}
|
|
|
|
// Initialize the share options
|
|
const shareDropdownButton = document.getElementById('article-show-more-button');
|
|
|
|
if (shareDropdownButton.dataset.initialized !== 'true') {
|
|
if (Runtime.isNativeAndroid('shareText')) {
|
|
// Android native apps have enhanced sharing capabilities for Articles and don't use our standard dropdown
|
|
shareDropdownButton.addEventListener('click', () =>
|
|
AndroidBridge.shareText(location.href),
|
|
);
|
|
} else {
|
|
const { closeDropdown } = initializeDropdown({
|
|
triggerElementId: 'article-show-more-button',
|
|
dropdownContentId: 'article-show-more-dropdown',
|
|
onClose: hideCopyLinkAnnouncerIfVisible,
|
|
});
|
|
|
|
// We want to close the dropdown on link select (since they open in a new tab)
|
|
document
|
|
.querySelectorAll('#article-show-more-dropdown [href]')
|
|
.forEach((link) => {
|
|
link.addEventListener('click', (event) => {
|
|
closeDropdown(event);
|
|
});
|
|
});
|
|
}
|
|
|
|
shareDropdownButton.dataset.initialized = 'true';
|
|
}
|
|
|
|
// Initialize the copy to clipboard functionality
|
|
function showAnnouncer() {
|
|
document.getElementById('article-copy-link-announcer').hidden = false;
|
|
}
|
|
|
|
function copyArticleLink() {
|
|
const postUrlValue = document
|
|
.getElementById('copy-post-url-button')
|
|
.getAttribute('data-postUrl');
|
|
Runtime.copyToClipboard(postUrlValue).then(() => {
|
|
showAnnouncer();
|
|
});
|
|
}
|
|
document
|
|
.getElementById('copy-post-url-button')
|
|
?.addEventListener('click', copyArticleLink);
|
|
|
|
// Comment Subscription
|
|
getCsrfToken().then(async () => {
|
|
const { user = null, userStatus } = document.body.dataset;
|
|
const root = document.getElementById('comment-subscription');
|
|
const isLoggedIn = userStatus === 'logged-in';
|
|
|
|
if (!root) {
|
|
return;
|
|
}
|
|
try {
|
|
const {
|
|
getCommentSubscriptionStatus,
|
|
setCommentSubscriptionStatus,
|
|
CommentSubscription,
|
|
} = await import('../CommentSubscription');
|
|
|
|
const { articleId } = document.getElementById('article-body').dataset;
|
|
|
|
let subscriptionType = 'not_subscribed';
|
|
|
|
if (isLoggedIn && user !== null) {
|
|
({ config: subscriptionType } = await getCommentSubscriptionStatus(
|
|
articleId,
|
|
));
|
|
}
|
|
|
|
const subscriptionRequestHandler = async (type) => {
|
|
const message = await setCommentSubscriptionStatus(articleId, type);
|
|
|
|
addSnackbarItem({ message, addCloseButton: true });
|
|
};
|
|
|
|
render(
|
|
<CommentSubscription
|
|
subscriptionType={subscriptionType}
|
|
positionType="static"
|
|
onSubscribe={subscriptionRequestHandler}
|
|
onUnsubscribe={subscriptionRequestHandler}
|
|
isLoggedIn={isLoggedIn}
|
|
/>,
|
|
root,
|
|
);
|
|
} catch (e) {
|
|
root.innerHTML =
|
|
'<p className="color-accent-danger">Unable to load Comment Subscription component.<br />Try refreshing the page.</p>';
|
|
}
|
|
});
|
|
|
|
const targetNode = document.querySelector('#comments');
|
|
targetNode && embedGists(targetNode);
|
|
|
|
initializeUserSubscriptionLiquidTagContent();
|