fastcomments-react-native-sdk
Version:
React Native FastComments Components. Add live commenting to any React Native application.
299 lines (298 loc) • 14.1 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { FastCommentsImageAsset } from "../types";
import { Alert, Image } from "react-native";
import { createURLQueryString, makeRequest } from "../services/http";
import { CommentActionEdit } from './comment-action-edit';
import { CommentPromptDelete } from "./comment-action-delete";
import { repositionComment } from "../services/comment-positioning";
import { CAN_CLOSE, CAN_NOT_CLOSE } from "./modal-menu";
import { incChangeCounter, incChangeCounterState } from "../services/comment-render-determination";
import { addTranslationsToState, getMergedTranslations } from "../services/translations";
import { newBroadcastId } from '../services/broadcast-id';
async function startEditingComment({ state, comment }, setModalId) {
const response = await makeRequest({
apiHost: state.apiHost.get(),
method: 'GET',
url: `/comments/${state.config.tenantId.get()}/${comment._id}/text${createURLQueryString({
sso: state.ssoConfigString.get(),
editKey: comment.editKey
})}`
});
if (response.status === 'success') {
comment.comment = response.commentText;
setModalId('edit');
}
else {
const translations = getMergedTranslations(state.translations.get({ stealth: true }), response);
const message = response.code === 'edit-key-invalid' ? translations.LOGIN_TO_EDIT : translations.FAILED_TO_SAVE_EDIT;
Alert.alert(":(", message, [
{
text: translations.DISMISS
}
]);
}
}
async function setCommentPinStatus({ state, comment }, doPin) {
const response = await makeRequest({
apiHost: state.apiHost.get(),
method: 'POST',
url: `/comments/${state.config.tenantId.get()}/${comment._id}/${doPin ? 'pin' : 'unpin'}${createURLQueryString({
sso: state.ssoConfigString.get(),
editKey: comment.editKey,
broadcastId: newBroadcastId()
})}`
});
if (response.status === 'success') {
comment.isPinned = doPin;
repositionComment(comment._id, response.commentPositions, state);
incChangeCounter(comment);
incChangeCounterState(state.commentsById[comment._id]);
}
else {
const translations = getMergedTranslations(state.translations.get({ stealth: true }), response);
Alert.alert(":(", translations.ERROR_MESSAGE, [
{
text: translations.DISMISS
}
]);
}
}
async function setCommentBlockedStatus({ state, comment }, doBlock) {
const response = await makeRequest({
apiHost: state.apiHost.get(),
method: doBlock ? 'POST' : 'DELETE',
url: `/block-from-comment/${comment._id}/${createURLQueryString({
tenantId: state.config.tenantId.get(),
urlId: state.config.urlId.get(),
sso: state.ssoConfigString.get(),
editKey: comment.editKey,
broadcastId: newBroadcastId()
})}`,
body: {
commentIds: Object.keys(state.commentsById.get())
}
});
if (response.status === 'success') {
comment.isBlocked = doBlock;
incChangeCounter(comment);
for (const otherCommentId in response.commentStatuses) {
if (state.commentsById[otherCommentId].get()) {
const existing = !!state.commentsById[otherCommentId].isBlocked.get();
const newValue = response.commentStatuses[otherCommentId];
if (existing !== newValue) {
state.commentsById[otherCommentId].isBlocked.set(newValue);
incChangeCounterState(state.commentsById.nested(otherCommentId));
}
}
}
}
else {
const translations = getMergedTranslations(state.translations.get({ stealth: true }), response);
Alert.alert(":(", translations.ERROR_MESSAGE, [
{
text: translations.DISMISS
}
]);
}
}
async function setCommentFlaggedStatus({ state, comment }, doFlag) {
const response = await makeRequest({
apiHost: state.apiHost.get(),
method: 'POST',
url: `/flag-comment/${comment._id}/${createURLQueryString({
tenantId: state.config.tenantId.get(),
urlId: state.config.urlId.get(),
sso: state.ssoConfigString.get(),
isFlagged: doFlag,
broadcastId: newBroadcastId()
})}`
});
if (response.status === 'success') {
comment.isFlagged = doFlag;
state.commentsById[comment._id].isFlagged.set(doFlag);
incChangeCounter(comment);
}
else {
// response.translatedError is supported here
const translations = getMergedTranslations(state.translations.get({ stealth: true }), response);
Alert.alert(":(", response.translatedError ? response.translatedError : translations.ERROR_MESSAGE, [
{
text: translations.DISMISS
}
]);
}
}
export function getCommentMenuState(state, comment) {
const currentUser = state.currentUser.get({ stealth: true });
const isMyComment = !!currentUser && 'id' in currentUser && (comment.userId === currentUser.id || comment.anonUserId === currentUser.id);
const canEdit = !comment.isDeleted && !!((currentUser && 'authorized' in currentUser && !!currentUser.authorized && (state.isSiteAdmin.get({ stealth: true }) || isMyComment))); // can have edit key and be anon
const canPin = state.isSiteAdmin.get({ stealth: true }) && !comment.parentId;
const canBlockOrFlag = !comment.isDeleted && !comment.isByAdmin && !comment.isByModerator && !isMyComment && !!currentUser && 'authorized' in currentUser && !!currentUser.authorized;
return {
canEdit,
canPin,
canBlockOrFlag
};
}
export function getCommentMenuItems({ comment, onCommentFlagged, onUserBlocked, pickGIF, pickImage, styles, state }, { canEdit, canPin, canBlockOrFlag, }) {
const hasDarkBackground = state.config.hasDarkBackground.get();
const menuItems = []; // creating an array for every comment rendered is not ideal
if (canEdit) {
const isDirtyRef = {}; // can't use useRef here due to hook lifecycle
menuItems.push({
id: 'edit',
label: state.translations.COMMENT_MENU_EDIT.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_EDIT_BIG_WHITE : FastCommentsImageAsset.ICON_EDIT_BIG].get(), style: styles.commentMenu?.itemIcon }),
handler: async (setModalId) => {
await startEditingComment({ comment, state }, setModalId);
},
subModalContent: (close) => _jsx(CommentActionEdit, { comment: comment, isDirtyRef: isDirtyRef, pickGIF: pickGIF, pickImage: pickImage, state: state, styles: styles, close: close }),
requestClose: async () => {
if (isDirtyRef.current && isDirtyRef.current()) {
if (!state.translations.CONFIRM_CANCEL_EDIT.get()) {
let url = '/translations/widgets/comment-ui-cancel?useFullTranslationIds=true';
if (state.config.locale.get()) {
url += '&locale=' + state.config.locale.get();
}
const translationsResponse = await makeRequest({
apiHost: state.apiHost.get(),
method: 'GET',
url
});
if (translationsResponse.status === 'success') {
addTranslationsToState(state.translations, translationsResponse.translations);
}
}
return new Promise((resolve) => {
Alert.alert(state.translations.CONFIRM_CANCEL_EDIT_TITLE.get(), state.translations.CONFIRM_CANCEL_EDIT.get(), [
{
text: state.translations.CONFIRM_CANCEL_EDIT_CANCEL.get(),
onPress: () => {
resolve(CAN_NOT_CLOSE);
},
style: 'cancel'
},
{
text: state.translations.CONFIRM_CANCEL_EDIT_OK.get(),
onPress: () => {
resolve(CAN_CLOSE);
},
style: 'destructive'
}
], {
onDismiss: () => {
resolve(CAN_NOT_CLOSE);
}
});
});
}
return CAN_CLOSE;
}
});
}
if (canPin) {
if (comment.isPinned) {
menuItems.push({
id: 'unpin',
label: state.translations.COMMENT_MENU_UNPIN.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_UNPIN_BIG_WHITE : FastCommentsImageAsset.ICON_UNPIN_BIG].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentPinStatus({ comment, state }, false);
}
});
}
else {
menuItems.push({
id: 'pin',
label: state.translations.COMMENT_MENU_PIN.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_PIN_BIG_WHITE : FastCommentsImageAsset.ICON_PIN_BIG].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentPinStatus({ comment, state }, true);
}
});
}
}
if (canEdit) {
menuItems.push({
id: 'delete',
label: state.translations.COMMENT_MENU_DELETE.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_TRASH_WHITE : FastCommentsImageAsset.ICON_TRASH].get(), style: styles.commentMenu?.itemIcon }),
handler: async (setModalId) => {
await CommentPromptDelete({
comment,
state,
close: () => setModalId(null)
});
}
});
}
if (canBlockOrFlag) {
if (comment.isBlocked) {
menuItems.push({
id: 'unblock',
label: state.translations.COMMENT_MENU_UNBLOCK_USER.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_BLOCK_WHITE : FastCommentsImageAsset.ICON_BLOCK].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentBlockedStatus({ comment, state }, false);
if (onUserBlocked) {
const currentUser = state.currentUser.get();
if (currentUser && 'id' in currentUser) {
onUserBlocked(currentUser.id, comment, false);
}
}
}
});
}
else {
menuItems.push({
id: 'block',
label: state.translations.COMMENT_MENU_BLOCK_USER.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_BLOCK_WHITE : FastCommentsImageAsset.ICON_BLOCK].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentBlockedStatus({ comment, state }, true);
if (onUserBlocked) {
const currentUser = state.currentUser.get();
if (currentUser && 'id' in currentUser) {
onUserBlocked(currentUser.id, comment, true);
}
}
}
});
}
}
if (canBlockOrFlag) {
if (comment.isFlagged) {
menuItems.push({
id: 'unflag',
label: state.translations.COMMENT_MENU_UNFLAG.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_BLOCK_WHITE : FastCommentsImageAsset.ICON_BLOCK].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentFlaggedStatus({ comment, state }, false);
if (onCommentFlagged) {
const currentUser = state.currentUser.get();
if (currentUser && 'id' in currentUser) {
onCommentFlagged(currentUser.id, comment, false);
}
}
}
});
}
else {
menuItems.push({
id: 'flag',
label: state.translations.COMMENT_MENU_FLAG.get(),
icon: _jsx(Image, { source: state.imageAssets[hasDarkBackground ? FastCommentsImageAsset.ICON_BLOCK_WHITE : FastCommentsImageAsset.ICON_BLOCK].get(), style: styles.commentMenu?.itemIcon }),
handler: async () => {
await setCommentFlaggedStatus({ comment, state }, true);
if (onCommentFlagged) {
const currentUser = state.currentUser.get();
if (currentUser && 'id' in currentUser) {
onCommentFlagged(currentUser.id, comment, true);
}
}
}
});
}
}
return menuItems;
}