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}
);
}
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;