diff --git a/src/events/mod-tools/ModToolsEvent.ts b/src/events/mod-tools/ModToolsEvent.ts new file mode 100644 index 00000000..fca082ec --- /dev/null +++ b/src/events/mod-tools/ModToolsEvent.ts @@ -0,0 +1,10 @@ +import { NitroEvent } from 'nitro-renderer'; + +export class ModToolsEvent extends NitroEvent +{ + public static SHOW_MOD_TOOLS: string = 'MTE_SHOW_MOD_TOOLS'; + public static HIDE_MOD_TOOLS: string = 'MTE_HIDE_MOD_TOOLS'; + public static TOGGLE_MOD_TOOLS: string = 'MTE_TOGGLE_MOD_TOOLS'; + public static SELECT_USER: string = 'MTE_SELECT_USER'; + public static OPEN_ROOM_INFO: string = 'MTE_OPEN_ROOM_INFO'; +} diff --git a/src/events/mod-tools/ModToolsOpenRoomInfoEvent.ts b/src/events/mod-tools/ModToolsOpenRoomInfoEvent.ts new file mode 100644 index 00000000..24465610 --- /dev/null +++ b/src/events/mod-tools/ModToolsOpenRoomInfoEvent.ts @@ -0,0 +1,18 @@ +import { ModToolsEvent } from './ModToolsEvent'; + +export class ModToolsOpenRoomInfoEvent extends ModToolsEvent +{ + private _roomId: number; + + constructor(roomId: number) + { + super(ModToolsEvent.OPEN_ROOM_INFO); + + this._roomId = roomId; + } + + public get roomId(): number + { + return this._roomId; + } +} diff --git a/src/events/mod-tools/ModToolsSelectUserEvent.ts b/src/events/mod-tools/ModToolsSelectUserEvent.ts new file mode 100644 index 00000000..148ffe28 --- /dev/null +++ b/src/events/mod-tools/ModToolsSelectUserEvent.ts @@ -0,0 +1,25 @@ +import { ModToolsEvent } from './ModToolsEvent'; + +export class ModToolsSelectUserEvent extends ModToolsEvent +{ + private _webID: number; + private _name: string; + + constructor(webID: number, name: string) + { + super(ModToolsEvent.SELECT_USER); + + this._webID = webID; + this._name = name; + } + + public get webID(): number + { + return this._webID; + } + + public get name(): string + { + return this._name; + } +} diff --git a/src/views/Styles.scss b/src/views/Styles.scss index c4964b7e..0a172311 100644 --- a/src/views/Styles.scss +++ b/src/views/Styles.scss @@ -15,3 +15,4 @@ @import './room-host/RoomHostView'; @import './toolbar/ToolbarView'; @import './wired/WiredView'; +@import './mod-tools/ModToolsView'; diff --git a/src/views/main/MainView.tsx b/src/views/main/MainView.tsx index 540ff32f..96cacefb 100644 --- a/src/views/main/MainView.tsx +++ b/src/views/main/MainView.tsx @@ -6,6 +6,7 @@ import { CatalogView } from '../catalog/CatalogView'; import { FriendListView } from '../friend-list/FriendListView'; import { HotelView } from '../hotel-view/HotelView'; import { InventoryView } from '../inventory/InventoryView'; +import { ModToolsView } from '../mod-tools/ModToolsView'; import { NavigatorView } from '../navigator/NavigatorView'; import { NotificationCenterView } from '../notification-center/NotificationCenterView'; import { RightSideView } from '../right-side/RightSideView'; @@ -46,6 +47,7 @@ export const MainView: FC = props =>
{ landingViewVisible && } + diff --git a/src/views/mod-tools/ModToolsView.scss b/src/views/mod-tools/ModToolsView.scss new file mode 100644 index 00000000..9f5554e9 --- /dev/null +++ b/src/views/mod-tools/ModToolsView.scss @@ -0,0 +1,6 @@ +.nitro-mod-tools { + width: 200px; +} + +@import './views/chatlog/ModToolsChatlogView'; +@import './views/room/ModToolsRoomView'; diff --git a/src/views/mod-tools/ModToolsView.tsx b/src/views/mod-tools/ModToolsView.tsx new file mode 100644 index 00000000..fca38aab --- /dev/null +++ b/src/views/mod-tools/ModToolsView.tsx @@ -0,0 +1,182 @@ +import { RoomEngineEvent } from 'nitro-renderer'; +import { FC, useCallback, useEffect, useReducer, useState } from 'react'; +import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; +import { ModToolsOpenRoomInfoEvent } from '../../events/mod-tools/ModToolsOpenRoomInfoEvent'; +import { ModToolsSelectUserEvent } from '../../events/mod-tools/ModToolsSelectUserEvent'; +import { useRoomEngineEvent } from '../../hooks/events'; +import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout'; +import { ModToolsContextProvider } from './context/ModToolsContext'; +import { ModToolsViewProps } from './ModToolsView.types'; +import { initialModTools, ModToolsActions, ModToolsReducer } from './reducers/ModToolsReducer'; +import { ModToolsRoomView } from './views/room/ModToolsRoomView'; +import { ModToolsTicketsView } from './views/tickets/ModToolsTicketsView'; +import { ModToolsUserView } from './views/user/ModToolsUserView'; + +export const ModToolsView: FC = props => +{ + const [ isVisible, setIsVisible ] = useState(false); + const [ modToolsState, dispatchModToolsState ] = useReducer(ModToolsReducer, initialModTools); + const { currentRoomId = null, selectedUser = null, openRooms = null, openChatlogs = null } = modToolsState; + + const [ isUserVisible, setIsUserVisible ] = useState(false); + const [ isTicketsVisible, setIsTicketsVisible ] = useState(false); + + const onModToolsEvent = useCallback((event: ModToolsEvent) => + { + switch(event.type) + { + case ModToolsEvent.SHOW_MOD_TOOLS: + setIsVisible(true); + return; + case ModToolsEvent.HIDE_MOD_TOOLS: + setIsVisible(false); + return; + case ModToolsEvent.TOGGLE_MOD_TOOLS: + setIsVisible(value => !value); + return; + case ModToolsEvent.SELECT_USER: { + const castedEvent = (event as ModToolsSelectUserEvent); + + dispatchModToolsState({ + type: ModToolsActions.SET_SELECTED_USER, + payload: { + selectedUser: { + webID: castedEvent.webID, + name: castedEvent.name + } + } + }); + return; + } + case ModToolsEvent.OPEN_ROOM_INFO: { + const castedEvent = (event as ModToolsOpenRoomInfoEvent); + + if(openRooms && openRooms.includes(castedEvent.roomId)) return; + + dispatchModToolsState({ + type: ModToolsActions.SET_OPEN_ROOMS, + payload: { + openRooms: [...openRooms, castedEvent.roomId] + } + }); + return; + } + } + }, [ dispatchModToolsState, setIsVisible, openRooms ]); + + useUiEvent(ModToolsEvent.SHOW_MOD_TOOLS, onModToolsEvent); + useUiEvent(ModToolsEvent.HIDE_MOD_TOOLS, onModToolsEvent); + useUiEvent(ModToolsEvent.TOGGLE_MOD_TOOLS, onModToolsEvent); + useUiEvent(ModToolsEvent.SELECT_USER, onModToolsEvent); + useUiEvent(ModToolsEvent.OPEN_ROOM_INFO, onModToolsEvent); + + const onRoomEngineEvent = useCallback((event: RoomEngineEvent) => + { + switch(event.type) + { + case RoomEngineEvent.INITIALIZED: + dispatchModToolsState({ + type: ModToolsActions.SET_CURRENT_ROOM_ID, + payload: { + currentRoomId: event.roomId + } + }); + return; + case RoomEngineEvent.DISPOSED: + dispatchModToolsState({ + type: ModToolsActions.SET_CURRENT_ROOM_ID, + payload: { + currentRoomId: null + } + }); + return; + } + }, [ dispatchModToolsState ]); + + useRoomEngineEvent(RoomEngineEvent.INITIALIZED, onRoomEngineEvent); + useRoomEngineEvent(RoomEngineEvent.DISPOSED, onRoomEngineEvent); + + const handleClick = useCallback((action: string, value?: string) => + { + if(!action) return; + + switch(action) + { + case 'toggle_room': { + if(!openRooms) + { + dispatchUiEvent(new ModToolsOpenRoomInfoEvent(currentRoomId)); + return; + } + + const itemIndex = openRooms.indexOf(currentRoomId); + + if(itemIndex > -1) + { + handleClick('close_room', currentRoomId.toString()); + } + else + { + dispatchUiEvent(new ModToolsOpenRoomInfoEvent(currentRoomId)); + } + return; + } + case 'close_room': { + const itemIndex = openRooms.indexOf(Number(value)); + + const clone = Array.from(openRooms); + clone.splice(itemIndex, 1); + + dispatchModToolsState({ + type: ModToolsActions.SET_OPEN_ROOMS, + payload: { + openRooms: clone + } + }); + return; + } + case 'close_chatlog': { + const itemIndex = openChatlogs.indexOf(Number(value)); + + const clone = Array.from(openChatlogs); + clone.splice(itemIndex, 1); + + dispatchModToolsState({ + type: ModToolsActions.SET_OPEN_CHATLOGS, + payload: { + openChatlogs: clone + } + }); + return; + } + } + }, [ dispatchModToolsState, openRooms, openChatlogs, currentRoomId ]); + + useEffect(() => + { + if(!isVisible) return; + }, [ isVisible ]); + + return ( + + { isVisible && + + setIsVisible(false) } /> + + + + + + + } + { openRooms && openRooms.map(roomId => + { + return handleClick('close_room', roomId.toString()) } />; + }) } + + { isUserVisible && } + { isTicketsVisible && } + + ); +} diff --git a/src/views/mod-tools/ModToolsView.types.ts b/src/views/mod-tools/ModToolsView.types.ts new file mode 100644 index 00000000..3aa7691f --- /dev/null +++ b/src/views/mod-tools/ModToolsView.types.ts @@ -0,0 +1,2 @@ +export interface ModToolsViewProps +{} diff --git a/src/views/mod-tools/context/ModToolsContext.tsx b/src/views/mod-tools/context/ModToolsContext.tsx new file mode 100644 index 00000000..97873603 --- /dev/null +++ b/src/views/mod-tools/context/ModToolsContext.tsx @@ -0,0 +1,14 @@ +import { createContext, FC, useContext } from 'react'; +import { IModToolsContext, ModToolsContextProps } from './ModToolsContext.types'; + +const ModToolsContext = createContext({ + modToolsState: null, + dispatchModToolsState: null +}); + +export const ModToolsContextProvider: FC = props => +{ + return { props.children } +} + +export const useModToolsContext = () => useContext(ModToolsContext); diff --git a/src/views/mod-tools/context/ModToolsContext.types.ts b/src/views/mod-tools/context/ModToolsContext.types.ts new file mode 100644 index 00000000..46c6a9b8 --- /dev/null +++ b/src/views/mod-tools/context/ModToolsContext.types.ts @@ -0,0 +1,13 @@ +import { Dispatch, ProviderProps } from 'react'; +import { IModToolsAction, IModToolsState } from '../reducers/ModToolsReducer'; + +export interface IModToolsContext +{ + modToolsState: IModToolsState; + dispatchModToolsState: Dispatch; +} + +export interface ModToolsContextProps extends ProviderProps +{ + +} diff --git a/src/views/mod-tools/reducers/ModToolsReducer.tsx b/src/views/mod-tools/reducers/ModToolsReducer.tsx new file mode 100644 index 00000000..955d70b9 --- /dev/null +++ b/src/views/mod-tools/reducers/ModToolsReducer.tsx @@ -0,0 +1,63 @@ +import { Reducer } from 'react'; + +export interface IModToolsState +{ + selectedUser: {webID: number, name: string}; + currentRoomId: number; + openRooms: number[]; + openChatlogs: number[]; +} + +export interface IModToolsAction +{ + type: string; + payload: { + selectedUser?: {webID: number, name: string}; + currentRoomId?: number; + openRooms?: number[]; + openChatlogs?: number[]; + } +} + +export class ModToolsActions +{ + public static SET_SELECTED_USER: string = 'MTA_SET_SELECTED_USER'; + public static SET_CURRENT_ROOM_ID: string = 'MTA_SET_CURRENT_ROOM_ID'; + public static SET_OPEN_ROOMS: string = 'MTA_SET_OPEN_ROOMS'; + public static SET_OPEN_CHATLOGS: string = 'MTA_SET_OPEN_CHATLOGS'; + public static RESET_STATE: string = 'MTA_RESET_STATE'; +} + +export const initialModTools: IModToolsState = { + selectedUser: null, + currentRoomId: null, + openRooms: null, + openChatlogs: null +}; + +export const ModToolsReducer: Reducer = (state, action) => +{ + switch(action.type) + { + case ModToolsActions.SET_SELECTED_USER: { + const selectedUser = (action.payload.selectedUser || state.selectedUser || null); + + return { ...state, selectedUser }; + } + case ModToolsActions.SET_CURRENT_ROOM_ID: { + const currentRoomId = (action.payload.currentRoomId || state.currentRoomId || null); + + return { ...state, currentRoomId }; + } + case ModToolsActions.SET_OPEN_ROOMS: { + const openRooms = (action.payload.openRooms || state.openRooms || null); + + return { ...state, openRooms }; + } + case ModToolsActions.RESET_STATE: { + return { ...initialModTools }; + } + default: + return state; + } +} diff --git a/src/views/mod-tools/views/chatlog/ModToolsChatlogView.scss b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.scss new file mode 100644 index 00000000..7a2ddc8a --- /dev/null +++ b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.scss @@ -0,0 +1,26 @@ +.nitro-mod-tools-chatlog { + width: 480px; + + .chatlog-messages { + height: 300px; + max-height: 300px; + + .table { + color: $black; + + > :not(caption) > * > * { + box-shadow: none; + border-bottom: 1px solid rgba(0, 0, 0, .2); + } + + &.table-striped > tbody > tr:nth-of-type(odd) { + color: $black; + background: rgba(0, 0, 0, .05); + } + + td { + padding: 0px 5px; + } + } + } +} diff --git a/src/views/mod-tools/views/chatlog/ModToolsChatlogView.tsx b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.tsx new file mode 100644 index 00000000..3eef566f --- /dev/null +++ b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.tsx @@ -0,0 +1,84 @@ +import { ModtoolRequestRoomChatlogComposer, ModtoolRoomChatlogEvent, ModtoolRoomChatlogLine } from 'nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { TryVisitRoom } from '../../../../api/navigator/TryVisitRoom'; +import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { ModToolsChatlogViewProps } from './ModToolsChatlogView.types'; + +export const ModToolsChatlogView: FC = props => +{ + const { roomId = null, onCloseClick = null } = props; + + const [ roomName, setRoomName ] = useState(null); + const [ messages, setMessages ] = useState(null); + const [ loadedRoomId, setLoadedRoomId ] = useState(null); + + const [ messagesRequested, setMessagesRequested ] = useState(false); + + useEffect(() => + { + if(messagesRequested) return; + + SendMessageHook(new ModtoolRequestRoomChatlogComposer(roomId)); + setMessagesRequested(true); + }, [ roomId, messagesRequested, setMessagesRequested ]); + + const onModtoolRoomChatlogEvent = useCallback((event: ModtoolRoomChatlogEvent) => + { + const parser = event.getParser(); + + setRoomName(parser.name); + setMessages(parser.chatlogs); + setLoadedRoomId(parser.id); + }, [ setRoomName, setMessages ]); + + CreateMessageHook(ModtoolRoomChatlogEvent, onModtoolRoomChatlogEvent); + + const handleClick = useCallback((action: string, value?: string) => + { + if(!action) return; + + switch(action) + { + case 'close': + onCloseClick(); + return; + case 'visit_room': + TryVisitRoom(loadedRoomId); + return; + } + }, [ onCloseClick, loadedRoomId ]); + + return ( + + handleClick('close') } /> + +
+ + +
+
+ { messages && + + + + + + + + + { messages.map((message, index) => + { + return + + + + ; + }) } + +
TimeUserMessage
{ message.timestamp }{ message.userName }{ message.message }
} +
+
+
+ ); +} diff --git a/src/views/mod-tools/views/chatlog/ModToolsChatlogView.types.ts b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.types.ts new file mode 100644 index 00000000..0589cd02 --- /dev/null +++ b/src/views/mod-tools/views/chatlog/ModToolsChatlogView.types.ts @@ -0,0 +1,5 @@ +export interface ModToolsChatlogViewProps +{ + roomId: number; + onCloseClick: () => void; +} diff --git a/src/views/mod-tools/views/room/ModToolsRoomView.scss b/src/views/mod-tools/views/room/ModToolsRoomView.scss new file mode 100644 index 00000000..55ed938a --- /dev/null +++ b/src/views/mod-tools/views/room/ModToolsRoomView.scss @@ -0,0 +1,3 @@ +.nitro-mod-tools-room { + width: 240px; +} diff --git a/src/views/mod-tools/views/room/ModToolsRoomView.tsx b/src/views/mod-tools/views/room/ModToolsRoomView.tsx new file mode 100644 index 00000000..dc385bbb --- /dev/null +++ b/src/views/mod-tools/views/room/ModToolsRoomView.tsx @@ -0,0 +1,104 @@ +import { ModtoolRequestRoomInfoComposer, ModtoolRoomInfoEvent } from 'nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { ModToolsRoomViewProps } from './ModToolsRoomView.types'; + +export const ModToolsRoomView: FC = props => +{ + const { roomId = null, onCloseClick = null } = props; + + const [ infoRequested, setInfoRequested ] = useState(false); + const [ loadedRoomId, setLoadedRoomId ] = useState(null); + + const [ name, setName ] = useState(null); + const [ ownerId, setOwnerId ] = useState(null); + const [ ownerName, setOwnerName ] = useState(null); + const [ ownerInRoom, setOwnerInRoom ] = useState(false); + const [ usersInRoom, setUsersInRoom ] = useState(0); + + useEffect(() => + { + if(infoRequested) return; + + SendMessageHook(new ModtoolRequestRoomInfoComposer(roomId)); + setInfoRequested(true); + }, [ roomId, infoRequested, setInfoRequested ]); + + const onModtoolRoomInfoEvent = useCallback((event: ModtoolRoomInfoEvent) => + { + const parser = event.getParser(); + + setLoadedRoomId(parser.id); + setName(parser.name); + setOwnerId(parser.ownerId); + setOwnerName(parser.ownerName); + setOwnerInRoom(parser.ownerInRoom); + setUsersInRoom(parser.playerAmount); + }, [ setLoadedRoomId, setName, setOwnerId, setOwnerName, setOwnerInRoom, setUsersInRoom ]); + + CreateMessageHook(ModtoolRoomInfoEvent, onModtoolRoomInfoEvent); + + const handleClick = useCallback((action: string, value?: string) => + { + if(!action) return; + + switch(action) + { + case 'close': + onCloseClick(); + return; + } + }, [ onCloseClick ]); + + return ( + + handleClick('close') } /> + +
+
+ Room Owner: { ownerName } +
+ +
+
+
+ Users in room: { usersInRoom } +
+ +
+
+
+ Owner in room: { ownerInRoom ? 'Yes' : 'No' } +
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ ); +} diff --git a/src/views/mod-tools/views/room/ModToolsRoomView.types.ts b/src/views/mod-tools/views/room/ModToolsRoomView.types.ts new file mode 100644 index 00000000..d096fcbe --- /dev/null +++ b/src/views/mod-tools/views/room/ModToolsRoomView.types.ts @@ -0,0 +1,5 @@ +export interface ModToolsRoomViewProps +{ + roomId: number; + onCloseClick: () => void; +} diff --git a/src/views/mod-tools/views/tickets/ModToolsTicketsView.tsx b/src/views/mod-tools/views/tickets/ModToolsTicketsView.tsx new file mode 100644 index 00000000..060af699 --- /dev/null +++ b/src/views/mod-tools/views/tickets/ModToolsTicketsView.tsx @@ -0,0 +1,15 @@ +import { FC } from 'react'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { ModToolsTicketsViewProps } from './ModToolsTicketsView.types'; + +export const ModToolsTicketsView: FC = props => +{ + return ( + + {} } /> + + + + + ); +} diff --git a/src/views/mod-tools/views/tickets/ModToolsTicketsView.types.ts b/src/views/mod-tools/views/tickets/ModToolsTicketsView.types.ts new file mode 100644 index 00000000..a8713d1f --- /dev/null +++ b/src/views/mod-tools/views/tickets/ModToolsTicketsView.types.ts @@ -0,0 +1,2 @@ +export interface ModToolsTicketsViewProps +{} diff --git a/src/views/mod-tools/views/user/ModToolsUserView.tsx b/src/views/mod-tools/views/user/ModToolsUserView.tsx new file mode 100644 index 00000000..44351831 --- /dev/null +++ b/src/views/mod-tools/views/user/ModToolsUserView.tsx @@ -0,0 +1,15 @@ +import { FC } from 'react'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { ModToolsUserViewProps } from './ModToolsUserView.types'; + +export const ModToolsUserView: FC = props => +{ + return ( + + {} } /> + + + + + ); +} diff --git a/src/views/mod-tools/views/user/ModToolsUserView.types.ts b/src/views/mod-tools/views/user/ModToolsUserView.types.ts new file mode 100644 index 00000000..55b9477c --- /dev/null +++ b/src/views/mod-tools/views/user/ModToolsUserView.types.ts @@ -0,0 +1,2 @@ +export interface ModToolsUserViewProps +{} diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx index 72ed9010..36c04479 100644 --- a/src/views/toolbar/ToolbarView.tsx +++ b/src/views/toolbar/ToolbarView.tsx @@ -1,8 +1,8 @@ -import { Dispose, DropBounce, EaseOut, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserFigureEvent, Wait } from 'nitro-renderer'; -import { UserInfoEvent } from 'nitro-renderer/src/nitro/communication/messages/incoming/user/data/UserInfoEvent'; -import { UserInfoDataParser } from 'nitro-renderer/src/nitro/communication/messages/parser/user/data/UserInfoDataParser'; +import { Dispose, DropBounce, EaseOut, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserFigureEvent, UserInfoDataParser, UserInfoEvent, Wait } from 'nitro-renderer'; import { FC, useCallback, useState } from 'react'; -import { AvatarEditorEvent, CatalogEvent, FriendListEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent, UnseenItemTrackerUpdateEvent } from '../../events'; +import { AvatarEditorEvent, CatalogEvent, FriendListEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; +import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent'; +import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { useRoomEngineEvent } from '../../hooks'; import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event'; import { CreateMessageHook } from '../../hooks/messages/message-event'; @@ -114,6 +114,9 @@ export const ToolbarView: FC = props => dispatchUiEvent(new AvatarEditorEvent(AvatarEditorEvent.TOGGLE_EDITOR)); setMeExpanded(false); return; + case ToolbarViewItems.MOD_TOOLS_ITEM: + dispatchUiEvent(new ModToolsEvent(ModToolsEvent.TOGGLE_MOD_TOOLS)); + return; } }, []); @@ -160,13 +163,21 @@ export const ToolbarView: FC = props =>
{ isInRoom && (
handleToolbarItemClick(ToolbarViewItems.CAMERA_ITEM) }> - -
) } + + ) }
+
handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }> + + { (unseenFriendListCount > 0) && ( +
{ unseenFriendListCount }
) } +
+
handleToolbarItemClick(ToolbarViewItems.MOD_TOOLS_ITEM) }> + +
diff --git a/src/views/toolbar/ToolbarView.types.ts b/src/views/toolbar/ToolbarView.types.ts index 6c280e6c..d9ab106a 100644 --- a/src/views/toolbar/ToolbarView.types.ts +++ b/src/views/toolbar/ToolbarView.types.ts @@ -11,4 +11,5 @@ export class ToolbarViewItems public static FRIEND_LIST_ITEM: string = 'TVI_FRIEND_LIST_ITEM'; public static CLOTHING_ITEM: string = 'TVI_CLOTHING_ITEM'; public static CAMERA_ITEM: string = 'TVI_CAMERA_ITEM'; + public static MOD_TOOLS_ITEM: string = 'TVI_MOD_TOOLS_ITEM'; }