diff --git a/landing/team.react.js b/landing/team.react.js index 015181c5f..3802acccb 100644 --- a/landing/team.react.js +++ b/landing/team.react.js @@ -1,101 +1,101 @@ // @flow import * as React from 'react'; import { assetsCacheURLPrefix } from './asset-meta-data'; import Button from './button.react.js'; -import TeamProfile from './team-profile.react.js'; +import TeamProfile from './team-profile.react'; import css from './team.css'; function Team(): React.Node { const onRolesClick = React.useCallback(() => { window.open( 'https://www.notion.so/commapp/Comm-is-hiring-db097b0d63eb4695b32f8988c8e640fd', '_blank', ); }, []); return (

Team

Comm is the keyserver company. Come join us and help build the future of the decentralized web!

Team at Software Mansion

); } export default Team; diff --git a/lib/shared/emojis.js b/lib/shared/emojis.js index a7192c832..9c7fe3d21 100644 --- a/lib/shared/emojis.js +++ b/lib/shared/emojis.js @@ -1,14 +1,14 @@ // @flow -import emojiRegex from 'emoji-regex/RGI_Emoji.js'; +import emojiRegex from 'emoji-regex/RGI_Emoji'; import invariant from 'invariant'; const emojiRegexMatches = emojiRegex().toString().match('^/(.+)/g$'); invariant( emojiRegexMatches.length === 2, 'could not extract innerEmojiRegex from emoji-regex/RGI_Emoji.js', ); const innerEmojiRegexString = emojiRegexMatches[1]; const onlyEmojiRegex: RegExp = new RegExp(`^(${innerEmojiRegexString})+$`); export { onlyEmojiRegex }; diff --git a/lib/utils/message-ops-utils.test.js b/lib/utils/message-ops-utils.test.js index 2e47fb6f3..e2e6a7239 100644 --- a/lib/utils/message-ops-utils.test.js +++ b/lib/utils/message-ops-utils.test.js @@ -1,381 +1,381 @@ // @flow import type { RawSidebarSourceMessageInfo } from '../types/message-types'; import type { RawAddMembersMessageInfo } from '../types/messages/add-members'; import type { RawChangeSettingsMessageInfo } from '../types/messages/change-settings'; import type { RawCreateEntryMessageInfo } from '../types/messages/create-entry'; import type { RawCreateSidebarMessageInfo } from '../types/messages/create-sidebar'; import type { RawCreateSubthreadMessageInfo } from '../types/messages/create-subthread'; -import type { RawCreateThreadMessageInfo } from '../types/messages/create-thread.js'; +import type { RawCreateThreadMessageInfo } from '../types/messages/create-thread'; import type { RawDeleteEntryMessageInfo } from '../types/messages/delete-entry'; import type { RawEditEntryMessageInfo } from '../types/messages/edit-entry'; import type { RawImagesMessageInfo } from '../types/messages/images'; import type { RawJoinThreadMessageInfo } from '../types/messages/join-thread'; import type { RawLeaveThreadMessageInfo } from '../types/messages/leave-thread'; import type { RawRemoveMembersMessageInfo } from '../types/messages/remove-members'; import type { RawRestoreEntryMessageInfo } from '../types/messages/restore-entry'; import type { RawTextMessageInfo } from '../types/messages/text'; import type { RawUpdateRelationshipMessageInfo } from '../types/messages/update-relationship'; import { translateRawMessageInfoToClientDBMessageInfo, translateClientDBMessageInfoToRawMessageInfo, } from './message-ops-utils'; test('TEXT: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawTextMessageInfo: RawTextMessageInfo = { type: 0, localID: 'local7', threadID: '85466', text: 'Hello world', creatorID: '85435', time: 1637788332565, id: '85551', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawTextMessageInfo), ), ).toStrictEqual(rawTextMessageInfo); }); test('TEXT (local): rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const localRawTextMessageInfo: RawTextMessageInfo = { type: 0, localID: 'local7', threadID: '85466', text: 'Hello world', creatorID: '85435', time: 1637788332565, }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(localRawTextMessageInfo), ), ).toStrictEqual(localRawTextMessageInfo); }); test('CREATE_THREAD: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawCreateThreadMessageInfo: RawCreateThreadMessageInfo = { type: 1, threadID: '85466', creatorID: '85435', time: 1637778853178, initialThreadState: { type: 6, name: null, parentThreadID: '1', color: '648CAA', memberIDs: ['256', '85435'], }, id: '85482', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawCreateThreadMessageInfo), ), ).toStrictEqual(rawCreateThreadMessageInfo); }); test('ADD_MEMBER: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawAddMemberMessageInfo: RawAddMembersMessageInfo = { type: 2, threadID: '85946', creatorID: '83809', time: 1638236346010, addedUserIDs: ['256'], id: '85986', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawAddMemberMessageInfo), ), ).toStrictEqual(rawAddMemberMessageInfo); }); test('CREATE_SUB_THREAD: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawCreateSubthreadMessageInfo: RawCreateSubthreadMessageInfo = { type: 3, threadID: '85946', creatorID: '83809', time: 1638237345553, childThreadID: '85990', id: '85997', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo( rawCreateSubthreadMessageInfo, ), ), ).toStrictEqual(rawCreateSubthreadMessageInfo); }); test('CHANGE_SETTINGS: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawChangeSettingsMessageInfo: RawChangeSettingsMessageInfo = { type: 4, threadID: '85946', creatorID: '83809', time: 1638236125774, field: 'color', value: '009cc8', id: '85972', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo( rawChangeSettingsMessageInfo, ), ), ).toStrictEqual(rawChangeSettingsMessageInfo); }); test('REMOVE_MEMBERS: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawRemoveMembersMessageInfo: RawRemoveMembersMessageInfo = { type: 5, threadID: '85990', creatorID: '83809', time: 1638237832234, removedUserIDs: ['85435'], id: '86014', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawRemoveMembersMessageInfo), ), ).toStrictEqual(rawRemoveMembersMessageInfo); }); test('LEAVE_THREAD: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawLeaveThreadMessageInfo: RawLeaveThreadMessageInfo = { type: 7, id: '86088', threadID: '85946', time: 1638238389038, creatorID: '85435', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawLeaveThreadMessageInfo), ), ).toStrictEqual(rawLeaveThreadMessageInfo); }); test('JOIN_THREAD: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawJoinThreadMessageInfo: RawJoinThreadMessageInfo = { type: 8, threadID: '86125', creatorID: '85435', time: 1638239691665, id: '86149', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawJoinThreadMessageInfo), ), ).toStrictEqual(rawJoinThreadMessageInfo); }); test('CREATE_ENTRY: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawCreateEntryMessageInfo: RawCreateEntryMessageInfo = { type: 9, threadID: '85630', creatorID: '85435', time: 1638239928303, entryID: '86151', date: '2021-11-29', text: 'Hello world', id: '86154', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawCreateEntryMessageInfo), ), ).toStrictEqual(rawCreateEntryMessageInfo); }); test('EDIT_ENTRY: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawEditEntryMessageInfo: RawEditEntryMessageInfo = { type: 10, threadID: '85630', creatorID: '85435', time: 1638240110661, entryID: '86151', date: '2021-11-29', text: 'Hello universe', id: '86179', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawEditEntryMessageInfo), ), ).toStrictEqual(rawEditEntryMessageInfo); }); test('DELETE_ENTRY: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawDeleteEntryMessageInfo: RawDeleteEntryMessageInfo = { type: 11, threadID: '85630', creatorID: '85435', time: 1638240286574, entryID: '86151', date: '2021-11-29', text: 'Hello universe', id: '86189', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawDeleteEntryMessageInfo), ), ).toStrictEqual(rawDeleteEntryMessageInfo); }); test('RESTORE_ENTRY: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawRestoreEntryMessageInfo: RawRestoreEntryMessageInfo = { type: 12, threadID: '85630', creatorID: '83809', time: 1638240605195, entryID: '86151', date: '2021-11-29', text: 'Hello universe', id: '86211', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawRestoreEntryMessageInfo), ), ).toStrictEqual(rawRestoreEntryMessageInfo); }); test('IMAGES: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawImagesMessageInfo: RawImagesMessageInfo = { type: 14, threadID: '85466', creatorID: '85435', time: 1637779260087, media: [ { id: '85504', type: 'photo', uri: 'http://localhost/comm/upload/85504/ba36cea2b5a796f6', dimensions: { width: 1920, height: 1281, }, }, ], id: '85505', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawImagesMessageInfo), ), ).toStrictEqual(rawImagesMessageInfo); }); test('IMAGES (local): rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const localRawImagesMessageInfo: RawImagesMessageInfo = { type: 14, threadID: '85466', creatorID: '85435', time: 1637779260087, media: [ { id: '85504', type: 'photo', uri: 'http://localhost/comm/upload/85504/ba36cea2b5a796f6', dimensions: { width: 1920, height: 1281, }, }, ], localID: 'local123', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(localRawImagesMessageInfo), ), ).toStrictEqual(localRawImagesMessageInfo); }); test('UPDATE_RELATIONSHIP: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawUpdateRelationshipMessageInfo: RawUpdateRelationshipMessageInfo = { type: 16, id: '85651', threadID: '85630', time: 1638235869690, creatorID: '83809', targetID: '85435', operation: 'request_accepted', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo( rawUpdateRelationshipMessageInfo, ), ), ).toStrictEqual(rawUpdateRelationshipMessageInfo); }); test('SIDEBAR_SOURCE: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawSidebarSourceMessageInfo: RawSidebarSourceMessageInfo = { type: 17, threadID: '86219', creatorID: '85435', time: 1638250532831, sourceMessage: { type: 0, id: '85486', threadID: '85466', time: 1637778853216, creatorID: '256', text: 'as you inevitably discover bugs, have feature requests, or design suggestions, feel free to message them to me in the app.', }, id: '86223', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawSidebarSourceMessageInfo), ), ).toStrictEqual(rawSidebarSourceMessageInfo); }); test('CREATE_SIDEBAR: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { const rawCreateSidebarMessageInfo: RawCreateSidebarMessageInfo = { type: 18, threadID: '86219', creatorID: '85435', time: 1638250532831, sourceMessageAuthorID: '256', initialThreadState: { name: 'as you inevitably discover ...', parentThreadID: '85466', color: 'ffffff', memberIDs: ['256', '85435'], }, id: '86224', }; expect( translateClientDBMessageInfoToRawMessageInfo( translateRawMessageInfoToClientDBMessageInfo(rawCreateSidebarMessageInfo), ), ).toStrictEqual(rawCreateSidebarMessageInfo); }); diff --git a/web/chat/message-action-buttons.js b/web/chat/message-action-buttons.js index c03663914..97188bd04 100644 --- a/web/chat/message-action-buttons.js +++ b/web/chat/message-action-buttons.js @@ -1,275 +1,275 @@ // @flow import classNames from 'classnames'; import invariant from 'invariant'; import * as React from 'react'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors'; import { useSidebarExistsOrCanBeCreated } from 'lib/shared/thread-utils'; import type { ThreadInfo } from 'lib/types/thread-types'; -import { longAbsoluteDate } from 'lib/utils/date-utils.js'; +import { longAbsoluteDate } from 'lib/utils/date-utils'; -import type { InputState } from '../input/input-state.js'; -import { useSelector } from '../redux/redux-utils.js'; +import type { InputState } from '../input/input-state'; +import { useSelector } from '../redux/redux-utils'; import { useOnClickThread, useOnClickPendingSidebar, } from '../selectors/nav-selectors'; import SWMansionIcon from '../SWMansionIcon.react'; import css from './message-action-buttons.css'; import MessageReplyButton from './message-reply-button.react'; import type { ItemAndContainerPositionInfo, MessagePositionInfo, OnMessagePositionWithContainerInfo, PositionInfo, } from './position-types'; import { tooltipPositions, type TooltipPosition } from './tooltip-utils'; import { TooltipMenu, type TooltipStyle, TooltipTextItem, } from './tooltip.react'; const messageActionIconExcessVerticalWhitespace = 10; const openSidebarText = 'Go to sidebar'; const createSidebarText = 'Create sidebar'; type TooltipType = 'sidebar' | 'reply'; type MessageActionButtonsProps = { +threadInfo: ThreadInfo, +item: ChatMessageInfoItem, +availableTooltipPositions: $ReadOnlyArray, +setMouseOverMessagePosition?: ( messagePositionInfo: MessagePositionInfo, ) => void, +mouseOverMessagePosition: OnMessagePositionWithContainerInfo, +canReply?: boolean, +inputState?: ?InputState, }; function MessageActionButtons(props: MessageActionButtonsProps): React.Node { const { threadInfo, item, availableTooltipPositions, setMouseOverMessagePosition, mouseOverMessagePosition, canReply, inputState, } = props; const { containerPosition } = mouseOverMessagePosition; const [activeTooltip, setActiveTooltip] = React.useState(); const [pointingTo, setPointingTo] = React.useState(); const showTooltip = React.useCallback( (tooltipType: TooltipType, iconPosition: ItemAndContainerPositionInfo) => { if (activeTooltip) { return; } setActiveTooltip(tooltipType); setPointingTo(iconPosition); }, [activeTooltip], ); const hideTooltip = React.useCallback(() => { setActiveTooltip(null); }, []); const showSidebarTooltip = React.useCallback( (event: SyntheticEvent) => { const rect = event.currentTarget.getBoundingClientRect(); const iconPosition = getIconPosition(rect, containerPosition); showTooltip('sidebar', iconPosition); }, [containerPosition, showTooltip], ); const showReplyTooltip = React.useCallback( (event: SyntheticEvent) => { const rect = event.currentTarget.getBoundingClientRect(); const iconPosition = getIconPosition(rect, containerPosition); showTooltip('reply', iconPosition); }, [containerPosition, showTooltip], ); const { threadCreatedFromMessage, messageInfo } = item; const onThreadOpen = useOnClickThread(threadCreatedFromMessage); const onPendingSidebarOpen = useOnClickPendingSidebar( messageInfo, threadInfo, ); const onSidebarButtonClick = React.useCallback( (event: SyntheticEvent) => { if (threadCreatedFromMessage) { onThreadOpen(event); } else { onPendingSidebarOpen(event); } }, [onPendingSidebarOpen, onThreadOpen, threadCreatedFromMessage], ); const onReplyButtonClick = React.useCallback(() => { invariant( setMouseOverMessagePosition, 'setMouseOverMessagePosition should be set if replyButton exists', ); setMouseOverMessagePosition({ type: 'off', item: item }); }, [item, setMouseOverMessagePosition]); let tooltipText = ''; if (activeTooltip === 'reply') { tooltipText = 'Reply'; } else if (activeTooltip === 'sidebar') { tooltipText = threadCreatedFromMessage ? openSidebarText : createSidebarText; } let tooltipMenu = null; if (pointingTo && activeTooltip) { tooltipMenu = ( ); } let replyButton; if (canReply) { invariant(inputState, 'inputState must be set if replyButton exists'); invariant( mouseOverMessagePosition, 'mouseOverMessagePosition must be set if replyButton exists', ); replyButton = (
{activeTooltip === 'reply' ? tooltipMenu : null}
); } const sidebarExistsOrCanBeCreated = useSidebarExistsOrCanBeCreated( threadInfo, item, ); let sidebarButton; if (sidebarExistsOrCanBeCreated) { sidebarButton = (
{activeTooltip === 'sidebar' ? tooltipMenu : null}
); } const timezone = useSelector(state => state.timeZone); const timestampText = React.useMemo( () => longAbsoluteDate(messageInfo.time, timezone), [messageInfo.time, timezone], ); const { isViewer } = messageInfo.creator; const messageActionButtonsContainerClassName = classNames({ [css.messageActionContainer]: true, [css.messageActionButtons]: true, [css.messageActionButtonsViewer]: isViewer, [css.messageActionButtonsNonViewer]: !isViewer, }); return (
{sidebarButton} {replyButton}

{timestampText}

); } function getIconPosition( rect: ClientRect, containerPosition: PositionInfo, ): ItemAndContainerPositionInfo { const { top, bottom, left, right, width, height } = rect; return { containerPosition, itemPosition: { top: top - containerPosition.top + messageActionIconExcessVerticalWhitespace, bottom: bottom - containerPosition.top - messageActionIconExcessVerticalWhitespace, left: left - containerPosition.left, right: right - containerPosition.left, width, height: height - messageActionIconExcessVerticalWhitespace * 2, }, }; } function getMessageActionTooltipStyle( tooltipPosition: TooltipPosition, ): TooltipStyle { let className; if (tooltipPosition === tooltipPositions.TOP_RIGHT) { className = classNames( css.messageActionTopRightTooltip, css.messageActionExtraAreaTop, css.messageActionExtraAreaTopRight, ); } else if (tooltipPosition === tooltipPositions.TOP_LEFT) { className = classNames( css.messageActionTopLeftTooltip, css.messageActionExtraAreaTop, css.messageActionExtraAreaTopLeft, ); } else if (tooltipPosition === tooltipPositions.RIGHT) { className = classNames( css.messageActionRightTooltip, css.messageActionExtraArea, css.messageActionExtraAreaRight, ); } else if (tooltipPosition === tooltipPositions.LEFT) { className = classNames( css.messageActionLeftTooltip, css.messageActionExtraArea, css.messageActionExtraAreaLeft, ); } invariant(className, `${tooltipPosition} is not valid for message tooltip`); return { className }; } export default MessageActionButtons; diff --git a/web/modals/account/log-in-modal.react.js b/web/modals/account/log-in-modal.react.js index 9527bae25..2d62153b5 100644 --- a/web/modals/account/log-in-modal.react.js +++ b/web/modals/account/log-in-modal.react.js @@ -1,18 +1,18 @@ // @flow import * as React from 'react'; -import LoginForm from '../../account/log-in-form.react.js'; +import LoginForm from '../../account/log-in-form.react'; import { useModalContext } from '../modal-provider.react'; import Modal from '../modal.react'; function LoginModal(): React.Node { const modalContext = useModalContext(); return ( ); } export default LoginModal; diff --git a/web/sidebar/community-picker.react.js b/web/sidebar/community-picker.react.js index 8fde672de..f4b178874 100644 --- a/web/sidebar/community-picker.react.js +++ b/web/sidebar/community-picker.react.js @@ -1,29 +1,29 @@ // @flow import * as React from 'react'; import Button from '../components/button.react'; -import UserSettingsModal from '../modals/account/user-settings-modal.react.js'; +import UserSettingsModal from '../modals/account/user-settings-modal.react'; import { useModalContext } from '../modals/modal-provider.react'; import SWMansionIcon from '../SWMansionIcon.react'; import css from './community-picker.css'; function CommunityPicker(): React.Node { const { setModal } = useModalContext(); const setModalToUserSettings = React.useCallback(() => { setModal(); }, [setModal]); return (
); } export default CommunityPicker;