mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-23 22:40:50 +01:00
Merge branch 'dev' into feature/room-quiz
This commit is contained in:
commit
a9690e88fa
14
src/App.scss
14
src/App.scss
@ -10,9 +10,9 @@ $infostand-zindex: 30;
|
|||||||
$chat-zindex: 20;
|
$chat-zindex: 20;
|
||||||
$highscore-zindex: 19;
|
$highscore-zindex: 19;
|
||||||
|
|
||||||
$grid-bg-color: #CDD3D9;
|
$grid-bg-color: #cdd3d9;
|
||||||
$grid-border-color: $muted;
|
$grid-border-color: $muted;
|
||||||
$grid-active-bg-color: #ECECEC;
|
$grid-active-bg-color: #ececec;
|
||||||
$grid-active-border-color: $white;
|
$grid-active-border-color: $white;
|
||||||
|
|
||||||
$toolbar-height: 55px;
|
$toolbar-height: 55px;
|
||||||
@ -44,10 +44,16 @@ $nitro-widget-custom-stack-height-height: 220px;
|
|||||||
$nitro-widget-exchange-credit-width: 375px;
|
$nitro-widget-exchange-credit-width: 375px;
|
||||||
$nitro-widget-exchange-credit-height: 150px;
|
$nitro-widget-exchange-credit-height: 150px;
|
||||||
|
|
||||||
|
$chat-history-width: 300px;
|
||||||
|
$chat-history-height: 300px;
|
||||||
|
|
||||||
|
$friends-list-width: 250px;
|
||||||
|
$friends-list-height: 300px;
|
||||||
|
|
||||||
.nitro-app {
|
.nitro-app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './layout/Layout';
|
@import "./layout/Layout";
|
||||||
@import './views/Styles';
|
@import "./views/Styles";
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
|
||||||
|
|
||||||
|
export class RoomWidgetUpdateFriendRequestEvent extends RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
public static SHOW_FRIEND_REQUEST: string = 'RWFRUE_SHOW_FRIEND_REQUEST';
|
||||||
|
public static HIDE_FRIEND_REQUEST: string = 'RWFRUE_HIDE_FRIEND_REQUEST';
|
||||||
|
|
||||||
|
private _requestId: number;
|
||||||
|
private _userId: number;
|
||||||
|
private _userName: string;
|
||||||
|
|
||||||
|
constructor(type: string, requestId: number = -1, userId: number = -1, userName: string = null)
|
||||||
|
{
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this._requestId = requestId;
|
||||||
|
this._userId = userId;
|
||||||
|
this._userName = userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get requestId(): number
|
||||||
|
{
|
||||||
|
return this._requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get userId(): number
|
||||||
|
{
|
||||||
|
return this._userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get userName(): string
|
||||||
|
{
|
||||||
|
return this._userName;
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ export * from './RoomWidgetUpdateDimmerEvent';
|
|||||||
export * from './RoomWidgetUpdateDimmerStateEvent';
|
export * from './RoomWidgetUpdateDimmerStateEvent';
|
||||||
export * from './RoomWidgetUpdateEvent';
|
export * from './RoomWidgetUpdateEvent';
|
||||||
export * from './RoomWidgetUpdateExternalImageEvent';
|
export * from './RoomWidgetUpdateExternalImageEvent';
|
||||||
|
export * from './RoomWidgetUpdateFriendRequestEvent';
|
||||||
export * from './RoomWidgetUpdateInfostandEvent';
|
export * from './RoomWidgetUpdateInfostandEvent';
|
||||||
export * from './RoomWidgetUpdateInfostandFurniEvent';
|
export * from './RoomWidgetUpdateInfostandFurniEvent';
|
||||||
export * from './RoomWidgetUpdateInfostandPetEvent';
|
export * from './RoomWidgetUpdateInfostandPetEvent';
|
||||||
@ -31,5 +32,6 @@ export * from './RoomWidgetUpdateRoomViewEvent';
|
|||||||
export * from './RoomWidgetUpdateSongEvent';
|
export * from './RoomWidgetUpdateSongEvent';
|
||||||
export * from './RoomWidgetUpdateTrophyEvent';
|
export * from './RoomWidgetUpdateTrophyEvent';
|
||||||
export * from './RoomWidgetUpdateUserDataEvent';
|
export * from './RoomWidgetUpdateUserDataEvent';
|
||||||
|
export * from './RoomWidgetUpdateYoutubeDisplayEvent';
|
||||||
export * from './RoomWidgetUseProductBubbleEvent';
|
export * from './RoomWidgetUseProductBubbleEvent';
|
||||||
export * from './UseProductItem';
|
export * from './UseProductItem';
|
||||||
|
65
src/api/nitro/room/widgets/handlers/FriendRequestHandler.ts
Normal file
65
src/api/nitro/room/widgets/handlers/FriendRequestHandler.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { NitroEvent, RoomSessionFriendRequestEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
||||||
|
import { FriendRequestEvent, FriendsAcceptFriendRequestEvent, FriendsDeclineFriendRequestEvent } from '../../../../../events';
|
||||||
|
import { dispatchUiEvent } from '../../../../../hooks';
|
||||||
|
import { RoomWidgetUpdateEvent, RoomWidgetUpdateFriendRequestEvent } from '../events';
|
||||||
|
import { RoomWidgetFriendRequestMessage, RoomWidgetMessage } from '../messages';
|
||||||
|
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
||||||
|
|
||||||
|
export class FriendRequestHandler extends RoomWidgetHandler
|
||||||
|
{
|
||||||
|
public processEvent(event: NitroEvent): void
|
||||||
|
{
|
||||||
|
const friendRequestEvent = (event as RoomSessionFriendRequestEvent);
|
||||||
|
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case RoomSessionFriendRequestEvent.RSFRE_FRIEND_REQUEST:
|
||||||
|
this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateFriendRequestEvent(RoomWidgetUpdateFriendRequestEvent.SHOW_FRIEND_REQUEST, friendRequestEvent.requestId, friendRequestEvent.userId, friendRequestEvent.userName));
|
||||||
|
return;
|
||||||
|
case FriendRequestEvent.ACCEPTED:
|
||||||
|
case FriendRequestEvent.DECLINED:
|
||||||
|
this.container.eventDispatcher.dispatchEvent(new RoomWidgetUpdateFriendRequestEvent(RoomWidgetUpdateFriendRequestEvent.HIDE_FRIEND_REQUEST, friendRequestEvent.requestId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
const friendMessage = (message as RoomWidgetFriendRequestMessage);
|
||||||
|
|
||||||
|
switch(message.type)
|
||||||
|
{
|
||||||
|
case RoomWidgetFriendRequestMessage.ACCEPT:
|
||||||
|
dispatchUiEvent(new FriendsAcceptFriendRequestEvent(friendMessage.requestId));
|
||||||
|
break;
|
||||||
|
case RoomWidgetFriendRequestMessage.DECLINE:
|
||||||
|
dispatchUiEvent(new FriendsDeclineFriendRequestEvent(friendMessage.requestId));
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return RoomWidgetEnum.FRIEND_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get eventTypes(): string[]
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
RoomSessionFriendRequestEvent.RSFRE_FRIEND_REQUEST,
|
||||||
|
FriendRequestEvent.ACCEPTED,
|
||||||
|
FriendRequestEvent.DECLINED
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get messageTypes(): string[]
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
RoomWidgetFriendRequestMessage.ACCEPT,
|
||||||
|
RoomWidgetFriendRequestMessage.DECLINE
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
import { NitroEvent, RoomObjectVariable, RoomWidgetEnum } from '@nitrots/nitro-renderer';
|
||||||
|
import { RoomWidgetUpdateEvent } from '..';
|
||||||
|
import { GetRoomEngine } from '../..';
|
||||||
|
import { RoomWidgetFurniToWidgetMessage, RoomWidgetMessage } from '../messages';
|
||||||
|
import { RoomWidgetHandler } from './RoomWidgetHandler';
|
||||||
|
|
||||||
|
export class FurnitureTrophyWidgetHandler extends RoomWidgetHandler
|
||||||
|
{
|
||||||
|
public processEvent(event: NitroEvent): void
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent
|
||||||
|
{
|
||||||
|
switch(message.type)
|
||||||
|
{
|
||||||
|
case RoomWidgetFurniToWidgetMessage.REQUEST_TROPHY: {
|
||||||
|
const widgetMessage = (message as RoomWidgetFurniToWidgetMessage);
|
||||||
|
const roomObject = GetRoomEngine().getRoomObject(widgetMessage.roomId, widgetMessage.objectId, widgetMessage.category);
|
||||||
|
|
||||||
|
if(!roomObject) return;
|
||||||
|
|
||||||
|
const color = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_COLOR);
|
||||||
|
const extra = parseInt(roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_EXTRAS));
|
||||||
|
|
||||||
|
let data = roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_DATA);
|
||||||
|
|
||||||
|
const ownerName = data.substring(0, data.indexOf('\t'));
|
||||||
|
|
||||||
|
data = data.substring((ownerName.length + 1), data.length);
|
||||||
|
|
||||||
|
const date = data.substring(0, data.indexOf('\t'));
|
||||||
|
const text = data.substr((date.length + 1), data.length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get type(): string
|
||||||
|
{
|
||||||
|
return RoomWidgetEnum.FURNI_TROPHY_WIDGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get eventTypes(): string[]
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get messageTypes(): string[]
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
RoomWidgetFurniToWidgetMessage.REQUEST_TROPHY
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import { FriendsSendFriendRequestEvent } from '../../../../../events/friends/Fri
|
|||||||
import { HelpReportUserEvent } from '../../../../../events/help/HelpReportUserEvent';
|
import { HelpReportUserEvent } from '../../../../../events/help/HelpReportUserEvent';
|
||||||
import { dispatchUiEvent } from '../../../../../hooks/events';
|
import { dispatchUiEvent } from '../../../../../hooks/events';
|
||||||
import { SendMessageHook } from '../../../../../hooks/messages';
|
import { SendMessageHook } from '../../../../../hooks/messages';
|
||||||
|
import { FriendsHelper } from '../../../../../views/friends/common/FriendsHelper';
|
||||||
import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum';
|
import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum';
|
||||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||||
import { RoomWidgetObjectNameEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent } from '../events';
|
import { RoomWidgetObjectNameEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent } from '../events';
|
||||||
@ -77,7 +78,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
|
|||||||
case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO:
|
case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO:
|
||||||
return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage));
|
return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage));
|
||||||
case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST:
|
case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST:
|
||||||
dispatchUiEvent(new FriendsSendFriendRequestEvent(userId));
|
dispatchUiEvent(new FriendsSendFriendRequestEvent(userData.webID, userData.name));
|
||||||
break;
|
break;
|
||||||
case RoomWidgetUserActionMessage.RESPECT_USER:
|
case RoomWidgetUserActionMessage.RESPECT_USER:
|
||||||
GetSessionDataManager().giveRespect(userId);
|
GetSessionDataManager().giveRespect(userId);
|
||||||
@ -461,15 +462,18 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
|
|||||||
|
|
||||||
if(eventType === RoomWidgetUpdateInfostandUserEvent.PEER)
|
if(eventType === RoomWidgetUpdateInfostandUserEvent.PEER)
|
||||||
{
|
{
|
||||||
// userInfoData.canBeAskedAsFriend = this._container.friendService.canBeAskedForAFriend(userData.webID);
|
event.canBeAskedAsFriend = FriendsHelper.canRequestFriend(userData.webID);
|
||||||
|
|
||||||
// const friend = this._container.friendService.getFriend(userData.webID);
|
if(!event.canBeAskedAsFriend)
|
||||||
|
{
|
||||||
|
const friend = FriendsHelper.getFriend(userData.webID);
|
||||||
|
|
||||||
// if(friend)
|
if(friend)
|
||||||
// {
|
{
|
||||||
// userInfoData.realName = friend.realName;
|
event.realName = friend.realName;
|
||||||
// userInfoData.isFriend = true;
|
event.isFriend = true;
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(roomObject)
|
if(roomObject)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export * from './DoorbellWidgetHandler';
|
export * from './DoorbellWidgetHandler';
|
||||||
|
export * from './FriendRequestHandler';
|
||||||
export * from './FurniChooserWidgetHandler';
|
export * from './FurniChooserWidgetHandler';
|
||||||
export * from './FurnitureContextMenuWidgetHandler';
|
export * from './FurnitureContextMenuWidgetHandler';
|
||||||
export * from './FurnitureCreditWidgetHandler';
|
export * from './FurnitureCreditWidgetHandler';
|
||||||
@ -7,6 +8,8 @@ export * from './FurnitureDimmerWidgetHandler';
|
|||||||
export * from './FurnitureExternalImageWidgetHandler';
|
export * from './FurnitureExternalImageWidgetHandler';
|
||||||
export * from './FurnitureMannequinWidgetHandler';
|
export * from './FurnitureMannequinWidgetHandler';
|
||||||
export * from './FurniturePresentWidgetHandler';
|
export * from './FurniturePresentWidgetHandler';
|
||||||
|
export * from './FurnitureTrophyWidgetHandler';
|
||||||
|
export * from './FurnitureYoutubeDisplayWidgetHandler';
|
||||||
export * from './IRoomWidgetHandler';
|
export * from './IRoomWidgetHandler';
|
||||||
export * from './IRoomWidgetHandlerManager';
|
export * from './IRoomWidgetHandlerManager';
|
||||||
export * from './RoomWidgetAvatarInfoHandler';
|
export * from './RoomWidgetAvatarInfoHandler';
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import { RoomWidgetMessage } from './RoomWidgetMessage';
|
||||||
|
|
||||||
|
export class RoomWidgetFriendRequestMessage extends RoomWidgetMessage
|
||||||
|
{
|
||||||
|
public static ACCEPT: string = 'RWFRM_ACCEPT';
|
||||||
|
public static DECLINE: string = 'RMFRM_DECLINE';
|
||||||
|
|
||||||
|
private _requestId: number;
|
||||||
|
|
||||||
|
constructor(type: string, requestId: number)
|
||||||
|
{
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this._requestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get requestId(): number
|
||||||
|
{
|
||||||
|
return this._requestId;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ export * from './RoomWidgetDanceMessage';
|
|||||||
export * from './RoomWidgetDimmerChangeStateMessage';
|
export * from './RoomWidgetDimmerChangeStateMessage';
|
||||||
export * from './RoomWidgetDimmerPreviewMessage';
|
export * from './RoomWidgetDimmerPreviewMessage';
|
||||||
export * from './RoomWidgetDimmerSavePresetMessage';
|
export * from './RoomWidgetDimmerSavePresetMessage';
|
||||||
|
export * from './RoomWidgetFriendRequestMessage';
|
||||||
export * from './RoomWidgetFurniActionMessage';
|
export * from './RoomWidgetFurniActionMessage';
|
||||||
export * from './RoomWidgetFurniToWidgetMessage';
|
export * from './RoomWidgetFurniToWidgetMessage';
|
||||||
export * from './RoomWidgetLetUserInMessage';
|
export * from './RoomWidgetLetUserInMessage';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
import { MessengerFriend } from '../../views/friends/common/MessengerFriend';
|
import { MessengerFriend } from '../../views/friends/common/MessengerFriend';
|
||||||
import { FriendsEvent } from './FriendsEvent';
|
|
||||||
|
|
||||||
export class FriendListContentEvent extends FriendsEvent
|
export class FriendListContentEvent extends NitroEvent
|
||||||
{
|
{
|
||||||
public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT';
|
public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT';
|
||||||
|
|
||||||
|
21
src/events/friends/FriendRequestEvent.ts
Normal file
21
src/events/friends/FriendRequestEvent.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export class FriendRequestEvent extends NitroEvent
|
||||||
|
{
|
||||||
|
public static ACCEPTED: string = 'FRE_ACCEPTED';
|
||||||
|
public static DECLINED: string = 'FRE_DECLINED';
|
||||||
|
|
||||||
|
private _requestId: number;
|
||||||
|
|
||||||
|
constructor(type: string, requestId: number)
|
||||||
|
{
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this._requestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get requestId(): number
|
||||||
|
{
|
||||||
|
return this._requestId;
|
||||||
|
}
|
||||||
|
}
|
20
src/events/friends/FriendsAcceptFriendRequestEvent.ts
Normal file
20
src/events/friends/FriendsAcceptFriendRequestEvent.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export class FriendsAcceptFriendRequestEvent extends NitroEvent
|
||||||
|
{
|
||||||
|
public static ACCEPT_FRIEND_REQUEST: string = 'FAFRE_ACCEPT_FRIEND_REQUEST';
|
||||||
|
|
||||||
|
private _requestId: number;
|
||||||
|
|
||||||
|
constructor(requestId: number)
|
||||||
|
{
|
||||||
|
super(FriendsAcceptFriendRequestEvent.ACCEPT_FRIEND_REQUEST);
|
||||||
|
|
||||||
|
this._requestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get requestId(): number
|
||||||
|
{
|
||||||
|
return this._requestId;
|
||||||
|
}
|
||||||
|
}
|
20
src/events/friends/FriendsDeclineFriendRequestEvent.ts
Normal file
20
src/events/friends/FriendsDeclineFriendRequestEvent.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export class FriendsDeclineFriendRequestEvent extends NitroEvent
|
||||||
|
{
|
||||||
|
public static DECLINE_FRIEND_REQUEST: string = 'FAFRE_DECLINE_FRIEND_REQUEST';
|
||||||
|
|
||||||
|
private _requestId: number;
|
||||||
|
|
||||||
|
constructor(requestId: number)
|
||||||
|
{
|
||||||
|
super(FriendsDeclineFriendRequestEvent.DECLINE_FRIEND_REQUEST);
|
||||||
|
|
||||||
|
this._requestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get requestId(): number
|
||||||
|
{
|
||||||
|
return this._requestId;
|
||||||
|
}
|
||||||
|
}
|
20
src/events/friends/FriendsRequestCountEvent.ts
Normal file
20
src/events/friends/FriendsRequestCountEvent.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
|
export class FriendsRequestCountEvent extends NitroEvent
|
||||||
|
{
|
||||||
|
public static UPDATE_COUNT: string = 'FRCE_UPDATE_COUNT';
|
||||||
|
|
||||||
|
private _count: number;
|
||||||
|
|
||||||
|
constructor(count: number)
|
||||||
|
{
|
||||||
|
super(FriendsRequestCountEvent.UPDATE_COUNT);
|
||||||
|
|
||||||
|
this._count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get count(): number
|
||||||
|
{
|
||||||
|
return this._count;
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,27 @@
|
|||||||
import { FriendsEvent } from './FriendsEvent';
|
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||||
|
|
||||||
export class FriendsSendFriendRequestEvent extends FriendsEvent
|
export class FriendsSendFriendRequestEvent extends NitroEvent
|
||||||
{
|
{
|
||||||
public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST';
|
public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST';
|
||||||
|
|
||||||
private _userId: number;
|
private _userId: number;
|
||||||
|
private _userName: string;
|
||||||
|
|
||||||
constructor(userId: number)
|
constructor(userId: number, userName: string)
|
||||||
{
|
{
|
||||||
super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST);
|
super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST);
|
||||||
|
|
||||||
this._userId = userId;
|
this._userId = userId;
|
||||||
|
this._userName = userName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get userId(): number
|
public get userId(): number
|
||||||
{
|
{
|
||||||
return this._userId;
|
return this._userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get userName(): string
|
||||||
|
{
|
||||||
|
return this._userName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
export * from './FriendEnteredRoomEvent';
|
export * from './FriendEnteredRoomEvent';
|
||||||
export * from './FriendListContentEvent';
|
export * from './FriendListContentEvent';
|
||||||
|
export * from './FriendRequestEvent';
|
||||||
|
export * from './FriendsAcceptFriendRequestEvent';
|
||||||
|
export * from './FriendsDeclineFriendRequestEvent';
|
||||||
export * from './FriendsEvent';
|
export * from './FriendsEvent';
|
||||||
export * from './FriendsMessengerIconEvent';
|
export * from './FriendsMessengerIconEvent';
|
||||||
|
export * from './FriendsRequestCountEvent';
|
||||||
export * from './FriendsSendFriendRequestEvent';
|
export * from './FriendsSendFriendRequestEvent';
|
||||||
|
@ -5,15 +5,26 @@ $nitro-card-tabs-height: 33px;
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
resize: both;
|
resize: both;
|
||||||
|
|
||||||
&.theme-dark {
|
|
||||||
padding: 2px;
|
|
||||||
background-color: #1C323F;
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.5);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.theme-primary {
|
&.theme-primary {
|
||||||
border: $border-width solid $border-color;
|
border: $border-width solid $border-color;
|
||||||
|
|
||||||
|
.nitro-card-header-container {
|
||||||
|
background-color: $primary;
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
.header-text {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
background-color: $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
background-color: $light;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +38,6 @@ $nitro-card-tabs-height: 33px;
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@include media-breakpoint-down(lg) {
|
@include media-breakpoint-down(lg) {
|
||||||
|
|
||||||
.draggable-window {
|
.draggable-window {
|
||||||
top: 0 !important;
|
top: 0 !important;
|
||||||
left: 0 !important;
|
left: 0 !important;
|
||||||
@ -41,15 +51,10 @@ $nitro-card-tabs-height: 33px;
|
|||||||
max-width: 75%;
|
max-width: 75%;
|
||||||
max-height: calc(100% - 20px);
|
max-height: calc(100% - 20px);
|
||||||
margin: 10px auto 10px;
|
margin: 10px auto 10px;
|
||||||
|
|
||||||
// &.rounded {
|
|
||||||
// border-radius: 0 !important;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-down(sm) {
|
@include media-breakpoint-down(sm) {
|
||||||
|
|
||||||
.draggable-window {
|
.draggable-window {
|
||||||
top: 0 !important;
|
top: 0 !important;
|
||||||
left: 0 !important;
|
left: 0 !important;
|
||||||
@ -72,8 +77,8 @@ $nitro-card-tabs-height: 33px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './accordion/NitroCardAccordionView';
|
@import "./accordion/NitroCardAccordionView";
|
||||||
@import './content/NitroCardContentView';
|
@import "./content/NitroCardContentView";
|
||||||
@import './grid/NitroCardGridView';
|
@import "./grid/NitroCardGridView";
|
||||||
@import './header/NitroCardHeaderView';
|
@import "./header/NitroCardHeaderView";
|
||||||
@import './tabs/NitroCardTabsView';
|
@import "./tabs/NitroCardTabsView";
|
||||||
|
@ -1 +1 @@
|
|||||||
@import './item/NitroCardAccordionItemView';
|
@import "./set/NitroCardAccordionSetView";
|
||||||
|
@ -6,7 +6,7 @@ export const NitroCardAccordionView: FC<NitroCardAccordionViewProps> = props =>
|
|||||||
const { className = '' } = props;
|
const { className = '' } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ 'nitro-card-accordion bg-light text-black ' + className }>
|
<div className={ 'nitro-card-accordion text-black ' + className }>
|
||||||
{ props.children }
|
{ props.children }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from './item';
|
export * from './item';
|
||||||
export * from './NitroCardAccordionView';
|
export * from './NitroCardAccordionView';
|
||||||
export * from './NitroCardAccordionView.types';
|
export * from './NitroCardAccordionView.types';
|
||||||
|
export * from './set';
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
.nitro-card-accordion-item {
|
|
||||||
.nitro-card-accordion-item-header {
|
|
||||||
border-bottom: 1px solid rgba($black, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nitro-card-accordion-item-content {
|
|
||||||
background: rgba($white, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +1,14 @@
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { NitroLayoutBase } from '../../../base';
|
||||||
import { NitroCardAccordionItemViewProps } from './NitroCardAccordionItemView.types';
|
import { NitroCardAccordionItemViewProps } from './NitroCardAccordionItemView.types';
|
||||||
|
|
||||||
export const NitroCardAccordionItemView: FC<NitroCardAccordionItemViewProps> = props =>
|
export const NitroCardAccordionItemView: FC<NitroCardAccordionItemViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { className = '', headerClassName = '', contentClassName = '', headerText = '', defaultState = false } = props;
|
const { children = null, ...rest } = props;
|
||||||
|
|
||||||
const [ isExpanded, setIsExpanded ] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
setIsExpanded(defaultState);
|
|
||||||
}, [ defaultState ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ 'nitro-card-accordion-item ' + className + (isExpanded ? ' active' : '') }>
|
<NitroLayoutBase className="px-2 py-1 d-flex gap-1 align-items-center">
|
||||||
<div className={ 'nitro-card-accordion-item-header px-2 py-1 d-flex ' + headerClassName } onClick={ () => setIsExpanded((value) => !value) }>
|
{ children }
|
||||||
<div className="w-100">
|
</NitroLayoutBase>
|
||||||
{ headerText }
|
|
||||||
</div>
|
|
||||||
<div className="justify-self-center">
|
|
||||||
<i className={ 'fas fa-caret-' + (isExpanded ? 'up' : 'down') } />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={ 'nitro-card-accordion-item-content ' + contentClassName + (!isExpanded ? ' d-none' : '') }>
|
|
||||||
{ props.children }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
export interface NitroCardAccordionItemViewProps
|
import { NitroLayoutBaseProps } from '../../../base';
|
||||||
|
|
||||||
|
export interface NitroCardAccordionItemViewProps extends NitroLayoutBaseProps
|
||||||
{
|
{
|
||||||
className?: string;
|
|
||||||
headerClassName?: string;
|
|
||||||
contentClassName?: string;
|
|
||||||
headerText: string;
|
|
||||||
defaultState?: boolean;
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
.nitro-card-accordion-set {
|
||||||
|
.nitro-card-accordion-set-header {
|
||||||
|
border-bottom: 1px solid rgba($black, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-accordion-set-content {
|
||||||
|
background: rgba($white, 0.5);
|
||||||
|
}
|
||||||
|
}
|
43
src/layout/card/accordion/set/NitroCardAccordionSetView.tsx
Normal file
43
src/layout/card/accordion/set/NitroCardAccordionSetView.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { NitroLayoutFlex } from '../../..';
|
||||||
|
import { NitroLayoutBase } from '../../../base';
|
||||||
|
import { NitroCardAccordionSetViewProps } from './NitroCardAccordionSetView.types';
|
||||||
|
|
||||||
|
export const NitroCardAccordionSetView: FC<NitroCardAccordionSetViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { headerText = '', isExpanded = false, className = '', children = null, ...rest } = props;
|
||||||
|
const [ isOpen, setIsOpen ] = useState(false);
|
||||||
|
|
||||||
|
const getClassName = useMemo(() =>
|
||||||
|
{
|
||||||
|
let newClassName = 'nitro-card-accordion-set';
|
||||||
|
|
||||||
|
if(isOpen) newClassName += ' active';
|
||||||
|
|
||||||
|
if(className && className.length) newClassName += ` ${ className }`;
|
||||||
|
|
||||||
|
return newClassName;
|
||||||
|
}, [ className, isOpen ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsOpen(isExpanded);
|
||||||
|
}, [ isExpanded ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroLayoutBase className={ getClassName } { ...rest }>
|
||||||
|
<NitroLayoutFlex className="nitro-card-accordion-set-header px-2 py-1" onClick={ event => setIsOpen(!isOpen) }>
|
||||||
|
<div className="w-100">
|
||||||
|
{ headerText }
|
||||||
|
</div>
|
||||||
|
<div className="justify-self-center">
|
||||||
|
<i className={ 'fas fa-caret-' + (isOpen ? 'up' : 'down') } />
|
||||||
|
</div>
|
||||||
|
</NitroLayoutFlex>
|
||||||
|
<NitroLayoutBase className={ 'nitro-card-accordion-set-content ' + classNames({ 'd-none': !isOpen }) }>
|
||||||
|
{ children }
|
||||||
|
</NitroLayoutBase>
|
||||||
|
</NitroLayoutBase>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NitroLayoutBaseProps } from '../../../base';
|
||||||
|
|
||||||
|
export interface NitroCardAccordionSetViewProps extends NitroLayoutBaseProps
|
||||||
|
{
|
||||||
|
headerText: string;
|
||||||
|
isExpanded?: boolean;
|
||||||
|
}
|
2
src/layout/card/accordion/set/index.ts
Normal file
2
src/layout/card/accordion/set/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './NitroCardAccordionSetView';
|
||||||
|
export * from './NitroCardAccordionSetView.types';
|
@ -8,7 +8,7 @@ export const NitroCardContentView: FC<NitroCardContentViewProps> = props =>
|
|||||||
const { simple = false } = useNitroCardContext();
|
const { simple = false } = useNitroCardContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `container-fluid ${ theme === 'primary' ? 'bg-light' : ''} content-area d-flex flex-column overflow-auto theme-${theme} ${ (simple ? 'simple' : '') } ${ className || '' }` } { ...rest }>
|
<div className={ `container-fluid content-area d-flex flex-column overflow-auto ${ (simple ? 'simple' : '') } ${ className || '' }` } { ...rest }>
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -22,12 +22,6 @@
|
|||||||
background-color: rgba($success, 0.4);
|
background-color: rgba($success, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
|
||||||
top: 2px;
|
|
||||||
right: 2px;
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-image {
|
.avatar-image {
|
||||||
background-position-y: 10px;
|
background-position-y: 10px;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { FC, useMemo } from 'react';
|
import { FC, useMemo } from 'react';
|
||||||
|
import { ItemCountView } from '../../../../views/shared/item-count/ItemCountView';
|
||||||
import { LimitedEditionStyledNumberView } from '../../../../views/shared/limited-edition/styled-number/LimitedEditionStyledNumberView';
|
import { LimitedEditionStyledNumberView } from '../../../../views/shared/limited-edition/styled-number/LimitedEditionStyledNumberView';
|
||||||
import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types';
|
import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types';
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ export const NitroCardGridItemView: FC<NitroCardGridItemViewProps> = props =>
|
|||||||
return (
|
return (
|
||||||
<div className={ getClassName } style={ getStyle } { ...rest }>
|
<div className={ getClassName } style={ getStyle } { ...rest }>
|
||||||
{ (itemCount > itemCountMinimum) &&
|
{ (itemCount > itemCountMinimum) &&
|
||||||
<span className="position-absolute badge border bg-danger px-1 rounded-circle">{ itemCount }</span> }
|
<ItemCountView count={ itemCount } /> }
|
||||||
{ (itemUniqueNumber > 0) &&
|
{ (itemUniqueNumber > 0) &&
|
||||||
<div className="position-absolute unique-item-counter">
|
<div className="position-absolute unique-item-counter">
|
||||||
<LimitedEditionStyledNumberView value={ itemUniqueNumber } />
|
<LimitedEditionStyledNumberView value={ itemUniqueNumber } />
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
.nitro-card-header-container {
|
||||||
.nitro-card-header {
|
.nitro-card-header {
|
||||||
min-height: 33px;
|
min-height: 33px;
|
||||||
max-height: 33px;
|
max-height: 33px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
.header-text {
|
.header-text {
|
||||||
margin: 0 35px;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.simple-header {
|
&.simple-header {
|
||||||
@ -62,3 +63,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -16,10 +16,10 @@ export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
|
|||||||
if(simple)
|
if(simple)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid bg-light">
|
<div className="drag-handler container-fluid nitro-card-header-container bg-tertiary-split">
|
||||||
<div className="row nitro-card-header simple-header overflow-hidden">
|
<div className="row nitro-card-header overflow-hidden">
|
||||||
<div className="d-flex justify-content-center align-items-center w-100 position-relative px-0">
|
<div className="d-flex justify-content-center align-items-center w-100 position-relative">
|
||||||
<div className="h5 text-white text-center text-shadow bg-tertiary-split border-top-0 drag-handler">{ headerText }</div>
|
<div className="h5 text-shadow header-text">{ headerText }</div>
|
||||||
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
||||||
<i className="fas fa-times" />
|
<i className="fas fa-times" />
|
||||||
</div>
|
</div>
|
||||||
@ -30,10 +30,10 @@ export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="drag-handler container-fluid bg-primary">
|
<div className="drag-handler container-fluid nitro-card-header-container">
|
||||||
<div className={`row nitro-card-header overflow-hidden theme-${theme}`}>
|
<div className="row nitro-card-header overflow-hidden">
|
||||||
<div className="d-flex justify-content-center align-items-center w-100 position-relative">
|
<div className="d-flex justify-content-center align-items-center w-100 position-relative">
|
||||||
<div className="h4 text-white text-shadow header-text">{ headerText }</div>
|
<div className="h4 text-shadow header-text">{ headerText }</div>
|
||||||
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
|
||||||
<i className="fas fa-times" />
|
<i className="fas fa-times" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,4 @@
|
|||||||
min-height: $nitro-card-tabs-height;
|
min-height: $nitro-card-tabs-height;
|
||||||
max-height: $nitro-card-tabs-height;
|
max-height: $nitro-card-tabs-height;
|
||||||
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
|
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
|
||||||
|
|
||||||
@import './tabs-item/NitroCardTabsItemView';
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import { NitroCardTabsViewProps } from './NitroCardTabsView.types';
|
|||||||
export const NitroCardTabsView: FC<NitroCardTabsViewProps> = props =>
|
export const NitroCardTabsView: FC<NitroCardTabsViewProps> = props =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid d-flex bg-secondary pt-1 nitro-card-tabs justify-content-center">
|
<div className="container-fluid d-flex pt-1 nitro-card-tabs justify-content-center">
|
||||||
<ul className="nav nav-tabs border-0">
|
<ul className="nav nav-tabs border-0 gap-1">
|
||||||
{ props.children }
|
{ props.children }
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
.nav-item {
|
|
||||||
|
|
||||||
&:last-child() {
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.count {
|
|
||||||
color: $white;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 10px;
|
|
||||||
padding: 2px 3px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { ItemCountView } from '../../../../views/shared/item-count/ItemCountView';
|
||||||
import { NitroCardTabsItemViewProps } from './NitroCardTabsItemView.types';
|
import { NitroCardTabsItemViewProps } from './NitroCardTabsItemView.types';
|
||||||
|
|
||||||
export const NitroCardTabsItemView: FC<NitroCardTabsItemViewProps> = props =>
|
export const NitroCardTabsItemView: FC<NitroCardTabsItemViewProps> = props =>
|
||||||
@ -7,12 +8,10 @@ export const NitroCardTabsItemView: FC<NitroCardTabsItemViewProps> = props =>
|
|||||||
const { children = null, isActive = false, count = 0, onClick = null } = props;
|
const { children = null, isActive = false, count = 0, onClick = null } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="nav-item me-1 cursor-pointer" onClick={ onClick }>
|
<li className={ 'nav-link cursor-pointer position-relative' + classNames({ ' active': isActive }) } onClick={ onClick }>
|
||||||
<span className={ 'nav-link ' + classNames({ 'active': isActive }) }>
|
|
||||||
{ children }
|
{ children }
|
||||||
{ (count > 0) &&
|
{ (count > 0) &&
|
||||||
<span className="bg-danger ms-1 rounded count">{ count }</span> }
|
<ItemCountView count={ count } /> }
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ export const CatalogNavigationView: FC<CatalogNavigationViewProps> = props =>
|
|||||||
}, [ page ]);
|
}, [ page ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroLayoutFlexColumn gap={ 2 } overflow="auto">
|
<NitroLayoutFlexColumn className="h-100" gap={ 2 } overflow="auto">
|
||||||
<CatalogSearchView />
|
<CatalogSearchView />
|
||||||
<NitroLayoutFlexColumn className="nitro-catalog-navigation-grid-container p-1" overflow="hidden">
|
<NitroLayoutFlexColumn className="nitro-catalog-navigation-grid-container p-1 h-100" overflow="hidden">
|
||||||
<NitroCardGridView columns={ 1 } gap={ 1 }>
|
<NitroCardGridView columns={ 1 } gap={ 1 }>
|
||||||
<CatalogNavigationSetView page={ page } isFirstSet={ true } pendingTree={ pendingTree } setPendingTree={ setPendingTree } />
|
<CatalogNavigationSetView page={ page } isFirstSet={ true } pendingTree={ pendingTree } setPendingTree={ setPendingTree } />
|
||||||
</NitroCardGridView>
|
</NitroCardGridView>
|
||||||
|
@ -1,72 +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 { useFriendsContext } from './context/FriendsContext';
|
|
||||||
import { FriendsActions } from './reducers/FriendsReducer';
|
|
||||||
|
|
||||||
export const FriendsMessageHandler: FC<{}> = props =>
|
|
||||||
{
|
|
||||||
const { friendsState = null, dispatchFriendsState = null } = useFriendsContext();
|
|
||||||
|
|
||||||
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 ]);
|
|
||||||
|
|
||||||
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
|
|
||||||
CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent);
|
|
||||||
CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent);
|
|
||||||
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
.nitro-friends {
|
.nitro-friends {
|
||||||
width: 250px;
|
width: $friends-list-width;
|
||||||
|
height: $friends-list-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './views/friend-bar/FriendBarView';
|
@import "./views/friend-bar/FriendBarView";
|
||||||
@import './views/messenger/FriendsMessengerView';
|
@import "./views/messenger/FriendsMessengerView";
|
||||||
|
@ -1,57 +1,272 @@
|
|||||||
import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
import { AcceptFriendMessageComposer, FriendListFragmentEvent, FriendListUpdateEvent, FriendParser, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitComposer, MessengerInitEvent, NewFriendRequestEvent, RequestFriendComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
|
import { DeclineFriendMessageComposer } from '@nitrots/nitro-renderer/src';
|
||||||
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { GetRoomSession } from '../../api';
|
import { GetRoomSession } from '../../api';
|
||||||
import { FriendEnteredRoomEvent, FriendListContentEvent, FriendsEvent } from '../../events';
|
import { FriendEnteredRoomEvent, FriendListContentEvent, FriendsEvent, FriendsRequestCountEvent } from '../../events';
|
||||||
import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent';
|
import { FriendsSendFriendRequestEvent } from '../../events/friends/FriendsSendFriendRequestEvent';
|
||||||
import { useRoomEngineEvent } from '../../hooks/events';
|
import { CreateMessageHook, useRoomEngineEvent } from '../../hooks';
|
||||||
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
|
import { dispatchUiEvent, useUiEvent } from '../../hooks/events/ui/ui-event';
|
||||||
import { SendMessageHook } from '../../hooks/messages/message-event';
|
import { SendMessageHook } from '../../hooks/messages/message-event';
|
||||||
|
import { FriendsHelper } from './common/FriendsHelper';
|
||||||
|
import { MessengerFriend } from './common/MessengerFriend';
|
||||||
|
import { MessengerRequest } from './common/MessengerRequest';
|
||||||
|
import { MessengerSettings } from './common/MessengerSettings';
|
||||||
import { FriendsContextProvider } from './context/FriendsContext';
|
import { FriendsContextProvider } from './context/FriendsContext';
|
||||||
import { FriendsMessageHandler } from './FriendsMessageHandler';
|
|
||||||
import { FriendsReducer, initialFriends } from './reducers/FriendsReducer';
|
|
||||||
import { FriendBarView } from './views/friend-bar/FriendBarView';
|
import { FriendBarView } from './views/friend-bar/FriendBarView';
|
||||||
import { FriendsListView } from './views/friends-list/FriendsListView';
|
import { FriendsListView } from './views/friends-list/FriendsListView';
|
||||||
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
|
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
|
||||||
|
|
||||||
export const FriendsView: FC<{}> = props =>
|
export const FriendsView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ friendsState, dispatchFriendsState ] = useReducer(FriendsReducer, initialFriends);
|
|
||||||
const { friends = [], requests = [], settings = null } = friendsState;
|
|
||||||
|
|
||||||
const [ isReady, setIsReady ] = useState(false);
|
const [ isReady, setIsReady ] = useState(false);
|
||||||
const [ isListVisible, setIsListVisible ] = useState(false);
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ friends, setFriends ] = useState<MessengerFriend[]>([]);
|
||||||
|
const [ requests, setRequests ] = useState<MessengerRequest[]>([]);
|
||||||
|
const [ settings, setSettings ] = useState<MessengerSettings>(null);
|
||||||
|
const [ sentRequests, setSentRequests ] = useState<number[]>([]);
|
||||||
|
|
||||||
useEffect(() =>
|
const getFriend = useCallback((userId: number) =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new MessengerInitComposer());
|
for(const friend of friends)
|
||||||
|
{
|
||||||
|
if(friend.id === userId) return friend;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}, [ friends ]);
|
||||||
|
|
||||||
|
FriendsHelper.getFriend = getFriend;
|
||||||
|
|
||||||
|
const canRequestFriend = useCallback((userId: number) =>
|
||||||
|
{
|
||||||
|
if(getFriend(userId)) return false;
|
||||||
|
|
||||||
|
if(sentRequests.indexOf(userId) >= 0) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, [ sentRequests, getFriend ]);
|
||||||
|
|
||||||
|
FriendsHelper.canRequestFriend = canRequestFriend;
|
||||||
|
|
||||||
|
const requestFriend = useCallback((userId: number, userName: string) =>
|
||||||
|
{
|
||||||
|
if(sentRequests.indexOf(userId) >= 0) return true;
|
||||||
|
|
||||||
|
if(!canRequestFriend(userId)) return false;
|
||||||
|
|
||||||
|
setSentRequests(prevValue =>
|
||||||
|
{
|
||||||
|
const newSentRequests = [ ...prevValue ];
|
||||||
|
|
||||||
|
newSentRequests.push(userId);
|
||||||
|
|
||||||
|
return newSentRequests;
|
||||||
|
});
|
||||||
|
|
||||||
|
SendMessageHook(new RequestFriendComposer(userName));
|
||||||
|
}, [ sentRequests, canRequestFriend ]);
|
||||||
|
|
||||||
|
const acceptFriend = useCallback((userId: number) =>
|
||||||
|
{
|
||||||
|
setRequests(prevValue =>
|
||||||
|
{
|
||||||
|
const newRequests: MessengerRequest[] = [];
|
||||||
|
|
||||||
|
for(const request of prevValue)
|
||||||
|
{
|
||||||
|
if(request.requesterUserId !== userId)
|
||||||
|
{
|
||||||
|
newRequests.push(request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessageHook(new AcceptFriendMessageComposer(request.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRequests;
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() =>
|
const declineFriend = useCallback((userId: number, declineAll: boolean = false) =>
|
||||||
{
|
{
|
||||||
if(!settings) return;
|
setRequests(prevValue =>
|
||||||
|
{
|
||||||
|
if(declineAll)
|
||||||
|
{
|
||||||
|
SendMessageHook(new DeclineFriendMessageComposer(true));
|
||||||
|
|
||||||
setIsReady(true);
|
return [];
|
||||||
}, [ settings ]);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const newRequests: MessengerRequest[] = [];
|
||||||
|
|
||||||
|
for(const request of prevValue)
|
||||||
|
{
|
||||||
|
if(request.requesterUserId !== userId)
|
||||||
|
{
|
||||||
|
newRequests.push(request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessageHook(new DeclineFriendMessageComposer(false, request.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRequests;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onMessengerInitEvent = useCallback((event: MessengerInitEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setSettings(new MessengerSettings(
|
||||||
|
parser.userFriendLimit,
|
||||||
|
parser.normalFriendLimit,
|
||||||
|
parser.extendedFriendLimit,
|
||||||
|
parser.categories));
|
||||||
|
|
||||||
|
SendMessageHook(new GetFriendRequestsComposer());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
|
||||||
|
|
||||||
|
const onFriendsFragmentEvent = useCallback((event: FriendListFragmentEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setFriends(prevValue =>
|
||||||
|
{
|
||||||
|
const newFriends = [ ...prevValue ];
|
||||||
|
|
||||||
|
for(const friend of parser.fragment)
|
||||||
|
{
|
||||||
|
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||||
|
const newFriend = new MessengerFriend();
|
||||||
|
|
||||||
|
newFriend.populate(friend);
|
||||||
|
|
||||||
|
if(index > -1) newFriends[index] = newFriend;
|
||||||
|
else newFriends.push(newFriend);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFriends;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(FriendListFragmentEvent, onFriendsFragmentEvent);
|
||||||
|
|
||||||
|
const onFriendsUpdateEvent = useCallback((event: FriendListUpdateEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setFriends(prevValue =>
|
||||||
|
{
|
||||||
|
const newFriends = [ ...prevValue ];
|
||||||
|
|
||||||
|
const processUpdate = (friend: FriendParser) =>
|
||||||
|
{
|
||||||
|
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||||
|
|
||||||
|
if(index === -1)
|
||||||
|
{
|
||||||
|
const newFriend = new MessengerFriend();
|
||||||
|
newFriend.populate(friend);
|
||||||
|
|
||||||
|
newFriends.unshift(newFriend);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newFriends[index].populate(friend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const friend of parser.addedFriends) processUpdate(friend);
|
||||||
|
|
||||||
|
for(const friend of parser.updatedFriends) processUpdate(friend);
|
||||||
|
|
||||||
|
for(const removedFriendId of parser.removedFriendIds)
|
||||||
|
{
|
||||||
|
const index = newFriends.findIndex(existingFriend => (existingFriend.id === removedFriendId));
|
||||||
|
|
||||||
|
if(index > -1) newFriends.splice(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFriends;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(FriendListUpdateEvent, onFriendsUpdateEvent);
|
||||||
|
|
||||||
|
const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setRequests(prevValue =>
|
||||||
|
{
|
||||||
|
const newRequests = [ ...prevValue ];
|
||||||
|
|
||||||
|
for(const request of parser.requests)
|
||||||
|
{
|
||||||
|
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||||
|
|
||||||
|
if(index > 0) continue;
|
||||||
|
|
||||||
|
const newRequest = new MessengerRequest();
|
||||||
|
newRequest.populate(request);
|
||||||
|
|
||||||
|
newRequests.push(newRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRequests;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
|
||||||
|
|
||||||
|
const onNewFriendRequestEvent = useCallback((event: NewFriendRequestEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
const request = parser.request;
|
||||||
|
|
||||||
|
setRequests(prevValue =>
|
||||||
|
{
|
||||||
|
const newRequests = [ ...prevValue ];
|
||||||
|
|
||||||
|
const newRequest = new MessengerRequest();
|
||||||
|
newRequest.populate(request);
|
||||||
|
|
||||||
|
newRequests.push(newRequest);
|
||||||
|
|
||||||
|
return newRequests;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(NewFriendRequestEvent, onNewFriendRequestEvent);
|
||||||
|
|
||||||
const onFriendsEvent = useCallback((event: FriendsEvent) =>
|
const onFriendsEvent = useCallback((event: FriendsEvent) =>
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
{
|
{
|
||||||
case FriendsEvent.SHOW_FRIEND_LIST:
|
case FriendsEvent.SHOW_FRIEND_LIST:
|
||||||
setIsListVisible(true);
|
setIsVisible(true);
|
||||||
return;
|
return;
|
||||||
case FriendsEvent.TOGGLE_FRIEND_LIST:
|
case FriendsEvent.TOGGLE_FRIEND_LIST:
|
||||||
setIsListVisible(value => !value);
|
setIsVisible(value => !value);
|
||||||
return;
|
return;
|
||||||
case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST:
|
case FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST:
|
||||||
const requestEvent = (event as FriendsSendFriendRequestEvent);
|
const requestEvent = (event as FriendsSendFriendRequestEvent);
|
||||||
|
requestFriend(requestEvent.userId, requestEvent.userName);
|
||||||
return;
|
return;
|
||||||
case FriendsEvent.REQUEST_FRIEND_LIST:
|
case FriendsEvent.REQUEST_FRIEND_LIST:
|
||||||
dispatchUiEvent(new FriendListContentEvent(friendsState.friends));
|
dispatchUiEvent(new FriendListContentEvent(friends));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [ friendsState.friends ]);
|
}, [ friends, requestFriend ]);
|
||||||
|
|
||||||
useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent);
|
useUiEvent(FriendsEvent.SHOW_FRIEND_LIST, onFriendsEvent);
|
||||||
useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent);
|
useUiEvent(FriendsEvent.TOGGLE_FRIEND_LIST, onFriendsEvent);
|
||||||
@ -70,33 +285,70 @@ export const FriendsView: FC<{}> = props =>
|
|||||||
|
|
||||||
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
|
if(!userData || (userData.type !== RoomObjectUserType.getTypeNumber(RoomObjectUserType.USER))) return;
|
||||||
|
|
||||||
const friend = friendsState.friends.find(friend =>
|
const friend = getFriend(userData.webID);
|
||||||
{
|
|
||||||
return (friend.id === userData.webID);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!friend) return;
|
if(!friend) return;
|
||||||
|
|
||||||
dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
|
dispatchUiEvent(new FriendEnteredRoomEvent(userData.roomIndex, RoomObjectCategory.UNIT, userData.webID, userData.name, userData.type));
|
||||||
}, [ friendsState.friends ]);
|
}, [ getFriend ]);
|
||||||
|
|
||||||
useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
|
useRoomEngineEvent(RoomEngineObjectEvent.ADDED, onRoomEngineObjectEvent);
|
||||||
|
|
||||||
const onlineFriends = useMemo(() =>
|
const onlineFriends = useMemo(() =>
|
||||||
{
|
{
|
||||||
return friends.filter(f => f.online);
|
const onlineFriends = friends.filter(friend => friend.online);
|
||||||
|
|
||||||
|
onlineFriends.sort((a, b) =>
|
||||||
|
{
|
||||||
|
if( a.name < b.name ) return -1;
|
||||||
|
|
||||||
|
if( a.name > b.name ) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return onlineFriends;
|
||||||
}, [ friends ]);
|
}, [ friends ]);
|
||||||
|
|
||||||
const offlineFriends = useMemo(() =>
|
const offlineFriends = useMemo(() =>
|
||||||
{
|
{
|
||||||
return friends.filter(f => !f.online);
|
const offlineFriends = friends.filter(friend => !friend.online);
|
||||||
|
|
||||||
|
offlineFriends.sort((a, b) =>
|
||||||
|
{
|
||||||
|
if( a.name < b.name ) return -1;
|
||||||
|
|
||||||
|
if( a.name > b.name ) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return offlineFriends;
|
||||||
}, [ friends ]);
|
}, [ friends ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
SendMessageHook(new MessengerInitComposer());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!settings) return;
|
||||||
|
|
||||||
|
setIsReady(true);
|
||||||
|
}, [ settings ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
dispatchUiEvent(new FriendsRequestCountEvent(requests.length));
|
||||||
|
}, [ requests ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FriendsContextProvider value={ { friendsState, dispatchFriendsState } }>
|
<FriendsContextProvider value={ { friends, requests, settings, acceptFriend, declineFriend } }>
|
||||||
<FriendsMessageHandler />
|
{ isReady &&
|
||||||
{ isReady && createPortal(<FriendBarView onlineFriends={ onlineFriends } />, document.getElementById('toolbar-friend-bar-container')) }
|
createPortal(<FriendBarView onlineFriends={ onlineFriends } />, document.getElementById('toolbar-friend-bar-container')) }
|
||||||
{ isListVisible && <FriendsListView onlineFriends={ onlineFriends } offlineFriends={ offlineFriends } friendRequests={ requests } onCloseClick={ () => setIsListVisible(false) } /> }
|
{ isVisible &&
|
||||||
|
<FriendsListView onlineFriends={ onlineFriends } offlineFriends={ offlineFriends } friendRequests={ requests } onCloseClick={ () => setIsVisible(false) } /> }
|
||||||
<FriendsMessengerView />
|
<FriendsMessengerView />
|
||||||
</FriendsContextProvider>
|
</FriendsContextProvider>
|
||||||
);
|
);
|
||||||
|
14
src/views/friends/common/FriendsHelper.ts
Normal file
14
src/views/friends/common/FriendsHelper.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { MessengerFriend } from './MessengerFriend';
|
||||||
|
|
||||||
|
export class FriendsHelper
|
||||||
|
{
|
||||||
|
public static getFriend(userId: number): MessengerFriend
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static canRequestFriend(userId: number): boolean
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,11 @@ import { createContext, FC, useContext } from 'react';
|
|||||||
import { FriendsContextProps, IFriendsContext } from './FriendsContext.type';
|
import { FriendsContextProps, IFriendsContext } from './FriendsContext.type';
|
||||||
|
|
||||||
const FriendsContext = createContext<IFriendsContext>({
|
const FriendsContext = createContext<IFriendsContext>({
|
||||||
friendsState: null,
|
friends: null,
|
||||||
dispatchFriendsState: null
|
requests: null,
|
||||||
|
settings: null,
|
||||||
|
acceptFriend: null,
|
||||||
|
declineFriend: null
|
||||||
});
|
});
|
||||||
|
|
||||||
export const FriendsContextProvider: FC<FriendsContextProps> = props =>
|
export const FriendsContextProvider: FC<FriendsContextProps> = props =>
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
import { Dispatch, ProviderProps } from 'react';
|
import { ProviderProps } from 'react';
|
||||||
import { IFriendsAction, IFriendsState } from '../reducers/FriendsReducer';
|
import { MessengerFriend } from '../common/MessengerFriend';
|
||||||
|
import { MessengerRequest } from '../common/MessengerRequest';
|
||||||
|
import { MessengerSettings } from '../common/MessengerSettings';
|
||||||
|
|
||||||
export interface IFriendsContext
|
export interface IFriendsContext
|
||||||
{
|
{
|
||||||
friendsState: IFriendsState;
|
friends: MessengerFriend[];
|
||||||
dispatchFriendsState: Dispatch<IFriendsAction>;
|
requests: MessengerRequest[];
|
||||||
|
settings: MessengerSettings;
|
||||||
|
acceptFriend: (userId: number) => void;
|
||||||
|
declineFriend: (userId: number, declineAll?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FriendsContextProps extends ProviderProps<IFriendsContext>
|
export interface FriendsContextProps extends ProviderProps<IFriendsContext>
|
||||||
|
@ -1,147 +0,0 @@
|
|||||||
import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer';
|
|
||||||
import { Reducer } from 'react';
|
|
||||||
import { MessengerFriend } from '../common/MessengerFriend';
|
|
||||||
import { MessengerRequest } from '../common/MessengerRequest';
|
|
||||||
import { MessengerSettings } from '../common/MessengerSettings';
|
|
||||||
|
|
||||||
function compareName(a, b)
|
|
||||||
{
|
|
||||||
if( a.name < b.name ) return -1;
|
|
||||||
if( a.name > b.name ) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFriendsState
|
|
||||||
{
|
|
||||||
settings: MessengerSettings;
|
|
||||||
friends: MessengerFriend[];
|
|
||||||
requests: MessengerRequest[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFriendsAction
|
|
||||||
{
|
|
||||||
type: string;
|
|
||||||
payload: {
|
|
||||||
settings?: MessengerSettings;
|
|
||||||
fragment?: FriendParser[];
|
|
||||||
update?: FriendListUpdateParser;
|
|
||||||
requests?: FriendRequestData[];
|
|
||||||
numberValue?: number;
|
|
||||||
boolValue?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FriendsActions
|
|
||||||
{
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initialFriends: IFriendsState = {
|
|
||||||
settings: null,
|
|
||||||
friends: [],
|
|
||||||
requests: []
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FriendsReducer: Reducer<IFriendsState, IFriendsAction> = (state, action) =>
|
|
||||||
{
|
|
||||||
switch(action.type)
|
|
||||||
{
|
|
||||||
case FriendsActions.UPDATE_SETTINGS: {
|
|
||||||
const settings = (action.payload.settings || state.settings || null);
|
|
||||||
|
|
||||||
return { ...state, settings };
|
|
||||||
}
|
|
||||||
case FriendsActions.PROCESS_FRAGMENT: {
|
|
||||||
const fragment = (action.payload.fragment || null);
|
|
||||||
let friends = [ ...state.friends ];
|
|
||||||
|
|
||||||
for(const friend of fragment)
|
|
||||||
{
|
|
||||||
const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id));
|
|
||||||
const newFriend = new MessengerFriend();
|
|
||||||
|
|
||||||
newFriend.id = friend.id;
|
|
||||||
newFriend.name = friend.name;
|
|
||||||
newFriend.gender = friend.gender;
|
|
||||||
newFriend.online = friend.online;
|
|
||||||
newFriend.followingAllowed = friend.followingAllowed;
|
|
||||||
newFriend.figure = friend.figure;
|
|
||||||
newFriend.categoryId = friend.categoryId;
|
|
||||||
newFriend.motto = friend.motto;
|
|
||||||
newFriend.realName = friend.realName;
|
|
||||||
newFriend.lastAccess = friend.lastAccess;
|
|
||||||
newFriend.persistedMessageUser = friend.persistedMessageUser;
|
|
||||||
newFriend.vipMember = friend.vipMember;
|
|
||||||
newFriend.pocketHabboUser = friend.pocketHabboUser;
|
|
||||||
newFriend.relationshipStatus = friend.relationshipStatus;
|
|
||||||
|
|
||||||
if(index > -1) friends[index] = newFriend;
|
|
||||||
else friends.push(newFriend);
|
|
||||||
}
|
|
||||||
|
|
||||||
friends.sort(compareName);
|
|
||||||
|
|
||||||
return { ...state, friends };
|
|
||||||
}
|
|
||||||
case FriendsActions.PROCESS_UPDATE: {
|
|
||||||
const update = (action.payload.update || null);
|
|
||||||
let friends = [ ...state.friends ];
|
|
||||||
|
|
||||||
if(update)
|
|
||||||
{
|
|
||||||
const processUpdate = (friend: FriendParser) =>
|
|
||||||
{
|
|
||||||
const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id));
|
|
||||||
|
|
||||||
if(index === -1)
|
|
||||||
{
|
|
||||||
const newFriend = new MessengerFriend();
|
|
||||||
newFriend.populate(friend);
|
|
||||||
|
|
||||||
friends.unshift(newFriend);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
friends[index].populate(friend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const friend of update.addedFriends) processUpdate(friend);
|
|
||||||
|
|
||||||
for(const friend of update.updatedFriends) processUpdate(friend);
|
|
||||||
|
|
||||||
for(const removedFriendId of update.removedFriendIds)
|
|
||||||
{
|
|
||||||
const index = friends.findIndex(existingFriend => (existingFriend.id === removedFriendId));
|
|
||||||
|
|
||||||
if(index > -1) friends.splice(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
friends.sort(compareName);
|
|
||||||
|
|
||||||
return { ...state, friends };
|
|
||||||
}
|
|
||||||
case FriendsActions.PROCESS_REQUESTS: {
|
|
||||||
const newRequests = (action.payload.requests || null);
|
|
||||||
let requests = [ ...state.requests ];
|
|
||||||
|
|
||||||
for(const request of newRequests)
|
|
||||||
{
|
|
||||||
const newRequest = new MessengerRequest();
|
|
||||||
newRequest.populate(request);
|
|
||||||
requests.push(newRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
requests.sort(compareName);
|
|
||||||
|
|
||||||
return { ...state, requests };
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import { FollowFriendMessageComposer, MouseEventType, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { FollowFriendMessageComposer, MouseEventType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { LocalizeText, OpenMessengerChat } from '../../../../api';
|
import { GetUserProfile, LocalizeText, OpenMessengerChat } from '../../../../api';
|
||||||
import { SendMessageHook } from '../../../../hooks/messages';
|
import { SendMessageHook } from '../../../../hooks/messages';
|
||||||
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
||||||
import { FriendBarItemViewProps } from './FriendBarItemView.types';
|
import { FriendBarItemViewProps } from './FriendBarItemView.types';
|
||||||
@ -23,15 +23,12 @@ export const FriendBarItemView: FC<FriendBarItemViewProps> = props =>
|
|||||||
OpenMessengerChat(friend.id);
|
OpenMessengerChat(friend.id);
|
||||||
}, [ friend ]);
|
}, [ friend ]);
|
||||||
|
|
||||||
const openProfile = useCallback(() =>
|
|
||||||
{
|
|
||||||
SendMessageHook(new UserProfileComposer(friend.id));
|
|
||||||
}, [ friend ]);
|
|
||||||
|
|
||||||
const onClick = useCallback((event: MouseEvent) =>
|
const onClick = useCallback((event: MouseEvent) =>
|
||||||
{
|
{
|
||||||
const element = elementRef.current;
|
const element = elementRef.current;
|
||||||
|
|
||||||
|
if(!element) return;
|
||||||
|
|
||||||
if((event.target !== element) && !element.contains((event.target as Node)))
|
if((event.target !== element) && !element.contains((event.target as Node)))
|
||||||
{
|
{
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
@ -68,7 +65,7 @@ export const FriendBarItemView: FC<FriendBarItemViewProps> = props =>
|
|||||||
<div className="d-flex justify-content-between">
|
<div className="d-flex justify-content-between">
|
||||||
<i onClick={ openMessengerChat } className="icon icon-fb-chat cursor-pointer" />
|
<i onClick={ openMessengerChat } className="icon icon-fb-chat cursor-pointer" />
|
||||||
{ friend.followingAllowed && <i onClick={ followFriend } className="icon icon-fb-visit cursor-pointer" /> }
|
{ friend.followingAllowed && <i onClick={ followFriend } className="icon icon-fb-visit cursor-pointer" /> }
|
||||||
<i onClick={ openProfile } className="icon icon-fb-profile cursor-pointer" />
|
<i onClick={ event => GetUserProfile(friend.id) } className="icon icon-fb-profile cursor-pointer" />
|
||||||
</div> }
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { MessengerFriend } from '../../common/MessengerFriend';
|
|
||||||
import { MessengerRequest } from '../../common/MessengerRequest';
|
|
||||||
import { FriendsGroupItemView } from '../friends-group-item/FriendsGroupItemView';
|
import { FriendsGroupItemView } from '../friends-group-item/FriendsGroupItemView';
|
||||||
import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView';
|
|
||||||
import { FriendsGroupViewProps } from './FriendsGroupView.types';
|
import { FriendsGroupViewProps } from './FriendsGroupView.types';
|
||||||
|
|
||||||
export const FriendsGroupView: FC<FriendsGroupViewProps> = props =>
|
export const FriendsGroupView: FC<FriendsGroupViewProps> = props =>
|
||||||
@ -11,15 +8,12 @@ export const FriendsGroupView: FC<FriendsGroupViewProps> = props =>
|
|||||||
|
|
||||||
if(!list) return null;
|
if(!list) return null;
|
||||||
|
|
||||||
return (<>
|
return (
|
||||||
|
<>
|
||||||
{ list.map((item, index) =>
|
{ list.map((item, index) =>
|
||||||
{
|
{
|
||||||
if(item instanceof MessengerFriend)
|
return <FriendsGroupItemView key={ index } friend={ item } />;
|
||||||
return <FriendsGroupItemView key={ index } friend={ item } />
|
|
||||||
else if(item instanceof MessengerRequest)
|
|
||||||
return <FriendsRequestItemView key={ index } request={ item } />
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}) }
|
}) }
|
||||||
</>);
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { MessengerFriend } from '../../common/MessengerFriend';
|
import { MessengerFriend } from '../../common/MessengerFriend';
|
||||||
import { MessengerRequest } from '../../common/MessengerRequest';
|
|
||||||
|
|
||||||
export interface FriendsGroupViewProps
|
export interface FriendsGroupViewProps
|
||||||
{
|
{
|
||||||
list: MessengerFriend[] | MessengerRequest[];
|
list: MessengerFriend[];
|
||||||
}
|
}
|
||||||
|
@ -1,42 +1,46 @@
|
|||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { LocalizeText } from '../../../../api';
|
import { LocalizeText } from '../../../../api';
|
||||||
import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
|
import { NitroCardAccordionSetView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
|
||||||
import { FriendsGroupView } from '../friends-group/FriendsGroupView';
|
import { FriendsGroupView } from '../friends-group/FriendsGroupView';
|
||||||
|
import { FriendsRequestView } from '../friends-request/FriendsRequestView';
|
||||||
import { FriendsListViewProps } from './FriendsListView.types';
|
import { FriendsListViewProps } from './FriendsListView.types';
|
||||||
|
|
||||||
const TABS: string[] = ['friendlist.friends', 'generic.search'];
|
const MODE_FRIENDS: number = 0;
|
||||||
|
const MODE_SEARCH: number = 1;
|
||||||
|
|
||||||
export const FriendsListView: FC<FriendsListViewProps> = props =>
|
export const FriendsListView: FC<FriendsListViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props;
|
|
||||||
|
|
||||||
const [ currentTab, setCurrentTab ] = useState<number>(0);
|
const { onlineFriends = [], offlineFriends = [], friendRequests = [], onCloseClick = null } = props;
|
||||||
|
const [ mode, setMode ] = useState<number>(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardView className="nitro-friends">
|
<NitroCardView className="nitro-friends">
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ onCloseClick } />
|
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ onCloseClick } />
|
||||||
<NitroCardContentView className="p-0">
|
|
||||||
<NitroCardTabsView>
|
<NitroCardTabsView>
|
||||||
{ TABS.map((tab, index) =>
|
<NitroCardTabsItemView isActive={ (mode === MODE_FRIENDS) } count={ friendRequests.length } onClick={ event => setMode(MODE_FRIENDS) }>
|
||||||
{
|
{ LocalizeText('friendlist.friends') }
|
||||||
return (<NitroCardTabsItemView key={ index } isActive={ currentTab === index } onClick={ () => setCurrentTab(index) }>
|
</NitroCardTabsItemView>
|
||||||
{ LocalizeText(tab) }
|
<NitroCardTabsItemView isActive={ (mode === MODE_SEARCH) } onClick={ event => setMode(MODE_SEARCH) }>
|
||||||
</NitroCardTabsItemView>);
|
{ LocalizeText('generic.search') }
|
||||||
}) }
|
</NitroCardTabsItemView>
|
||||||
</NitroCardTabsView>
|
</NitroCardTabsView>
|
||||||
<div className="text-black">
|
<NitroCardContentView className="p-0 text-black">
|
||||||
{ currentTab === 0 && <NitroCardAccordionView>
|
{ (mode === MODE_FRIENDS) &&
|
||||||
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends') + ` (${onlineFriends.length})` } defaultState={ true }>
|
<NitroCardAccordionView>
|
||||||
|
<NitroCardAccordionSetView headerText={ LocalizeText('friendlist.friends') + ` (${onlineFriends.length})` } isExpanded={ true }>
|
||||||
<FriendsGroupView list={ onlineFriends } />
|
<FriendsGroupView list={ onlineFriends } />
|
||||||
</NitroCardAccordionItemView>
|
</NitroCardAccordionSetView>
|
||||||
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends.offlinecaption') + ` (${offlineFriends.length})` }>
|
<NitroCardAccordionSetView headerText={ LocalizeText('friendlist.friends.offlinecaption') + ` (${offlineFriends.length})` }>
|
||||||
<FriendsGroupView list={ offlineFriends } />
|
<FriendsGroupView list={ offlineFriends } />
|
||||||
</NitroCardAccordionItemView>
|
</NitroCardAccordionSetView>
|
||||||
{ friendRequests.length > 0 && <NitroCardAccordionItemView headerText={ LocalizeText('friendlist.tab.friendrequests') + ` (${friendRequests.length})` }>
|
|
||||||
<FriendsGroupView list={ friendRequests } />
|
|
||||||
</NitroCardAccordionItemView> }
|
<FriendsRequestView requests={ friendRequests } />
|
||||||
</NitroCardAccordionView> }
|
</NitroCardAccordionView> }
|
||||||
</div>
|
{ (mode === MODE_SEARCH) &&
|
||||||
|
<>
|
||||||
|
</> }
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
</NitroCardView>
|
</NitroCardView>
|
||||||
);
|
);
|
||||||
|
@ -1,37 +1,24 @@
|
|||||||
import { AcceptFriendMessageComposer, DeclineFriendMessageComposer } from '@nitrots/nitro-renderer';
|
import { FC } from 'react';
|
||||||
import { FC, useCallback } from 'react';
|
import { NitroCardAccordionItemView } from '../../../../layout';
|
||||||
import { SendMessageHook } from '../../../../hooks/messages/message-event';
|
|
||||||
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
|
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
|
||||||
|
import { useFriendsContext } from '../../context/FriendsContext';
|
||||||
import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types';
|
import { FriendsRequestItemViewProps } from './FriendsRequestItemView.types';
|
||||||
|
|
||||||
export const FriendsRequestItemView: FC<FriendsRequestItemViewProps> = props =>
|
export const FriendsRequestItemView: FC<FriendsRequestItemViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { request = null } = props;
|
const { request = null } = props;
|
||||||
|
const { acceptFriend = null, declineFriend = null } = useFriendsContext();
|
||||||
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;
|
if(!request) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-2 py-1 d-flex gap-1 align-items-center">
|
<NitroCardAccordionItemView>
|
||||||
<UserProfileIconView userId={ request.id } />
|
<UserProfileIconView userId={ request.id } />
|
||||||
<div>{ request.name }</div>
|
<div>{ request.name }</div>
|
||||||
<div className="ms-auto d-flex align-items-center gap-1">
|
<div className="ms-auto d-flex align-items-center gap-1">
|
||||||
<i className="icon icon-accept cursor-pointer" onClick={ accept } />
|
<i className="icon icon-accept cursor-pointer" onClick={ event => acceptFriend(request.requesterUserId) } />
|
||||||
<i className="icon icon-deny cursor-pointer" onClick={ decline } />
|
<i className="icon icon-deny cursor-pointer" onClick={ event => declineFriend(request.requesterUserId) } />
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</NitroCardAccordionItemView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { LocalizeText } from '../../../../api';
|
||||||
|
import { NitroCardAccordionSetView, NitroLayoutButton, NitroLayoutFlex } from '../../../../layout';
|
||||||
|
import { useFriendsContext } from '../../context/FriendsContext';
|
||||||
|
import { FriendsRequestItemView } from '../friends-request-item/FriendsRequestItemView';
|
||||||
|
import { FriendsRequestViewProps } from './FriendsRequestView.types';
|
||||||
|
|
||||||
|
export const FriendsRequestView: FC<FriendsRequestViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { requests = [] } = props;
|
||||||
|
const { declineFriend = null } = useFriendsContext();
|
||||||
|
|
||||||
|
if(!requests.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardAccordionSetView headerText={ LocalizeText('friendlist.tab.friendrequests') + ` (${ requests.length })` } isExpanded={ true }>
|
||||||
|
{ requests.map(request =>
|
||||||
|
{
|
||||||
|
return <FriendsRequestItemView key={ request.requesterUserId } request={ request } />
|
||||||
|
}) }
|
||||||
|
<NitroLayoutFlex className="justify-content-center p-1">
|
||||||
|
<NitroLayoutButton size="sm" onClick={ event => declineFriend(-1, true) }>
|
||||||
|
{ LocalizeText('friendlist.requests.dismissall') }
|
||||||
|
</NitroLayoutButton>
|
||||||
|
</NitroLayoutFlex>
|
||||||
|
</NitroCardAccordionSetView>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
import { MessengerRequest } from '../../common/MessengerRequest';
|
||||||
|
|
||||||
|
export interface FriendsRequestViewProps
|
||||||
|
{
|
||||||
|
requests: MessengerRequest[];
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../../../api';
|
import { AddEventLinkTracker, GetUserProfile, LocalizeText, RemoveLinkEventTracker } from '../../../../api';
|
||||||
import { FriendsMessengerIconEvent } from '../../../../events';
|
import { FriendsMessengerIconEvent } from '../../../../events';
|
||||||
import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks';
|
import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks';
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutFlex } from '../../../../layout';
|
||||||
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
||||||
import { MessengerThread } from '../../common/MessengerThread';
|
import { MessengerThread } from '../../common/MessengerThread';
|
||||||
import { MessengerThreadChat } from '../../common/MessengerThreadChat';
|
import { MessengerThreadChat } from '../../common/MessengerThreadChat';
|
||||||
@ -17,10 +17,9 @@ export const FriendsMessengerView: FC<{}> = props =>
|
|||||||
const [ activeThreadIndex, setActiveThreadIndex ] = useState(-1);
|
const [ activeThreadIndex, setActiveThreadIndex ] = useState(-1);
|
||||||
const [ hiddenThreadIndexes, setHiddenThreadIndexes ] = useState<number[]>([]);
|
const [ hiddenThreadIndexes, setHiddenThreadIndexes ] = useState<number[]>([]);
|
||||||
const [ messageText, setMessageText ] = useState('');
|
const [ messageText, setMessageText ] = useState('');
|
||||||
const { friendsState = null } = useFriendsContext();
|
|
||||||
const { friends = [] } = friendsState;
|
|
||||||
const messagesBox = useRef<HTMLDivElement>();
|
|
||||||
const [ updateValue, setUpdateValue ] = useState({});
|
const [ updateValue, setUpdateValue ] = useState({});
|
||||||
|
const { friends = [] } = useFriendsContext();
|
||||||
|
const messagesBox = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
const followFriend = useCallback(() =>
|
const followFriend = useCallback(() =>
|
||||||
{
|
{
|
||||||
@ -29,7 +28,7 @@ export const FriendsMessengerView: FC<{}> = props =>
|
|||||||
|
|
||||||
const openProfile = useCallback(() =>
|
const openProfile = useCallback(() =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new UserProfileComposer(messageThreads[activeThreadIndex].participant.id));
|
GetUserProfile(messageThreads[activeThreadIndex].participant.id);
|
||||||
}, [ messageThreads, activeThreadIndex ]);
|
}, [ messageThreads, activeThreadIndex ]);
|
||||||
|
|
||||||
const getFriend = useCallback((userId: number) =>
|
const getFriend = useCallback((userId: number) =>
|
||||||
@ -236,7 +235,7 @@ export const FriendsMessengerView: FC<{}> = props =>
|
|||||||
<NitroCardView className="nitro-friends-messenger" simple={ true }>
|
<NitroCardView className="nitro-friends-messenger" simple={ true }>
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('messenger.window.title', [ 'OPEN_CHAT_COUNT' ], [ visibleThreads.length.toString() ]) } onCloseClick={ event => setIsVisible(false) } />
|
<NitroCardHeaderView headerText={ LocalizeText('messenger.window.title', [ 'OPEN_CHAT_COUNT' ], [ visibleThreads.length.toString() ]) } onCloseClick={ event => setIsVisible(false) } />
|
||||||
<NitroCardContentView>
|
<NitroCardContentView>
|
||||||
<div className="d-flex gap-2 overflow-auto pb-1">
|
<NitroLayoutFlex gap={ 2 } overflow="auto">
|
||||||
{ visibleThreads && (visibleThreads.length > 0) && visibleThreads.map((thread, index) =>
|
{ visibleThreads && (visibleThreads.length > 0) && visibleThreads.map((thread, index) =>
|
||||||
{
|
{
|
||||||
const messageThreadIndex = messageThreads.indexOf(thread);
|
const messageThreadIndex = messageThreads.indexOf(thread);
|
||||||
@ -248,13 +247,16 @@ export const FriendsMessengerView: FC<{}> = props =>
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}) }
|
}) }
|
||||||
</div>
|
</NitroLayoutFlex>
|
||||||
<hr className="bg-dark mt-3 mb-2" />
|
<NitroLayoutFlex className="align-items-center my-1" position="relative">
|
||||||
|
{ (activeThreadIndex >= 0) &&
|
||||||
|
<div className="text-black bg-light pe-2 flex-none">
|
||||||
|
{ LocalizeText('messenger.window.separator', [ 'FRIEND_NAME' ], [ messageThreads[activeThreadIndex].participant.name ]) }
|
||||||
|
</div> }
|
||||||
|
<hr className="bg-dark m-0 w-100" />
|
||||||
|
</NitroLayoutFlex>
|
||||||
{ (activeThreadIndex >= 0) &&
|
{ (activeThreadIndex >= 0) &&
|
||||||
<>
|
<>
|
||||||
<div className="text-black chat-title bg-light pe-2 position-absolute">
|
|
||||||
{ LocalizeText('messenger.window.separator', [ 'FRIEND_NAME' ], [ messageThreads[activeThreadIndex].participant.name ]) }
|
|
||||||
</div>
|
|
||||||
<div className="d-flex gap-2 mb-2">
|
<div className="d-flex gap-2 mb-2">
|
||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
<button className="d-flex justify-content-center align-items-center btn btn-sm btn-primary" onClick={ followFriend }>
|
<button className="d-flex justify-content-center align-items-center btn btn-sm btn-primary" onClick={ followFriend }>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { EventDispatcher, NitroRectangle, RoomGeometry, RoomVariableEnum, Vector3d } from '@nitrots/nitro-renderer';
|
import { EventDispatcher, NitroRectangle, RoomGeometry, RoomVariableEnum, Vector3d } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect, useRef, useState } from 'react';
|
import { FC, useEffect, useRef, useState } from 'react';
|
||||||
import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCreditWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureExternalImageWidgetHandler, FurnitureMannequinWidgetHandler, FurniturePresentWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api';
|
import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FriendRequestHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCreditWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureExternalImageWidgetHandler, FurnitureMannequinWidgetHandler, FurniturePresentWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api';
|
||||||
import { FurnitureYoutubeDisplayWidgetHandler } from '../../api/nitro/room/widgets/handlers/FurnitureYoutubeDisplayWidgetHandler';
|
import { FurnitureYoutubeDisplayWidgetHandler } from '../../api/nitro/room/widgets/handlers/FurnitureYoutubeDisplayWidgetHandler';
|
||||||
import { PollWidgetHandler } from '../../api/nitro/room/widgets/handlers/PollWidgetHandler';
|
import { PollWidgetHandler } from '../../api/nitro/room/widgets/handlers/PollWidgetHandler';
|
||||||
import { WordQuizWidgetHandler } from '../../api/nitro/room/widgets/handlers/WordQuizWidgetHandler';
|
import { WordQuizWidgetHandler } from '../../api/nitro/room/widgets/handlers/WordQuizWidgetHandler';
|
||||||
@ -41,6 +41,7 @@ export const RoomView: FC<RoomViewProps> = props =>
|
|||||||
widgetHandlerManager.registerHandler(new DoorbellWidgetHandler());
|
widgetHandlerManager.registerHandler(new DoorbellWidgetHandler());
|
||||||
widgetHandlerManager.registerHandler(new WordQuizWidgetHandler());
|
widgetHandlerManager.registerHandler(new WordQuizWidgetHandler());
|
||||||
widgetHandlerManager.registerHandler(new PollWidgetHandler());
|
widgetHandlerManager.registerHandler(new PollWidgetHandler());
|
||||||
|
widgetHandlerManager.registerHandler(new FriendRequestHandler());
|
||||||
|
|
||||||
widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler());
|
widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler());
|
||||||
widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
|
widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler());
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
export interface RoomWidgetViewProps
|
|
||||||
{}
|
|
@ -15,9 +15,9 @@ import { FurnitureWidgetsView } from './furniture/FurnitureWidgetsView';
|
|||||||
import { InfoStandWidgetView } from './infostand/InfoStandWidgetView';
|
import { InfoStandWidgetView } from './infostand/InfoStandWidgetView';
|
||||||
import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView';
|
import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView';
|
||||||
import { RoomToolsWidgetView } from './room-tools/RoomToolsWidgetView';
|
import { RoomToolsWidgetView } from './room-tools/RoomToolsWidgetView';
|
||||||
import { RoomWidgetViewProps } from './RoomWidgets.types';
|
|
||||||
import { WordQuizWidgetView } from './word-quiz/WordQuizWidgetView';
|
import { WordQuizWidgetView } from './word-quiz/WordQuizWidgetView';
|
||||||
export const RoomWidgetsView: FC<RoomWidgetViewProps> = props =>
|
|
||||||
|
export const RoomWidgetsView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import { AvatarInfoUseProductView } from './views/use-product/AvatarInfoUseProdu
|
|||||||
|
|
||||||
export const AvatarInfoWidgetView: FC<{}> = props =>
|
export const AvatarInfoWidgetView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
|
||||||
const [ name, setName ] = useState<RoomWidgetObjectNameEvent>(null);
|
const [ name, setName ] = useState<RoomWidgetObjectNameEvent>(null);
|
||||||
const [ nameBubbles, setNameBubbles ] = useState<RoomWidgetObjectNameEvent[]>([]);
|
const [ nameBubbles, setNameBubbles ] = useState<RoomWidgetObjectNameEvent[]>([]);
|
||||||
const [ productBubbles, setProductBubbles ] = useState<UseProductItem[]>([]);
|
const [ productBubbles, setProductBubbles ] = useState<UseProductItem[]>([]);
|
||||||
@ -26,6 +25,7 @@ export const AvatarInfoWidgetView: FC<{}> = props =>
|
|||||||
const [ isDancing, setIsDancing ] = useState(false);
|
const [ isDancing, setIsDancing ] = useState(false);
|
||||||
const [ isDecorating, setIsDecorating ] = useState(false);
|
const [ isDecorating, setIsDecorating ] = useState(false);
|
||||||
const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState<RoomWidgetUpdateRentableBotChatEvent>(null);
|
const [ rentableBotChatEvent, setRentableBotChatEvent ] = useState<RoomWidgetUpdateRentableBotChatEvent>(null);
|
||||||
|
const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
const removeNameBubble = useCallback((index: number) =>
|
const removeNameBubble = useCallback((index: number) =>
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { RoomControllerLevel, RoomObjectCategory, RoomObjectVariable, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { RoomControllerLevel, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { GetOwnRoomObject, LocalizeText, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetOwnRoomObject, GetUserProfile, LocalizeText, RoomWidgetMessage, RoomWidgetUserActionMessage } from '../../../../../../api';
|
||||||
import { SendMessageHook } from '../../../../../../hooks';
|
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { useRoomContext } from '../../../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
||||||
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
import { ContextMenuHeaderView } from '../../../context-menu/views/header/ContextMenuHeaderView';
|
||||||
@ -192,14 +191,9 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
return flag;
|
return flag;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const openProfile = useCallback(() =>
|
|
||||||
{
|
|
||||||
SendMessageHook(new UserProfileComposer(userData.webID));
|
|
||||||
}, [ userData ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
||||||
<ContextMenuHeaderView className="cursor-pointer" onClick={ () => openProfile() }>
|
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
||||||
{ userData.name }
|
{ userData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
{ (mode === MODE_NORMAL) &&
|
{ (mode === MODE_NORMAL) &&
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { AvatarAction, AvatarExpressionEnum, RoomControllerLevel, RoomObjectCategory, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { AvatarAction, AvatarExpressionEnum, RoomControllerLevel, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useMemo, useState } from 'react';
|
import { FC, useCallback, useMemo, useState } from 'react';
|
||||||
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
|
import { GetCanStandUp, GetCanUseExpression, GetOwnPosture, GetUserProfile, HasHabboClub, HasHabboVip, IsRidingHorse, LocalizeText, RoomWidgetAvatarExpressionMessage, RoomWidgetChangePostureMessage, RoomWidgetDanceMessage, RoomWidgetMessage, RoomWidgetUpdateDecorateModeEvent, RoomWidgetUserActionMessage } from '../../../../../../api';
|
||||||
import { AvatarEditorEvent } from '../../../../../../events';
|
import { AvatarEditorEvent } from '../../../../../../events';
|
||||||
import { dispatchUiEvent, SendMessageHook } from '../../../../../../hooks';
|
import { dispatchUiEvent } from '../../../../../../hooks';
|
||||||
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
|
||||||
import { useRoomContext } from '../../../../context/RoomContext';
|
import { useRoomContext } from '../../../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../../../context-menu/ContextMenuView';
|
||||||
@ -103,11 +103,6 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
if(hideMenu) close();
|
if(hideMenu) close();
|
||||||
}, [ roomSession, eventDispatcher, widgetHandler, userData, close ]);
|
}, [ roomSession, eventDispatcher, widgetHandler, userData, close ]);
|
||||||
|
|
||||||
const openProfile = useCallback(() =>
|
|
||||||
{
|
|
||||||
SendMessageHook(new UserProfileComposer(userData.webID));
|
|
||||||
}, [ userData ]);
|
|
||||||
|
|
||||||
const isShowDecorate = useMemo(() =>
|
const isShowDecorate = useMemo(() =>
|
||||||
{
|
{
|
||||||
return (userData.amIOwner || userData.amIAnyRoomController || (userData.roomControllerLevel > RoomControllerLevel.GUEST));
|
return (userData.amIOwner || userData.amIAnyRoomController || (userData.roomControllerLevel > RoomControllerLevel.GUEST));
|
||||||
@ -117,7 +112,7 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
||||||
<ContextMenuHeaderView className="cursor-pointer" onClick={ () => openProfile() }>
|
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
||||||
{ userData.name }
|
{ userData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
{ (mode === MODE_NORMAL) &&
|
{ (mode === MODE_NORMAL) &&
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
@import './avatar-image/AvatarImage';
|
@import "./avatar-image/AvatarImage";
|
||||||
@import './badge-image/BadgeImage';
|
@import "./badge-image/BadgeImage";
|
||||||
@import './currency-icon/CurrencyIcon';
|
@import "./currency-icon/CurrencyIcon";
|
||||||
@import './furni-image/FurniImageView';
|
@import "./furni-image/FurniImageView";
|
||||||
@import './limited-edition/LimitedEdition';
|
@import "./limited-edition/LimitedEdition";
|
||||||
@import './pet-image/PetImage';
|
@import "./pet-image/PetImage";
|
||||||
@import './rarity-level/RarityLevelView';
|
@import "./rarity-level/RarityLevelView";
|
||||||
@import './room-previewer/RoomPreviewerView';
|
@import "./room-previewer/RoomPreviewerView";
|
||||||
|
@import "./item-count/ItemCountView";
|
||||||
|
6
src/views/shared/item-count/ItemCountView.scss
Normal file
6
src/views/shared/item-count/ItemCountView.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.nitro-item-count {
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
font-size: 8px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
9
src/views/shared/item-count/ItemCountView.tsx
Normal file
9
src/views/shared/item-count/ItemCountView.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { ItemCountViewProps } from './ItemCountView.types';
|
||||||
|
|
||||||
|
export const ItemCountView: FC<ItemCountViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { count = 0 } = props;
|
||||||
|
|
||||||
|
return <div className="position-absolute badge border bg-danger px-1 rounded-circle nitro-item-count">{ count }</div>
|
||||||
|
}
|
4
src/views/shared/item-count/ItemCountView.types.ts
Normal file
4
src/views/shared/item-count/ItemCountView.types.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface ItemCountViewProps
|
||||||
|
{
|
||||||
|
count: number;
|
||||||
|
}
|
@ -9,15 +9,16 @@
|
|||||||
.nitro-toolbar {
|
.nitro-toolbar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
background: rgba($dark,.95);
|
background: rgba($dark, 0.95);
|
||||||
box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4);
|
box-shadow: inset 0px 5px lighten(rgba($dark, 0.6), 2.5),
|
||||||
|
inset 0 -4px darken(rgba($dark, 0.6), 4);
|
||||||
|
|
||||||
#toolbar-chat-input-container {
|
#toolbar-chat-input-container {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
|
|
||||||
@include media-breakpoint-down(sm) {
|
@include media-breakpoint-down(sm) {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
height: 0px
|
height: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +27,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.navigation-avatar {
|
&.navigation-avatar {
|
||||||
border-right: 1px solid rgba(0, 0, 0, .3);
|
border-right: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-item {
|
.navigation-item {
|
||||||
@ -53,7 +54,8 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
//transition: transform .2s ease-out;
|
//transition: transform .2s ease-out;
|
||||||
|
|
||||||
&:hover, &.active {
|
&:hover,
|
||||||
|
&.active {
|
||||||
-webkit-transform: translate(-1px, -1px);
|
-webkit-transform: translate(-1px, -1px);
|
||||||
transform: translate(-1px, -1px);
|
transform: translate(-1px, -1px);
|
||||||
filter: drop-shadow(2px 2px 0 rgba($black, 0.8));
|
filter: drop-shadow(2px 2px 0 rgba($black, 0.8));
|
||||||
@ -67,12 +69,6 @@
|
|||||||
.chat-input-container {
|
.chat-input-container {
|
||||||
left: 60px;
|
left: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
|
||||||
top: 0rem;
|
|
||||||
right: 2px;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +80,9 @@
|
|||||||
z-index: $toolbar-memenu-zindex;
|
z-index: $toolbar-memenu-zindex;
|
||||||
|
|
||||||
.list-group {
|
.list-group {
|
||||||
|
|
||||||
.list-group-item {
|
.list-group-item {
|
||||||
min-width: 70px;
|
min-width: 70px;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
@ -123,7 +118,9 @@
|
|||||||
max-width: 120px;
|
max-width: 120px;
|
||||||
max-height: 150px;
|
max-height: 150px;
|
||||||
z-index: 500;
|
z-index: 500;
|
||||||
filter: drop-shadow(2px 1px 0 rgba($white, 1)) drop-shadow(-2px 1px 0 rgba($white, 1)) drop-shadow(0 -2px 0 rgba($white, 1));
|
filter: drop-shadow(2px 1px 0 rgba($white, 1))
|
||||||
|
drop-shadow(-2px 1px 0 rgba($white, 1))
|
||||||
|
drop-shadow(0 -2px 0 rgba($white, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './me/ToolbarMeView';
|
@import "./me/ToolbarMeView";
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, UserProfileComposer, Wait } from '@nitrots/nitro-renderer';
|
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, Queue, UserInfoDataParser, UserInfoEvent, Wait } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { CreateLinkEvent, GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GoToDesktop, OpenMessengerChat } from '../../api';
|
import { CreateLinkEvent, GetRoomSession, GetRoomSessionManager, GetSessionDataManager, GetUserProfile, GoToDesktop, OpenMessengerChat } from '../../api';
|
||||||
import { AvatarEditorEvent, CatalogEvent, FriendsEvent, FriendsMessengerIconEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
|
import { AvatarEditorEvent, CatalogEvent, FriendsEvent, FriendsMessengerIconEvent, FriendsRequestCountEvent, InventoryEvent, NavigatorEvent, RoomWidgetCameraEvent } from '../../events';
|
||||||
import { AchievementsUIEvent, AchievementsUIUnseenCountEvent } from '../../events/achievements';
|
import { AchievementsUIEvent, AchievementsUIUnseenCountEvent } from '../../events/achievements';
|
||||||
import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent';
|
import { UnseenItemTrackerUpdateEvent } from '../../events/inventory/UnseenItemTrackerUpdateEvent';
|
||||||
import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent';
|
import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent';
|
||||||
import { UserSettingsUIEvent } from '../../events/user-settings/UserSettingsUIEvent';
|
import { UserSettingsUIEvent } from '../../events/user-settings/UserSettingsUIEvent';
|
||||||
import { dispatchUiEvent, useRoomEngineEvent, useUiEvent } from '../../hooks';
|
import { dispatchUiEvent, useRoomEngineEvent, useUiEvent } from '../../hooks';
|
||||||
import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event';
|
import { CreateMessageHook } from '../../hooks/messages/message-event';
|
||||||
import { TransitionAnimation } from '../../layout/transitions/TransitionAnimation';
|
import { TransitionAnimation } from '../../layout/transitions/TransitionAnimation';
|
||||||
import { TransitionAnimationTypes } from '../../layout/transitions/TransitionAnimation.types';
|
import { TransitionAnimationTypes } from '../../layout/transitions/TransitionAnimation.types';
|
||||||
import { AvatarImageView } from '../shared/avatar-image/AvatarImageView';
|
import { AvatarImageView } from '../shared/avatar-image/AvatarImageView';
|
||||||
|
import { ItemCountView } from '../shared/item-count/ItemCountView';
|
||||||
import { ToolbarMeView } from './me/ToolbarMeView';
|
import { ToolbarMeView } from './me/ToolbarMeView';
|
||||||
import { ToolbarViewItems, ToolbarViewProps } from './ToolbarView.types';
|
import { ToolbarViewItems, ToolbarViewProps } from './ToolbarView.types';
|
||||||
|
|
||||||
@ -28,9 +29,8 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
|
const [ chatIconType, setChatIconType ] = useState(CHAT_ICON_HIDDEN);
|
||||||
const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0);
|
const [ unseenInventoryCount, setUnseenInventoryCount ] = useState(0);
|
||||||
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
||||||
|
const [ unseenFriendRequestCount, setFriendRequestCount ] = useState(0);
|
||||||
const isMod = GetSessionDataManager().isModerator;
|
const isMod = GetSessionDataManager().isModerator;
|
||||||
const unseenFriendListCount = 0;
|
|
||||||
|
|
||||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||||
{
|
{
|
||||||
@ -72,6 +72,13 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
|
|
||||||
useUiEvent(AchievementsUIUnseenCountEvent.UNSEEN_COUNT, onAchievementsUIUnseenCountEvent);
|
useUiEvent(AchievementsUIUnseenCountEvent.UNSEEN_COUNT, onAchievementsUIUnseenCountEvent);
|
||||||
|
|
||||||
|
const onFriendsRequestCountEvent = useCallback((event: FriendsRequestCountEvent) =>
|
||||||
|
{
|
||||||
|
setFriendRequestCount(event.count);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useUiEvent(FriendsRequestCountEvent.UPDATE_COUNT, onFriendsRequestCountEvent);
|
||||||
|
|
||||||
const animationIconToToolbar = useCallback((iconName: string, image: HTMLImageElement, x: number, y: number) =>
|
const animationIconToToolbar = useCallback((iconName: string, image: HTMLImageElement, x: number, y: number) =>
|
||||||
{
|
{
|
||||||
const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement);
|
const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement);
|
||||||
@ -144,7 +151,7 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
setMeExpanded(false);
|
setMeExpanded(false);
|
||||||
return;
|
return;
|
||||||
case ToolbarViewItems.PROFILE_ITEM:
|
case ToolbarViewItems.PROFILE_ITEM:
|
||||||
SendMessageHook(new UserProfileComposer(GetSessionDataManager().userId));
|
GetUserProfile(GetSessionDataManager().userId);
|
||||||
setMeExpanded(false);
|
setMeExpanded(false);
|
||||||
return;
|
return;
|
||||||
case ToolbarViewItems.SETTINGS_ITEM:
|
case ToolbarViewItems.SETTINGS_ITEM:
|
||||||
@ -176,7 +183,7 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
<div className={ 'navigation-item item-avatar ' + (isMeExpanded ? 'active ' : '') } onClick={ event => setMeExpanded(!isMeExpanded) }>
|
<div className={ 'navigation-item item-avatar ' + (isMeExpanded ? 'active ' : '') } onClick={ event => setMeExpanded(!isMeExpanded) }>
|
||||||
<AvatarImageView figure={ userFigure } direction={ 2 } />
|
<AvatarImageView figure={ userFigure } direction={ 2 } />
|
||||||
{ (unseenAchievementCount > 0) &&
|
{ (unseenAchievementCount > 0) &&
|
||||||
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenAchievementCount }</div> }
|
<ItemCountView count={ unseenAchievementCount } /> }
|
||||||
</div>
|
</div>
|
||||||
{ isInRoom && (
|
{ isInRoom && (
|
||||||
<div className="navigation-item" onClick={ visitDesktop }>
|
<div className="navigation-item" onClick={ visitDesktop }>
|
||||||
@ -194,8 +201,8 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
</div>
|
</div>
|
||||||
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.INVENTORY_ITEM) }>
|
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.INVENTORY_ITEM) }>
|
||||||
<i className="icon icon-inventory"></i>
|
<i className="icon icon-inventory"></i>
|
||||||
{ (unseenInventoryCount > 0) && (
|
{ (unseenInventoryCount > 0) &&
|
||||||
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenInventoryCount }</div>) }
|
<ItemCountView count={ unseenInventoryCount } /> }
|
||||||
</div>
|
</div>
|
||||||
{ isInRoom && (
|
{ isInRoom && (
|
||||||
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.CAMERA_ITEM) }>
|
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.CAMERA_ITEM) }>
|
||||||
@ -212,15 +219,13 @@ export const ToolbarView: FC<ToolbarViewProps> = props =>
|
|||||||
<div className="navigation-items gap-2">
|
<div className="navigation-items gap-2">
|
||||||
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }>
|
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.FRIEND_LIST_ITEM) }>
|
||||||
<i className="icon icon-friendall"></i>
|
<i className="icon icon-friendall"></i>
|
||||||
{ (unseenFriendListCount > 0) && (
|
{ (unseenFriendRequestCount > 0) &&
|
||||||
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenFriendListCount }</div>) }
|
<ItemCountView count={ unseenFriendRequestCount } /> }
|
||||||
</div>
|
</div>
|
||||||
{ ((chatIconType === CHAT_ICON_SHOWING) || (chatIconType === CHAT_ICON_UNREAD)) &&
|
{ ((chatIconType === CHAT_ICON_SHOWING) || (chatIconType === CHAT_ICON_UNREAD)) &&
|
||||||
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.FRIEND_CHAT_ITEM) }>
|
<div className="navigation-item" onClick={ event => handleToolbarItemClick(ToolbarViewItems.FRIEND_CHAT_ITEM) }>
|
||||||
{ (chatIconType === CHAT_ICON_SHOWING) && <i className="icon icon-message" /> }
|
{ (chatIconType === CHAT_ICON_SHOWING) && <i className="icon icon-message" /> }
|
||||||
{ (chatIconType === CHAT_ICON_UNREAD) && <i className="icon icon-message is-unseen" /> }
|
{ (chatIconType === CHAT_ICON_UNREAD) && <i className="icon icon-message is-unseen" /> }
|
||||||
{ (unseenFriendListCount > 0) &&
|
|
||||||
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenFriendListCount }</div> }
|
|
||||||
</div> }
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
<div id="toolbar-friend-bar-container" className="d-none d-lg-block" />
|
<div id="toolbar-friend-bar-container" className="d-none d-lg-block" />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect } from 'react';
|
||||||
import { GetRoomEngine, GetRoomSession } from '../../../api';
|
import { GetRoomEngine, GetRoomSession } from '../../../api';
|
||||||
|
import { ItemCountView } from '../../shared/item-count/ItemCountView';
|
||||||
import { ToolbarViewItems } from '../ToolbarView.types';
|
import { ToolbarViewItems } from '../ToolbarView.types';
|
||||||
import { ToolbarMeViewProps } from './ToolbarMeView.types';
|
import { ToolbarMeViewProps } from './ToolbarMeView.types';
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ export const ToolbarMeView: FC<ToolbarMeViewProps> = props =>
|
|||||||
<div className="navigation-item" onClick={ () => handleToolbarItemClick(ToolbarViewItems.ACHIEVEMENTS_ITEM) }>
|
<div className="navigation-item" onClick={ () => handleToolbarItemClick(ToolbarViewItems.ACHIEVEMENTS_ITEM) }>
|
||||||
<i className="icon icon-me-achievements"></i>
|
<i className="icon icon-me-achievements"></i>
|
||||||
{ (unseenAchievementCount > 0) &&
|
{ (unseenAchievementCount > 0) &&
|
||||||
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenAchievementCount }</div> }
|
<ItemCountView count={ unseenAchievementCount } /> }
|
||||||
</div>
|
</div>
|
||||||
<div className="navigation-item" onClick={ () => handleToolbarItemClick(ToolbarViewItems.PROFILE_ITEM) }>
|
<div className="navigation-item" onClick={ () => handleToolbarItemClick(ToolbarViewItems.PROFILE_ITEM) }>
|
||||||
<i className="icon icon-me-profile"></i>
|
<i className="icon icon-me-profile"></i>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserProfileComposer, UserProfileEvent, UserProfileParser, UserRelationshipsComposer } from '@nitrots/nitro-renderer';
|
import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, UserCurrentBadgesComposer, UserCurrentBadgesEvent, UserProfileEvent, UserProfileParser, UserRelationshipsComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { GetSessionDataManager, LocalizeText } from '../../api';
|
import { GetSessionDataManager, GetUserProfile, LocalizeText } from '../../api';
|
||||||
import { CreateMessageHook, SendMessageHook } from '../../hooks';
|
import { CreateMessageHook, SendMessageHook } from '../../hooks';
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
|
||||||
import { BadgesContainerView } from './views/badges-container/BadgesContainerView';
|
import { BadgesContainerView } from './views/badges-container/BadgesContainerView';
|
||||||
@ -23,7 +23,10 @@ export const UserProfileView: FC = props =>
|
|||||||
|
|
||||||
const onLeaveGroup = useCallback(() =>
|
const onLeaveGroup = useCallback(() =>
|
||||||
{
|
{
|
||||||
if(userProfile && userProfile.id === GetSessionDataManager().userId) SendMessageHook(new UserProfileComposer(userProfile.id));
|
if(userProfile && userProfile.id === GetSessionDataManager().userId)
|
||||||
|
{
|
||||||
|
GetUserProfile(userProfile.id);
|
||||||
|
}
|
||||||
}, [ userProfile ]);
|
}, [ userProfile ]);
|
||||||
|
|
||||||
const OnUserCurrentBadgesEvent = useCallback((event: UserCurrentBadgesEvent) =>
|
const OnUserCurrentBadgesEvent = useCallback((event: UserCurrentBadgesEvent) =>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { RelationshipStatusEnum, RelationshipStatusInfo, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { RelationshipStatusEnum, RelationshipStatusInfo } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { LocalizeText } from '../../../../api';
|
import { GetUserProfile, LocalizeText } from '../../../../api';
|
||||||
import { SendMessageHook } from '../../../../hooks';
|
|
||||||
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
||||||
import { RelationshipsContainerViewProps } from './RelationshipsContainerView.types';
|
import { RelationshipsContainerViewProps } from './RelationshipsContainerView.types';
|
||||||
|
|
||||||
@ -11,8 +10,9 @@ export const RelationshipsContainerView: FC<RelationshipsContainerViewProps> = p
|
|||||||
|
|
||||||
const OnUserClick = useCallback((user: RelationshipStatusInfo) =>
|
const OnUserClick = useCallback((user: RelationshipStatusInfo) =>
|
||||||
{
|
{
|
||||||
if(user)
|
if(!user) return;
|
||||||
SendMessageHook(new UserProfileComposer(user.randomFriendId));
|
|
||||||
|
GetUserProfile(user.randomFriendId);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const RelationshipComponent = useCallback(({ type }) =>
|
const RelationshipComponent = useCallback(({ type }) =>
|
||||||
@ -28,7 +28,7 @@ export const RelationshipsContainerView: FC<RelationshipsContainerViewProps> = p
|
|||||||
<i className={`icon icon-relationship-${relationshipName} flex-shrink-0 align-self-baseline mt-2`} />
|
<i className={`icon icon-relationship-${relationshipName} flex-shrink-0 align-self-baseline mt-2`} />
|
||||||
<div className="w-100 d-flex flex-column">
|
<div className="w-100 d-flex flex-column">
|
||||||
<span className={'relationship mx-2' + (!simple ? ' advanced' : '')}>
|
<span className={'relationship mx-2' + (!simple ? ' advanced' : '')}>
|
||||||
<span className="cursor-pointer relationship-text" onClick={() => OnUserClick(relationshipInfo)}>
|
<span className="cursor-pointer relationship-text" onClick={ event => OnUserClick(relationshipInfo)}>
|
||||||
{
|
{
|
||||||
(relationshipInfo && relationshipInfo.friendCount > 0) ? relationshipInfo.randomFriendName : LocalizeText('extendedprofile.add.friends')
|
(relationshipInfo && relationshipInfo.friendCount > 0) ? relationshipInfo.randomFriendName : LocalizeText('extendedprofile.add.friends')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user