Add ability to set nickname using /nick command in chat
This commit is contained in:
parent
54659863b5
commit
ba92214296
20
src/client/actions/NicknameActions.ts
Normal file
20
src/client/actions/NicknameActions.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NICKNAME_SET } from '../constants'
|
||||
|
||||
interface NicknameSetPayload {
|
||||
nickname: string
|
||||
userId: string
|
||||
}
|
||||
|
||||
interface NicknameSetAction {
|
||||
type: 'NICKNAME_SET'
|
||||
payload: NicknameSetPayload
|
||||
}
|
||||
|
||||
export function setNickname(payload: NicknameSetPayload): NicknameSetAction {
|
||||
return {
|
||||
type: NICKNAME_SET,
|
||||
payload,
|
||||
}
|
||||
}
|
||||
|
||||
export type NicknameActions = NicknameSetAction
|
||||
@ -7,6 +7,7 @@ import { EventEmitter } from 'events'
|
||||
import { createStore, Store, GetState } from '../store'
|
||||
import { Dispatch } from 'redux'
|
||||
import { ClientSocket } from '../socket'
|
||||
import { PEERCALLS, PEER_EVENT_DATA, ME } from '../constants'
|
||||
|
||||
describe('PeerActions', () => {
|
||||
function createSocket () {
|
||||
@ -74,20 +75,30 @@ describe('PeerActions', () => {
|
||||
})
|
||||
|
||||
describe('events', () => {
|
||||
let peer: Peer.Instance
|
||||
|
||||
beforeEach(() => {
|
||||
function createPeer() {
|
||||
PeerActions.createPeer({ socket, user, initiator: 'user1', stream })(
|
||||
dispatch, getState)
|
||||
peer = instances[0]
|
||||
})
|
||||
const peer = instances[instances.length - 1]
|
||||
return peer
|
||||
}
|
||||
|
||||
describe('connect', () => {
|
||||
beforeEach(() => peer.emit('connect'))
|
||||
|
||||
it('dispatches peer connection established message', () => {
|
||||
createPeer().emit('connect')
|
||||
// TODO
|
||||
})
|
||||
|
||||
it('sends existing local streams to new peer', () => {
|
||||
PeerActions.sendMessage({
|
||||
payload: {nickname: 'john'},
|
||||
type: 'nickname',
|
||||
})(dispatch, getState)
|
||||
const peer = createPeer()
|
||||
peer.emit('connect')
|
||||
})
|
||||
|
||||
it('sends current nickname to new peer', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('data', () => {
|
||||
@ -103,10 +114,15 @@ describe('PeerActions', () => {
|
||||
})
|
||||
|
||||
it('decodes a message', () => {
|
||||
const payload = 'test'
|
||||
const object = JSON.stringify({ payload })
|
||||
const peer = createPeer()
|
||||
const message = {
|
||||
type: 'text',
|
||||
payload: 'test',
|
||||
}
|
||||
const object = JSON.stringify(message)
|
||||
peer.emit('data', Buffer.from(object, 'utf-8'))
|
||||
const { list } = store.getState().messages
|
||||
expect(list.length).toBeGreaterThan(0)
|
||||
expect(list[list.length - 1]).toEqual({
|
||||
userId: 'user2',
|
||||
timestamp: jasmine.any(String),
|
||||
@ -162,7 +178,7 @@ describe('PeerActions', () => {
|
||||
})(dispatch, getState)
|
||||
})
|
||||
|
||||
it('sends a message to all peers', () => {
|
||||
it('sends a text message to all peers', () => {
|
||||
PeerActions.sendMessage({ payload: 'test', type: 'text' })(
|
||||
dispatch, getState)
|
||||
const { peers } = store.getState()
|
||||
@ -172,5 +188,76 @@ describe('PeerActions', () => {
|
||||
.toEqual([[ '{"payload":"test","type":"text"}' ]])
|
||||
})
|
||||
|
||||
it('sends a nickname change to all peers', () => {
|
||||
PeerActions.sendMessage({
|
||||
payload: {nickname: 'john'},
|
||||
type: 'nickname',
|
||||
})(dispatch, getState)
|
||||
const { nicknames, peers } = store.getState()
|
||||
expect((peers['user2'].send as jest.Mock).mock.calls)
|
||||
.toEqual([[ '{"payload":{"nickname":"john"},"type":"nickname"}' ]])
|
||||
expect((peers['user3'].send as jest.Mock).mock.calls)
|
||||
.toEqual([[ '{"payload":{"nickname":"john"},"type":"nickname"}' ]])
|
||||
expect(nicknames[ME]).toBe('john')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('receive message (handleData)', () => {
|
||||
let peer: Peer.Instance
|
||||
function emitData(message: PeerActions.Message) {
|
||||
peer.emit(PEER_EVENT_DATA, JSON.stringify(message))
|
||||
}
|
||||
beforeEach(() => {
|
||||
PeerActions.createPeer({
|
||||
socket, user: { id: 'user2' }, initiator: 'user2', stream,
|
||||
})(dispatch, getState)
|
||||
peer = store.getState().peers['user2']
|
||||
})
|
||||
|
||||
it('handles a message', () => {
|
||||
emitData({
|
||||
payload: 'hello',
|
||||
type: 'text',
|
||||
})
|
||||
expect(store.getState().messages.list)
|
||||
.toEqual([{
|
||||
message: 'Connecting to peer...',
|
||||
userId: PEERCALLS,
|
||||
timestamp: jasmine.any(String),
|
||||
}, {
|
||||
message: 'hello',
|
||||
userId: 'user2',
|
||||
image: undefined,
|
||||
timestamp: jasmine.any(String),
|
||||
}])
|
||||
})
|
||||
|
||||
it('handles nickname changes', () => {
|
||||
emitData({
|
||||
payload: {nickname: 'john'},
|
||||
type: 'nickname',
|
||||
})
|
||||
emitData({
|
||||
payload: {nickname: 'john2'},
|
||||
type: 'nickname',
|
||||
})
|
||||
expect(store.getState().messages.list)
|
||||
.toEqual([{
|
||||
message: 'Connecting to peer...',
|
||||
userId: PEERCALLS,
|
||||
timestamp: jasmine.any(String),
|
||||
}, {
|
||||
message: 'User user2 is now known as john',
|
||||
userId: PEERCALLS,
|
||||
image: undefined,
|
||||
timestamp: jasmine.any(String),
|
||||
}, {
|
||||
message: 'User john is now known as john2',
|
||||
userId: PEERCALLS,
|
||||
image: undefined,
|
||||
timestamp: jasmine.any(String),
|
||||
}])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import * as ChatActions from '../actions/ChatActions'
|
||||
import * as NotifyActions from '../actions/NotifyActions'
|
||||
import * as StreamActions from '../actions/StreamActions'
|
||||
import * as ChatActions from './ChatActions'
|
||||
import * as NicknameActions from './NicknameActions'
|
||||
import * as NotifyActions from './NotifyActions'
|
||||
import * as StreamActions from './StreamActions'
|
||||
import * as constants from '../constants'
|
||||
import Peer, { SignalData } from 'simple-peer'
|
||||
import forEach from 'lodash/forEach'
|
||||
@ -8,6 +9,7 @@ import _debug from 'debug'
|
||||
import { iceServers } from '../window'
|
||||
import { Dispatch, GetState } from '../store'
|
||||
import { ClientSocket } from '../socket'
|
||||
import { getNickname } from '../nickname'
|
||||
|
||||
const debug = _debug('peercalls')
|
||||
|
||||
@ -65,6 +67,13 @@ class PeerHandler {
|
||||
peer.addTrack(track, s.stream)
|
||||
})
|
||||
})
|
||||
const nickname = state.nicknames[constants.ME]
|
||||
if (nickname) {
|
||||
sendData(peer, {
|
||||
payload: {nickname},
|
||||
type: 'nickname',
|
||||
})
|
||||
}
|
||||
}
|
||||
handleTrack = (track: MediaStreamTrack, stream: MediaStream) => {
|
||||
const { user, dispatch } = this
|
||||
@ -86,7 +95,8 @@ class PeerHandler {
|
||||
}))
|
||||
}
|
||||
handleData = (buffer: ArrayBuffer) => {
|
||||
const { dispatch, user } = this
|
||||
const { dispatch, getState, user } = this
|
||||
const state = getState()
|
||||
const message = JSON.parse(new window.TextDecoder('utf-8').decode(buffer))
|
||||
debug('peer: %s, message: %o', user.id, buffer)
|
||||
switch (message.type) {
|
||||
@ -98,6 +108,19 @@ class PeerHandler {
|
||||
image: message.payload.data,
|
||||
}))
|
||||
break
|
||||
case 'nickname':
|
||||
dispatch(ChatActions.addMessage({
|
||||
userId: constants.PEERCALLS,
|
||||
message: 'User ' + getNickname(state.nicknames, user.id) +
|
||||
' is now known as ' + message.payload.nickname,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
image: undefined,
|
||||
}))
|
||||
dispatch(NicknameActions.setNickname({
|
||||
userId: user.id,
|
||||
nickname: message.payload.nickname,
|
||||
}))
|
||||
break
|
||||
default:
|
||||
dispatch(ChatActions.addMessage({
|
||||
userId: user.id,
|
||||
@ -234,7 +257,18 @@ export interface FileMessage {
|
||||
payload: Base64File
|
||||
}
|
||||
|
||||
export type Message = TextMessage | FileMessage
|
||||
export interface NicknameMessage {
|
||||
type: 'nickname'
|
||||
payload: {
|
||||
nickname: string
|
||||
}
|
||||
}
|
||||
|
||||
export type Message = TextMessage | FileMessage | NicknameMessage
|
||||
|
||||
function sendData(peer: Peer.Instance, message: Message) {
|
||||
peer.send(JSON.stringify(message))
|
||||
}
|
||||
|
||||
export const sendMessage = (message: Message) =>
|
||||
(dispatch: Dispatch, getState: GetState) => {
|
||||
@ -244,23 +278,37 @@ export const sendMessage = (message: Message) =>
|
||||
switch (message.type) {
|
||||
case 'file':
|
||||
dispatch(ChatActions.addMessage({
|
||||
userId: 'You',
|
||||
userId: constants.ME,
|
||||
message: 'Send file: "' +
|
||||
message.payload.name + '" to all peers',
|
||||
timestamp: new Date().toLocaleString(),
|
||||
image: message.payload.data,
|
||||
}))
|
||||
break
|
||||
case 'nickname':
|
||||
dispatch(ChatActions.addMessage({
|
||||
userId: constants.PEERCALLS,
|
||||
message: 'You are now known as: ' + message.payload.nickname,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
image: undefined,
|
||||
}))
|
||||
dispatch(NicknameActions.setNickname({
|
||||
userId: constants.ME,
|
||||
nickname: message.payload.nickname,
|
||||
}))
|
||||
window.localStorage &&
|
||||
(window.localStorage.nickname = message.payload.nickname)
|
||||
break
|
||||
default:
|
||||
dispatch(ChatActions.addMessage({
|
||||
userId: 'You',
|
||||
userId: constants.ME,
|
||||
message: message.payload,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
image: undefined,
|
||||
}))
|
||||
}
|
||||
forEach(peers, (peer, userId) => {
|
||||
peer.send(JSON.stringify(message))
|
||||
sendData(peer, message)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import React from 'react'
|
||||
import Peer from 'simple-peer'
|
||||
import { Message } from '../actions/ChatActions'
|
||||
import { dismissNotification, Notification } from '../actions/NotifyActions'
|
||||
import { TextMessage } from '../actions/PeerActions'
|
||||
import { Message as MessageType } from '../actions/PeerActions'
|
||||
import { removeStream } from '../actions/StreamActions'
|
||||
import * as constants from '../constants'
|
||||
import Chat from './Chat'
|
||||
@ -15,17 +15,19 @@ import Toolbar from './Toolbar'
|
||||
import Video from './Video'
|
||||
import { getDesktopStream } from '../actions/MediaActions'
|
||||
import { StreamsState } from '../reducers/streams'
|
||||
import { Nicknames } from '../reducers/nicknames'
|
||||
|
||||
export interface AppProps {
|
||||
active: string | null
|
||||
dismissNotification: typeof dismissNotification
|
||||
init: () => void
|
||||
nicknames: Nicknames
|
||||
notifications: Record<string, Notification>
|
||||
messages: Message[]
|
||||
messagesCount: number
|
||||
peers: Record<string, Peer.Instance>
|
||||
play: () => void
|
||||
sendMessage: (message: TextMessage) => void
|
||||
sendMessage: (message: MessageType) => void
|
||||
streams: StreamsState
|
||||
getDesktopStream: typeof getDesktopStream
|
||||
removeStream: typeof removeStream
|
||||
@ -79,6 +81,7 @@ export default class App extends React.PureComponent<AppProps, AppState> {
|
||||
active,
|
||||
dismissNotification,
|
||||
notifications,
|
||||
nicknames,
|
||||
messages,
|
||||
messagesCount,
|
||||
onSendFile,
|
||||
@ -127,6 +130,7 @@ export default class App extends React.PureComponent<AppProps, AppState> {
|
||||
</Side>
|
||||
<Chat
|
||||
messages={messages}
|
||||
nicknames={nicknames}
|
||||
onClose={this.handleHideChat}
|
||||
sendMessage={sendMessage}
|
||||
visible={this.state.chatVisible}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import classnames from 'classnames'
|
||||
import React from 'react'
|
||||
import { Message as MessageType } from '../actions/ChatActions'
|
||||
import { TextMessage } from '../actions/PeerActions'
|
||||
import { Message as ChatMessage } from '../actions/ChatActions'
|
||||
import { Message } from '../actions/PeerActions'
|
||||
import { Nicknames } from '../reducers/nicknames'
|
||||
import Input from './Input'
|
||||
import { ME } from '../constants'
|
||||
import { getNickname } from '../nickname'
|
||||
|
||||
export interface MessageProps {
|
||||
message: MessageType
|
||||
message: ChatMessage
|
||||
}
|
||||
|
||||
function Message (props: MessageProps) {
|
||||
function MessageEntry (props: MessageProps) {
|
||||
const { message } = props
|
||||
return (
|
||||
<p className="message-text">
|
||||
@ -22,9 +25,10 @@ function Message (props: MessageProps) {
|
||||
|
||||
export interface ChatProps {
|
||||
visible: boolean
|
||||
messages: MessageType[]
|
||||
messages: ChatMessage[]
|
||||
nicknames: Nicknames
|
||||
onClose: () => void
|
||||
sendMessage: (message: TextMessage) => void
|
||||
sendMessage: (message: Message) => void
|
||||
}
|
||||
|
||||
export default class Chat extends React.PureComponent<ChatProps> {
|
||||
@ -67,15 +71,15 @@ export default class Chat extends React.PureComponent<ChatProps> {
|
||||
{messages.length ? (
|
||||
messages.map((message, i) => (
|
||||
<div key={i}>
|
||||
{message.userId === 'You' ? (
|
||||
{message.userId === ME ? (
|
||||
<div className="chat-item chat-item-me">
|
||||
<div className="message">
|
||||
<span className="message-user-name">
|
||||
{message.userId}
|
||||
{getNickname(this.props.nicknames, message.userId)}
|
||||
</span>
|
||||
<span className="icon icon-schedule" />
|
||||
<time className="message-time">{message.timestamp}</time>
|
||||
<Message message={message} />
|
||||
<MessageEntry message={message} />
|
||||
</div>
|
||||
{message.image ? (
|
||||
<img className="chat-item-img" src={message.image} />
|
||||
@ -92,11 +96,11 @@ export default class Chat extends React.PureComponent<ChatProps> {
|
||||
)}
|
||||
<div className="message">
|
||||
<span className="message-user-name">
|
||||
{message.userId}
|
||||
{getNickname(this.props.nicknames, message.userId)}
|
||||
</span>
|
||||
<span className="icon icon-schedule" />
|
||||
<time className="message-time">{message.timestamp}</time>
|
||||
<Message message={message} />
|
||||
<MessageEntry message={message} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,12 +2,12 @@ import Input from './Input'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
import { TextMessage } from '../actions/PeerActions'
|
||||
import { Message } from '../actions/PeerActions'
|
||||
|
||||
describe('components/Input', () => {
|
||||
|
||||
let node: Element
|
||||
let sendMessage: jest.Mock<(message: TextMessage) => void>
|
||||
let sendMessage: jest.MockedFunction<(message: Message) => void>
|
||||
async function render () {
|
||||
sendMessage = jest.fn()
|
||||
const div = document.createElement('div')
|
||||
@ -32,23 +32,61 @@ describe('components/Input', () => {
|
||||
beforeEach(() => {
|
||||
sendMessage.mockClear()
|
||||
input = node.querySelector('textarea')!
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: message } as any,
|
||||
})
|
||||
expect(input.value).toBe(message)
|
||||
})
|
||||
|
||||
describe('handleSubmit', () => {
|
||||
it('does nothing when no message', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: '' } as any,
|
||||
})
|
||||
TestUtils.Simulate.submit(node)
|
||||
expect(sendMessage.mock.calls)
|
||||
.toEqual([])
|
||||
})
|
||||
|
||||
it('sends a message', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: message } as any,
|
||||
})
|
||||
TestUtils.Simulate.submit(node)
|
||||
expect(input.value).toBe('')
|
||||
expect(sendMessage.mock.calls)
|
||||
.toEqual([[ { payload: message, type: 'text' } ]])
|
||||
})
|
||||
|
||||
it('sends a nickname command', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: '/nick john' } as any,
|
||||
})
|
||||
TestUtils.Simulate.submit(node)
|
||||
expect(sendMessage.mock.calls)
|
||||
.toEqual([[ { payload: {nickname: 'john'}, type: 'nickname' } ]])
|
||||
})
|
||||
|
||||
it('does not fail when command is empty', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: '/nick ' } as any,
|
||||
})
|
||||
TestUtils.Simulate.submit(node)
|
||||
expect(sendMessage.mock.calls)
|
||||
.toEqual([[ { payload: {nickname: ''}, type: 'nickname' } ]])
|
||||
})
|
||||
|
||||
it('sends message when command is invalid', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: '/nick' } as any,
|
||||
})
|
||||
TestUtils.Simulate.submit(node)
|
||||
expect(sendMessage.mock.calls)
|
||||
.toEqual([[ { payload: '/nick', type: 'text' } ]])
|
||||
})
|
||||
})
|
||||
|
||||
describe('handleKeyPress', () => {
|
||||
it('sends a message', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: message } as any,
|
||||
})
|
||||
TestUtils.Simulate.keyPress(input, {
|
||||
key: 'Enter',
|
||||
})
|
||||
@ -67,6 +105,9 @@ describe('components/Input', () => {
|
||||
|
||||
describe('handleSmileClick', () => {
|
||||
it('adds smile to message', () => {
|
||||
TestUtils.Simulate.change(input, {
|
||||
target: { value: message } as any,
|
||||
})
|
||||
const div = node.querySelector('.chat-controls-buttons-smile')!
|
||||
TestUtils.Simulate.click(div)
|
||||
expect(input.value).toBe('test message😑')
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
import React, { ReactEventHandler, ChangeEventHandler, KeyboardEventHandler, MouseEventHandler } from 'react'
|
||||
import { TextMessage } from '../actions/PeerActions'
|
||||
import { Message } from '../actions/PeerActions'
|
||||
|
||||
export interface InputProps {
|
||||
sendMessage: (message: TextMessage) => void
|
||||
sendMessage: (message: Message) => void
|
||||
}
|
||||
|
||||
export interface InputState {
|
||||
message: string
|
||||
}
|
||||
|
||||
const regexp = /^\/([a-z0-9]+) (.*)$/
|
||||
|
||||
export default class Input extends React.PureComponent<InputProps, InputState> {
|
||||
textArea = React.createRef<HTMLTextAreaElement>()
|
||||
state = {
|
||||
@ -38,10 +40,22 @@ export default class Input extends React.PureComponent<InputProps, InputState> {
|
||||
const { sendMessage } = this.props
|
||||
const { message } = this.state
|
||||
if (message) {
|
||||
sendMessage({
|
||||
payload: message,
|
||||
type: 'text',
|
||||
})
|
||||
const matches = regexp.exec(message)
|
||||
const command = matches && matches[1]
|
||||
const restOfMessage = matches && matches[2] || ''
|
||||
switch (command) {
|
||||
case 'nick':
|
||||
sendMessage({
|
||||
type: 'nickname',
|
||||
payload: {nickname: restOfMessage},
|
||||
})
|
||||
break
|
||||
default:
|
||||
sendMessage({
|
||||
payload: message,
|
||||
type: 'text',
|
||||
})
|
||||
}
|
||||
// let image = null
|
||||
|
||||
// // take snapshoot
|
||||
|
||||
@ -8,6 +8,7 @@ export const ALERT_CLEAR = 'ALERT_CLEAR'
|
||||
export const INIT = 'INIT'
|
||||
|
||||
export const ME = '_me_'
|
||||
export const PEERCALLS = '[PeerCalls]'
|
||||
|
||||
export const NOTIFY = 'NOTIFY'
|
||||
export const NOTIFY_DISMISS = 'NOTIFY_DISMISS'
|
||||
@ -21,6 +22,8 @@ export const MEDIA_VIDEO_CONSTRAINT_SET = 'MEDIA_VIDEO_CONSTRAINT_SET'
|
||||
export const MEDIA_AUDIO_CONSTRAINT_SET = 'MEDIA_AUDIO_CONSTRAINT_SET'
|
||||
export const MEDIA_PLAY = 'MEDIA_PLAY'
|
||||
|
||||
export const NICKNAME_SET = 'NICKNAME_SET'
|
||||
|
||||
export const PEER_ADD = 'PEER_ADD'
|
||||
export const PEER_REMOVE = 'PEER_REMOVE'
|
||||
export const PEERS_DESTROY = 'PEERS_DESTROY'
|
||||
|
||||
@ -12,6 +12,7 @@ function mapStateToProps (state: State) {
|
||||
streams: state.streams,
|
||||
peers: state.peers,
|
||||
notifications: state.notifications,
|
||||
nicknames: state.nicknames,
|
||||
messages: state.messages.list,
|
||||
messagesCount: state.messages.count,
|
||||
active: state.active,
|
||||
|
||||
13
src/client/nickname.ts
Normal file
13
src/client/nickname.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Nicknames } from './reducers/nicknames'
|
||||
import { ME } from './constants'
|
||||
|
||||
export function getNickname(nicknames: Nicknames, userId: string): string {
|
||||
const nickname = nicknames[userId]
|
||||
if (nickname) {
|
||||
return nickname
|
||||
}
|
||||
if (userId === ME) {
|
||||
return 'You'
|
||||
}
|
||||
return userId
|
||||
}
|
||||
@ -4,6 +4,7 @@ import messages from './messages'
|
||||
import peers from './peers'
|
||||
import media from './media'
|
||||
import streams from './streams'
|
||||
import nicknames from './nicknames'
|
||||
import { combineReducers } from 'redux'
|
||||
|
||||
export default combineReducers({
|
||||
@ -11,6 +12,7 @@ export default combineReducers({
|
||||
notifications,
|
||||
messages,
|
||||
media,
|
||||
nicknames,
|
||||
peers,
|
||||
streams,
|
||||
})
|
||||
|
||||
27
src/client/reducers/nicknames.ts
Normal file
27
src/client/reducers/nicknames.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { NICKNAME_SET, PEER_REMOVE, ME } from '../constants'
|
||||
import { NicknameActions } from '../actions/NicknameActions'
|
||||
import { RemovePeerAction } from '../actions/PeerActions'
|
||||
import omit = require('lodash/omit')
|
||||
|
||||
export type Nicknames = Record<string, string | undefined>
|
||||
|
||||
const defaultState: Nicknames = {
|
||||
[ME]: localStorage && localStorage.nickname,
|
||||
}
|
||||
|
||||
export default function nicknames(
|
||||
state = defaultState,
|
||||
action: NicknameActions | RemovePeerAction,
|
||||
) {
|
||||
switch (action.type) {
|
||||
case PEER_REMOVE:
|
||||
return omit(state, [action.payload.userId])
|
||||
case NICKNAME_SET:
|
||||
return {
|
||||
...state,
|
||||
[action.payload.userId]: action.payload.nickname,
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user