From 7926bb7469bd0cbc17d699d1ae003629f7e6f17d Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Thu, 16 Sep 2021 01:37:17 -0300 Subject: [PATCH 01/21] Updates DONT TOUCH IT --- .../handlers/RoomWidgetInfostandHandler.ts | 4 +- src/events/friend-list/index.ts | 2 - .../FriendEnteredRoomEvent.ts | 0 .../FriendListContentEvent.ts | 4 +- .../FriendsEvent.ts} | 4 +- .../FriendsSendFriendRequestEvent.ts} | 6 +- src/events/friends/index.ts | 4 + src/events/index.ts | 2 +- .../friends/FriendListMessageHandler.tsx | 73 ---------- .../friends/FriendListMessageHandler.types.ts | 5 - src/views/friends/FriendsMessageHandler.tsx | 90 ++++++++++++ src/views/friends/FriendsView.scss | 2 +- src/views/friends/FriendsView.tsx | 128 +++++++----------- src/views/friends/common/MessengerChat.ts | 34 +++++ .../friends/common/MessengerChatMessage.ts | 13 ++ .../friends/context/FriendListContext.tsx | 14 -- .../friends/context/FriendListContext.type.ts | 13 -- src/views/friends/context/FriendsContext.tsx | 14 ++ .../friends/context/FriendsContext.type.ts | 13 ++ ...iendListReducer.tsx => FriendsReducer.tsx} | 40 ++++-- .../views/friend-bar/FriendBarView.tsx | 6 +- .../views/friend-item/FriendsListItemView.tsx | 3 +- .../FriendsGroupItemView.tsx | 63 +++++++++ .../FriendsGroupItemView.types.ts | 6 + .../FriendsGroupView.tsx} | 10 +- .../FriendsGroupView.types.ts} | 2 +- .../views/friends-list/FriendsListView.tsx | 43 ++++++ .../friends-list/FriendsListView.types.ts | 9 ++ .../FriendsRequestItemView.tsx | 37 +++++ .../FriendsRequestItemView.types.ts | 6 + .../views/messenger/FriendsMessengerView.tsx | 13 ++ .../FriendsRequestItemView.types.ts | 3 +- .../NavigatorRoomSettingsView.tsx | 6 +- src/views/toolbar/ToolbarView.tsx | 4 +- 34 files changed, 450 insertions(+), 226 deletions(-) delete mode 100644 src/events/friend-list/index.ts rename src/events/{friend-list => friends}/FriendEnteredRoomEvent.ts (100%) rename src/events/{friend-list => friends}/FriendListContentEvent.ts (83%) rename src/events/{friend-list/FriendListEvent.ts => friends/FriendsEvent.ts} (57%) rename src/events/{friend-list/FriendListSendFriendRequestEvent.ts => friends/FriendsSendFriendRequestEvent.ts} (57%) create mode 100644 src/events/friends/index.ts delete mode 100644 src/views/friends/FriendListMessageHandler.tsx delete mode 100644 src/views/friends/FriendListMessageHandler.types.ts create mode 100644 src/views/friends/FriendsMessageHandler.tsx create mode 100644 src/views/friends/common/MessengerChat.ts create mode 100644 src/views/friends/common/MessengerChatMessage.ts delete mode 100644 src/views/friends/context/FriendListContext.tsx delete mode 100644 src/views/friends/context/FriendListContext.type.ts create mode 100644 src/views/friends/context/FriendsContext.tsx create mode 100644 src/views/friends/context/FriendsContext.type.ts rename src/views/friends/reducers/{FriendListReducer.tsx => FriendsReducer.tsx} (77%) create mode 100644 src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx create mode 100644 src/views/friends/views/friends-group-item/FriendsGroupItemView.types.ts rename src/views/friends/views/{list/FriendsListView.tsx => friends-group/FriendsGroupView.tsx} (58%) rename src/views/friends/views/{list/FriendsListView.types.ts => friends-group/FriendsGroupView.types.ts} (82%) create mode 100644 src/views/friends/views/friends-list/FriendsListView.tsx create mode 100644 src/views/friends/views/friends-list/FriendsListView.types.ts create mode 100644 src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx create mode 100644 src/views/friends/views/friends-request-item/FriendsRequestItemView.types.ts create mode 100644 src/views/friends/views/messenger/FriendsMessengerView.tsx diff --git a/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts b/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts index 1ee584ce..e86aba4e 100644 --- a/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts +++ b/src/api/nitro/room/widgets/handlers/RoomWidgetInfostandHandler.ts @@ -1,7 +1,7 @@ import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer'; import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..'; import { InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events'; -import { FriendListSendFriendRequestEvent } from '../../../../../events/friend-list/FriendListSendFriendRequestEvent'; +import { FriendsSendFriendRequestEvent } from '../../../../../events/friends/FriendsSendFriendRequestEvent'; import { dispatchUiEvent } from '../../../../../hooks/events'; import { SendMessageHook } from '../../../../../hooks/messages'; import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum'; @@ -76,7 +76,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO: return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage)); case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST: - dispatchUiEvent(new FriendListSendFriendRequestEvent(userId)); + dispatchUiEvent(new FriendsSendFriendRequestEvent(userId)); break; case RoomWidgetUserActionMessage.RESPECT_USER: GetSessionDataManager().giveRespect(userId); diff --git a/src/events/friend-list/index.ts b/src/events/friend-list/index.ts deleted file mode 100644 index 4789fde9..00000000 --- a/src/events/friend-list/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './FriendEnteredRoomEvent'; -export * from './FriendListEvent'; diff --git a/src/events/friend-list/FriendEnteredRoomEvent.ts b/src/events/friends/FriendEnteredRoomEvent.ts similarity index 100% rename from src/events/friend-list/FriendEnteredRoomEvent.ts rename to src/events/friends/FriendEnteredRoomEvent.ts diff --git a/src/events/friend-list/FriendListContentEvent.ts b/src/events/friends/FriendListContentEvent.ts similarity index 83% rename from src/events/friend-list/FriendListContentEvent.ts rename to src/events/friends/FriendListContentEvent.ts index a7623cbc..80048267 100644 --- a/src/events/friend-list/FriendListContentEvent.ts +++ b/src/events/friends/FriendListContentEvent.ts @@ -1,7 +1,7 @@ import { MessengerFriend } from '../../views/friends/common/MessengerFriend'; -import { FriendListEvent } from './FriendListEvent'; +import { FriendsEvent } from './FriendsEvent'; -export class FriendListContentEvent extends FriendListEvent +export class FriendListContentEvent extends FriendsEvent { public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT'; diff --git a/src/events/friend-list/FriendListEvent.ts b/src/events/friends/FriendsEvent.ts similarity index 57% rename from src/events/friend-list/FriendListEvent.ts rename to src/events/friends/FriendsEvent.ts index d450144e..0f8be1d7 100644 --- a/src/events/friend-list/FriendListEvent.ts +++ b/src/events/friends/FriendsEvent.ts @@ -1,8 +1,10 @@ import { NitroEvent } from '@nitrots/nitro-renderer'; -export class FriendListEvent extends NitroEvent +export class FriendsEvent extends NitroEvent { public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST'; public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST'; + public static SHOW_FRIEND_MESSENGER: string = 'IE_SHOW_FRIEND_MESSENGER'; + public static TOGGLE_FRIEND_MESSENGER: string = 'IE_TOGGLE_FRIEND_MESSENGER'; public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST'; } diff --git a/src/events/friend-list/FriendListSendFriendRequestEvent.ts b/src/events/friends/FriendsSendFriendRequestEvent.ts similarity index 57% rename from src/events/friend-list/FriendListSendFriendRequestEvent.ts rename to src/events/friends/FriendsSendFriendRequestEvent.ts index 02d7c006..9e42661b 100644 --- a/src/events/friend-list/FriendListSendFriendRequestEvent.ts +++ b/src/events/friends/FriendsSendFriendRequestEvent.ts @@ -1,6 +1,6 @@ -import { FriendListEvent } from './FriendListEvent'; +import { FriendsEvent } from './FriendsEvent'; -export class FriendListSendFriendRequestEvent extends FriendListEvent +export class FriendsSendFriendRequestEvent extends FriendsEvent { public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST'; @@ -8,7 +8,7 @@ export class FriendListSendFriendRequestEvent extends FriendListEvent constructor(userId: number) { - super(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST); + super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST); this._userId = userId; } diff --git a/src/events/friends/index.ts b/src/events/friends/index.ts new file mode 100644 index 00000000..9a4bb3ed --- /dev/null +++ b/src/events/friends/index.ts @@ -0,0 +1,4 @@ +export * from './FriendEnteredRoomEvent'; +export * from './FriendListContentEvent'; +export * from './FriendsEvent'; +export * from './FriendsSendFriendRequestEvent'; diff --git a/src/events/index.ts b/src/events/index.ts index 006285c8..9d4842ca 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,7 +1,7 @@ export * from './avatar-editor'; export * from './camera'; export * from './catalog'; -export * from './friend-list'; +export * from './friends'; export * from './inventory'; export * from './navigator'; export * from './notification-center'; diff --git a/src/views/friends/FriendListMessageHandler.tsx b/src/views/friends/FriendListMessageHandler.tsx deleted file mode 100644 index e84e72a5..00000000 --- a/src/views/friends/FriendListMessageHandler.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent } from '@nitrots/nitro-renderer'; -import { FC, useCallback } from 'react'; -import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; -import { MessengerSettings } from './common/MessengerSettings'; -import { useFriendListContext } from './context/FriendListContext'; -import { FriendListMessageHandlerProps } from './FriendListMessageHandler.types'; -import { FriendListActions } from './reducers/FriendListReducer'; - -export const FriendListMessageHandler: FC = props => -{ - const { friendListState = null, dispatchFriendListState = null } = useFriendListContext(); - - const onMessengerInitEvent = useCallback((event: MessengerInitEvent) => - { - const parser = event.getParser(); - - dispatchFriendListState({ - type: FriendListActions.UPDATE_SETTINGS, - payload: { - settings: new MessengerSettings( - parser.userFriendLimit, - parser.normalFriendLimit, - parser.extendedFriendLimit, - parser.categories) - } - }); - - SendMessageHook(new GetFriendRequestsComposer()); - }, [ dispatchFriendListState ]); - - const onFriendListFragmentEvent = useCallback((event: FriendListFragmentEvent) => - { - const parser = event.getParser(); - - dispatchFriendListState({ - type: FriendListActions.PROCESS_FRAGMENT, - payload: { - fragment: parser.fragment - } - }); - }, [ dispatchFriendListState ]); - - const onFriendListUpdateEvent = useCallback((event: FriendListUpdateEvent) => - { - const parser = event.getParser(); - - dispatchFriendListState({ - type: FriendListActions.PROCESS_UPDATE, - payload: { - update: parser - } - }); - }, [ dispatchFriendListState ]); - - const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) => - { - const parser = event.getParser(); - - dispatchFriendListState({ - type: FriendListActions.PROCESS_REQUESTS, - payload: { - requests: parser.requests - } - }); - }, [ dispatchFriendListState ]); - - CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); - CreateMessageHook(FriendListFragmentEvent, onFriendListFragmentEvent); - CreateMessageHook(FriendListUpdateEvent, onFriendListUpdateEvent); - CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent); - - return null; -} diff --git a/src/views/friends/FriendListMessageHandler.types.ts b/src/views/friends/FriendListMessageHandler.types.ts deleted file mode 100644 index 2a810612..00000000 --- a/src/views/friends/FriendListMessageHandler.types.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export interface FriendListMessageHandlerProps -{ - -} diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx new file mode 100644 index 00000000..579230a5 --- /dev/null +++ b/src/views/friends/FriendsMessageHandler.tsx @@ -0,0 +1,90 @@ +import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent, NewConsoleMessageEvent } from '@nitrots/nitro-renderer'; +import { FC, useCallback } from 'react'; +import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; +import { MessengerSettings } from './common/MessengerSettings'; +import { useFriendsContext } from './context/FriendsContext'; +import { FriendsActions } from './reducers/FriendsReducer'; + +export const FriendsMessageHandler: FC<{}> = props => +{ + const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); + const { activeChats = [] } = friendsState; + + const onMessengerInitEvent = useCallback((event: MessengerInitEvent) => + { + const parser = event.getParser(); + + dispatchFriendsState({ + type: FriendsActions.UPDATE_SETTINGS, + payload: { + settings: new MessengerSettings( + parser.userFriendLimit, + parser.normalFriendLimit, + parser.extendedFriendLimit, + parser.categories) + } + }); + + SendMessageHook(new GetFriendRequestsComposer()); + }, [ dispatchFriendsState ]); + + const onFriendsFragmentEvent = useCallback((event: FriendListFragmentEvent) => + { + const parser = event.getParser(); + + dispatchFriendsState({ + type: FriendsActions.PROCESS_FRAGMENT, + payload: { + fragment: parser.fragment + } + }); + }, [ dispatchFriendsState ]); + + const onFriendsUpdateEvent = useCallback((event: FriendListUpdateEvent) => + { + const parser = event.getParser(); + + dispatchFriendsState({ + type: FriendsActions.PROCESS_UPDATE, + payload: { + update: parser + } + }); + }, [ dispatchFriendsState ]); + + const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) => + { + const parser = event.getParser(); + + dispatchFriendsState({ + type: FriendsActions.PROCESS_REQUESTS, + payload: { + requests: parser.requests + } + }); + }, [ dispatchFriendsState ]); + + const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) => + { + const parser = event.getParser(); + + const activeChat = activeChats.find(c => c.friendId === parser.senderId); + + if(activeChat) + { + + } + else + { + + } + }, [ friendsState, dispatchFriendsState ]); + + CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); + CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent); + CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent); + CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent); + CreateMessageHook(NewConsoleMessageEvent, onNewConsoleMessageEvent); + + return null; +} diff --git a/src/views/friends/FriendsView.scss b/src/views/friends/FriendsView.scss index 1d882087..519d6d1e 100644 --- a/src/views/friends/FriendsView.scss +++ b/src/views/friends/FriendsView.scss @@ -1,4 +1,4 @@ -.nitro-friend-list { +.nitro-friends { width: 250px; } diff --git a/src/views/friends/FriendsView.tsx b/src/views/friends/FriendsView.tsx index 6e2d74eb..8c8e5316 100644 --- a/src/views/friends/FriendsView.tsx +++ b/src/views/friends/FriendsView.tsx @@ -1,54 +1,69 @@ import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react'; import { createPortal } from 'react-dom'; -import { GetRoomSession, LocalizeText } from '../../api'; -import { FriendEnteredRoomEvent, FriendListEvent } from '../../events'; -import { FriendListContentEvent } from '../../events/friend-list/FriendListContentEvent'; -import { FriendListSendFriendRequestEvent } from '../../events/friend-list/FriendListSendFriendRequestEvent'; +import { GetRoomSession } from '../../api'; +import { FriendEnteredRoomEvent, FriendListContentEvent, FriendsEvent } from '../../events'; +import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent'; import { useRoomEngineEvent } from '../../hooks/events'; import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; -import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout'; -import { FriendListContextProvider } from './context/FriendListContext'; -import { FriendListMessageHandler } from './FriendListMessageHandler'; -import { FriendListReducer, initialFriendList } from './reducers/FriendListReducer'; +import { FriendsContextProvider } from './context/FriendsContext'; +import { FriendsMessageHandler } from './FriendsMessageHandler'; +import { FriendsReducer, initialFriends } from './reducers/FriendsReducer'; import { FriendBarView } from './views/friend-bar/FriendBarView'; -import { FriendsListView } from './views/list/FriendsListView'; - -const TABS: string[] = ['friendlist.friends', 'generic.search']; +import { FriendsListView } from './views/friends-list/FriendsListView'; +import { FriendsMessengerView } from './views/messenger/FriendsMessengerView'; export const FriendsView: FC<{}> = props => { - const [ friendListState, dispatchFriendListState ] = useReducer(FriendListReducer, initialFriendList); - const { friends = null, requests = null, settings = null } = friendListState; + const [ friendsState, dispatchFriendsState ] = useReducer(FriendsReducer, initialFriends); + const { friends = [], requests = [], settings = null } = friendsState; - const [ isVisible, setIsVisible ] = useState(false); const [ isReady, setIsReady ] = useState(false); - const [ currentTab, setCurrentTab ] = useState(0); + const [ isListVisible, setIsListVisible ] = useState(false); + const [ isMessengerVisible, setIsMessengerVisible ] = useState(false); - const onFriendListEvent = useCallback((event: FriendListEvent) => + useEffect(() => + { + SendMessageHook(new MessengerInitComposer()); + }, []); + + useEffect(() => + { + if(!settings) return; + + setIsReady(true); + }, [ settings ]); + + const onFriendsEvent = useCallback((event: FriendsEvent) => { switch(event.type) { - case FriendListEvent.SHOW_FRIEND_LIST: - setIsVisible(true); + case FriendsEvent.SHOW_FRIEND_LIST: + setIsListVisible(true); return; - case FriendListEvent.TOGGLE_FRIEND_LIST: - setIsVisible(value => !value); + case FriendsEvent.TOGGLE_FRIEND_LIST: + setIsListVisible(value => !value); return; - case FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST: - const requestEvent = (event as FriendListSendFriendRequestEvent); + case FriendsEvent.SHOW_FRIEND_MESSENGER: + setIsMessengerVisible(true); return; - case FriendListEvent.REQUEST_FRIEND_LIST: - dispatchUiEvent(new FriendListContentEvent(friendListState.friends)); + case FriendsEvent.TOGGLE_FRIEND_MESSENGER: + setIsMessengerVisible(value => !value); + return; + case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST: + const requestEvent = (event as FriendsSendFriendRequestEvent); + return; + case FriendsEvent.REQUEST_FRIEND_LIST: + dispatchUiEvent(new FriendListContentEvent(friendsState.friends)); return; } - }, [friendListState.friends]); + }, [ friendsState.friends ]); - useUiEvent(FriendListEvent.SHOW_FRIEND_LIST, onFriendListEvent); - useUiEvent(FriendListEvent.TOGGLE_FRIEND_LIST, onFriendListEvent); - useUiEvent(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendListEvent); - useUiEvent(FriendListEvent.REQUEST_FRIEND_LIST, onFriendListEvent); + useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent); + useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent); + useUiEvent(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST, onFriendsEvent); + useUiEvent(FriendsEvent.REQUEST_FRIEND_LIST, onFriendsEvent); const onRoomEngineObjectEvent = useCallback((event: RoomEngineObjectEvent) => { @@ -62,7 +77,7 @@ export const FriendsView: FC<{}> = props => if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return; - const friend = friendListState.friends.find(friend => + const friend = friendsState.friends.find(friend => { return (friend.id === userData.webID); }); @@ -70,67 +85,26 @@ export const FriendsView: FC<{}> = props => if(!friend) return; dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type)); - }, [ friendListState.friends ]); + }, [ friendsState.friends ]); useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent); - useEffect(() => - { - if(!settings) return; - - setIsReady(true); - }, [ settings ]); - - useEffect(() => - { - SendMessageHook(new MessengerInitComposer()); - }, []); - const onlineFriends = useMemo(() => { - if(!friends) return []; - return friends.filter(f => f.online); }, [ friends ]); const offlineFriends = useMemo(() => { - if(!friends) return []; - return friends.filter(f => !f.online); }, [ friends ]); return ( - - + + { isReady && createPortal(, document.getElementById('toolbar-friend-bar-container')) } - { isVisible && - - setIsVisible(false) } /> - - - { TABS.map((tab, index) => - { - return ( setCurrentTab(index) }> - { LocalizeText(tab) } - ); - }) } - -
- { currentTab === 0 && - - - - - - - { requests.length > 0 && - - } - } -
-
-
} -
+ { isListVisible && setIsListVisible(false) } /> } + { isMessengerVisible && } + ); } diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts new file mode 100644 index 00000000..d21982c9 --- /dev/null +++ b/src/views/friends/common/MessengerChat.ts @@ -0,0 +1,34 @@ +import { MessengerChatMessage } from './MessengerChatMessage'; +export class MessengerChat +{ + private _friendId: number; + private _isRead: boolean; + private _messages: MessengerChatMessage[]; + + constructor(friendId: number, isRead: boolean = true) + { + this._friendId = friendId; + this._isRead = isRead; + this._messages = []; + } + + public addMessage(): void + { + this._messages.push(); + } + + public get friendId(): number + { + return this._friendId; + } + + public get isRead(): boolean + { + return this._isRead; + } + + public get messages(): MessengerChatMessage[] + { + return this._messages; + } +} diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerChatMessage.ts new file mode 100644 index 00000000..28b54787 --- /dev/null +++ b/src/views/friends/common/MessengerChatMessage.ts @@ -0,0 +1,13 @@ +export class MessengerChatMessage +{ + private _type: number; + private _senderId: number; + private _message: string; + private _extraData: string; + private _sentAt: number; + + constructor(type: number, senderId: number, message: string, extraData: string, sentAt: number) + { + + } +} diff --git a/src/views/friends/context/FriendListContext.tsx b/src/views/friends/context/FriendListContext.tsx deleted file mode 100644 index 39d23764..00000000 --- a/src/views/friends/context/FriendListContext.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createContext, FC, useContext } from 'react'; -import { FriendListContextProps, IFriendListContext } from './FriendListContext.type'; - -const FriendListContext = createContext({ - friendListState: null, - dispatchFriendListState: null -}); - -export const FriendListContextProvider: FC = props => -{ - return { props.children } -} - -export const useFriendListContext = () => useContext(FriendListContext); diff --git a/src/views/friends/context/FriendListContext.type.ts b/src/views/friends/context/FriendListContext.type.ts deleted file mode 100644 index 6e74c4cb..00000000 --- a/src/views/friends/context/FriendListContext.type.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Dispatch, ProviderProps } from 'react'; -import { IFriendListAction, IFriendListState } from '../reducers/FriendListReducer'; - -export interface IFriendListContext -{ - friendListState: IFriendListState; - dispatchFriendListState: Dispatch; -} - -export interface FriendListContextProps extends ProviderProps -{ - -} diff --git a/src/views/friends/context/FriendsContext.tsx b/src/views/friends/context/FriendsContext.tsx new file mode 100644 index 00000000..5b551102 --- /dev/null +++ b/src/views/friends/context/FriendsContext.tsx @@ -0,0 +1,14 @@ +import { createContext, FC, useContext } from 'react'; +import { FriendsContextProps, IFriendsContext } from './FriendsContext.type'; + +const FriendsContext = createContext({ + friendsState: null, + dispatchFriendsState: null +}); + +export const FriendsContextProvider: FC = props => +{ + return { props.children } +} + +export const useFriendsContext = () => useContext(FriendsContext); diff --git a/src/views/friends/context/FriendsContext.type.ts b/src/views/friends/context/FriendsContext.type.ts new file mode 100644 index 00000000..a61ef776 --- /dev/null +++ b/src/views/friends/context/FriendsContext.type.ts @@ -0,0 +1,13 @@ +import { Dispatch, ProviderProps } from 'react'; +import { IFriendsAction, IFriendsState } from '../reducers/FriendsReducer'; + +export interface IFriendsContext +{ + friendsState: IFriendsState; + dispatchFriendsState: Dispatch; +} + +export interface FriendsContextProps extends ProviderProps +{ + +} diff --git a/src/views/friends/reducers/FriendListReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx similarity index 77% rename from src/views/friends/reducers/FriendListReducer.tsx rename to src/views/friends/reducers/FriendsReducer.tsx index 3139d735..1b1ab612 100644 --- a/src/views/friends/reducers/FriendListReducer.tsx +++ b/src/views/friends/reducers/FriendsReducer.tsx @@ -1,5 +1,6 @@ import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer'; import { Reducer } from 'react'; +import { MessengerChat } from '../common/MessengerChat'; import { MessengerFriend } from '../common/MessengerFriend'; import { MessengerRequest } from '../common/MessengerRequest'; import { MessengerSettings } from '../common/MessengerSettings'; @@ -11,14 +12,15 @@ function compareName(a, b) return 0; } -export interface IFriendListState +export interface IFriendsState { settings: MessengerSettings; friends: MessengerFriend[]; requests: MessengerRequest[]; + activeChats: MessengerChat[]; } -export interface IFriendListAction +export interface IFriendsAction { type: string; payload: { @@ -26,34 +28,37 @@ export interface IFriendListAction fragment?: FriendParser[]; update?: FriendListUpdateParser; requests?: FriendRequestData[]; + chats?: MessengerChat[]; } } -export class FriendListActions +export class FriendsActions { - public static RESET_STATE: string = 'FLA_RESET_STATE'; - public static UPDATE_SETTINGS: string = 'FLA_UPDATE_SETTINGS'; - public static PROCESS_FRAGMENT: string = 'FLA_PROCESS_FRAGMENT'; - public static PROCESS_UPDATE: string = 'FLA_PROCESS_UPDATE'; - public static PROCESS_REQUESTS: string = 'FLA_PROCESS_REQUESTS'; + public static RESET_STATE: string = 'FA_RESET_STATE'; + public static UPDATE_SETTINGS: string = 'FA_UPDATE_SETTINGS'; + public static PROCESS_FRAGMENT: string = 'FA_PROCESS_FRAGMENT'; + public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; + public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; + public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS'; } -export const initialFriendList: IFriendListState = { +export const initialFriends: IFriendsState = { settings: null, friends: [], - requests: [] + requests: [], + activeChats: [] } -export const FriendListReducer: Reducer = (state, action) => +export const FriendsReducer: Reducer = (state, action) => { switch(action.type) { - case FriendListActions.UPDATE_SETTINGS: { + case FriendsActions.UPDATE_SETTINGS: { const settings = (action.payload.settings || state.settings || null); return { ...state, settings }; } - case FriendListActions.PROCESS_FRAGMENT: { + case FriendsActions.PROCESS_FRAGMENT: { const fragment = (action.payload.fragment || null); let friends = [ ...state.friends ]; @@ -85,7 +90,7 @@ export const FriendListReducer: Reducer = ( return { ...state, friends }; } - case FriendListActions.PROCESS_UPDATE: { + case FriendsActions.PROCESS_UPDATE: { const update = (action.payload.update || null); let friends = [ ...state.friends ]; @@ -118,7 +123,7 @@ export const FriendListReducer: Reducer = ( return { ...state, friends }; } - case FriendListActions.PROCESS_REQUESTS: { + case FriendsActions.PROCESS_REQUESTS: { const newRequests = (action.payload.requests || null); let requests = [ ...state.requests ]; @@ -133,6 +138,11 @@ export const FriendListReducer: Reducer = ( return { ...state, requests }; } + case FriendsActions.SET_ACTIVE_CHATS: { + const activeChats = (action.payload.chats || []); + + return { ...state, activeChats }; + } default: return state; } diff --git a/src/views/friends/views/friend-bar/FriendBarView.tsx b/src/views/friends/views/friend-bar/FriendBarView.tsx index 3931c4f4..dd7c698b 100644 --- a/src/views/friends/views/friend-bar/FriendBarView.tsx +++ b/src/views/friends/views/friend-bar/FriendBarView.tsx @@ -1,12 +1,12 @@ import { FC, useMemo, useState } from 'react'; -import { useFriendListContext } from '../../context/FriendListContext'; +import { useFriendsContext } from '../../context/FriendsContext'; import { FriendBarItemView } from '../friend-bar-item/FriendBarItemView'; import { FriendBarViewProps } from './FriendBarView.types'; export const FriendBarView: FC = props => { - const { friendListState = null } = useFriendListContext(); - const { friends = null } = friendListState; + const { friendsState = null } = useFriendsContext(); + const { friends = null } = friendsState; const [ indexOffset, setIndexOffset ] = useState(0); const [ maxDisplayCount, setMaxDisplayCount ] = useState(3); diff --git a/src/views/friends/views/friend-item/FriendsListItemView.tsx b/src/views/friends/views/friend-item/FriendsListItemView.tsx index bac0415d..3b398814 100644 --- a/src/views/friends/views/friend-item/FriendsListItemView.tsx +++ b/src/views/friends/views/friend-item/FriendsListItemView.tsx @@ -1,4 +1,5 @@ -import { FollowFriendMessageComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; +import { SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; +import { FollowFriendMessageComposer } from '@nitrots/nitro-renderer/src/nitro/communication/messages/outgoing/friendlist/FollowFriendMessageComposer'; import { FC, useCallback, useState } from 'react'; import { LocalizeText } from '../../../../api'; import { SendMessageHook } from '../../../../hooks'; diff --git a/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx b/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx new file mode 100644 index 00000000..bd9203f1 --- /dev/null +++ b/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx @@ -0,0 +1,63 @@ +import { FollowFriendMessageComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useState } from 'react'; +import { LocalizeText } from '../../../../api'; +import { SendMessageHook } from '../../../../hooks'; +import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; +import { MessengerFriend } from '../../common/MessengerFriend'; +import { FriendsGroupItemViewProps } from './FriendsGroupItemView.types'; + +export const FriendsGroupItemView: FC = props => +{ + const { friend = null } = props; + + const [ isExpanded, setIsExpanded ] = useState(false); + + const followFriend = useCallback(() => + { + if(!friend) return; + + SendMessageHook(new FollowFriendMessageComposer(friend.id)); + }, [ friend ]); + + const getCurrentRelationshipName = useCallback(() => + { + if(!friend) return 'none'; + + switch(friend.relationshipStatus) + { + case MessengerFriend.RELATIONSHIP_HEART: return 'heart'; + case MessengerFriend.RELATIONSHIP_SMILE: return 'smile'; + case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba'; + default: return 'none'; + } + }, [ friend ]); + + const updateRelationship = useCallback((type: number) => + { + if(type !== friend.relationshipStatus) SendMessageHook(new SetRelationshipStatusComposer(friend.id, type)); + + setIsExpanded(false); + }, [ friend ]); + + if(!friend) return null; + + return ( +
+ +
{ friend.name }
+
+ { !isExpanded && <> + { friend.followingAllowed && } + { friend.online && } + setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } /> + } + { isExpanded && <> + updateRelationship(MessengerFriend.RELATIONSHIP_HEART) } /> + updateRelationship(MessengerFriend.RELATIONSHIP_SMILE) } /> + updateRelationship(MessengerFriend.RELATIONSHIP_BOBBA) } /> + updateRelationship(MessengerFriend.RELATIONSHIP_NONE) } /> + } +
+
+ ); +} diff --git a/src/views/friends/views/friends-group-item/FriendsGroupItemView.types.ts b/src/views/friends/views/friends-group-item/FriendsGroupItemView.types.ts new file mode 100644 index 00000000..345532b1 --- /dev/null +++ b/src/views/friends/views/friends-group-item/FriendsGroupItemView.types.ts @@ -0,0 +1,6 @@ +import { MessengerFriend } from '../../common/MessengerFriend'; + +export interface FriendsGroupItemViewProps +{ + friend: MessengerFriend; +} diff --git a/src/views/friends/views/list/FriendsListView.tsx b/src/views/friends/views/friends-group/FriendsGroupView.tsx similarity index 58% rename from src/views/friends/views/list/FriendsListView.tsx rename to src/views/friends/views/friends-group/FriendsGroupView.tsx index 86ed2707..c5eb989b 100644 --- a/src/views/friends/views/list/FriendsListView.tsx +++ b/src/views/friends/views/friends-group/FriendsGroupView.tsx @@ -1,11 +1,11 @@ import React, { FC } from 'react'; import { MessengerFriend } from '../../common/MessengerFriend'; import { MessengerRequest } from '../../common/MessengerRequest'; -import { FriendsListItemView } from '../friend-item/FriendsListItemView'; -import { FriendsRequestItemView } from '../request-item/FriendsRequestItemView'; -import { FriendsListViewProps } from './FriendsListView.types'; +import { FriendsGroupItemView } from '../friends-group-item/FriendsGroupItemView'; +import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView'; +import { FriendsGroupViewProps } from './FriendsGroupView.types'; -export const FriendsListView: FC = props => +export const FriendsGroupView: FC = props => { const { list = null } = props; @@ -15,7 +15,7 @@ export const FriendsListView: FC = props => { list.map((item, index) => { if(item instanceof MessengerFriend) - return + return else if(item instanceof MessengerRequest) return else diff --git a/src/views/friends/views/list/FriendsListView.types.ts b/src/views/friends/views/friends-group/FriendsGroupView.types.ts similarity index 82% rename from src/views/friends/views/list/FriendsListView.types.ts rename to src/views/friends/views/friends-group/FriendsGroupView.types.ts index 8a4c4bc9..48bc5ee6 100644 --- a/src/views/friends/views/list/FriendsListView.types.ts +++ b/src/views/friends/views/friends-group/FriendsGroupView.types.ts @@ -1,7 +1,7 @@ import { MessengerFriend } from '../../common/MessengerFriend'; import { MessengerRequest } from '../../common/MessengerRequest'; -export interface FriendsListViewProps +export interface FriendsGroupViewProps { list: MessengerFriend[] | MessengerRequest[]; } diff --git a/src/views/friends/views/friends-list/FriendsListView.tsx b/src/views/friends/views/friends-list/FriendsListView.tsx new file mode 100644 index 00000000..fd796044 --- /dev/null +++ b/src/views/friends/views/friends-list/FriendsListView.tsx @@ -0,0 +1,43 @@ +import { FC, useState } from 'react'; +import { LocalizeText } from '../../../../api'; +import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout'; +import { FriendsGroupView } from '../friends-group/FriendsGroupView'; +import { FriendsListViewProps } from './FriendsListView.types'; + +const TABS: string[] = ['friendlist.friends', 'generic.search']; + +export const FriendsListView: FC = props => +{ + const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props; + + const [ currentTab, setCurrentTab ] = useState(0); + + return ( + + + + + { TABS.map((tab, index) => + { + return ( setCurrentTab(index) }> + { LocalizeText(tab) } + ); + }) } + +
+ { currentTab === 0 && + + + + + + + { friendRequests.length > 0 && + + } + } +
+
+
+ ); +}; diff --git a/src/views/friends/views/friends-list/FriendsListView.types.ts b/src/views/friends/views/friends-list/FriendsListView.types.ts new file mode 100644 index 00000000..01bfcc84 --- /dev/null +++ b/src/views/friends/views/friends-list/FriendsListView.types.ts @@ -0,0 +1,9 @@ +import { MessengerFriend } from './../../common/MessengerFriend'; +import { MessengerRequest } from './../../common/MessengerRequest'; +export interface FriendsListViewProps +{ + onCloseClick: () => void; + onlineFriends: MessengerFriend[]; + offlineFriends: MessengerFriend[]; + friendRequests: MessengerRequest[]; +} diff --git a/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx b/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx new file mode 100644 index 00000000..f25c42f9 --- /dev/null +++ b/src/views/friends/views/friends-request-item/FriendsRequestItemView.tsx @@ -0,0 +1,37 @@ +import { AcceptFriendMessageComposer, DeclineFriendMessageComposer } from '@nitrots/nitro-renderer'; +import { FC, useCallback } from 'react'; +import { SendMessageHook } from '../../../../hooks/messages/message-event'; +import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; +import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types'; + +export const FriendsRequestItemView: FC = props => +{ + const { request = null } = props; + + const accept = useCallback(() => + { + if(!request) return; + + SendMessageHook(new AcceptFriendMessageComposer(request.id)); + }, [ request ]); + + const decline = useCallback(() => + { + if(!request) return; + + SendMessageHook(new DeclineFriendMessageComposer(false, request.id)); + }, [ request ]); + + if(!request) return null; + + return ( +
+ +
{ request.name }
+
+ + +
+
+ ); +}; diff --git a/src/views/friends/views/friends-request-item/FriendsRequestItemView.types.ts b/src/views/friends/views/friends-request-item/FriendsRequestItemView.types.ts new file mode 100644 index 00000000..4f5c38d5 --- /dev/null +++ b/src/views/friends/views/friends-request-item/FriendsRequestItemView.types.ts @@ -0,0 +1,6 @@ +import { MessengerRequest } from '../../common/MessengerRequest'; + +export interface FriendsRequestItemViewProps +{ + request: MessengerRequest; +} diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx new file mode 100644 index 00000000..38a3c07b --- /dev/null +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -0,0 +1,13 @@ +import { FC } from 'react'; +import { LocalizeText } from '../../../../api'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; + +export const FriendsMessengerView: FC<{}> = props => +{ + return ( + {} } /> + + + + ); +}; diff --git a/src/views/friends/views/request-item/FriendsRequestItemView.types.ts b/src/views/friends/views/request-item/FriendsRequestItemView.types.ts index 4f5c38d5..bc01f938 100644 --- a/src/views/friends/views/request-item/FriendsRequestItemView.types.ts +++ b/src/views/friends/views/request-item/FriendsRequestItemView.types.ts @@ -1,5 +1,4 @@ -import { MessengerRequest } from '../../common/MessengerRequest'; - +import { MessengerRequest } from './../../common/MessengerRequest'; export interface FriendsRequestItemViewProps { request: MessengerRequest; diff --git a/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx b/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx index 385a0a4f..8fe49ce2 100644 --- a/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx +++ b/src/views/navigator/views/room-settings/NavigatorRoomSettingsView.tsx @@ -1,8 +1,8 @@ import { RoomBannedUsersComposer, RoomBannedUsersEvent, RoomSettingsEvent, RoomUsersWithRightsComposer, RoomUsersWithRightsEvent, SaveRoomSettingsComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useState } from 'react'; import { LocalizeText } from '../../../../api'; -import { FriendListEvent } from '../../../../events'; -import { FriendListContentEvent } from '../../../../events/friend-list/FriendListContentEvent'; +import { FriendsEvent } from '../../../../events'; +import { FriendListContentEvent } from '../../../../events/friends/FriendListContentEvent'; import { dispatchUiEvent, useUiEvent } from '../../../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages'; import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout'; @@ -87,7 +87,7 @@ export const NavigatorRoomSettingsView: FC<{}> = props => useEffect(() => { - if(roomSettingsData) dispatchUiEvent(new FriendListEvent(FriendListEvent.REQUEST_FRIEND_LIST)); + if(roomSettingsData) dispatchUiEvent(new FriendsEvent(FriendsEvent.REQUEST_FRIEND_LIST)); }, [roomSettingsData]) const save = useCallback((data: RoomSettingsData) => diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx index 74b22062..3ab96937 100644 --- a/src/views/toolbar/ToolbarView.tsx +++ b/src/views/toolbar/ToolbarView.tsx @@ -1,7 +1,7 @@ import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer'; import { FC, useCallback, useState } from 'react'; import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop } from '../../api'; -import { AvatarEditorEvent, CatalogEvent, FriendListEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; +import { AvatarEditorEvent, CatalogEvent, FriendsEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; import { AchievementsUIEvent } from '../../events/achievements'; import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; @@ -107,7 +107,7 @@ export const ToolbarView: FC = props => dispatchUiEvent(new CatalogEvent(CatalogEvent.TOGGLE_CATALOG)); return; case ToolbarViewItems.FRIEND_LIST_ITEM: - dispatchUiEvent(new CatalogEvent(FriendListEvent.TOGGLE_FRIEND_LIST)); + dispatchUiEvent(new CatalogEvent(FriendsEvent.TOGGLE_FRIEND_LIST)); return; case ToolbarViewItems.CAMERA_ITEM: dispatchUiEvent(new RoomWidgetCameraEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA)); From b5850c1995494ce5872a1ee07d027ccd02deb9a3 Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Fri, 17 Sep 2021 08:15:53 -0300 Subject: [PATCH 02/21] Updates --- src/api/friends/OpenMessengerChat.ts | 7 ++ src/api/friends/index.ts | 1 + src/api/index.ts | 1 + src/views/friends/FriendsView.tsx | 9 +-- src/views/friends/common/MessengerChat.ts | 4 +- .../friends/common/MessengerChatMessage.ts | 35 ++++++++- .../views/friend-item/FriendsListItemView.tsx | 13 +++- .../views/messenger/FriendsMessengerView.tsx | 75 ++++++++++++++++++- 8 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 src/api/friends/OpenMessengerChat.ts create mode 100644 src/api/friends/index.ts diff --git a/src/api/friends/OpenMessengerChat.ts b/src/api/friends/OpenMessengerChat.ts new file mode 100644 index 00000000..e5c685cd --- /dev/null +++ b/src/api/friends/OpenMessengerChat.ts @@ -0,0 +1,7 @@ +import { CreateLinkEvent } from '..'; + +export function OpenMessengerChat(friendId: number): void +{ + console.log(`friends/messenger/${friendId}`); + CreateLinkEvent(`friends/messenger/${friendId}`); +} diff --git a/src/api/friends/index.ts b/src/api/friends/index.ts new file mode 100644 index 00000000..ffb458ee --- /dev/null +++ b/src/api/friends/index.ts @@ -0,0 +1 @@ +export * from './OpenMessengerChat'; diff --git a/src/api/index.ts b/src/api/index.ts index 773325c3..0b87703a 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,4 +1,5 @@ export * from './core'; +export * from './friends'; export * from './groups'; export * from './navigator'; export * from './nitro'; diff --git a/src/views/friends/FriendsView.tsx b/src/views/friends/FriendsView.tsx index 8c8e5316..3e593a88 100644 --- a/src/views/friends/FriendsView.tsx +++ b/src/views/friends/FriendsView.tsx @@ -21,7 +21,6 @@ export const FriendsView: FC<{}> = props => const [ isReady, setIsReady ] = useState(false); const [ isListVisible, setIsListVisible ] = useState(false); - const [ isMessengerVisible, setIsMessengerVisible ] = useState(false); useEffect(() => { @@ -45,12 +44,6 @@ export const FriendsView: FC<{}> = props => case FriendsEvent.TOGGLE_FRIEND_LIST: setIsListVisible(value => !value); return; - case FriendsEvent.SHOW_FRIEND_MESSENGER: - setIsMessengerVisible(true); - return; - case FriendsEvent.TOGGLE_FRIEND_MESSENGER: - setIsMessengerVisible(value => !value); - return; case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST: const requestEvent = (event as FriendsSendFriendRequestEvent); return; @@ -104,7 +97,7 @@ export const FriendsView: FC<{}> = props => { isReady && createPortal(, document.getElementById('toolbar-friend-bar-container')) } { isListVisible && setIsListVisible(false) } /> } - { isMessengerVisible && } + ); } diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts index d21982c9..963a941b 100644 --- a/src/views/friends/common/MessengerChat.ts +++ b/src/views/friends/common/MessengerChat.ts @@ -12,9 +12,9 @@ export class MessengerChat this._messages = []; } - public addMessage(): void + public addMessage(type: number, senderId: number, message: string, sentAt: number, extraData?: string): void { - this._messages.push(); + this._messages.push(new MessengerChatMessage(type, senderId, message, sentAt, extraData)); } public get friendId(): number diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerChatMessage.ts index 28b54787..0b410216 100644 --- a/src/views/friends/common/MessengerChatMessage.ts +++ b/src/views/friends/common/MessengerChatMessage.ts @@ -3,11 +3,40 @@ export class MessengerChatMessage private _type: number; private _senderId: number; private _message: string; - private _extraData: string; private _sentAt: number; + private _extraData: string; - constructor(type: number, senderId: number, message: string, extraData: string, sentAt: number) + constructor(type: number, senderId: number, message: string, sentAt: number, extraData?: string) { - + this._type = type; + this._senderId = senderId; + this._message = message; + this._sentAt = sentAt; + this._extraData = extraData; + } + + public get type(): number + { + return this._type; + } + + public get senderId(): number + { + return this._senderId; + } + + public get message(): string + { + return this._message; + } + + public get sentAt(): number + { + return this._sentAt; + } + + public get extraData(): string + { + return this._extraData; } } diff --git a/src/views/friends/views/friend-item/FriendsListItemView.tsx b/src/views/friends/views/friend-item/FriendsListItemView.tsx index 3b398814..2edafd90 100644 --- a/src/views/friends/views/friend-item/FriendsListItemView.tsx +++ b/src/views/friends/views/friend-item/FriendsListItemView.tsx @@ -1,7 +1,7 @@ import { SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; import { FollowFriendMessageComposer } from '@nitrots/nitro-renderer/src/nitro/communication/messages/outgoing/friendlist/FollowFriendMessageComposer'; import { FC, useCallback, useState } from 'react'; -import { LocalizeText } from '../../../../api'; +import { LocalizeText, OpenMessengerChat } from '../../../../api'; import { SendMessageHook } from '../../../../hooks'; import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; import { MessengerFriend } from '../../common/MessengerFriend'; @@ -20,6 +20,13 @@ export const FriendsListItemView: FC = props => SendMessageHook(new FollowFriendMessageComposer(friend.id)); }, [ friend ]); + const openMessengerChat = useCallback(() => + { + if(!friend) return; + + OpenMessengerChat(friend.id); + }, [ friend ]); + const getCurrentRelationshipName = useCallback(() => { if(!friend) return 'none'; @@ -48,8 +55,8 @@ export const FriendsListItemView: FC = props =>
{ friend.name }
{ !isExpanded && <> - { friend.followingAllowed && } - { friend.online && } + { friend.followingAllowed && } + { friend.online && } setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } /> } { isExpanded && <> diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index 38a3c07b..b64ed9d2 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,9 +1,80 @@ -import { FC } from 'react'; -import { LocalizeText } from '../../../../api'; +import { ILinkEventTracker, NitroEvent } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; +import { FriendsEvent } from '../../../../events/friends/FriendsEvent'; +import { useUiEvent } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { MessengerChat } from '../../common/MessengerChat'; +import { useFriendsContext } from '../../context/FriendsContext'; +import { FriendsActions } from '../../reducers/FriendsReducer'; export const FriendsMessengerView: FC<{}> = props => { + const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); + const { activeChats = [] } = friendsState; + + const [ isVisible, setIsVisible ] = useState(false); + const [ activeChatIndex, setActiveChatIndex ] = useState(0); + + const onNitroEvent = useCallback((event: NitroEvent) => + { + switch(event.type) + { + case FriendsEvent.SHOW_FRIEND_MESSENGER: + setIsVisible(true); + return; + case FriendsEvent.TOGGLE_FRIEND_MESSENGER: + setIsVisible(value => !value); + return; + } + }, []); + + useUiEvent(FriendsEvent.SHOW_FRIEND_MESSENGER, onNitroEvent); + useUiEvent(FriendsEvent.TOGGLE_FRIEND_MESSENGER, onNitroEvent); + + const linkReceived = useCallback((url: string) => + { + const parts = url.split('/'); + console.log(parts); + if(parts.length < 3) return; + + const friendId = parseInt(parts[2]); + console.log(friendId); + let existingChatIndex = activeChats.findIndex(c => c.friendId === friendId); + + if(existingChatIndex === -1) + { + const clonedActiveChats = Array.from(activeChats); + clonedActiveChats.push(new MessengerChat(friendId, true)); + + dispatchFriendsState({ + type: FriendsActions.SET_ACTIVE_CHATS, + payload: { + chats: clonedActiveChats + } + }); + + existingChatIndex = clonedActiveChats.length - 1; + } + + setActiveChatIndex(existingChatIndex); + setIsVisible(true); + }, [ activeChats, dispatchFriendsState ]); + + useEffect(() => + { + const linkTracker: ILinkEventTracker = { + linkReceived, + eventUrlPrefix: 'friends/messenger/' + }; + + AddEventLinkTracker(linkTracker); + + return () => RemoveLinkEventTracker(linkTracker); + }, [ linkReceived ]); + + if(!isVisible) return null; + return ( {} } /> From 7a6fe87aedd54715462945fdccf16b66a41e2bce Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Sat, 18 Sep 2021 03:04:50 -0300 Subject: [PATCH 03/21] Messenger Chat --- src/layout/card/NitroCardView.scss | 4 + src/layout/card/NitroCardView.tsx | 2 +- src/views/friends/FriendsMessageHandler.tsx | 20 +-- src/views/friends/FriendsView.scss | 1 + src/views/friends/FriendsView.tsx | 2 +- src/views/friends/common/MessengerChat.ts | 21 ++- .../friends/common/MessengerChatMessage.ts | 4 + .../common/MessengerChatMessageGroup.ts | 28 ++++ src/views/friends/reducers/FriendsReducer.tsx | 22 +++ .../friend-bar-item/FriendBarItemView.tsx | 11 +- .../views/friend-bar/FriendBarView.tsx | 10 +- .../views/friend-bar/FriendBarView.types.ts | 3 +- .../views/friend-item/FriendsListItemView.tsx | 71 --------- .../friend-item/FriendsListItemView.types.ts | 6 - .../FriendsGroupItemView.tsx | 11 +- .../views/messenger/FriendsMessengerView.scss | 71 +++++++++ .../views/messenger/FriendsMessengerView.tsx | 141 ++++++++++++++++-- 17 files changed, 309 insertions(+), 119 deletions(-) create mode 100644 src/views/friends/common/MessengerChatMessageGroup.ts delete mode 100644 src/views/friends/views/friend-item/FriendsListItemView.tsx delete mode 100644 src/views/friends/views/friend-item/FriendsListItemView.types.ts create mode 100644 src/views/friends/views/messenger/FriendsMessengerView.scss diff --git a/src/layout/card/NitroCardView.scss b/src/layout/card/NitroCardView.scss index 44285071..cd7bfebf 100644 --- a/src/layout/card/NitroCardView.scss +++ b/src/layout/card/NitroCardView.scss @@ -19,6 +19,10 @@ $nitro-card-tabs-height: 33px; height: 100%; pointer-events: none; + .theme-primary { + border: $border-width solid $border-color; + } + @include media-breakpoint-down(lg) { .draggable-window { diff --git a/src/layout/card/NitroCardView.tsx b/src/layout/card/NitroCardView.tsx index aaf4178a..f44ee67f 100644 --- a/src/layout/card/NitroCardView.tsx +++ b/src/layout/card/NitroCardView.tsx @@ -11,7 +11,7 @@ export const NitroCardView: FC = props =>
-
+
{ children }
diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx index 579230a5..e1e055f2 100644 --- a/src/views/friends/FriendsMessageHandler.tsx +++ b/src/views/friends/FriendsMessageHandler.tsx @@ -1,6 +1,8 @@ import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent, NewConsoleMessageEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; +import { GetSessionDataManager } from '../../api'; import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; +import { MessengerChatMessage } from './common/MessengerChatMessage'; import { MessengerSettings } from './common/MessengerSettings'; import { useFriendsContext } from './context/FriendsContext'; import { FriendsActions } from './reducers/FriendsReducer'; @@ -68,17 +70,17 @@ export const FriendsMessageHandler: FC<{}> = props => { const parser = event.getParser(); - const activeChat = activeChats.find(c => c.friendId === parser.senderId); + let userId = parser.senderId; - if(activeChat) - { + if(userId === GetSessionDataManager().userId) userId = 0; - } - else - { - - } - }, [ friendsState, dispatchFriendsState ]); + dispatchFriendsState({ + type: FriendsActions.ADD_CHAT_MESSAGE, + payload: { + chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData) + } + }); + }, [ dispatchFriendsState ]); CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent); diff --git a/src/views/friends/FriendsView.scss b/src/views/friends/FriendsView.scss index 519d6d1e..3d55929f 100644 --- a/src/views/friends/FriendsView.scss +++ b/src/views/friends/FriendsView.scss @@ -3,3 +3,4 @@ } @import './views/friend-bar/FriendBarView'; +@import './views/messenger/FriendsMessengerView'; diff --git a/src/views/friends/FriendsView.tsx b/src/views/friends/FriendsView.tsx index 3e593a88..0c9415f7 100644 --- a/src/views/friends/FriendsView.tsx +++ b/src/views/friends/FriendsView.tsx @@ -95,7 +95,7 @@ export const FriendsView: FC<{}> = props => return ( - { isReady && createPortal(, document.getElementById('toolbar-friend-bar-container')) } + { isReady && createPortal(, document.getElementById('toolbar-friend-bar-container')) } { isListVisible && setIsListVisible(false) } /> } diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts index 963a941b..2369a7c9 100644 --- a/src/views/friends/common/MessengerChat.ts +++ b/src/views/friends/common/MessengerChat.ts @@ -1,20 +1,24 @@ import { MessengerChatMessage } from './MessengerChatMessage'; +import { MessengerChatMessageGroup } from './MessengerChatMessageGroup'; export class MessengerChat { private _friendId: number; private _isRead: boolean; - private _messages: MessengerChatMessage[]; + private _messageGroups: MessengerChatMessageGroup[]; constructor(friendId: number, isRead: boolean = true) { this._friendId = friendId; this._isRead = isRead; - this._messages = []; + this._messageGroups = []; } - public addMessage(type: number, senderId: number, message: string, sentAt: number, extraData?: string): void + public addMessage(message: MessengerChatMessage): void { - this._messages.push(new MessengerChatMessage(type, senderId, message, sentAt, extraData)); + if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId)); + + this.lastMessageGroup.addMessage(message); + this._isRead = false; } public get friendId(): number @@ -27,8 +31,13 @@ export class MessengerChat return this._isRead; } - public get messages(): MessengerChatMessage[] + public get messageGroups(): MessengerChatMessageGroup[] { - return this._messages; + return this._messageGroups; + } + + public get lastMessageGroup(): MessengerChatMessageGroup + { + return this._messageGroups[this._messageGroups.length - 1]; } } diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerChatMessage.ts index 0b410216..5ded0a7d 100644 --- a/src/views/friends/common/MessengerChatMessage.ts +++ b/src/views/friends/common/MessengerChatMessage.ts @@ -1,5 +1,9 @@ export class MessengerChatMessage { + public static MESSAGE: number = 0; + public static ROOM_INVITE: number = 1; + public static SYSTEM_NOTIFICATION: number = 2; + private _type: number; private _senderId: number; private _message: string; diff --git a/src/views/friends/common/MessengerChatMessageGroup.ts b/src/views/friends/common/MessengerChatMessageGroup.ts new file mode 100644 index 00000000..0bb27fe3 --- /dev/null +++ b/src/views/friends/common/MessengerChatMessageGroup.ts @@ -0,0 +1,28 @@ +import { MessengerChatMessage } from './MessengerChatMessage'; + +export class MessengerChatMessageGroup +{ + private _userId: number; + private _messages: MessengerChatMessage[]; + + constructor(userId: number) + { + this._userId = userId; + this._messages = []; + } + + public addMessage(message: MessengerChatMessage): void + { + this._messages.push(message); + } + + public get userId(): number + { + return this._userId; + } + + public get messages(): MessengerChatMessage[] + { + return this._messages; + } +} diff --git a/src/views/friends/reducers/FriendsReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx index 1b1ab612..f66ce6fd 100644 --- a/src/views/friends/reducers/FriendsReducer.tsx +++ b/src/views/friends/reducers/FriendsReducer.tsx @@ -1,6 +1,7 @@ import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer'; import { Reducer } from 'react'; import { MessengerChat } from '../common/MessengerChat'; +import { MessengerChatMessage } from '../common/MessengerChatMessage'; import { MessengerFriend } from '../common/MessengerFriend'; import { MessengerRequest } from '../common/MessengerRequest'; import { MessengerSettings } from '../common/MessengerSettings'; @@ -29,6 +30,8 @@ export interface IFriendsAction update?: FriendListUpdateParser; requests?: FriendRequestData[]; chats?: MessengerChat[]; + chatMessage?: MessengerChatMessage; + numberValue?: number; } } @@ -40,6 +43,7 @@ export class FriendsActions public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS'; + public static ADD_CHAT_MESSAGE: string = 'FA_ADD_CHAT_MESSAGE'; } export const initialFriends: IFriendsState = { @@ -143,6 +147,24 @@ export const FriendsReducer: Reducer = (state, ac return { ...state, activeChats }; } + case FriendsActions.ADD_CHAT_MESSAGE: { + const message = action.payload.chatMessage; + const toFriendId = action.payload.numberValue; + + const activeChats = Array.from(state.activeChats); + + let activeChatIndex = activeChats.findIndex(c => c.friendId === toFriendId ? toFriendId : message.senderId); + + if(activeChatIndex === -1) + { + activeChats.push(new MessengerChat(message.senderId, false)); + activeChatIndex = activeChats.length - 1; + } + + activeChats[activeChatIndex].addMessage(message); + + return { ...state, activeChats }; + } default: return state; } diff --git a/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx b/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx index b845f530..40873386 100644 --- a/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx +++ b/src/views/friends/views/friend-bar-item/FriendBarItemView.tsx @@ -1,6 +1,6 @@ import { FollowFriendMessageComposer, MouseEventType, UserProfileComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useRef, useState } from 'react'; -import { LocalizeText } from '../../../../api'; +import { LocalizeText, OpenMessengerChat } from '../../../../api'; import { SendMessageHook } from '../../../../hooks/messages'; import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { FriendBarItemViewProps } from './FriendBarItemView.types'; @@ -16,6 +16,13 @@ export const FriendBarItemView: FC = props => SendMessageHook(new FollowFriendMessageComposer(friend.id)); }, [ friend ]); + const openMessengerChat = useCallback(() => + { + if(!friend) return; + + OpenMessengerChat(friend.id); + }, [ friend ]); + const openProfile = useCallback(() => { SendMessageHook(new UserProfileComposer(friend.id)); @@ -59,7 +66,7 @@ export const FriendBarItemView: FC = props =>
{ friend.name }
{ isVisible &&
- + { friend.followingAllowed && }
} diff --git a/src/views/friends/views/friend-bar/FriendBarView.tsx b/src/views/friends/views/friend-bar/FriendBarView.tsx index dd7c698b..a0347c94 100644 --- a/src/views/friends/views/friend-bar/FriendBarView.tsx +++ b/src/views/friends/views/friend-bar/FriendBarView.tsx @@ -1,20 +1,14 @@ import { FC, useMemo, useState } from 'react'; -import { useFriendsContext } from '../../context/FriendsContext'; import { FriendBarItemView } from '../friend-bar-item/FriendBarItemView'; import { FriendBarViewProps } from './FriendBarView.types'; export const FriendBarView: FC = props => { - const { friendsState = null } = useFriendsContext(); - const { friends = null } = friendsState; + const { onlineFriends = null } = props; + const [ indexOffset, setIndexOffset ] = useState(0); const [ maxDisplayCount, setMaxDisplayCount ] = useState(3); - const onlineFriends = useMemo(() => - { - return friends.filter(friend => friend.online); - }, [ friends ]); - const canDecreaseIndex = useMemo(() => { if(indexOffset === 0) return false; diff --git a/src/views/friends/views/friend-bar/FriendBarView.types.ts b/src/views/friends/views/friend-bar/FriendBarView.types.ts index f47af57f..61a040ce 100644 --- a/src/views/friends/views/friend-bar/FriendBarView.types.ts +++ b/src/views/friends/views/friend-bar/FriendBarView.types.ts @@ -1,4 +1,5 @@ +import { MessengerFriend } from './../../common/MessengerFriend'; export interface FriendBarViewProps { - + onlineFriends: MessengerFriend[]; } diff --git a/src/views/friends/views/friend-item/FriendsListItemView.tsx b/src/views/friends/views/friend-item/FriendsListItemView.tsx deleted file mode 100644 index 2edafd90..00000000 --- a/src/views/friends/views/friend-item/FriendsListItemView.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; -import { FollowFriendMessageComposer } from '@nitrots/nitro-renderer/src/nitro/communication/messages/outgoing/friendlist/FollowFriendMessageComposer'; -import { FC, useCallback, useState } from 'react'; -import { LocalizeText, OpenMessengerChat } from '../../../../api'; -import { SendMessageHook } from '../../../../hooks'; -import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; -import { MessengerFriend } from '../../common/MessengerFriend'; -import { FriendsListItemViewProps } from './FriendsListItemView.types'; - -export const FriendsListItemView: FC = props => -{ - const { friend = null } = props; - - const [ isExpanded, setIsExpanded ] = useState(false); - - const followFriend = useCallback(() => - { - if(!friend) return; - - SendMessageHook(new FollowFriendMessageComposer(friend.id)); - }, [ friend ]); - - const openMessengerChat = useCallback(() => - { - if(!friend) return; - - OpenMessengerChat(friend.id); - }, [ friend ]); - - const getCurrentRelationshipName = useCallback(() => - { - if(!friend) return 'none'; - - switch(friend.relationshipStatus) - { - case MessengerFriend.RELATIONSHIP_HEART: return 'heart'; - case MessengerFriend.RELATIONSHIP_SMILE: return 'smile'; - case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba'; - default: return 'none'; - } - }, [ friend ]); - - const updateRelationship = useCallback((type: number) => - { - if(type !== friend.relationshipStatus) SendMessageHook(new SetRelationshipStatusComposer(friend.id, type)); - - setIsExpanded(false); - }, [ friend ]); - - if(!friend) return null; - - return ( -
- -
{ friend.name }
-
- { !isExpanded && <> - { friend.followingAllowed && } - { friend.online && } - setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } /> - } - { isExpanded && <> - updateRelationship(MessengerFriend.RELATIONSHIP_HEART) } /> - updateRelationship(MessengerFriend.RELATIONSHIP_SMILE) } /> - updateRelationship(MessengerFriend.RELATIONSHIP_BOBBA) } /> - updateRelationship(MessengerFriend.RELATIONSHIP_NONE) } /> - } -
-
- ); -} diff --git a/src/views/friends/views/friend-item/FriendsListItemView.types.ts b/src/views/friends/views/friend-item/FriendsListItemView.types.ts deleted file mode 100644 index df44d3b5..00000000 --- a/src/views/friends/views/friend-item/FriendsListItemView.types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { MessengerFriend } from '../../common/MessengerFriend'; - -export interface FriendsListItemViewProps -{ - friend: MessengerFriend; -} diff --git a/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx b/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx index bd9203f1..60b2066a 100644 --- a/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx +++ b/src/views/friends/views/friends-group-item/FriendsGroupItemView.tsx @@ -1,6 +1,6 @@ import { FollowFriendMessageComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useState } from 'react'; -import { LocalizeText } from '../../../../api'; +import { LocalizeText, OpenMessengerChat } from '../../../../api'; import { SendMessageHook } from '../../../../hooks'; import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView'; import { MessengerFriend } from '../../common/MessengerFriend'; @@ -19,6 +19,13 @@ export const FriendsGroupItemView: FC = props => SendMessageHook(new FollowFriendMessageComposer(friend.id)); }, [ friend ]); + const openMessengerChat = useCallback(() => + { + if(!friend) return; + + OpenMessengerChat(friend.id); + }, [ friend ]); + const getCurrentRelationshipName = useCallback(() => { if(!friend) return 'none'; @@ -48,7 +55,7 @@ export const FriendsGroupItemView: FC = props =>
{ !isExpanded && <> { friend.followingAllowed && } - { friend.online && } + { friend.online && } setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } /> } { isExpanded && <> diff --git a/src/views/friends/views/messenger/FriendsMessengerView.scss b/src/views/friends/views/messenger/FriendsMessengerView.scss new file mode 100644 index 00000000..429f64cf --- /dev/null +++ b/src/views/friends/views/messenger/FriendsMessengerView.scss @@ -0,0 +1,71 @@ +.nitro-friends-messenger { + width: 300px; + + .friend-head { + position: relative; + width: 40px; + height: 40px; + overflow: hidden; + + .avatar-image { + position: absolute; + margin-left: -27px; + margin-top: -27px; + } + } + + .chat-title { + margin-top: -21px; + } + + .chat-messages { + height: 200px; + min-height: 200px; + overflow-y: auto; + + .message-avatar { + position: relative; + overflow: hidden; + width: 50px; + height: 50px; + + .avatar-image { + position: absolute; + margin-left: -22px; + margin-top: -25px; + } + } + + .messages-group-left { + position: relative; + + &:before { + position: absolute; + content: ' '; + width: 0; + height: 0; + border-right: 8px solid rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; + border-top: 8px solid transparent; + border-bottom: 8px solid transparent; + top: 10px; + left: -8px; + } + } + + .messages-group-right { + position: relative; + + &:before { + position: absolute; + content: ' '; + width: 0; + height: 0; + border-left: 8px solid rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; + border-top: 8px solid transparent; + border-bottom: 8px solid transparent; + top: 10px; + right: -8px; + } + } + } +} diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index b64ed9d2..c3679025 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,20 +1,25 @@ -import { ILinkEventTracker, NitroEvent } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useEffect, useState } from 'react'; -import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; +import { FollowFriendMessageComposer, ILinkEventTracker, NitroEvent, SendMessageComposer, UserProfileComposer } from '@nitrots/nitro-renderer'; +import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { AddEventLinkTracker, GetSessionDataManager, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; import { FriendsEvent } from '../../../../events/friends/FriendsEvent'; -import { useUiEvent } from '../../../../hooks'; +import { SendMessageHook, useUiEvent } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { MessengerChat } from '../../common/MessengerChat'; +import { MessengerChatMessage } from '../../common/MessengerChatMessage'; import { useFriendsContext } from '../../context/FriendsContext'; import { FriendsActions } from '../../reducers/FriendsReducer'; export const FriendsMessengerView: FC<{}> = props => { const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); - const { activeChats = [] } = friendsState; + const { activeChats = [], friends = [] } = friendsState; const [ isVisible, setIsVisible ] = useState(false); - const [ activeChatIndex, setActiveChatIndex ] = useState(0); + const [ selectedChatIndex, setSelectedChatIndex ] = useState(0); + const [ message, setMessage ] = useState(''); + + const messagesBox = useRef(); const onNitroEvent = useCallback((event: NitroEvent) => { @@ -35,11 +40,11 @@ export const FriendsMessengerView: FC<{}> = props => const linkReceived = useCallback((url: string) => { const parts = url.split('/'); - console.log(parts); + if(parts.length < 3) return; const friendId = parseInt(parts[2]); - console.log(friendId); + let existingChatIndex = activeChats.findIndex(c => c.friendId === friendId); if(existingChatIndex === -1) @@ -57,10 +62,35 @@ export const FriendsMessengerView: FC<{}> = props => existingChatIndex = clonedActiveChats.length - 1; } - setActiveChatIndex(existingChatIndex); + setSelectedChatIndex(existingChatIndex); setIsVisible(true); }, [ activeChats, dispatchFriendsState ]); + const getFriendFigure = useCallback((id: number) => + { + const friend = friends.find(f => f.id === id); + + if(!friend) return null; + + return friend.figure; + }, [ friends ]); + + const selectedChat = useMemo(() => + { + return activeChats[selectedChatIndex]; + }, [ activeChats, selectedChatIndex ]); + + const selectedChatFriend = useMemo(() => + { + if(!selectedChat) return null; + + const friend = friends.find(f => f.id === selectedChat.friendId); + + if(!friend) return null; + + return friend; + }, [ friends, selectedChat ]); + useEffect(() => { const linkTracker: ILinkEventTracker = { @@ -73,12 +103,99 @@ export const FriendsMessengerView: FC<{}> = props => return () => RemoveLinkEventTracker(linkTracker); }, [ linkReceived ]); + useEffect(() => + { + if(!messagesBox || !messagesBox.current) return; + + messagesBox.current.scrollTop = messagesBox.current.scrollHeight; + + }, [ selectedChat ]); + + const followFriend = useCallback(() => + { + SendMessageHook(new FollowFriendMessageComposer(selectedChatFriend.id)); + }, [ selectedChatFriend ]); + + const openProfile = useCallback(() => + { + SendMessageHook(new UserProfileComposer(selectedChatFriend.id)); + }, [ selectedChatFriend ]); + + const sendMessage = useCallback(() => + { + if(message.length === 0) return; + + SendMessageHook(new SendMessageComposer(selectedChat.friendId, message)); + + dispatchFriendsState({ + type: FriendsActions.ADD_CHAT_MESSAGE, + payload: { + chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, 0, message, (new Date().getMilliseconds())), + numberValue: selectedChat.friendId + } + }); + setMessage(''); + }, [ selectedChat, message, dispatchFriendsState ]); + + const onKeyDown = useCallback((event: KeyboardEvent) => + { + if(event.key !== 'Enter') return; + + sendMessage(); + }, [ sendMessage ]); + if(!isVisible) return null; return ( - {} } /> - - + setIsVisible(false) } /> + +
+ { activeChats && activeChats.map((chat, index) => + { + return
setSelectedChatIndex(index) }> + +
; + }) } +
+
+ { selectedChat && selectedChatFriend && <> +
{ LocalizeText('messenger.window.separator', ['FRIEND_NAME'], [ selectedChatFriend.name ]) }
+
+
+ + +
+ + +
+
+ { selectedChat.messageGroups.map((group, groupIndex) => + { + return
+ { group.userId !== 0 &&
+ +
} +
+ { group.messages.map((message, messageIndex) => + { + return
{ message.message }
+ }) } +
+ { group.userId === 0 &&
+ +
} +
; + }) } +
+
+ setMessage(e.target.value) } onKeyDown={ onKeyDown } /> + +
+ }
); }; From 0ade1ee7cb4bee83e69b91d41324244d72a25b79 Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Sat, 18 Sep 2021 03:05:47 -0300 Subject: [PATCH 04/21] Remove Console Log --- src/api/friends/OpenMessengerChat.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/friends/OpenMessengerChat.ts b/src/api/friends/OpenMessengerChat.ts index e5c685cd..08520b1b 100644 --- a/src/api/friends/OpenMessengerChat.ts +++ b/src/api/friends/OpenMessengerChat.ts @@ -2,6 +2,5 @@ import { CreateLinkEvent } from '..'; export function OpenMessengerChat(friendId: number): void { - console.log(`friends/messenger/${friendId}`); CreateLinkEvent(`friends/messenger/${friendId}`); } From a54be45a4ff279e7fe148237f3b1c59a9eb40c9e Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Sat, 18 Sep 2021 04:09:49 -0300 Subject: [PATCH 05/21] Updates --- .../friendlist/icons/icon_new_message.png | Bin 0 -> 177 bytes .../images/friendlist/icons/icon_warning.png | Bin 0 -> 225 bytes src/assets/styles/icons.scss | 12 ++++ src/views/friends/FriendsMessageHandler.tsx | 3 +- src/views/friends/common/MessengerChat.ts | 16 +++-- .../friends/common/MessengerChatMessage.ts | 3 +- .../common/MessengerChatMessageGroup.ts | 9 ++- src/views/friends/reducers/FriendsReducer.tsx | 24 ++++++- .../views/messenger/FriendsMessengerView.scss | 9 ++- .../views/messenger/FriendsMessengerView.tsx | 61 +++++++++++++----- 10 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 src/assets/images/friendlist/icons/icon_new_message.png create mode 100644 src/assets/images/friendlist/icons/icon_warning.png diff --git a/src/assets/images/friendlist/icons/icon_new_message.png b/src/assets/images/friendlist/icons/icon_new_message.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a31fa00dc9ba26150a1722162be85e55cfaa45 GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_sR~aQ#}Es_vlAS-8Vqzopr090#4fdBvi literal 0 HcmV?d00001 diff --git a/src/assets/images/friendlist/icons/icon_warning.png b/src/assets/images/friendlist/icons/icon_warning.png new file mode 100644 index 0000000000000000000000000000000000000000..3a3ffcf9efa03104936b6823bd7435cff4b4a610 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6Q!3HGPJ}O-eq&N#aB8wRq_zr_GLB zeq{8kw;XW)eZ?&6#hu4Hmp!{Cm!HhG?puX)X7n1Ls;kD~hxUIs<=V=BrCNP;;4|i) Xl&z_ce_Xf+bRL7JtDnm{r-UW|QKMd} literal 0 HcmV?d00001 diff --git a/src/assets/styles/icons.scss b/src/assets/styles/icons.scss index a5108a7c..3d8f14ab 100644 --- a/src/assets/styles/icons.scss +++ b/src/assets/styles/icons.scss @@ -693,6 +693,18 @@ height: 16px; } + &.icon-friendlist-warning { + background: url('../images/friendlist/icons/icon_warning.png'); + width: 23px; + height: 21px; + } + + &.icon-friendlist-new-message { + background: url('../images/friendlist/icons/icon_new_message.png'); + width: 14px; + height: 16px; + } + &.spin { animation: rotating 1s linear infinite; } diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx index e1e055f2..479fc961 100644 --- a/src/views/friends/FriendsMessageHandler.tsx +++ b/src/views/friends/FriendsMessageHandler.tsx @@ -77,7 +77,8 @@ export const FriendsMessageHandler: FC<{}> = props => dispatchFriendsState({ type: FriendsActions.ADD_CHAT_MESSAGE, payload: { - chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData) + chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData), + boolValue: true } }); }, [ dispatchFriendsState ]); diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts index 2369a7c9..4b49d0ae 100644 --- a/src/views/friends/common/MessengerChat.ts +++ b/src/views/friends/common/MessengerChat.ts @@ -6,19 +6,25 @@ export class MessengerChat private _isRead: boolean; private _messageGroups: MessengerChatMessageGroup[]; - constructor(friendId: number, isRead: boolean = true) + constructor(friendId: number) { this._friendId = friendId; - this._isRead = isRead; + this._isRead = true; this._messageGroups = []; } - public addMessage(message: MessengerChatMessage): void + public addMessage(message: MessengerChatMessage, setAsNotRead: boolean = true, isSystem: boolean = false): void { - if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId)); + if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId || isSystem || this.lastMessageGroup.isSystem) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId, isSystem)); this.lastMessageGroup.addMessage(message); - this._isRead = false; + + if(setAsNotRead) this._isRead = false; + } + + public read(): void + { + this._isRead = true; } public get friendId(): number diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerChatMessage.ts index 5ded0a7d..6a0aced7 100644 --- a/src/views/friends/common/MessengerChatMessage.ts +++ b/src/views/friends/common/MessengerChatMessage.ts @@ -2,7 +2,8 @@ export class MessengerChatMessage { public static MESSAGE: number = 0; public static ROOM_INVITE: number = 1; - public static SYSTEM_NOTIFICATION: number = 2; + public static SECURITY_ALERT: number = 2; + public static STATUS_ALERT: number = 3; private _type: number; private _senderId: number; diff --git a/src/views/friends/common/MessengerChatMessageGroup.ts b/src/views/friends/common/MessengerChatMessageGroup.ts index 0bb27fe3..0fad7be8 100644 --- a/src/views/friends/common/MessengerChatMessageGroup.ts +++ b/src/views/friends/common/MessengerChatMessageGroup.ts @@ -4,11 +4,13 @@ export class MessengerChatMessageGroup { private _userId: number; private _messages: MessengerChatMessage[]; + private _isSystem: boolean; - constructor(userId: number) + constructor(userId: number, isSystem: boolean) { this._userId = userId; this._messages = []; + this._isSystem = isSystem; } public addMessage(message: MessengerChatMessage): void @@ -25,4 +27,9 @@ export class MessengerChatMessageGroup { return this._messages; } + + public get isSystem(): boolean + { + return this._isSystem; + } } diff --git a/src/views/friends/reducers/FriendsReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx index f66ce6fd..82f2e734 100644 --- a/src/views/friends/reducers/FriendsReducer.tsx +++ b/src/views/friends/reducers/FriendsReducer.tsx @@ -19,6 +19,7 @@ export interface IFriendsState friends: MessengerFriend[]; requests: MessengerRequest[]; activeChats: MessengerChat[]; + firstChatEverOpen: boolean; } export interface IFriendsAction @@ -32,6 +33,7 @@ export interface IFriendsAction chats?: MessengerChat[]; chatMessage?: MessengerChatMessage; numberValue?: number; + boolValue?: boolean; } } @@ -43,6 +45,7 @@ export class FriendsActions public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS'; + public static SET_CHAT_READ: string = 'FA_SET_CHAT_READ'; public static ADD_CHAT_MESSAGE: string = 'FA_ADD_CHAT_MESSAGE'; } @@ -50,7 +53,8 @@ export const initialFriends: IFriendsState = { settings: null, friends: [], requests: [], - activeChats: [] + activeChats: [], + firstChatEverOpen: false } export const FriendsReducer: Reducer = (state, action) => @@ -145,11 +149,25 @@ export const FriendsReducer: Reducer = (state, ac case FriendsActions.SET_ACTIVE_CHATS: { const activeChats = (action.payload.chats || []); + if(!state.firstChatEverOpen && activeChats.length > 0) activeChats[0].addMessage(new MessengerChatMessage(MessengerChatMessage.SECURITY_ALERT, 0, null, 0), false, true); + + return { ...state, activeChats, firstChatEverOpen: true }; + } + case FriendsActions.SET_CHAT_READ: { + const friendId = action.payload.numberValue; + + const activeChats = Array.from(state.activeChats); + + let activeChatIndex = activeChats.findIndex(c => c.friendId === friendId); + + if(activeChatIndex > -1) activeChats[activeChatIndex].read(); + return { ...state, activeChats }; } case FriendsActions.ADD_CHAT_MESSAGE: { const message = action.payload.chatMessage; const toFriendId = action.payload.numberValue; + const setAsNotRead = action.payload.boolValue; const activeChats = Array.from(state.activeChats); @@ -157,11 +175,11 @@ export const FriendsReducer: Reducer = (state, ac if(activeChatIndex === -1) { - activeChats.push(new MessengerChat(message.senderId, false)); + activeChats.push(new MessengerChat(message.senderId)); activeChatIndex = activeChats.length - 1; } - activeChats[activeChatIndex].addMessage(message); + activeChats[activeChatIndex].addMessage(message, setAsNotRead); return { ...state, activeChats }; } diff --git a/src/views/friends/views/messenger/FriendsMessengerView.scss b/src/views/friends/views/messenger/FriendsMessengerView.scss index 429f64cf..bbfdb0aa 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.scss +++ b/src/views/friends/views/messenger/FriendsMessengerView.scss @@ -1,5 +1,5 @@ .nitro-friends-messenger { - width: 300px; + width: 280px; .friend-head { position: relative; @@ -7,6 +7,13 @@ height: 40px; overflow: hidden; + .icon { + position: absolute; + top: 1px; + right: 1px; + z-index: 10; + } + .avatar-image { position: absolute; margin-left: -27px; diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index c3679025..882b435f 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -50,7 +50,7 @@ export const FriendsMessengerView: FC<{}> = props => if(existingChatIndex === -1) { const clonedActiveChats = Array.from(activeChats); - clonedActiveChats.push(new MessengerChat(friendId, true)); + clonedActiveChats.push(new MessengerChat(friendId)); dispatchFriendsState({ type: FriendsActions.SET_ACTIVE_CHATS, @@ -75,8 +75,24 @@ export const FriendsMessengerView: FC<{}> = props => return friend.figure; }, [ friends ]); - const selectedChat = useMemo(() => + const selectChat = useCallback((index: number) => { + const chat = activeChats[index]; + + if(!chat) return; + + dispatchFriendsState({ + type: FriendsActions.SET_CHAT_READ, + payload: { + numberValue: chat.friendId + } + }); + + setSelectedChatIndex(index); + }, [ activeChats, dispatchFriendsState ]); + + const selectedChat = useMemo(() => + { return activeChats[selectedChatIndex]; }, [ activeChats, selectedChatIndex ]); @@ -131,7 +147,8 @@ export const FriendsMessengerView: FC<{}> = props => type: FriendsActions.ADD_CHAT_MESSAGE, payload: { chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, 0, message, (new Date().getMilliseconds())), - numberValue: selectedChat.friendId + numberValue: selectedChat.friendId, + boolValue: false } }); setMessage(''); @@ -152,7 +169,8 @@ export const FriendsMessengerView: FC<{}> = props =>
{ activeChats && activeChats.map((chat, index) => { - return
setSelectedChatIndex(index) }> + return
selectChat(index) }> + { !chat.isRead && }
; }) } @@ -176,18 +194,31 @@ export const FriendsMessengerView: FC<{}> = props => { selectedChat.messageGroups.map((group, groupIndex) => { return
- { group.userId !== 0 &&
- -
} -
+ { group.isSystem && <> { group.messages.map((message, messageIndex) => - { - return
{ message.message }
- }) } -
- { group.userId === 0 &&
- -
} + { + return
+ { message.type === MessengerChatMessage.SECURITY_ALERT &&
+ +
{ LocalizeText('messenger.moderationinfo') }
+
} +
+ }) } + } + { !group.isSystem && <> + { group.userId !== 0 &&
+ +
} +
+ { group.messages.map((message, messageIndex) => + { + return
{ message.message }
+ }) } +
+ { group.userId === 0 &&
+ +
} + }
; }) }
From e97f18c53c8d56bc06ec1750c5b4b049294d7d49 Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 20 Sep 2021 04:17:38 -0400 Subject: [PATCH 06/21] Update craco config --- craco.config.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/craco.config.js b/craco.config.js index 661daecc..4f5320a4 100644 --- a/craco.config.js +++ b/craco.config.js @@ -5,6 +5,23 @@ module.exports = { webpack: { configure: (webpackConfig) => ({ ...webpackConfig, + optimization: { + ...webpackConfig.optimization, + splitChunks: { + cacheGroups: { + vendor: { + name: 'vendors', + test: /[\\/]node_modules[\\/]/, + chunks: 'all', + }, + renderer: { + name: 'renderer', + test: /[\\/]node_modules[\\/]@nitrots[\\/]nitro-renderer[\\/]/, + chunks: 'all', + } + } + } + }, module: { ...webpackConfig.module, rules: webpackConfig.module.rules.map((rule) => From 6a2821389688f5e75b3ddda2e05811dec2b2fbdb Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 21 Sep 2021 21:48:00 -0400 Subject: [PATCH 07/21] Messenger updates --- src/api/friends/OpenMessengerChat.ts | 5 +- .../friends/FriendsMessengerIconEvent.ts | 23 ++ src/events/friends/index.ts | 1 + .../card/content/NitroCardContentView.scss | 1 + .../catalog/common/AttemptCatalogPlacement.ts | 30 ++ .../catalog/common/IsCatalogOfferDraggable.ts | 8 + .../views/page/offer/CatalogPageOfferView.tsx | 15 +- .../views/page/product/CatalogProductView.tsx | 2 +- src/views/friends/FriendsMessageHandler.tsx | 23 +- src/views/friends/common/MessengerChat.ts | 49 --- .../common/MessengerChatMessageGroup.ts | 35 -- src/views/friends/common/MessengerThread.ts | 83 ++++ ...rChatMessage.ts => MessengerThreadChat.ts} | 25 +- .../common/MessengerThreadChatGroup.ts | 28 ++ src/views/friends/reducers/FriendsReducer.tsx | 64 +-- .../FriendsMessengerThreadGroup.tsx | 48 +++ .../FriendsMessengerThreadGroup.types.ts | 8 + .../FriendsMessengerThreadView.tsx | 17 + .../FriendsMessengerThreadView.types.ts | 6 + .../views/messenger/FriendsMessengerView.scss | 1 + .../views/messenger/FriendsMessengerView.tsx | 365 ++++++++++-------- .../chat/message/ChatWidgetMessageView.scss | 4 +- .../shared/avatar-image/AvatarImage.scss | 6 + .../shared/avatar-image/AvatarImageView.tsx | 11 +- .../room-previewer/RoomPreviewerView.scss | 1 - src/views/toolbar/ToolbarView.scss | 25 +- src/views/toolbar/ToolbarView.tsx | 48 ++- src/views/toolbar/ToolbarView.types.ts | 1 + tsconfig.json | 2 +- 29 files changed, 569 insertions(+), 366 deletions(-) create mode 100644 src/events/friends/FriendsMessengerIconEvent.ts create mode 100644 src/views/catalog/common/AttemptCatalogPlacement.ts create mode 100644 src/views/catalog/common/IsCatalogOfferDraggable.ts delete mode 100644 src/views/friends/common/MessengerChat.ts delete mode 100644 src/views/friends/common/MessengerChatMessageGroup.ts create mode 100644 src/views/friends/common/MessengerThread.ts rename src/views/friends/common/{MessengerChatMessage.ts => MessengerThreadChat.ts} (51%) create mode 100644 src/views/friends/common/MessengerThreadChatGroup.ts create mode 100644 src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.tsx create mode 100644 src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.types.ts create mode 100644 src/views/friends/views/messenger-thread/FriendsMessengerThreadView.tsx create mode 100644 src/views/friends/views/messenger-thread/FriendsMessengerThreadView.types.ts diff --git a/src/api/friends/OpenMessengerChat.ts b/src/api/friends/OpenMessengerChat.ts index 08520b1b..0b8ab554 100644 --- a/src/api/friends/OpenMessengerChat.ts +++ b/src/api/friends/OpenMessengerChat.ts @@ -1,6 +1,7 @@ import { CreateLinkEvent } from '..'; -export function OpenMessengerChat(friendId: number): void +export function OpenMessengerChat(friendId: number = -1): void { - CreateLinkEvent(`friends/messenger/${friendId}`); + if(friendId === -1) CreateLinkEvent('friends/messenger/open'); + else CreateLinkEvent(`friends/messenger/${friendId}`); } diff --git a/src/events/friends/FriendsMessengerIconEvent.ts b/src/events/friends/FriendsMessengerIconEvent.ts new file mode 100644 index 00000000..602eb726 --- /dev/null +++ b/src/events/friends/FriendsMessengerIconEvent.ts @@ -0,0 +1,23 @@ +import { NitroEvent } from '@nitrots/nitro-renderer'; + +export class FriendsMessengerIconEvent extends NitroEvent +{ + public static UPDATE_ICON: string = 'FMIE_UPDATE_ICON'; + public static HIDE_ICON: number = 0; + public static SHOW_ICON: number = 1; + public static UNREAD_ICON: number = 2; + + private _iconType: number; + + constructor(type: string, subType: number = FriendsMessengerIconEvent.SHOW_ICON) + { + super(type); + + this._iconType = subType; + } + + public get iconType(): number + { + return this._iconType; + } +} diff --git a/src/events/friends/index.ts b/src/events/friends/index.ts index 9a4bb3ed..2f3699c3 100644 --- a/src/events/friends/index.ts +++ b/src/events/friends/index.ts @@ -1,4 +1,5 @@ export * from './FriendEnteredRoomEvent'; export * from './FriendListContentEvent'; export * from './FriendsEvent'; +export * from './FriendsMessengerIconEvent'; export * from './FriendsSendFriendRequestEvent'; diff --git a/src/layout/card/content/NitroCardContentView.scss b/src/layout/card/content/NitroCardContentView.scss index 9ffd6fe9..4cbe6ee3 100644 --- a/src/layout/card/content/NitroCardContentView.scss +++ b/src/layout/card/content/NitroCardContentView.scss @@ -1,4 +1,5 @@ .content-area { + height: 100%; padding-top: $container-padding-x; padding-bottom: $container-padding-x; overflow: auto; diff --git a/src/views/catalog/common/AttemptCatalogPlacement.ts b/src/views/catalog/common/AttemptCatalogPlacement.ts new file mode 100644 index 00000000..af342ee3 --- /dev/null +++ b/src/views/catalog/common/AttemptCatalogPlacement.ts @@ -0,0 +1,30 @@ +import { CatalogPageMessageOfferData, RoomObjectCategory, RoomObjectPlacementSource } from '@nitrots/nitro-renderer'; +import { GetRoomEngine } from '../../../api'; +import { IsCatalogOfferDraggable } from './IsCatalogOfferDraggable'; +import { ProductTypeEnum } from './ProductTypeEnum'; + +export const AttemptCatalogPlacement = (offer: CatalogPageMessageOfferData) => +{ + if(!IsCatalogOfferDraggable(offer)) return; + + const product = offer.products[0]; + + let category: number = -1; + + switch(product.productType) + { + case ProductTypeEnum.FLOOR: + category = RoomObjectCategory.FLOOR; + break; + case ProductTypeEnum.WALL: + category = RoomObjectCategory.WALL; + break; + } + + if(category === -1) return; + + if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.furniClassId, (product.extraParam) ? product.extraParam.toString() : null)) + { + + } +} diff --git a/src/views/catalog/common/IsCatalogOfferDraggable.ts b/src/views/catalog/common/IsCatalogOfferDraggable.ts new file mode 100644 index 00000000..174ce4d0 --- /dev/null +++ b/src/views/catalog/common/IsCatalogOfferDraggable.ts @@ -0,0 +1,8 @@ +import { CatalogPageMessageOfferData, RoomControllerLevel } from '@nitrots/nitro-renderer'; +import { GetRoomSession } from '../../../api'; +import { ProductTypeEnum } from './ProductTypeEnum'; + +export const IsCatalogOfferDraggable = (offer: CatalogPageMessageOfferData) => +{ + return ((GetRoomSession().isRoomOwner || (GetRoomSession().isGuildRoom && (GetRoomSession().controllerLevel >= RoomControllerLevel.GUILD_MEMBER))) && (offer.products.length === 1) && (offer.products[0].productType !== ProductTypeEnum.EFFECT) && (offer.products[0].productType !== ProductTypeEnum.HABBO_CLUB)) +} diff --git a/src/views/catalog/views/page/offer/CatalogPageOfferView.tsx b/src/views/catalog/views/page/offer/CatalogPageOfferView.tsx index 89f6b90f..980ee8e7 100644 --- a/src/views/catalog/views/page/offer/CatalogPageOfferView.tsx +++ b/src/views/catalog/views/page/offer/CatalogPageOfferView.tsx @@ -1,5 +1,5 @@ import { MouseEventType } from '@nitrots/nitro-renderer'; -import { FC, MouseEvent, useCallback } from 'react'; +import { FC, MouseEvent, useCallback, useState } from 'react'; import { useCatalogContext } from '../../../context/CatalogContext'; import { CatalogActions } from '../../../reducers/CatalogReducer'; import { CatalogProductView } from '../product/CatalogProductView'; @@ -8,6 +8,7 @@ import { CatalogPageOfferViewProps } from './CatalogPageOfferView.types'; export const CatalogPageOfferView: FC = props => { const { isActive = false, offer = null } = props; + const [ isMouseDown, setMouseDown ] = useState(false); const { dispatchCatalogState = null } = useCatalogContext(); const onMouseEvent = useCallback((event: MouseEvent) => @@ -24,8 +25,18 @@ export const CatalogPageOfferView: FC = props => } }); return; + case MouseEventType.MOUSE_DOWN: + console.log('ye') + setMouseDown(true); + return; + case MouseEventType.MOUSE_UP: + setMouseDown(false); + return; + case MouseEventType.ROLL_OUT: + if(!isMouseDown || !isActive) return; + return; } - }, [ isActive, offer, dispatchCatalogState ]); + }, [ isActive, offer, isMouseDown, dispatchCatalogState ]); const product = ((offer.products && offer.products[0]) || null); diff --git a/src/views/catalog/views/page/product/CatalogProductView.tsx b/src/views/catalog/views/page/product/CatalogProductView.tsx index 684488d0..2bb1c543 100644 --- a/src/views/catalog/views/page/product/CatalogProductView.tsx +++ b/src/views/catalog/views/page/product/CatalogProductView.tsx @@ -65,7 +65,7 @@ export const CatalogProductView: FC = props => return (
-
+
{ !imageUrl && (product.productType === ProductTypeEnum.ROBOT) && } { (product.productCount > 1) && { product.productCount } } diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx index 479fc961..ce84725e 100644 --- a/src/views/friends/FriendsMessageHandler.tsx +++ b/src/views/friends/FriendsMessageHandler.tsx @@ -1,8 +1,6 @@ -import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent, NewConsoleMessageEvent } from '@nitrots/nitro-renderer'; +import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; -import { GetSessionDataManager } from '../../api'; import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; -import { MessengerChatMessage } from './common/MessengerChatMessage'; import { MessengerSettings } from './common/MessengerSettings'; import { useFriendsContext } from './context/FriendsContext'; import { FriendsActions } from './reducers/FriendsReducer'; @@ -10,7 +8,6 @@ import { FriendsActions } from './reducers/FriendsReducer'; export const FriendsMessageHandler: FC<{}> = props => { const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); - const { activeChats = [] } = friendsState; const onMessengerInitEvent = useCallback((event: MessengerInitEvent) => { @@ -66,28 +63,10 @@ export const FriendsMessageHandler: FC<{}> = props => }); }, [ dispatchFriendsState ]); - const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) => - { - const parser = event.getParser(); - - let userId = parser.senderId; - - if(userId === GetSessionDataManager().userId) userId = 0; - - dispatchFriendsState({ - type: FriendsActions.ADD_CHAT_MESSAGE, - payload: { - chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData), - boolValue: true - } - }); - }, [ dispatchFriendsState ]); - CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent); CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent); CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent); - CreateMessageHook(NewConsoleMessageEvent, onNewConsoleMessageEvent); return null; } diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts deleted file mode 100644 index 4b49d0ae..00000000 --- a/src/views/friends/common/MessengerChat.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { MessengerChatMessage } from './MessengerChatMessage'; -import { MessengerChatMessageGroup } from './MessengerChatMessageGroup'; -export class MessengerChat -{ - private _friendId: number; - private _isRead: boolean; - private _messageGroups: MessengerChatMessageGroup[]; - - constructor(friendId: number) - { - this._friendId = friendId; - this._isRead = true; - this._messageGroups = []; - } - - public addMessage(message: MessengerChatMessage, setAsNotRead: boolean = true, isSystem: boolean = false): void - { - if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId || isSystem || this.lastMessageGroup.isSystem) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId, isSystem)); - - this.lastMessageGroup.addMessage(message); - - if(setAsNotRead) this._isRead = false; - } - - public read(): void - { - this._isRead = true; - } - - public get friendId(): number - { - return this._friendId; - } - - public get isRead(): boolean - { - return this._isRead; - } - - public get messageGroups(): MessengerChatMessageGroup[] - { - return this._messageGroups; - } - - public get lastMessageGroup(): MessengerChatMessageGroup - { - return this._messageGroups[this._messageGroups.length - 1]; - } -} diff --git a/src/views/friends/common/MessengerChatMessageGroup.ts b/src/views/friends/common/MessengerChatMessageGroup.ts deleted file mode 100644 index 0fad7be8..00000000 --- a/src/views/friends/common/MessengerChatMessageGroup.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { MessengerChatMessage } from './MessengerChatMessage'; - -export class MessengerChatMessageGroup -{ - private _userId: number; - private _messages: MessengerChatMessage[]; - private _isSystem: boolean; - - constructor(userId: number, isSystem: boolean) - { - this._userId = userId; - this._messages = []; - this._isSystem = isSystem; - } - - public addMessage(message: MessengerChatMessage): void - { - this._messages.push(message); - } - - public get userId(): number - { - return this._userId; - } - - public get messages(): MessengerChatMessage[] - { - return this._messages; - } - - public get isSystem(): boolean - { - return this._isSystem; - } -} diff --git a/src/views/friends/common/MessengerThread.ts b/src/views/friends/common/MessengerThread.ts new file mode 100644 index 00000000..a2ee75e1 --- /dev/null +++ b/src/views/friends/common/MessengerThread.ts @@ -0,0 +1,83 @@ +import { LocalizeText } from '../../../api'; +import { MessengerFriend } from './MessengerFriend'; +import { MessengerThreadChat } from './MessengerThreadChat'; +import { MessengerThreadChatGroup } from './MessengerThreadChatGroup'; + +export class MessengerThread +{ + public static MESSAGE_RECEIVED: string = 'MT_MESSAGE_RECEIVED'; + + private _participant: MessengerFriend; + private _groups: MessengerThreadChatGroup[]; + private _lastUpdated: Date; + private _unread: boolean; + + constructor(participant: MessengerFriend, isNew: boolean = true) + { + this._participant = participant; + this._groups = []; + this._lastUpdated = new Date(); + this._unread = false; + + if(isNew) + { + this.addMessage(-1, LocalizeText('messenger.moderationinfo'), 0, null, MessengerThreadChat.SECURITY_NOTIFICATION); + + this._unread = false; + } + } + + public addMessage(senderId: number, message: string, secondsSinceSent: number = 0, extraData: string = null, type: number = 0): MessengerThreadChat + { + const group = this.getLastGroup(senderId); + + if(!group) return; + + const chat = new MessengerThreadChat(senderId, message, secondsSinceSent, extraData, type); + + group.addChat(chat); + + this._lastUpdated = new Date(); + this._unread = true; + + return chat; + } + + private getLastGroup(userId: number): MessengerThreadChatGroup + { + let group = this._groups[(this._groups.length - 1)]; + + if(group && (group.userId === userId)) return group; + + group = new MessengerThreadChatGroup(userId); + + this._groups.push(group); + + return group; + } + + public setRead(): void + { + this._unread = false; + } + + public get participant(): MessengerFriend + { + return this._participant; + } + + public get groups(): MessengerThreadChatGroup[] + { + return this._groups; + } + + public get lastUpdated(): Date + { + return this._lastUpdated; + } + + public get unread(): boolean + { + return this._unread; + } +} diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerThreadChat.ts similarity index 51% rename from src/views/friends/common/MessengerChatMessage.ts rename to src/views/friends/common/MessengerThreadChat.ts index 6a0aced7..2927fecc 100644 --- a/src/views/friends/common/MessengerChatMessage.ts +++ b/src/views/friends/common/MessengerThreadChat.ts @@ -1,23 +1,25 @@ -export class MessengerChatMessage +export class MessengerThreadChat { - public static MESSAGE: number = 0; + public static CHAT: number = 0; public static ROOM_INVITE: number = 1; - public static SECURITY_ALERT: number = 2; - public static STATUS_ALERT: number = 3; + public static STATUS_NOTIFICATION: number = 2; + public static SECURITY_NOTIFICATION: number = 3; private _type: number; private _senderId: number; private _message: string; - private _sentAt: number; + private _secondsSinceSent: number; private _extraData: string; + private _date: Date; - constructor(type: number, senderId: number, message: string, sentAt: number, extraData?: string) + constructor(senderId: number, message: string, secondsSinceSent: number = 0, extraData: string = null, type: number = 0) { this._type = type; this._senderId = senderId; this._message = message; - this._sentAt = sentAt; + this._secondsSinceSent = secondsSinceSent; this._extraData = extraData; + this._date = new Date(); } public get type(): number @@ -35,13 +37,18 @@ export class MessengerChatMessage return this._message; } - public get sentAt(): number + public get secondsSinceSent(): number { - return this._sentAt; + return this._secondsSinceSent; } public get extraData(): string { return this._extraData; } + + public get date(): Date + { + return this._date; + } } diff --git a/src/views/friends/common/MessengerThreadChatGroup.ts b/src/views/friends/common/MessengerThreadChatGroup.ts new file mode 100644 index 00000000..661dcb07 --- /dev/null +++ b/src/views/friends/common/MessengerThreadChatGroup.ts @@ -0,0 +1,28 @@ +import { MessengerThreadChat } from './MessengerThreadChat'; + +export class MessengerThreadChatGroup +{ + private _userId: number; + private _chats: MessengerThreadChat[]; + + constructor(userId: number) + { + this._userId = userId; + this._chats = []; + } + + public addChat(message: MessengerThreadChat): void + { + this._chats.push(message); + } + + public get userId(): number + { + return this._userId; + } + + public get chats(): MessengerThreadChat[] + { + return this._chats; + } +} diff --git a/src/views/friends/reducers/FriendsReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx index 82f2e734..1901bb49 100644 --- a/src/views/friends/reducers/FriendsReducer.tsx +++ b/src/views/friends/reducers/FriendsReducer.tsx @@ -1,7 +1,5 @@ import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer'; import { Reducer } from 'react'; -import { MessengerChat } from '../common/MessengerChat'; -import { MessengerChatMessage } from '../common/MessengerChatMessage'; import { MessengerFriend } from '../common/MessengerFriend'; import { MessengerRequest } from '../common/MessengerRequest'; import { MessengerSettings } from '../common/MessengerSettings'; @@ -18,8 +16,6 @@ export interface IFriendsState settings: MessengerSettings; friends: MessengerFriend[]; requests: MessengerRequest[]; - activeChats: MessengerChat[]; - firstChatEverOpen: boolean; } export interface IFriendsAction @@ -30,8 +26,6 @@ export interface IFriendsAction fragment?: FriendParser[]; update?: FriendListUpdateParser; requests?: FriendRequestData[]; - chats?: MessengerChat[]; - chatMessage?: MessengerChatMessage; numberValue?: number; boolValue?: boolean; } @@ -44,17 +38,12 @@ export class FriendsActions public static PROCESS_FRAGMENT: string = 'FA_PROCESS_FRAGMENT'; public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; - public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS'; - public static SET_CHAT_READ: string = 'FA_SET_CHAT_READ'; - public static ADD_CHAT_MESSAGE: string = 'FA_ADD_CHAT_MESSAGE'; } export const initialFriends: IFriendsState = { settings: null, friends: [], - requests: [], - activeChats: [], - firstChatEverOpen: false + requests: [] } export const FriendsReducer: Reducer = (state, action) => @@ -108,11 +97,17 @@ export const FriendsReducer: Reducer = (state, ac { const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id)); - const newFriend = new MessengerFriend(); - newFriend.populate(friend); + if(index === -1) + { + const newFriend = new MessengerFriend(); + newFriend.populate(friend); - if(index > -1) friends[index] = newFriend; - else friends.unshift(newFriend); + friends.unshift(newFriend); + } + else + { + friends[index].populate(friend); + } } for(const friend of update.addedFriends) processUpdate(friend); @@ -146,43 +141,6 @@ export const FriendsReducer: Reducer = (state, ac return { ...state, requests }; } - case FriendsActions.SET_ACTIVE_CHATS: { - const activeChats = (action.payload.chats || []); - - if(!state.firstChatEverOpen && activeChats.length > 0) activeChats[0].addMessage(new MessengerChatMessage(MessengerChatMessage.SECURITY_ALERT, 0, null, 0), false, true); - - return { ...state, activeChats, firstChatEverOpen: true }; - } - case FriendsActions.SET_CHAT_READ: { - const friendId = action.payload.numberValue; - - const activeChats = Array.from(state.activeChats); - - let activeChatIndex = activeChats.findIndex(c => c.friendId === friendId); - - if(activeChatIndex > -1) activeChats[activeChatIndex].read(); - - return { ...state, activeChats }; - } - case FriendsActions.ADD_CHAT_MESSAGE: { - const message = action.payload.chatMessage; - const toFriendId = action.payload.numberValue; - const setAsNotRead = action.payload.boolValue; - - const activeChats = Array.from(state.activeChats); - - let activeChatIndex = activeChats.findIndex(c => c.friendId === toFriendId ? toFriendId : message.senderId); - - if(activeChatIndex === -1) - { - activeChats.push(new MessengerChat(message.senderId)); - activeChatIndex = activeChats.length - 1; - } - - activeChats[activeChatIndex].addMessage(message, setAsNotRead); - - return { ...state, activeChats }; - } default: return state; } diff --git a/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.tsx b/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.tsx new file mode 100644 index 00000000..b0d30ea7 --- /dev/null +++ b/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.tsx @@ -0,0 +1,48 @@ +import { FC } from 'react'; +import { GetSessionDataManager } from '../../../../api'; +import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; +import { MessengerThreadChat } from '../../common/MessengerThreadChat'; +import { FriendsMessengerThreadGroupProps } from './FriendsMessengerThreadGroup.types'; + +export const FriendsMessengerThreadGroup: FC = props => +{ + const { thread = null, group = null } = props; + + if(!thread || !group) return null; + + if(group.userId === -1) + { + return ( +
+ { group.chats.map((chat, index) => + { + return ( +
+ { chat.type === MessengerThreadChat.SECURITY_NOTIFICATION && +
+ +
{ chat.message }
+
} +
+ ); + }) } +
+ ); + } + + return ( +
+ { (group.userId > 0) && +
+ +
} +
+ { group.chats.map((chat, index) =>
{ chat.message }
) } +
+ { (group.userId === 0) && +
+ +
} +
+ ); +} diff --git a/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.types.ts b/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.types.ts new file mode 100644 index 00000000..12a0ed17 --- /dev/null +++ b/src/views/friends/views/messenger-thread-group/FriendsMessengerThreadGroup.types.ts @@ -0,0 +1,8 @@ +import { MessengerThread } from '../../common/MessengerThread'; +import { MessengerThreadChatGroup } from '../../common/MessengerThreadChatGroup'; + +export interface FriendsMessengerThreadGroupProps +{ + thread: MessengerThread; + group: MessengerThreadChatGroup; +} diff --git a/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.tsx b/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.tsx new file mode 100644 index 00000000..3bf6326a --- /dev/null +++ b/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react'; +import { FriendsMessengerThreadGroup } from '../messenger-thread-group/FriendsMessengerThreadGroup'; +import { FriendsMessengerThreadViewProps } from './FriendsMessengerThreadView.types'; + +export const FriendsMessengerThreadView: FC = props => +{ + const { thread = null } = props; + + return ( + <> + { (thread.groups.length > 0) && thread.groups.map((group, index) => + { + return ; + }) } + + ); +} diff --git a/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.types.ts b/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.types.ts new file mode 100644 index 00000000..a6e0f4c4 --- /dev/null +++ b/src/views/friends/views/messenger-thread/FriendsMessengerThreadView.types.ts @@ -0,0 +1,6 @@ +import { MessengerThread } from '../../common/MessengerThread'; + +export interface FriendsMessengerThreadViewProps +{ + thread: MessengerThread; +} diff --git a/src/views/friends/views/messenger/FriendsMessengerView.scss b/src/views/friends/views/messenger/FriendsMessengerView.scss index bbfdb0aa..596ab19f 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.scss +++ b/src/views/friends/views/messenger/FriendsMessengerView.scss @@ -1,5 +1,6 @@ .nitro-friends-messenger { width: 280px; + resize: both; .friend-head { position: relative; diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index 882b435f..dac6a7a5 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,41 +1,134 @@ -import { FollowFriendMessageComposer, ILinkEventTracker, NitroEvent, SendMessageComposer, UserProfileComposer } from '@nitrots/nitro-renderer'; +import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer, UserProfileComposer } from '@nitrots/nitro-renderer'; import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { AddEventLinkTracker, GetSessionDataManager, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; -import { FriendsEvent } from '../../../../events/friends/FriendsEvent'; -import { SendMessageHook, useUiEvent } from '../../../../hooks'; +import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; +import { FriendsMessengerIconEvent } from '../../../../events'; +import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; -import { MessengerChat } from '../../common/MessengerChat'; -import { MessengerChatMessage } from '../../common/MessengerChatMessage'; +import { MessengerThread } from '../../common/MessengerThread'; +import { MessengerThreadChat } from '../../common/MessengerThreadChat'; import { useFriendsContext } from '../../context/FriendsContext'; -import { FriendsActions } from '../../reducers/FriendsReducer'; +import { FriendsMessengerThreadView } from '../messenger-thread/FriendsMessengerThreadView'; export const FriendsMessengerView: FC<{}> = props => { - const { friendsState = null, dispatchFriendsState = null } = useFriendsContext(); - const { activeChats = [], friends = [] } = friendsState; - const [ isVisible, setIsVisible ] = useState(false); - const [ selectedChatIndex, setSelectedChatIndex ] = useState(0); - const [ message, setMessage ] = useState(''); - + const [ messageThreads, setMessageThreads ] = useState([]); + const [ activeThreadIndex, setActiveThreadIndex ] = useState(-1); + const [ hiddenThreadIndexes, setHiddenThreadIndexes ] = useState([]); + const [ messageText, setMessageText ] = useState(''); + const { friendsState = null } = useFriendsContext(); + const { friends = [] } = friendsState; const messagesBox = useRef(); - - const onNitroEvent = useCallback((event: NitroEvent) => - { - switch(event.type) - { - case FriendsEvent.SHOW_FRIEND_MESSENGER: - setIsVisible(true); - return; - case FriendsEvent.TOGGLE_FRIEND_MESSENGER: - setIsVisible(value => !value); - return; - } - }, []); + const [ updateValue, setUpdateValue ] = useState({}); - useUiEvent(FriendsEvent.SHOW_FRIEND_MESSENGER, onNitroEvent); - useUiEvent(FriendsEvent.TOGGLE_FRIEND_MESSENGER, onNitroEvent); + const followFriend = useCallback(() => + { + SendMessageHook(new FollowFriendMessageComposer(messageThreads[activeThreadIndex].participant.id)); + }, [ messageThreads, activeThreadIndex ]); + + const openProfile = useCallback(() => + { + SendMessageHook(new UserProfileComposer(messageThreads[activeThreadIndex].participant.id)); + }, [ messageThreads, activeThreadIndex ]); + + const getFriend = useCallback((userId: number) => + { + return ((friends.find(friend => (friend.id === userId))) || null); + }, [ friends ]); + + const visibleThreads = useMemo(() => + { + return messageThreads.filter((thread, index) => + { + if(hiddenThreadIndexes.indexOf(index) >= 0) return false; + + return true; + }); + }, [ messageThreads, hiddenThreadIndexes ]); + + const getMessageThreadWithIndex = useCallback<(userId: number) => [ number, MessengerThread ]>((userId: number) => + { + if(messageThreads.length > 0) + { + for(let i = 0; i < messageThreads.length; i++) + { + const thread = messageThreads[i]; + + if(thread.participant && (thread.participant.id === userId)) + { + const hiddenIndex = hiddenThreadIndexes.indexOf(i); + + if(hiddenIndex >= 0) + { + setHiddenThreadIndexes(prevValue => + { + const newIndexes = [ ...prevValue ]; + + newIndexes.splice(hiddenIndex, 1); + + return newIndexes; + }); + } + + return [ i, thread ]; + } + } + } + + const friend = getFriend(userId); + + if(!friend) return [ -1, null ]; + + const thread = new MessengerThread(friend); + const newThreads = [ ...messageThreads, thread ]; + + setMessageThreads(newThreads); + + return [ (newThreads.length - 1), thread ]; + }, [ messageThreads, hiddenThreadIndexes, getFriend ]); + + const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) => + { + const parser = event.getParser(); + const [ threadIndex, thread ] = getMessageThreadWithIndex(parser.senderId); + + if((threadIndex === -1) || !thread) return; + + thread.addMessage(parser.senderId, parser.messageText, parser.secondsSinceSent, parser.extraData); + + setMessageThreads(prevValue => [ ...prevValue ]); + }, [ getMessageThreadWithIndex ]); + + CreateMessageHook(NewConsoleMessageEvent, onNewConsoleMessageEvent); + + const sendMessage = useCallback(() => + { + if(!messageText || !messageText.length) return; + + if(activeThreadIndex === -1) return; + + const thread = messageThreads[activeThreadIndex]; + + if(!thread) return; + + SendMessageHook(new SendMessageComposer(thread.participant.id, messageText)); + + thread.addMessage(0, messageText, 0, null, MessengerThreadChat.CHAT); + + BatchUpdates(() => + { + setMessageThreads(prevValue => [ ...prevValue ]); + setMessageText(''); + }); + }, [ messageThreads, activeThreadIndex, messageText ]); + + const onKeyDown = useCallback((event: KeyboardEvent) => + { + if(event.key !== 'Enter') return; + + sendMessage(); + }, [ sendMessage ]); const linkReceived = useCallback((url: string) => { @@ -43,69 +136,35 @@ export const FriendsMessengerView: FC<{}> = props => if(parts.length < 3) return; - const friendId = parseInt(parts[2]); - - let existingChatIndex = activeChats.findIndex(c => c.friendId === friendId); - - if(existingChatIndex === -1) + if(parts[2] === 'open') { - const clonedActiveChats = Array.from(activeChats); - clonedActiveChats.push(new MessengerChat(friendId)); + setIsVisible(true); - dispatchFriendsState({ - type: FriendsActions.SET_ACTIVE_CHATS, - payload: { - chats: clonedActiveChats - } - }); - - existingChatIndex = clonedActiveChats.length - 1; + return; } - setSelectedChatIndex(existingChatIndex); - setIsVisible(true); - }, [ activeChats, dispatchFriendsState ]); + const [ threadIndex ] = getMessageThreadWithIndex(parseInt(parts[2])); - const getFriendFigure = useCallback((id: number) => - { - const friend = friends.find(f => f.id === id); + if(threadIndex === -1) return; - if(!friend) return null; - - return friend.figure; - }, [ friends ]); - - const selectChat = useCallback((index: number) => - { - const chat = activeChats[index]; - - if(!chat) return; - - dispatchFriendsState({ - type: FriendsActions.SET_CHAT_READ, - payload: { - numberValue: chat.friendId - } + BatchUpdates(() => + { + setActiveThreadIndex(threadIndex); + setIsVisible(true); }); - - setSelectedChatIndex(index); - }, [ activeChats, dispatchFriendsState ]); + }, [ getMessageThreadWithIndex ]); - const selectedChat = useMemo(() => - { - return activeChats[selectedChatIndex]; - }, [ activeChats, selectedChatIndex ]); - - const selectedChatFriend = useMemo(() => + const closeThread = useCallback((threadIndex: number) => { - if(!selectedChat) return null; + setHiddenThreadIndexes(prevValue => + { + const values = [ ...prevValue ]; - const friend = friends.find(f => f.id === selectedChat.friendId); + if(values.indexOf(threadIndex) === -1) values.push(threadIndex); - if(!friend) return null; - - return friend; - }, [ friends, selectedChat ]); + return values; + }); + }, []); useEffect(() => { @@ -121,112 +180,102 @@ export const FriendsMessengerView: FC<{}> = props => useEffect(() => { - if(!messagesBox || !messagesBox.current) return; - - messagesBox.current.scrollTop = messagesBox.current.scrollHeight; + if(!isVisible) return; - }, [ selectedChat ]); + if(activeThreadIndex === -1) setActiveThreadIndex(0); + }, [ isVisible, activeThreadIndex ]); - const followFriend = useCallback(() => + useEffect(() => { - SendMessageHook(new FollowFriendMessageComposer(selectedChatFriend.id)); - }, [ selectedChatFriend ]); + if(hiddenThreadIndexes.indexOf(activeThreadIndex) >= 0) setActiveThreadIndex(0); + }, [ activeThreadIndex, hiddenThreadIndexes ]); - const openProfile = useCallback(() => + useEffect(() => { - SendMessageHook(new UserProfileComposer(selectedChatFriend.id)); - }, [ selectedChatFriend ]); + if(!isVisible || (activeThreadIndex === -1)) return; - const sendMessage = useCallback(() => + const activeThread = messageThreads[activeThreadIndex]; + + if(activeThread.unread) + { + messagesBox.current.scrollTop = messagesBox.current.scrollHeight; + activeThread.setRead(); + setUpdateValue({}); + } + }, [ isVisible, messageThreads, activeThreadIndex ]); + + useEffect(() => { - if(message.length === 0) return; + if(!visibleThreads.length) + { + setIsVisible(false); - SendMessageHook(new SendMessageComposer(selectedChat.friendId, message)); + dispatchUiEvent(new FriendsMessengerIconEvent(FriendsMessengerIconEvent.UPDATE_ICON, FriendsMessengerIconEvent.HIDE_ICON)); - dispatchFriendsState({ - type: FriendsActions.ADD_CHAT_MESSAGE, - payload: { - chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, 0, message, (new Date().getMilliseconds())), - numberValue: selectedChat.friendId, - boolValue: false + return; + } + + let isUnread = false; + + for(const thread of visibleThreads) + { + if(thread.unread) + { + isUnread = true; + + break; } - }); - setMessage(''); - }, [ selectedChat, message, dispatchFriendsState ]); + } - const onKeyDown = useCallback((event: KeyboardEvent) => - { - if(event.key !== 'Enter') return; - - sendMessage(); - }, [ sendMessage ]); + dispatchUiEvent(new FriendsMessengerIconEvent(FriendsMessengerIconEvent.UPDATE_ICON, isUnread ? FriendsMessengerIconEvent.UNREAD_ICON : FriendsMessengerIconEvent.SHOW_ICON)); + }, [ visibleThreads, updateValue ]); if(!isVisible) return null; - return ( - setIsVisible(false) } /> - -
- { activeChats && activeChats.map((chat, index) => + return ( + + setIsVisible(false) } /> + +
+ { visibleThreads && (visibleThreads.length > 0) && visibleThreads.map((thread, index) => { - return
selectChat(index) }> - { !chat.isRead && } - -
; + const messageThreadIndex = messageThreads.indexOf(thread); + + return ( +
setActiveThreadIndex(messageThreadIndex) }> + { thread.unread && } + +
+ ); }) } -
-
- { selectedChat && selectedChatFriend && <> -
{ LocalizeText('messenger.window.separator', ['FRIEND_NAME'], [ selectedChatFriend.name ]) }
+
+
+ { (activeThreadIndex >= 0) && + <> +
+ { LocalizeText('messenger.window.separator', [ 'FRIEND_NAME' ], [ messageThreads[activeThreadIndex].participant.name ]) } +
- -
- +
- { selectedChat.messageGroups.map((group, groupIndex) => - { - return
- { group.isSystem && <> - { group.messages.map((message, messageIndex) => - { - return
- { message.type === MessengerChatMessage.SECURITY_ALERT &&
- -
{ LocalizeText('messenger.moderationinfo') }
-
} -
- }) } - } - { !group.isSystem && <> - { group.userId !== 0 &&
- -
} -
- { group.messages.map((message, messageIndex) => - { - return
{ message.message }
- }) } -
- { group.userId === 0 &&
- -
} - } -
; - }) } +
- setMessage(e.target.value) } onKeyDown={ onKeyDown } /> + setMessageText(event.target.value) } onKeyDown={ onKeyDown } />
} -
-
); -}; + + + ); +} diff --git a/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss b/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss index 9bdbcb6b..9337ed85 100644 --- a/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss +++ b/src/views/room/widgets/chat/message/ChatWidgetMessageView.scss @@ -696,7 +696,6 @@ justify-content: center; height: 100%; max-height: 24px; - image-rendering: -webkit-optimize-contrast; overflow: hidden; .user-image { @@ -707,8 +706,9 @@ height: 130px; background-repeat: no-repeat; background-position: center; - transform: scale(0.5) translateZ(0); + transform: scale(0.5); overflow: hidden; + image-rendering: -webkit-optimize-contrast; } } diff --git a/src/views/shared/avatar-image/AvatarImage.scss b/src/views/shared/avatar-image/AvatarImage.scss index f85ca9c4..a552dbb2 100644 --- a/src/views/shared/avatar-image/AvatarImage.scss +++ b/src/views/shared/avatar-image/AvatarImage.scss @@ -6,4 +6,10 @@ background-position-x: center; background-position-y: -8px !important; pointer-events: none; + image-rendering: pixelated; + + &.scale-0-5, + &.scale-0-75 { + image-rendering: -webkit-optimize-contrast; + } } diff --git a/src/views/shared/avatar-image/AvatarImageView.tsx b/src/views/shared/avatar-image/AvatarImageView.tsx index 5d2a2a33..d8e96979 100644 --- a/src/views/shared/avatar-image/AvatarImageView.tsx +++ b/src/views/shared/avatar-image/AvatarImageView.tsx @@ -1,5 +1,5 @@ import { AvatarScaleType, AvatarSetType } from '@nitrots/nitro-renderer'; -import { FC, useEffect, useRef, useState } from 'react'; +import { FC, useEffect, useMemo, useRef, useState } from 'react'; import { GetAvatarRenderManager } from '../../../api'; import { AvatarImageViewProps } from './AvatarImageView.types'; @@ -10,6 +10,13 @@ export const AvatarImageView: FC = props => const [ randomValue, setRandomValue ] = useState(-1); const isDisposed = useRef(false); + const getScaleStyle = useMemo(() => + { + if(scale === .5) return '0-5'; + + return scale.toString(); + }, [ scale ]); + useEffect(() => { const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, gender, { @@ -50,5 +57,5 @@ export const AvatarImageView: FC = props => const url = `url('${ avatarUrl }')`; - return
; + return
; } diff --git a/src/views/shared/room-previewer/RoomPreviewerView.scss b/src/views/shared/room-previewer/RoomPreviewerView.scss index 55328299..e6192624 100644 --- a/src/views/shared/room-previewer/RoomPreviewerView.scss +++ b/src/views/shared/room-previewer/RoomPreviewerView.scss @@ -12,7 +12,6 @@ background-color: $light; background-repeat: no-repeat; background-position: center; - image-rendering: auto; &.border-0 { &::after { diff --git a/src/views/toolbar/ToolbarView.scss b/src/views/toolbar/ToolbarView.scss index 44abb043..57401e81 100644 --- a/src/views/toolbar/ToolbarView.scss +++ b/src/views/toolbar/ToolbarView.scss @@ -29,31 +29,28 @@ align-items: center; justify-content: center; cursor: pointer; - width: 50px; - margin: 0 1px; + //margin: 0 1px; position: relative; - .toolbar-avatar { - height: 50px; + &.item-avatar { + width: 50px; + height: 45px; + overflow: hidden; .avatar-image { margin-left: -5px; - margin-top: -30px; - } - - &:hover, &.active { - height: 53px; + margin-top: 25px; } } .icon, - .toolbar-avatar { + &.item-avatar { position: relative; - transition: transform .2s ease-out; + //transition: transform .2s ease-out; &:hover, &.active { - -webkit-transform: translate(0, -3px); - transform: translate(0, -3px); + -webkit-transform: translate(-1px, -1px); + transform: translate(-1px, -1px); filter: drop-shadow(2px 2px 0 rgba($black, 0.8)); } } @@ -68,7 +65,7 @@ .count { top: 0rem; - right: 5px; + right: 2px; font-size: 10px; } } diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx index 3ab96937..4d10456b 100644 --- a/src/views/toolbar/ToolbarView.tsx +++ b/src/views/toolbar/ToolbarView.tsx @@ -1,7 +1,7 @@ import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer'; import { FC, useCallback, useState } from 'react'; -import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop } from '../../api'; -import { AvatarEditorEvent, CatalogEvent, FriendsEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; +import { GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop, OpenMessengerChat } from '../../api'; +import { AvatarEditorEvent, CatalogEvent, FriendsEvent, FriendsMessengerIconEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events'; import { AchievementsUIEvent } from '../../events/achievements'; import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; @@ -14,6 +14,10 @@ import { AvatarImageView } from '../shared/avatar-image/AvatarImageView'; import { ToolbarMeView } from './me/ToolbarMeView'; import { ToolbarViewItems, ToolbarViewProps } from './ToolbarView.types'; +const CHAT_ICON_HIDDEN: number = 0; +const CHAT_ICON_SHOWING: number = 1; +const CHAT_ICON_UNREAD: number = 2; + export const ToolbarView: FC = props => { const { isInRoom } = props; @@ -21,6 +25,7 @@ export const ToolbarView: FC = props => const [ userInfo, setUserInfo ] = useState(null); const [ userFigure, setUserFigure ] = useState(null); const [ isMeExpanded, setMeExpanded ] = useState(false); + const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN); const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0); const unseenFriendListCount = 0; @@ -45,6 +50,13 @@ export const ToolbarView: FC = props => CreateMessageHook(FigureUpdateEvent, onUserFigureEvent); + const onFriendsMessengerIconEvent = useCallback((event: FriendsMessengerIconEvent) => + { + setChatIconType(event.iconType); + }, []); + + useUiEvent(FriendsMessengerIconEvent.UPDATE_ICON, onFriendsMessengerIconEvent); + const onUnseenItemTrackerUpdateEvent = useCallback((event: UnseenItemTrackerUpdateEvent) => { setUnseenInventoryCount(event.count); @@ -131,6 +143,9 @@ export const ToolbarView: FC = props => dispatchUiEvent(new UserSettingsUIEvent(UserSettingsUIEvent.TOGGLE_USER_SETTINGS)); setMeExpanded(false); return; + case ToolbarViewItems.FRIEND_CHAT_ITEM: + OpenMessengerChat(); + return; } }, []); @@ -148,20 +163,16 @@ export const ToolbarView: FC = props =>
-
-
-
-
setMeExpanded(!isMeExpanded) }> - -
+
+
+
setMeExpanded(!isMeExpanded) }> + + { (unseenAchievementsCount > 0) && +
{ unseenAchievementsCount }
}
- { (unseenAchievementsCount > 0) && ( -
{ unseenAchievementsCount }
) } -
-
{ isInRoom && (
- +
) } { !isInRoom && (
@@ -188,13 +199,20 @@ export const ToolbarView: FC = props =>
-
-
+
+
handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }> { (unseenFriendListCount > 0) && (
{ unseenFriendListCount }
) }
+ { ((chatIconType === CHAT_ICON_SHOWING) || (chatIconType === CHAT_ICON_UNREAD)) && +
handleToolbarItemClick(ToolbarViewItems.FRIEND_CHAT_ITEM) }> + { (chatIconType === CHAT_ICON_SHOWING) && } + { (chatIconType === CHAT_ICON_UNREAD) && } + { (unseenFriendListCount > 0) && +
{ unseenFriendListCount }
} +
}
diff --git a/src/views/toolbar/ToolbarView.types.ts b/src/views/toolbar/ToolbarView.types.ts index 0670bca7..48a376d1 100644 --- a/src/views/toolbar/ToolbarView.types.ts +++ b/src/views/toolbar/ToolbarView.types.ts @@ -9,6 +9,7 @@ export class ToolbarViewItems public static INVENTORY_ITEM: string = 'TVI_INVENTORY_ITEM'; public static CATALOG_ITEM: string = 'TVI_CATALOG_ITEM'; public static FRIEND_LIST_ITEM: string = 'TVI_FRIEND_LIST_ITEM'; + public static FRIEND_CHAT_ITEM: string = 'TVI_FRIEND_CHAT_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'; diff --git a/tsconfig.json b/tsconfig.json index df4dcf04..ac2a9fd7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,6 +24,6 @@ }, "include": [ "src", - "node_modules/@nitrots/nitro-renderer/**/*.ts", + "node_modules/@nitrots/nitro-renderer/src/**/*.ts", ] } From 34ab1e6fd381722f401f86551e2a449ad10c707f Mon Sep 17 00:00:00 2001 From: Bill Date: Wed, 22 Sep 2021 15:01:56 -0400 Subject: [PATCH 08/21] Layout updates --- src/App.scss | 15 +++ src/assets/styles/bootstrap/_variables.scss | 3 +- src/assets/styles/utils.scss | 8 ++ src/layout/card/NitroCardView.scss | 1 + .../card/content/NitroCardContentView.scss | 1 - .../card/content/NitroCardContentView.tsx | 2 +- src/layout/card/grid/NitroCardGridView.scss | 4 +- src/layout/card/grid/NitroCardGridView.tsx | 35 ++++-- .../card/grid/NitroCardGridView.types.ts | 7 -- .../grid/context/NitroCardGridContext.tsx | 13 -- .../context/NitroCardGridContext.types.ts | 11 -- src/layout/card/grid/context/index.ts | 2 - src/layout/card/grid/index.ts | 1 - .../card/grid/item/NitroCardGridItemView.scss | 112 ++++++------------ .../card/grid/item/NitroCardGridItemView.tsx | 53 ++++++--- .../grid/item/NitroCardGridItemView.types.ts | 2 - src/views/achievements/AchievementsView.scss | 8 +- src/views/avatar-editor/AvatarEditorView.scss | 39 +++++- .../figure-set/AvatarEditorFigureSetView.tsx | 3 +- .../views/model/AvatarEditorModelView.tsx | 2 +- .../AvatarEditorPaletteSetView.tsx | 3 +- .../wardrobe/AvatarEditorWardrobeView.tsx | 3 +- src/views/catalog/CatalogView.scss | 9 +- src/views/inventory/InventoryView.scss | 9 +- .../item/InventoryFurnitureItemView.tsx | 2 +- .../views/trade/InventoryTradeView.tsx | 6 +- src/views/navigator/NavigatorView.scss | 9 +- .../shared/avatar-image/AvatarImage.scss | 3 +- .../shared/avatar-image/AvatarImageView.tsx | 6 + 29 files changed, 183 insertions(+), 189 deletions(-) delete mode 100644 src/layout/card/grid/context/NitroCardGridContext.tsx delete mode 100644 src/layout/card/grid/context/NitroCardGridContext.types.ts delete mode 100644 src/layout/card/grid/context/index.ts diff --git a/src/App.scss b/src/App.scss index 8d450e5a..474a2f07 100644 --- a/src/App.scss +++ b/src/App.scss @@ -17,6 +17,21 @@ $grid-active-border-color: $white; $toolbar-height: 55px; +$achievement-width: 650px; +$achievement-height: 400px; + +$avatar-editor-width: 620px; +$avatar-editor-height: 374px; + +$catalog-width: 620px; +$catalog-height: 400px; + +$inventory-width: 485px; +$inventory-height: 315px; + +$navigator-width: 400px; +$navigator-height: 420px; + .nitro-app { width: 100%; height: 100%; diff --git a/src/assets/styles/bootstrap/_variables.scss b/src/assets/styles/bootstrap/_variables.scss index 57aa9b7d..feb71255 100644 --- a/src/assets/styles/bootstrap/_variables.scss +++ b/src/assets/styles/bootstrap/_variables.scss @@ -85,6 +85,7 @@ $ghost: #c8cad0 !default; $gray-chateau: #a3a7b1 !default; $gable-green: #1C323F !default; $william: #3d5f6e !default; +$bluewood: #304059 !default; $success: $green !default; $info: $cyan !default; $warning: $yellow !default; @@ -385,7 +386,7 @@ $enable-transitions: true !default; $enable-reduced-motion: true !default; $enable-smooth-scroll: true !default; $enable-grid-classes: true !default; -$enable-cssgrid: false !default; +$enable-cssgrid: true !default; $enable-button-pointers: true !default; $enable-rfs: true !default; $enable-validation-icons: true !default; diff --git a/src/assets/styles/utils.scss b/src/assets/styles/utils.scss index 0050c41b..cc44e17f 100644 --- a/src/assets/styles/utils.scss +++ b/src/assets/styles/utils.scss @@ -10,6 +10,14 @@ transform: scale(1) translateZ(0); } +.scale-1-25 { + transform: scale(1.25) translateZ(0); +} + +.scale-1-50 { + transform: scale(1.50) translateZ(0); +} + .scale-2 { transform: scale(2) translateZ(0); } diff --git a/src/layout/card/NitroCardView.scss b/src/layout/card/NitroCardView.scss index cd7bfebf..84390259 100644 --- a/src/layout/card/NitroCardView.scss +++ b/src/layout/card/NitroCardView.scss @@ -3,6 +3,7 @@ $nitro-card-tabs-height: 33px; .nitro-card { pointer-events: all; + resize: both; @import './accordion/NitroCardAccordionView'; @import './content/NitroCardContentView'; diff --git a/src/layout/card/content/NitroCardContentView.scss b/src/layout/card/content/NitroCardContentView.scss index 4cbe6ee3..c56cad8c 100644 --- a/src/layout/card/content/NitroCardContentView.scss +++ b/src/layout/card/content/NitroCardContentView.scss @@ -10,6 +10,5 @@ height: 100% !important; min-height: auto !important; max-height: 100% !important; - resize: none !important; } } diff --git a/src/layout/card/content/NitroCardContentView.tsx b/src/layout/card/content/NitroCardContentView.tsx index 969069b2..ee3c1a72 100644 --- a/src/layout/card/content/NitroCardContentView.tsx +++ b/src/layout/card/content/NitroCardContentView.tsx @@ -8,7 +8,7 @@ export const NitroCardContentView: FC = props => const { simple = false } = useNitroCardContext(); return ( -
+
{ children }
); diff --git a/src/layout/card/grid/NitroCardGridView.scss b/src/layout/card/grid/NitroCardGridView.scss index f5794406..71acb2ee 100644 --- a/src/layout/card/grid/NitroCardGridView.scss +++ b/src/layout/card/grid/NitroCardGridView.scss @@ -66,6 +66,6 @@ } } } - - @import './item/NitroCardGridItemView.scss'; } + +@import './item/NitroCardGridItemView.scss'; diff --git a/src/layout/card/grid/NitroCardGridView.tsx b/src/layout/card/grid/NitroCardGridView.tsx index a9a85c64..033927a4 100644 --- a/src/layout/card/grid/NitroCardGridView.tsx +++ b/src/layout/card/grid/NitroCardGridView.tsx @@ -1,18 +1,31 @@ -import { FC } from 'react'; -import { NitroCardGridContextProvider } from './context/NitroCardGridContext'; -import { NitroCardGridThemes, NitroCardGridViewProps } from './NitroCardGridView.types'; +import { FC, useMemo } from 'react'; +import { NitroCardGridViewProps } from './NitroCardGridView.types'; export const NitroCardGridView: FC = props => { - const { columns = 5, theme = NitroCardGridThemes.THEME_DEFAULT, className = '', children = null, ...rest } = props; + const { columns = 5, className = '', style = null, children = null, ...rest } = props; + + const getClassName = useMemo(() => + { + let newClassName = 'grid gap-2 overflow-auto'; + + if(className && className.length) newClassName += ' ' + className; + + return newClassName; + }, [ className ]); + + const getStyle = useMemo(() => + { + const newStyle = { ...style }; + + newStyle['--bs-columns'] = columns.toString(); + + return newStyle; + }, [ style, columns ]); return ( - -
-
- { children } -
-
-
+
+ { children } +
); } diff --git a/src/layout/card/grid/NitroCardGridView.types.ts b/src/layout/card/grid/NitroCardGridView.types.ts index f3cc6c80..d5dc256d 100644 --- a/src/layout/card/grid/NitroCardGridView.types.ts +++ b/src/layout/card/grid/NitroCardGridView.types.ts @@ -3,11 +3,4 @@ import { DetailsHTMLAttributes } from 'react'; export interface NitroCardGridViewProps extends DetailsHTMLAttributes { columns?: number; - theme?: string; -} - -export class NitroCardGridThemes -{ - public static THEME_DEFAULT: string = 'theme-default'; - public static THEME_SHADOWED: string = 'theme-shadowed'; } diff --git a/src/layout/card/grid/context/NitroCardGridContext.tsx b/src/layout/card/grid/context/NitroCardGridContext.tsx deleted file mode 100644 index 18661b76..00000000 --- a/src/layout/card/grid/context/NitroCardGridContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext, FC, useContext } from 'react'; -import { INitroCardGridContext, NitroCardGridContextProps } from './NitroCardGridContext.types'; - -const NitroCardGridContext = createContext({ - theme: null -}); - -export const NitroCardGridContextProvider: FC = props => -{ - return { props.children } -} - -export const useNitroCardGridContext = () => useContext(NitroCardGridContext); diff --git a/src/layout/card/grid/context/NitroCardGridContext.types.ts b/src/layout/card/grid/context/NitroCardGridContext.types.ts deleted file mode 100644 index a0f97c95..00000000 --- a/src/layout/card/grid/context/NitroCardGridContext.types.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ProviderProps } from 'react'; - -export interface INitroCardGridContext -{ - theme: string; -} - -export interface NitroCardGridContextProps extends ProviderProps -{ - -} diff --git a/src/layout/card/grid/context/index.ts b/src/layout/card/grid/context/index.ts deleted file mode 100644 index 9e3f79e8..00000000 --- a/src/layout/card/grid/context/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './NitroCardGridContext'; -export * from './NitroCardGridContext.types'; diff --git a/src/layout/card/grid/index.ts b/src/layout/card/grid/index.ts index 4b3dea50..8a191eec 100644 --- a/src/layout/card/grid/index.ts +++ b/src/layout/card/grid/index.ts @@ -1,4 +1,3 @@ -export * from './context'; export * from './item'; export * from './NitroCardGridView'; export * from './NitroCardGridView.types'; diff --git a/src/layout/card/grid/item/NitroCardGridItemView.scss b/src/layout/card/grid/item/NitroCardGridItemView.scss index b2959864..ab6ad600 100644 --- a/src/layout/card/grid/item/NitroCardGridItemView.scss +++ b/src/layout/card/grid/item/NitroCardGridItemView.scss @@ -1,86 +1,48 @@ -.grid-item-container { +.grid-item { + position: relative; + display: flex; + justify-content: center; + align-items: center; height: 50px; max-height: 50px; + width: 100%; + background-position: center; + background-repeat: no-repeat; + border-radius: $border-radius; + border-color: $grid-border-color !important; + background-color: $grid-bg-color; + border: nth(map-values($border-widths), 2) solid; - .grid-item { - display: flex; - justify-content: center; - align-items: center; - position: relative; - width: 100%; - height: 100%; - background-position: center; - background-repeat: no-repeat; - overflow: hidden; + &.active { + border-color: $grid-active-border-color !important; + background-color: $grid-active-bg-color !important; + } - &.theme-default { - border-radius: $border-radius; - border-color: $grid-border-color !important; - background-color: $grid-bg-color; - border: nth(map-values($border-widths), 2) solid; - } + &.unseen { + background-color: rgba($success, 0.4); + } - &.theme-shadowed { - border-radius: $border-radius; - background-color: $light; + .badge { + top: 2px; + right: 2px; + font-size: 8px; + } - &::after { - position: absolute; - content: ''; - top: 0; - bottom: 0; - left: 0; - right: 0; - border-radius: $border-radius; - border-bottom: 2px solid white; - border-right: 2px solid white; - box-shadow: -2px -2px rgba(0, 0, 0, .4), inset 3px 3px rgba(0, 0, 0, .2); - } + .avatar-image { + background-position-y: 10px; + } - &.active { - border: nth(map-values($border-widths), 2) solid; - border-color: $oslo-gray !important; - background-color: #F5F5F5; + .trade-button { + position: absolute; + bottom: 2px; + right: 2px; + font-size: 5px; + padding: 3px; + min-height: unset; - &:after { - content: unset; - } - } - } - - &.active { - border-color: $grid-active-border-color !important; - background-color: $grid-active-bg-color !important; - } - - &.unseen { - background-color: rgba($success, 0.4); - } - - .badge { - top: 2px; - right: 2px; - font-size: 8px; - } - - .avatar-image { - background-position: center; - background-repeat: no-repeat; - background-position-y: 12px !important; - } - - .trade-button { - position: absolute; - bottom: 2px; - right: 2px; - font-size: 5px; - padding: 3px; - min-height: unset; - - &.left { - right: unset; - left: 2px; - } + &.left { + right: unset; + left: 2px; } } } diff --git a/src/layout/card/grid/item/NitroCardGridItemView.tsx b/src/layout/card/grid/item/NitroCardGridItemView.tsx index a1e4b253..3713b490 100644 --- a/src/layout/card/grid/item/NitroCardGridItemView.tsx +++ b/src/layout/card/grid/item/NitroCardGridItemView.tsx @@ -1,27 +1,48 @@ -import { FC } from 'react'; +import { FC, useMemo } from 'react'; import { LimitedEditionStyledNumberView } from '../../../../views/shared/limited-edition/styled-number/LimitedEditionStyledNumberView'; -import { useNitroCardGridContext } from '../context'; -import { NitroCardGridThemes } from '../NitroCardGridView.types'; import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types'; export const NitroCardGridItemView: FC = props => { - const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUnique = false, itemUniqueNumber = 0, itemUnseen = false, columns = undefined, className = '', style = {}, children = null, ...rest } = props; - const { theme = NitroCardGridThemes.THEME_DEFAULT } = useNitroCardGridContext(); + const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUniqueNumber = 0, itemUnseen = false, className = '', style = {}, children = null, ...rest } = props; - const imageUrl = `url(${ itemImage })`; + const getClassName = useMemo(() => + { + let newClassName = 'grid-item cursor-pointer overflow-hidden'; + + if(itemActive) newClassName += ' active'; + + if(itemUniqueNumber > 0) newClassName += ' unique-item'; + + if(itemUnseen) newClassName += ' unseen'; + + if(itemImage === null) newClassName += ' icon loading-icon'; + + if(className && className.length) newClassName += ' ' + className; + + return newClassName; + }, [ className, itemActive, itemUniqueNumber, itemUnseen, itemImage ]); + + const getStyle = useMemo(() => + { + const newStyle = { ...style }; + + if(itemImage) newStyle.backgroundImage = `url(${ itemImage })`; + + if(itemColor) newStyle.backgroundColor = itemColor; + + return newStyle; + }, [ style, itemImage, itemColor ]); return ( -
-
- { (itemCount > 1) && - { itemCount } } - { itemUnique && -
- -
} - { children } -
+
+ { (itemCount > 1) && + { itemCount } } + { (itemUniqueNumber > 0) && +
+ +
} + { children }
); } diff --git a/src/layout/card/grid/item/NitroCardGridItemView.types.ts b/src/layout/card/grid/item/NitroCardGridItemView.types.ts index bf005811..97861569 100644 --- a/src/layout/card/grid/item/NitroCardGridItemView.types.ts +++ b/src/layout/card/grid/item/NitroCardGridItemView.types.ts @@ -6,8 +6,6 @@ export interface NitroCardGridItemViewProps extends DetailsHTMLAttributes = pro }, [ model, category, setMaxPaletteCount ]); return ( - + { (category.parts.length > 0) && category.parts.map((item, index) => { return ; diff --git a/src/views/avatar-editor/views/model/AvatarEditorModelView.tsx b/src/views/avatar-editor/views/model/AvatarEditorModelView.tsx index 68e1645b..7bce299c 100644 --- a/src/views/avatar-editor/views/model/AvatarEditorModelView.tsx +++ b/src/views/avatar-editor/views/model/AvatarEditorModelView.tsx @@ -71,7 +71,7 @@ export const AvatarEditorModelView: FC = props =>
-
+
{ (maxPaletteCount >= 1) && } { (maxPaletteCount === 2) && diff --git a/src/views/avatar-editor/views/palette-set/AvatarEditorPaletteSetView.tsx b/src/views/avatar-editor/views/palette-set/AvatarEditorPaletteSetView.tsx index 65c2968f..8b32c044 100644 --- a/src/views/avatar-editor/views/palette-set/AvatarEditorPaletteSetView.tsx +++ b/src/views/avatar-editor/views/palette-set/AvatarEditorPaletteSetView.tsx @@ -1,6 +1,5 @@ import { FC, useCallback } from 'react'; import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView'; -import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types'; import { AvatarEditorGridColorItem } from '../../common/AvatarEditorGridColorItem'; import { AvatarEditorPaletteSetItem } from '../palette-set-item/AvatarEditorPaletteSetItem'; import { AvatarEditorPaletteSetViewProps } from './AvatarEditorPaletteSetView.types'; @@ -19,7 +18,7 @@ export const AvatarEditorPaletteSetView: FC = p }, [ model, category, paletteSet, paletteIndex ]); return ( - + { (paletteSet.length > 0) && paletteSet.map((item, index) => { return selectColor(item) } />; diff --git a/src/views/avatar-editor/views/wardrobe/AvatarEditorWardrobeView.tsx b/src/views/avatar-editor/views/wardrobe/AvatarEditorWardrobeView.tsx index fd0e756b..f6c4e68d 100644 --- a/src/views/avatar-editor/views/wardrobe/AvatarEditorWardrobeView.tsx +++ b/src/views/avatar-editor/views/wardrobe/AvatarEditorWardrobeView.tsx @@ -5,7 +5,6 @@ import { GetAvatarRenderManager, GetSessionDataManager } from '../../../../api'; import { SendMessageHook } from '../../../../hooks'; import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView'; import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView'; -import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types'; import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon'; import { AvatarEditorWardrobeViewProps } from './AvatarEditorWardrobeView.types'; @@ -68,7 +67,7 @@ export const AvatarEditorWardrobeView: FC = props return (
- + { figures }
diff --git a/src/views/catalog/CatalogView.scss b/src/views/catalog/CatalogView.scss index 4061767a..ec71c0ad 100644 --- a/src/views/catalog/CatalogView.scss +++ b/src/views/catalog/CatalogView.scss @@ -1,11 +1,6 @@ .nitro-catalog { - width: 620px; - - .content-area { - min-height: 350px; - height: 350px; - resize: vertical; - } + width: $catalog-width; + height: $catalog-height; font[size="16"] { font-size: 20px; diff --git a/src/views/inventory/InventoryView.scss b/src/views/inventory/InventoryView.scss index 2da93ac4..8d5953d9 100644 --- a/src/views/inventory/InventoryView.scss +++ b/src/views/inventory/InventoryView.scss @@ -1,11 +1,6 @@ .nitro-inventory { - width: 475px; - - .content-area { - min-height: 240px; - height: 240px; - resize: vertical; - } + width: $inventory-width; + height: $inventory-height; .empty-image { background: url('../../assets/images/inventory/empty.png'); diff --git a/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx index 4b49d6a3..a75cf789 100644 --- a/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx +++ b/src/views/inventory/views/furniture/item/InventoryFurnitureItemView.tsx @@ -46,5 +46,5 @@ export const InventoryFurnitureItemView: FC = p const count = groupItem.getUnlockedCount(); - return ; + return ; } diff --git a/src/views/inventory/views/trade/InventoryTradeView.tsx b/src/views/inventory/views/trade/InventoryTradeView.tsx index 5969daec..c5f9b47d 100644 --- a/src/views/inventory/views/trade/InventoryTradeView.tsx +++ b/src/views/inventory/views/trade/InventoryTradeView.tsx @@ -233,7 +233,7 @@ export const InventoryTradeView: FC = props => const count = item.getUnlockedCount(); return ( - (count && setGroupItem(item)) }> + (count && setGroupItem(item)) }> { ((count > 0) && (groupItem === item)) && } + +
{ petBreedName }
+ + }
- { (petIndex === -1) && -
-
- -
-
{ GetCatalogPageText(pageParser, 0) }
-
} - { (petIndex >= 0) && -
- - { (petIndex > -1 && petIndex <= 7) && - } - -
{ petBreedName }
- -
}
); } diff --git a/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx b/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx index 9f1ebb31..c7b02518 100644 --- a/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx +++ b/src/views/catalog/views/page/layout/pets/purchase/CatalogLayoutPetPurchaseView.tsx @@ -6,6 +6,7 @@ import { useUiEvent } from '../../../../../../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../../../../../../hooks/messages/message-event'; import { CurrencyIcon } from '../../../../../../shared/currency-icon/CurrencyIcon'; import { CatalogPurchaseButtonView } from '../../../purchase/purchase-button/CatalogPurchaseButtonView'; +import { CatalogPurchaseGiftButtonView } from '../../../purchase/purchase-gift-button/CatalogPurchaseGiftButtonView'; import { CatalogPetNameApprovalView } from '../name-approval/CatalogPetNameApprovalView'; import { CatalogLayoutPetPurchaseViewProps } from './CatalogLayoutPetPurchaseView.types'; @@ -59,6 +60,8 @@ export const CatalogLayoutPetPurchaseView: FC
+ { offer.giftable && + }
diff --git a/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.scss b/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.scss deleted file mode 100644 index 1b85077d..00000000 --- a/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.scss +++ /dev/null @@ -1,2 +0,0 @@ -.nitro-catalog-layout-pets2 { -} diff --git a/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.tsx b/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.tsx index 3e901711..06dd970c 100644 --- a/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.tsx +++ b/src/views/catalog/views/page/layout/pets2/CatalogLayoutPets2View.tsx @@ -1,23 +1,8 @@ import { FC } from 'react'; -import { GetCatalogPageImage, GetCatalogPageText } from '../../../../common/CatalogUtilities'; +import { CatalogLayoutPets3View } from '../pets3/CatalogLayoutPets3View'; import { CatalogLayoutPets2ViewProps } from './CatalogLayoutPets2View.types'; export const CatalogLayoutPets2View: FC = props => { - const { pageParser = null } = props; - - return ( -
-
-
-
- -
-
{ GetCatalogPageText(pageParser, 1) }
-
-
- {GetCatalogPageText(pageParser, 3) &&
} -
-
- ); + return } diff --git a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss deleted file mode 100644 index 2f2bc31c..00000000 --- a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.scss +++ /dev/null @@ -1,2 +0,0 @@ -.nitro-catalog-layout-pets3 { -} diff --git a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx index 23fa4048..94ab0a81 100644 --- a/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx +++ b/src/views/catalog/views/page/layout/pets3/CatalogLayoutPets3View.tsx @@ -5,18 +5,24 @@ import { CatalogLayoutPets3ViewProps } from './CatalogLayoutPets3View.types'; export const CatalogLayoutPets3View: FC = props => { const { pageParser = null } = props; + + const imageUrl = GetCatalogPageImage(pageParser, 1); return ( -
-
-
-
- +
+
+
+
+ { imageUrl && } +
+
+
+
+
+
+
-
{ GetCatalogPageText(pageParser, 1) }
-
- {GetCatalogPageText(pageParser, 3) &&
}
); diff --git a/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.scss b/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.scss deleted file mode 100644 index 664041a9..00000000 --- a/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.scss +++ /dev/null @@ -1,6 +0,0 @@ -.nitro-catalog-layout-single-bundle { - - .single-bundle-items-container { - - } -} diff --git a/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.tsx b/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.tsx index c85baeae..bab6711f 100644 --- a/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.tsx +++ b/src/views/catalog/views/page/layout/single-bundle/CatalogLayoutSingleBundleView.tsx @@ -1,6 +1,7 @@ import { FC } from 'react'; -import { GetCatalogPageImage, GetCatalogPageText } from '../../../../common/CatalogUtilities'; +import { NitroCardGridView } from '../../../../../../layout'; import { useCatalogContext } from '../../../../context/CatalogContext'; +import { CatalogPageDetailsView } from '../../../page-details/CatalogPageDetailsView'; import { CatalogProductView } from '../../product/CatalogProductView'; import { CatalogPurchaseView } from '../../purchase/CatalogPurchaseView'; import { CatalogLayoutSingleBundleViewProps } from './CatalogLayoutSingleBundleView.types'; @@ -12,20 +13,17 @@ export const CatalogLayoutSingleBundleView: FC -
-
+
+
+ { activeOffer && activeOffer.products && (activeOffer.products.length > 0) && activeOffer.products.map((product, index) => { return }) } -
+
-
-
- -
-
{ GetCatalogPageText(pageParser, 0) }
+
+ { activeOffer && }
diff --git a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.scss b/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.scss deleted file mode 100644 index ce1e1c03..00000000 --- a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.scss +++ /dev/null @@ -1,3 +0,0 @@ -.nitro-catalog-layout-spaces { - -} diff --git a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx b/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx index c2c15a26..65da4622 100644 --- a/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx +++ b/src/views/catalog/views/page/layout/spaces-new/CatalogLayoutSpacesView.tsx @@ -1,12 +1,10 @@ import { CatalogPageMessageOfferData, IFurnitureData } from '@nitrots/nitro-renderer'; import { FC, useEffect, useState } from 'react'; import { GetSessionDataManager, LocalizeText } from '../../../../../../api'; -import { GetCatalogPageImage, GetCatalogPageText, GetOfferName } from '../../../../common/CatalogUtilities'; import { ProductTypeEnum } from '../../../../common/ProductTypeEnum'; import { useCatalogContext } from '../../../../context/CatalogContext'; -import { CatalogRoomPreviewerView } from '../../../catalog-room-previewer/CatalogRoomPreviewerView'; import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; -import { CatalogPurchaseView } from '../../purchase/CatalogPurchaseView'; +import { CatalogProductPreviewView } from '../../product-preview/CatalogProductPreviewView'; import { CatalogLayoutSpacesViewProps } from './CatalogLayoutSpacesView.types'; export const CatalogLayoutSpacesView: FC = props => @@ -68,9 +66,9 @@ export const CatalogLayoutSpacesView: FC = props = const product = ((activeOffer && activeOffer.products[0]) || null); return ( -
-
-
+
+
+
{ groupNames.map((name, index) => { return @@ -78,19 +76,9 @@ export const CatalogLayoutSpacesView: FC = props =
- { !product && -
-
- -
-
{ GetCatalogPageText(pageParser, 0) }
-
} - { product && -
- -
{ GetOfferName(activeOffer) }
- -
} +
+ +
); } diff --git a/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.scss b/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.scss deleted file mode 100644 index 58637ed9..00000000 --- a/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.scss +++ /dev/null @@ -1,8 +0,0 @@ -.nitro-catalog-layout-trophies { - - textarea { - height: 119px; - resize: none; - } - -} diff --git a/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.tsx b/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.tsx index 471001a1..03379cf0 100644 --- a/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.tsx +++ b/src/views/catalog/views/page/layout/trophies/CatalogLayoutTrophiesView.tsx @@ -1,9 +1,7 @@ import { FC, useState } from 'react'; -import { GetOfferName } from '../../../../common/CatalogUtilities'; import { useCatalogContext } from '../../../../context/CatalogContext'; -import { CatalogRoomPreviewerView } from '../../../catalog-room-previewer/CatalogRoomPreviewerView'; import { CatalogPageOffersView } from '../../offers/CatalogPageOffersView'; -import { CatalogPurchaseView } from '../../purchase/CatalogPurchaseView'; +import { CatalogProductPreviewView } from '../../product-preview/CatalogProductPreviewView'; import { CatalogLayoutTrophiesViewProps } from './CatalogLayoutTrophiesView.types'; export const CatalogLayoutTrophiesView: FC = props => @@ -16,19 +14,14 @@ export const CatalogLayoutTrophiesView: FC = pro const product = ((activeOffer && activeOffer.products[0]) || null); return ( -
-
+
+
-
- -
+