diff --git a/src/actions/index.js b/src/actions/index.js
index 44a7657..7ddd0a3 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -199,6 +199,7 @@ export function receiveChatMessage(
text: string,
country: string,
channel: number,
+ user: number,
isPing: boolean,
): Action {
return {
@@ -207,6 +208,7 @@ export function receiveChatMessage(
text,
country,
channel,
+ user,
isPing,
};
}
@@ -705,6 +707,35 @@ export function showCanvasSelectionModal(): Action {
return showModal('CANVAS_SELECTION');
}
+export function showContextMenu(
+ menuType: string,
+ xPos: number,
+ yPos: number,
+ args: Object,
+): Action {
+ return {
+ type: 'SHOW_CONTEXT_MENU',
+ menuType,
+ xPos,
+ yPos,
+ args,
+ };
+}
+
+export function setChatInputMessage(message: string): Action {
+ return {
+ type: 'SET_CHAT_INPUT_MSG',
+ message,
+ };
+}
+
+export function addToChatInputMessage(message: string): Action {
+ return {
+ type: 'ADD_CHAT_INPUT_MSG',
+ message,
+ };
+}
+
export function showChatModal(forceModal: boolean = false): Action {
if (window.innerWidth > 604 && !forceModal) { return toggleChatBox(); }
return showModal('CHAT');
@@ -723,6 +754,12 @@ export function hideModal(): Action {
};
}
+export function hideContextMenu(): Action {
+ return {
+ type: 'HIDE_CONTEXT_MENU',
+ };
+}
+
export function reloadUrl(): Action {
return {
type: 'RELOAD_URL',
diff --git a/src/actions/types.js b/src/actions/types.js
index 0add20d..5b0f6c4 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -65,11 +65,14 @@ export type Action =
text: string,
country: string,
channel: number,
+ user: number,
isPing: boolean,
}
| { type: 'RECEIVE_CHAT_HISTORY', cid: number, history: Array }
| { type: 'SET_CHAT_CHANNEL', channelId: number }
| { type: 'SET_CHAT_FETCHING', fetching: boolean }
+ | { type: 'SET_CHAT_INPUT_MSG', message: string }
+ | { type: 'ADD_CHAT_INPUT_MSG', message: string }
| { type: 'RECEIVE_ME',
name: string,
waitSeconds: number,
@@ -90,7 +93,14 @@ export type Action =
| { type: 'SET_MAILREG', mailreg: boolean }
| { type: 'REM_FROM_MESSAGES', message: string }
| { type: 'SHOW_MODAL', modalType: string }
+ | { type: 'SHOW_CONTEXT_MENU',
+ menuType: string,
+ xPos: number,
+ yPos: number,
+ args: Object,
+ }
| { type: 'HIDE_MODAL' }
+ | { type: 'HIDE_CONTEXT_MENU' }
| { type: 'RELOAD_URL' }
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
| { type: 'ON_VIEW_FINISH_CHANGE' };
diff --git a/src/client.js b/src/client.js
index 57d5a1b..7f6e5f3 100644
--- a/src/client.js
+++ b/src/client.js
@@ -52,9 +52,22 @@ function init() {
ProtocolClient.on('setWsName', (name) => {
nameRegExp = new RegExp(`(^|\\s+)(@${name})(\\s+|$)`, 'g');
});
- ProtocolClient.on('chatMessage', (name, text, country, channelId) => {
+ ProtocolClient.on('chatMessage', (
+ name,
+ text,
+ country,
+ channelId,
+ userId,
+ ) => {
const isPing = (nameRegExp && text.match(nameRegExp));
- store.dispatch(receiveChatMessage(name, text, country, channelId, isPing));
+ store.dispatch(receiveChatMessage(
+ name,
+ text,
+ country,
+ channelId,
+ userId,
+ isPing,
+ ));
});
ProtocolClient.on('changedMe', () => {
store.dispatch(fetchMe());
diff --git a/src/components/Chat.jsx b/src/components/Chat.jsx
index 83fb44a..995e9c0 100644
--- a/src/components/Chat.jsx
+++ b/src/components/Chat.jsx
@@ -17,6 +17,7 @@ import {
showUserAreaModal,
setChatChannel,
fetchChatMessages,
+ setChatInputMessage,
} from '../actions';
import ProtocolClient from '../socket/ProtocolClient';
import { saveSelection, restoreSelection } from '../utils/storeSelection';
@@ -32,13 +33,13 @@ const Chat = ({
chatChannel,
ownName,
open,
+ inputMessage,
+ setInputMessage,
setChannel,
fetchMessages,
fetching,
}) => {
const listRef = useRef();
- const inputRef = useRef();
- const [inputMessage, setInputMessage] = useState('');
const [selection, setSelection] = useState(null);
const [nameRegExp, setNameRegExp] = useState(null);
@@ -56,13 +57,15 @@ const Chat = ({
stayScrolled();
}, [channelMessages.length]);
+ /*
+ * TODO this removes focus from chat box, fix this
+ *
useEffect(() => {
- // TODO this removes focus from chat box, fix this
- return;
if (channelMessages.length === MAX_CHAT_MESSAGES) {
restoreSelection(selection);
}
}, [channelMessages]);
+ */
useEffect(() => {
const regExp = (ownName)
@@ -71,16 +74,6 @@ const Chat = ({
setNameRegExp(regExp);
}, [ownName]);
- function padToInputMessage(txt) {
- const lastChar = inputMessage.substr(-1);
- const pad = (lastChar && lastChar !== ' ');
- let newMsg = inputMessage;
- if (pad) newMsg += ' ';
- newMsg += txt;
- setInputMessage(newMsg);
- inputRef.current.focus();
- }
-
function handleSubmit(e) {
e.preventDefault();
const msg = inputMessage.trim();
@@ -123,7 +116,7 @@ const Chat = ({
name="info"
msgArray={splitChatMessage('Start chatting here', nameRegExp)}
country="xx"
- insertText={(txt) => padToInputMessage(txt)}
+ uid={0}
/>
)
}
@@ -133,7 +126,7 @@ const Chat = ({
name={message[0]}
msgArray={splitChatMessage(message[1], nameRegExp)}
country={message[2]}
- insertText={(txt) => padToInputMessage(txt)}
+ uid={message[3]}
/>
))
}
@@ -148,7 +141,7 @@ const Chat = ({
style={{ flexGrow: 1, minWidth: 40 }}
value={inputMessage}
onChange={(e) => setInputMessage(e.target.value)}
- ref={inputRef}
+ id="chatmsginput"
maxLength="200"
type="text"
placeholder="Chat here"
@@ -198,11 +191,17 @@ const Chat = ({
function mapStateToProps(state: State) {
const { name } = state.user;
const { chatChannel } = state.gui;
- const { channels, messages, fetching } = state.chat;
+ const {
+ channels,
+ messages,
+ fetching,
+ inputMessage,
+ } = state.chat;
return {
channels,
messages,
fetching,
+ inputMessage,
chatChannel,
ownName: name,
};
@@ -219,6 +218,9 @@ function mapDispatchToProps(dispatch) {
fetchMessages(channelId) {
dispatch(fetchChatMessages(channelId));
},
+ setInputMessage(message) {
+ dispatch(setChatInputMessage(message));
+ },
};
}
diff --git a/src/components/ChatMessage.jsx b/src/components/ChatMessage.jsx
index ce153ea..d1e1cff 100644
--- a/src/components/ChatMessage.jsx
+++ b/src/components/ChatMessage.jsx
@@ -5,14 +5,16 @@
import React from 'react';
import { connect } from 'react-redux';
+import { showContextMenu } from '../actions';
import { colorFromText, setBrightness } from '../core/utils';
function ChatMessage({
name,
- msgArray,
+ uid,
country,
- insertText,
+ msgArray,
+ openUserContextMenu,
darkMode,
}) {
if (!name || !msgArray) {
@@ -54,8 +56,17 @@ function ChatMessage({
}}
role="button"
tabIndex={-1}
- onClick={() => {
- insertText(`@${name} `);
+ onClick={(event) => {
+ const {
+ clientX,
+ clientY,
+ } = event;
+ openUserContextMenu(
+ clientX,
+ clientY,
+ uid,
+ name,
+ );
}}
>
{name}
@@ -103,4 +114,15 @@ function mapStateToProps(state: State) {
return { darkMode };
}
-export default connect(mapStateToProps)(ChatMessage);
+function mapDispatchToProps(dispatch) {
+ return {
+ openUserContextMenu(xPos, yPos, uid, name) {
+ dispatch(showContextMenu('USER', xPos, yPos, {
+ uid,
+ name,
+ }));
+ },
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ChatMessage);
diff --git a/src/components/UI.jsx b/src/components/UI.jsx
index 8ed58a9..43c0803 100644
--- a/src/components/UI.jsx
+++ b/src/components/UI.jsx
@@ -14,11 +14,28 @@ import PalselButton from './PalselButton';
import Palette from './Palette';
import HistorySelect from './HistorySelect';
import Mobile3DControls from './Mobile3DControls';
+import UserContextMenu from './UserContextMenu';
-const UI = ({ isHistoricalView, is3D, isOnMobile }) => {
+const CONTEXT_MENUS = {
+ USER: