mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-02-20 18:52:35 +01:00
Updates
This commit is contained in:
parent
6f865f05ec
commit
40856b8c94
@ -2,6 +2,8 @@ import { IGroupChatData } from './IGroupChatData';
|
||||
|
||||
export const GetGroupChatData = (extraData: string) =>
|
||||
{
|
||||
if(!extraData || !extraData.length) return null;
|
||||
|
||||
const splitData = extraData.split('/');
|
||||
const username = splitData[0];
|
||||
const figure = splitData[1];
|
||||
|
@ -1,18 +1,8 @@
|
||||
import { FurnitureListItemParser, IObjectData } from '@nitrots/nitro-renderer';
|
||||
import { DispatchUiEvent } from '../..';
|
||||
import { FurniCategory, FurnitureItem, GetRoomEngine, GroupItem } from '../../../api';
|
||||
import { CatalogPostMarketplaceOfferEvent } from '../../../events';
|
||||
|
||||
export const attemptPlaceMarketplaceOffer = (groupItem: GroupItem) =>
|
||||
{
|
||||
const item = groupItem.getLastItem();
|
||||
|
||||
if(!item) return false;
|
||||
|
||||
if(!item.sellable) return false;
|
||||
|
||||
DispatchUiEvent(new CatalogPostMarketplaceOfferEvent(item));
|
||||
}
|
||||
import { GetRoomEngine } from '../nitro';
|
||||
import { FurniCategory } from './FurniCategory';
|
||||
import { FurnitureItem } from './FurnitureItem';
|
||||
import { GroupItem } from './GroupItem';
|
||||
|
||||
export const createGroupItem = (type: number, category: number, stuffData: IObjectData, extra: number = NaN) => new GroupItem(type, category, GetRoomEngine(), stuffData, extra);
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { PetData } from '@nitrots/nitro-renderer';
|
||||
import { cancelRoomObjectPlacement, CreateLinkEvent, getPlacingItemId, UnseenItemCategory } from '../../../api';
|
||||
import { IPetItem } from '../../../api/inventory/IPetItem';
|
||||
import { CreateLinkEvent } from '../nitro';
|
||||
import { cancelRoomObjectPlacement, getPlacingItemId } from './InventoryUtilities';
|
||||
import { IPetItem } from './IPetItem';
|
||||
import { UnseenItemCategory } from './unseen';
|
||||
|
||||
export const getAllPetIds = (petItems: IPetItem[]) => petItems.map(item => item.petData.id);
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { AdvancedMap, IObjectData, ItemDataStructure, StringDataType } from '@nitrots/nitro-renderer';
|
||||
import { createGroupItem } from '.';
|
||||
import { FurniCategory, FurnitureItem, GetSessionDataManager, GroupItem } from '../../../api';
|
||||
import { GetSessionDataManager } from '../nitro';
|
||||
import { FurniCategory } from './FurniCategory';
|
||||
import { FurnitureItem } from './FurnitureItem';
|
||||
import { createGroupItem } from './FurnitureUtilities';
|
||||
import { GroupItem } from './GroupItem';
|
||||
|
||||
const isExternalImage = (spriteId: number) => GetSessionDataManager().getWallItemData(spriteId)?.isExternalImage || false;
|
||||
|
@ -1,12 +1,15 @@
|
||||
export * from './FurniCategory';
|
||||
export * from './FurnitureItem';
|
||||
export * from './FurnitureUtilities';
|
||||
export * from './GroupItem';
|
||||
export * from './IBotItem';
|
||||
export * from './IFurnitureItem';
|
||||
export * from './InventoryUtilities';
|
||||
export * from './IPetItem';
|
||||
export * from './PetUtilities';
|
||||
export * from './TradeState';
|
||||
export * from './TradeUserData';
|
||||
export * from './TradingNotificationMessage';
|
||||
export * from './TradingNotificationType';
|
||||
export * from './TradingUtilities';
|
||||
export * from './unseen';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { FC } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useFriends } from '../../hooks';
|
||||
import { FriendBarView } from './views/FriendBarView';
|
||||
import { FriendBarView } from './views/friends-bar/FriendsBarView';
|
||||
import { FriendsListView } from './views/friends-list/FriendsListView';
|
||||
import { FriendsMessengerView } from './views/messenger/FriendsMessengerView';
|
||||
|
||||
|
@ -1,93 +0,0 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useRef, useState } from 'react';
|
||||
import { GetUserProfile, LocalizeText, MessengerFriend, OpenMessengerChat } from '../../../api';
|
||||
import { Base, Button, Flex, LayoutAvatarImageView, LayoutBadgeImageView } from '../../../common';
|
||||
import { useFriends } from '../../../hooks';
|
||||
|
||||
interface FriendBarViewProps
|
||||
{
|
||||
onlineFriends: MessengerFriend[];
|
||||
}
|
||||
|
||||
export const FriendBarView: FC<FriendBarViewProps> = props =>
|
||||
{
|
||||
const { onlineFriends = null } = props;
|
||||
const [ indexOffset, setIndexOffset ] = useState(0);
|
||||
const [ maxDisplayCount, setMaxDisplayCount ] = useState(3);
|
||||
const { followFriend = null } = useFriends();
|
||||
|
||||
const FriendBarItemView: FC<{ friend: MessengerFriend }> = props =>
|
||||
{
|
||||
const { friend = null } = props;
|
||||
const [ isVisible, setVisible ] = useState(false);
|
||||
const elementRef = useRef<HTMLDivElement>();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const onClick = (event: MouseEvent) =>
|
||||
{
|
||||
const element = elementRef.current;
|
||||
|
||||
if(!element) return;
|
||||
|
||||
if((event.target !== element) && !element.contains((event.target as Node)))
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener(MouseEventType.MOUSE_CLICK, onClick);
|
||||
|
||||
return () =>
|
||||
{
|
||||
document.removeEventListener(MouseEventType.MOUSE_CLICK, onClick);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if(!friend)
|
||||
{
|
||||
return (
|
||||
<div ref={ elementRef } className="btn btn-primary friend-bar-item friend-bar-search">
|
||||
<div className="friend-bar-item-head position-absolute"/>
|
||||
<div className="text-truncate">{ LocalizeText('friend.bar.find.title') }</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={ elementRef } className={ 'btn btn-success friend-bar-item ' + (isVisible ? 'friend-bar-item-active' : '') } onClick={ event => setVisible(prevValue => !prevValue) }>
|
||||
<div className={`friend-bar-item-head position-absolute ${friend.id > 0 ? 'avatar': 'group'}`}>
|
||||
{ friend.id > 0 && <LayoutAvatarImageView headOnly={ true } figure={ friend.figure } direction={ 2 } /> }
|
||||
{ friend.id <= 0 && <LayoutBadgeImageView isGroup={ true } badgeCode={ friend.figure} />}
|
||||
</div>
|
||||
<div className="text-truncate">{ friend.name }</div>
|
||||
{ isVisible &&
|
||||
<div className="d-flex justify-content-between">
|
||||
<Base className="nitro-friends-spritesheet icon-friendbar-chat cursor-pointer" onClick={ event => OpenMessengerChat(friend.id) } />
|
||||
{ friend.followingAllowed &&
|
||||
<Base className="nitro-friends-spritesheet icon-friendbar-visit cursor-pointer" onClick={ event => followFriend(friend) } /> }
|
||||
<Base className="nitro-friends-spritesheet icon-profile cursor-pointer" onClick={ event => GetUserProfile(friend.id) } />
|
||||
</div> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const canDecreaseIndex = () => (indexOffset === 0) ? false : true;
|
||||
const canIncreaseIndex = () => ((onlineFriends.length <= maxDisplayCount) || (indexOffset === (onlineFriends.length - 1))) ? false : true;
|
||||
|
||||
return (
|
||||
<Flex alignItems="center" className="friend-bar">
|
||||
<Button variant="black" className="friend-bar-button" disabled={ !canDecreaseIndex } onClick={ event => setIndexOffset(indexOffset - 1) }>
|
||||
<FontAwesomeIcon icon="chevron-left" />
|
||||
</Button>
|
||||
{ Array.from(Array(maxDisplayCount), (e, i) =>
|
||||
{
|
||||
return <FriendBarItemView key={ i } friend={ (onlineFriends[ indexOffset + i ] || null) } />;
|
||||
}) }
|
||||
<Button variant="black" className="friend-bar-button" disabled={ !canIncreaseIndex } onClick={ event => setIndexOffset(indexOffset + 1) }>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</Button>
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
import { MouseEventType } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useRef, useState } from 'react';
|
||||
import { GetUserProfile, LocalizeText, MessengerFriend, OpenMessengerChat } from '../../../../api';
|
||||
import { Base, LayoutAvatarImageView, LayoutBadgeImageView } from '../../../../common';
|
||||
import { useFriends } from '../../../../hooks';
|
||||
|
||||
export const FriendBarItemView: FC<{ friend: MessengerFriend }> = props =>
|
||||
{
|
||||
const { friend = null } = props;
|
||||
const [ isVisible, setVisible ] = useState(false);
|
||||
const { followFriend = null } = useFriends();
|
||||
const elementRef = useRef<HTMLDivElement>();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const onClick = (event: MouseEvent) =>
|
||||
{
|
||||
const element = elementRef.current;
|
||||
|
||||
if(!element) return;
|
||||
|
||||
if((event.target !== element) && !element.contains((event.target as Node)))
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener(MouseEventType.MOUSE_CLICK, onClick);
|
||||
|
||||
return () => document.removeEventListener(MouseEventType.MOUSE_CLICK, onClick);
|
||||
}, []);
|
||||
|
||||
if(!friend)
|
||||
{
|
||||
return (
|
||||
<div ref={ elementRef } className="btn btn-primary friend-bar-item friend-bar-search">
|
||||
<div className="friend-bar-item-head position-absolute"/>
|
||||
<div className="text-truncate">{ LocalizeText('friend.bar.find.title') }</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={ elementRef } className={ 'btn btn-success friend-bar-item ' + (isVisible ? 'friend-bar-item-active' : '') } onClick={ event => setVisible(prevValue => !prevValue) }>
|
||||
<div className={`friend-bar-item-head position-absolute ${friend.id > 0 ? 'avatar': 'group'}`}>
|
||||
{ (friend.id > 0) && <LayoutAvatarImageView headOnly={ true } figure={ friend.figure } direction={ 2 } /> }
|
||||
{ (friend.id <= 0) && <LayoutBadgeImageView isGroup={ true } badgeCode={ friend.figure} /> }
|
||||
</div>
|
||||
<div className="text-truncate">{ friend.name }</div>
|
||||
{ isVisible &&
|
||||
<div className="d-flex justify-content-between">
|
||||
<Base className="nitro-friends-spritesheet icon-friendbar-chat cursor-pointer" onClick={ event => OpenMessengerChat(friend.id) } />
|
||||
{ friend.followingAllowed &&
|
||||
<Base className="nitro-friends-spritesheet icon-friendbar-visit cursor-pointer" onClick={ event => followFriend(friend) } /> }
|
||||
<Base className="nitro-friends-spritesheet icon-profile cursor-pointer" onClick={ event => GetUserProfile(friend.id) } />
|
||||
</div> }
|
||||
</div>
|
||||
);
|
||||
}
|
28
src/components/friends/views/friends-bar/FriendsBarView.tsx
Normal file
28
src/components/friends/views/friends-bar/FriendsBarView.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { FC, useState } from 'react';
|
||||
import { MessengerFriend } from '../../../../api';
|
||||
import { Button, Flex } from '../../../../common';
|
||||
import { FriendBarItemView } from './FriendBarItemView';
|
||||
|
||||
const MAX_DISPLAY_COUNT = 3;
|
||||
|
||||
export const FriendBarView: FC<{ onlineFriends: MessengerFriend[] }> = props =>
|
||||
{
|
||||
const { onlineFriends = null } = props;
|
||||
const [ indexOffset, setIndexOffset ] = useState(0);
|
||||
|
||||
const canDecreaseIndex = () => (indexOffset === 0) ? false : true;
|
||||
const canIncreaseIndex = () => ((onlineFriends.length <= MAX_DISPLAY_COUNT) || (indexOffset === (onlineFriends.length - 1))) ? false : true;
|
||||
|
||||
return (
|
||||
<Flex alignItems="center" className="friend-bar">
|
||||
<Button variant="black" className="friend-bar-button" disabled={ !canDecreaseIndex } onClick={ event => setIndexOffset(indexOffset - 1) }>
|
||||
<FontAwesomeIcon icon="chevron-left" />
|
||||
</Button>
|
||||
{ Array.from(Array(MAX_DISPLAY_COUNT), (e, i) => <FriendBarItemView key={ i } friend={ (onlineFriends[ indexOffset + i ] || null) } />) }
|
||||
<Button variant="black" className="friend-bar-button" disabled={ !canIncreaseIndex } onClick={ event => setIndexOffset(indexOffset + 1) }>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</Button>
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
import { FC, MouseEvent, useState } from 'react';
|
||||
import { LocalizeText, MessengerFriend, OpenMessengerChat } from '../../../../api';
|
||||
import { Base, Flex, NitroCardAccordionItemView, UserProfileIconView } from '../../../../common';
|
||||
import { useFriends } from '../../../../hooks';
|
||||
|
||||
interface FriendsListGroupViewProps
|
||||
{
|
||||
list: MessengerFriend[];
|
||||
selectedFriendsIds: number[];
|
||||
selectFriend: (userId: number) => void;
|
||||
}
|
||||
|
||||
export const FriendsListGroupView: FC<FriendsListGroupViewProps> = props =>
|
||||
{
|
||||
const { list = null, selectedFriendsIds = null, selectFriend = null } = props;
|
||||
const { followFriend = null, updateRelationship = null } = useFriends();
|
||||
|
||||
if(!list || !list.length) return null;
|
||||
|
||||
const FriendsListGroupItemView: FC<{ friend: MessengerFriend, selected: boolean }> = props =>
|
||||
{
|
||||
const { friend = null, selected = false } = props;
|
||||
const [ isRelationshipOpen, setIsRelationshipOpen ] = useState<boolean>(false);
|
||||
|
||||
const clickFollowFriend = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
followFriend(friend);
|
||||
}
|
||||
|
||||
const openMessengerChat = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
OpenMessengerChat(friend.id);
|
||||
}
|
||||
|
||||
const openRelationship = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
setIsRelationshipOpen(true);
|
||||
}
|
||||
|
||||
const clickUpdateRelationship = (event: MouseEvent<HTMLDivElement>, type: number) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
updateRelationship(friend, type);
|
||||
|
||||
setIsRelationshipOpen(false);
|
||||
}
|
||||
|
||||
const getCurrentRelationshipName = () =>
|
||||
{
|
||||
if(!friend) return 'none';
|
||||
|
||||
switch(friend.relationshipStatus)
|
||||
{
|
||||
case MessengerFriend.RELATIONSHIP_HEART: return 'heart';
|
||||
case MessengerFriend.RELATIONSHIP_SMILE: return 'smile';
|
||||
case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba';
|
||||
default: return 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if(!friend) return null;
|
||||
|
||||
return (
|
||||
<NitroCardAccordionItemView justifyContent="between" className={ `px-2 py-1 ${ selected && 'bg-primary text-white' }` } onClick={ event => selectFriend(friend.id) }>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<Base onClick={ event => event.stopPropagation() }>
|
||||
<UserProfileIconView userId={ friend.id } />
|
||||
</Base>
|
||||
<div>{ friend.name }</div>
|
||||
</Flex>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
{ !isRelationshipOpen &&
|
||||
<>
|
||||
{ friend.followingAllowed &&
|
||||
<Base pointer onClick={ clickFollowFriend } className="nitro-friends-spritesheet icon-follow" title={ LocalizeText('friendlist.tip.follow') } /> }
|
||||
{ friend.online &&
|
||||
<Base pointer className="nitro-friends-spritesheet icon-chat" onClick={ openMessengerChat } title={ LocalizeText('friendlist.tip.im') } /> }
|
||||
{ (friend.id > 0) &&
|
||||
<Base className={ `nitro-friends-spritesheet icon-${ getCurrentRelationshipName() } cursor-pointer` } onClick={ openRelationship } title={ LocalizeText('infostand.link.relationship') } /> }
|
||||
</> }
|
||||
{ isRelationshipOpen &&
|
||||
<>
|
||||
<Base pointer className="nitro-friends-spritesheet icon-heart" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_HEART) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-smile" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_SMILE) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-bobba" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_BOBBA) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-none" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_NONE) } />
|
||||
</> }
|
||||
</Flex>
|
||||
</NitroCardAccordionItemView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{ list.map((item, index) => <FriendsListGroupItemView key={ index } friend={ item } selected={ selectedFriendsIds && selectedFriendsIds.includes(item.id) } />) }
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
import { LocalizeText, MessengerRequest } from '../../../../api';
|
||||
import { Base, Button, Column, Flex, NitroCardAccordionItemView, NitroCardAccordionSetView, NitroCardAccordionSetViewProps, UserProfileIconView } from '../../../../common';
|
||||
import { useFriends } from '../../../../hooks';
|
||||
|
||||
export const FriendsListRequestView: FC<NitroCardAccordionSetViewProps> = props =>
|
||||
{
|
||||
const { children = null, ...rest } = props;
|
||||
const { requests = [], requestResponse = null } = useFriends();
|
||||
|
||||
if(!requests.length) return null;
|
||||
|
||||
const FriendsListRequestItemView: FC<{ request: MessengerRequest }> = props =>
|
||||
{
|
||||
const { request = null } = props;
|
||||
|
||||
if(!request) return null;
|
||||
|
||||
return (
|
||||
<NitroCardAccordionItemView justifyContent="between" className="px-2 py-1">
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<UserProfileIconView userId={ request.id } />
|
||||
<div>{ request.name }</div>
|
||||
</Flex>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<Base className="nitro-friends-spritesheet icon-accept cursor-pointer" onClick={ event => requestResponse(request.id, true) } />
|
||||
<Base className="nitro-friends-spritesheet icon-deny cursor-pointer" onClick={ event => requestResponse(request.id, false) } />
|
||||
</Flex>
|
||||
</NitroCardAccordionItemView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NitroCardAccordionSetView { ...rest }>
|
||||
<Column fullHeight justifyContent="between" gap={ 1 }>
|
||||
<Column gap={ 0 }>
|
||||
{ requests.map((request, index) => <FriendsListRequestItemView key={ index } request={ request } />) }
|
||||
</Column>
|
||||
<Flex justifyContent="center" className="px-2 py-1">
|
||||
<Button onClick={ event => requestResponse(-1, false) }>
|
||||
{ LocalizeText('friendlist.requests.dismissall') }
|
||||
</Button>
|
||||
</Flex>
|
||||
</Column>
|
||||
{ children }
|
||||
</NitroCardAccordionSetView>
|
||||
);
|
||||
}
|
@ -3,9 +3,9 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { AddEventLinkTracker, LocalizeText, MessengerFriend, RemoveLinkEventTracker, SendMessageComposer } from '../../../../api';
|
||||
import { Button, Flex, NitroCardAccordionSetView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../common';
|
||||
import { useFriends } from '../../../../hooks';
|
||||
import { FriendsListGroupView } from './FriendsListGroupView';
|
||||
import { FriendsListGroupView } from './friends-list-group/FriendsListGroupView';
|
||||
import { FriendsListRequestView } from './friends-list-request/FriendsListRequestView';
|
||||
import { FriendsRemoveConfirmationView } from './FriendsListRemoveConfirmationView';
|
||||
import { FriendsListRequestView } from './FriendsListRequestView';
|
||||
import { FriendsRoomInviteView } from './FriendsListRoomInviteView';
|
||||
import { FriendsSearchView } from './FriendsListSearchView';
|
||||
|
||||
|
@ -0,0 +1,85 @@
|
||||
import { FC, MouseEvent, useState } from 'react';
|
||||
import { LocalizeText, MessengerFriend, OpenMessengerChat } from '../../../../../api';
|
||||
import { Base, Flex, NitroCardAccordionItemView, UserProfileIconView } from '../../../../../common';
|
||||
import { useFriends } from '../../../../../hooks';
|
||||
|
||||
export const FriendsListGroupItemView: FC<{ friend: MessengerFriend, selected: boolean, selectFriend: (userId: number) => void }> = props =>
|
||||
{
|
||||
const { friend = null, selected = false, selectFriend = null } = props;
|
||||
const [ isRelationshipOpen, setIsRelationshipOpen ] = useState<boolean>(false);
|
||||
const { followFriend = null, updateRelationship = null } = useFriends();
|
||||
|
||||
const clickFollowFriend = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
followFriend(friend);
|
||||
}
|
||||
|
||||
const openMessengerChat = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
OpenMessengerChat(friend.id);
|
||||
}
|
||||
|
||||
const openRelationship = (event: MouseEvent<HTMLDivElement>) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
setIsRelationshipOpen(true);
|
||||
}
|
||||
|
||||
const clickUpdateRelationship = (event: MouseEvent<HTMLDivElement>, type: number) =>
|
||||
{
|
||||
event.stopPropagation();
|
||||
|
||||
updateRelationship(friend, type);
|
||||
|
||||
setIsRelationshipOpen(false);
|
||||
}
|
||||
|
||||
const getCurrentRelationshipName = () =>
|
||||
{
|
||||
if(!friend) return 'none';
|
||||
|
||||
switch(friend.relationshipStatus)
|
||||
{
|
||||
case MessengerFriend.RELATIONSHIP_HEART: return 'heart';
|
||||
case MessengerFriend.RELATIONSHIP_SMILE: return 'smile';
|
||||
case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba';
|
||||
default: return 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if(!friend) return null;
|
||||
|
||||
return (
|
||||
<NitroCardAccordionItemView justifyContent="between" className={ `px-2 py-1 ${ selected && 'bg-primary text-white' }` } onClick={ event => selectFriend(friend.id) }>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<Base onClick={ event => event.stopPropagation() }>
|
||||
<UserProfileIconView userId={ friend.id } />
|
||||
</Base>
|
||||
<div>{ friend.name }</div>
|
||||
</Flex>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
{ !isRelationshipOpen &&
|
||||
<>
|
||||
{ friend.followingAllowed &&
|
||||
<Base pointer onClick={ clickFollowFriend } className="nitro-friends-spritesheet icon-follow" title={ LocalizeText('friendlist.tip.follow') } /> }
|
||||
{ friend.online &&
|
||||
<Base pointer className="nitro-friends-spritesheet icon-chat" onClick={ openMessengerChat } title={ LocalizeText('friendlist.tip.im') } /> }
|
||||
{ (friend.id > 0) &&
|
||||
<Base className={ `nitro-friends-spritesheet icon-${ getCurrentRelationshipName() } cursor-pointer` } onClick={ openRelationship } title={ LocalizeText('infostand.link.relationship') } /> }
|
||||
</> }
|
||||
{ isRelationshipOpen &&
|
||||
<>
|
||||
<Base pointer className="nitro-friends-spritesheet icon-heart" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_HEART) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-smile" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_SMILE) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-bobba" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_BOBBA) } />
|
||||
<Base pointer className="nitro-friends-spritesheet icon-none" onClick={ event => clickUpdateRelationship(event, MessengerFriend.RELATIONSHIP_NONE) } />
|
||||
</> }
|
||||
</Flex>
|
||||
</NitroCardAccordionItemView>
|
||||
);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import { FC } from 'react';
|
||||
import { MessengerFriend } from '../../../../../api';
|
||||
import { FriendsListGroupItemView } from './FriendsListGroupItemView';
|
||||
|
||||
interface FriendsListGroupViewProps
|
||||
{
|
||||
list: MessengerFriend[];
|
||||
selectedFriendsIds: number[];
|
||||
selectFriend: (userId: number) => void;
|
||||
}
|
||||
|
||||
export const FriendsListGroupView: FC<FriendsListGroupViewProps> = props =>
|
||||
{
|
||||
const { list = null, selectedFriendsIds = null, selectFriend = null } = props;
|
||||
|
||||
if(!list || !list.length) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ list.map((item, index) => <FriendsListGroupItemView key={ index } friend={ item } selected={ selectedFriendsIds && (selectedFriendsIds.indexOf(item.id) >= 0) } selectFriend={ selectFriend } />) }
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { FC } from 'react';
|
||||
import { MessengerRequest } from '../../../../../api';
|
||||
import { Base, Flex, NitroCardAccordionItemView, UserProfileIconView } from '../../../../../common';
|
||||
import { useFriends } from '../../../../../hooks';
|
||||
|
||||
export const FriendsListRequestItemView: FC<{ request: MessengerRequest }> = props =>
|
||||
{
|
||||
const { request = null } = props;
|
||||
const { requestResponse = null } = useFriends();
|
||||
|
||||
if(!request) return null;
|
||||
|
||||
return (
|
||||
<NitroCardAccordionItemView justifyContent="between" className="px-2 py-1">
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<UserProfileIconView userId={ request.id } />
|
||||
<div>{ request.name }</div>
|
||||
</Flex>
|
||||
<Flex alignItems="center" gap={ 1 }>
|
||||
<Base className="nitro-friends-spritesheet icon-accept cursor-pointer" onClick={ event => requestResponse(request.id, true) } />
|
||||
<Base className="nitro-friends-spritesheet icon-deny cursor-pointer" onClick={ event => requestResponse(request.id, false) } />
|
||||
</Flex>
|
||||
</NitroCardAccordionItemView>
|
||||
);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import { FC } from 'react';
|
||||
import { LocalizeText } from '../../../../../api';
|
||||
import { Button, Column, Flex, NitroCardAccordionSetView, NitroCardAccordionSetViewProps } from '../../../../../common';
|
||||
import { useFriends } from '../../../../../hooks';
|
||||
import { FriendsListRequestItemView } from './FriendsListRequestItemView';
|
||||
|
||||
export const FriendsListRequestView: FC<NitroCardAccordionSetViewProps> = props =>
|
||||
{
|
||||
const { children = null, ...rest } = props;
|
||||
const { requests = [], requestResponse = null } = useFriends();
|
||||
|
||||
if(!requests.length) return null;
|
||||
|
||||
return (
|
||||
<NitroCardAccordionSetView { ...rest }>
|
||||
<Column fullHeight justifyContent="between" gap={ 1 }>
|
||||
<Column gap={ 0 }>
|
||||
{ requests.map((request, index) => <FriendsListRequestItemView key={ index } request={ request } />) }
|
||||
</Column>
|
||||
<Flex justifyContent="center" className="px-2 py-1">
|
||||
<Button onClick={ event => requestResponse(-1, false) }>
|
||||
{ LocalizeText('friendlist.requests.dismissall') }
|
||||
</Button>
|
||||
</Flex>
|
||||
</Column>
|
||||
{ children }
|
||||
</NitroCardAccordionSetView>
|
||||
);
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
import { FC, useMemo } from 'react';
|
||||
import { GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||
import { Base, Flex, LayoutAvatarImageView } from '../../../../common';
|
||||
import { GroupType } from '../../common/GroupType';
|
||||
import { MessengerThread } from '../../common/MessengerThread';
|
||||
import { MessengerThreadChat } from '../../common/MessengerThreadChat';
|
||||
import { MessengerThreadChatGroup } from '../../common/MessengerThreadChatGroup';
|
||||
import { getGroupChatData } from '../../common/Utils';
|
||||
|
||||
interface FriendsMessengerThreadGroupProps
|
||||
{
|
||||
thread: MessengerThread;
|
||||
group: MessengerThreadChatGroup;
|
||||
}
|
||||
|
||||
export const FriendsMessengerThreadGroup: FC<FriendsMessengerThreadGroupProps> = props =>
|
||||
{
|
||||
const { thread = null, group = null } = props;
|
||||
|
||||
const isOwnChat = useMemo(() =>
|
||||
{
|
||||
if(!thread || !group) return false;
|
||||
|
||||
if(group.type === GroupType.PRIVATE_CHAT && (group.userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
if( (group.type === GroupType.GROUP_CHAT) && (group.chats.length && getGroupChatData(group.chats[0].extraData).userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
return false;
|
||||
}, [ group, thread ]);
|
||||
|
||||
if(!thread || !group) return null;
|
||||
|
||||
if(!group.userId)
|
||||
{
|
||||
return (
|
||||
<>
|
||||
{ group.chats.map((chat, index) =>
|
||||
{
|
||||
return (
|
||||
<div key={ index } className="d-flex gap-2 w-100 justify-content-start">
|
||||
<Base className="w-100 text-break">
|
||||
{ chat.type === MessengerThreadChat.SECURITY_NOTIFICATION &&
|
||||
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-muted align-items-center">
|
||||
<Base className="nitro-friends-spritesheet icon-warning flex-shrink-0" />
|
||||
<Base>{ chat.message }</Base>
|
||||
</Base> }
|
||||
{ chat.type === MessengerThreadChat.ROOM_INVITE &&
|
||||
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-black align-items-center">
|
||||
<Base className="messenger-notification-icon flex-shrink-0" />
|
||||
<Base>{(LocalizeText('messenger.invitation') + ' ') }{ chat.message }</Base>
|
||||
</Base> }
|
||||
</Base>
|
||||
</div>
|
||||
);
|
||||
}) }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex className={ 'w-100 justify-content-' + (isOwnChat ? 'end' : 'start') } gap={ 2 }>
|
||||
<Base className="message-avatar flex-shrink-0">
|
||||
{ (group.type === GroupType.PRIVATE_CHAT && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ thread.participant.figure } direction={ 2 } />
|
||||
}
|
||||
{ (group.type === GroupType.GROUP_CHAT && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ getGroupChatData(group.chats[0].extraData).figure } direction={ 2} />
|
||||
}
|
||||
</Base>
|
||||
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat ? 'right' : 'left') }>
|
||||
<Base className='fw-bold'>
|
||||
{ (isOwnChat) && GetSessionDataManager().userName }
|
||||
{ (!isOwnChat) && ((group.type === GroupType.GROUP_CHAT) ? getGroupChatData(group.chats[0].extraData).username : thread.participant.name)
|
||||
}
|
||||
</Base>
|
||||
{ group.chats.map((chat, index) =><Base key={ index } className="text-break">{ chat.message }</Base>) }
|
||||
</Base>
|
||||
{ (isOwnChat) &&
|
||||
<Base className="message-avatar flex-shrink-0">
|
||||
<LayoutAvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
|
||||
</Base> }
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
import { FC, useMemo } from 'react';
|
||||
import { GetGroupChatData, GetSessionDataManager, GroupType, LocalizeText, MessengerThread, MessengerThreadChat, MessengerThreadChatGroup } from '../../../../api';
|
||||
import { Base, Flex, LayoutAvatarImageView } from '../../../../common';
|
||||
|
||||
export const FriendsMessengerThreadView: FC<{ thread: MessengerThread }> = props =>
|
||||
{
|
||||
const { thread = null } = props;
|
||||
|
||||
const FriendsMessengerThreadGroup: FC<{ thread: MessengerThread, group: MessengerThreadChatGroup }> = props =>
|
||||
{
|
||||
const { thread = null, group = null, ...rest } = props;
|
||||
|
||||
const isOwnChat = useMemo(() =>
|
||||
{
|
||||
if(!thread || !group) return false;
|
||||
|
||||
if(group.type === GroupType.PRIVATE_CHAT && (group.userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
if( (group.type === GroupType.GROUP_CHAT) && (group.chats.length && GetGroupChatData(group.chats[0].extraData).userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
return false;
|
||||
}, [ group, thread ]);
|
||||
|
||||
if(!thread || !group) return null;
|
||||
|
||||
if(!group.userId)
|
||||
{
|
||||
return (
|
||||
<>
|
||||
{ group.chats.map((chat, index) =>
|
||||
{
|
||||
return (
|
||||
<Flex key={ index } fullWidth justifyContent="start" gap={ 2 }>
|
||||
<Base className="w-100 text-break">
|
||||
{ (chat.type === MessengerThreadChat.SECURITY_NOTIFICATION) &&
|
||||
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-muted align-items-center">
|
||||
<Base className="nitro-friends-spritesheet icon-warning flex-shrink-0" />
|
||||
<Base>{ chat.message }</Base>
|
||||
</Base> }
|
||||
{ (chat.type === MessengerThreadChat.ROOM_INVITE) &&
|
||||
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-black align-items-center">
|
||||
<Base className="messenger-notification-icon flex-shrink-0" />
|
||||
<Base>{ `${ LocalizeText('messenger.invitation') } ${ chat.message }` }</Base>
|
||||
</Base> }
|
||||
</Base>
|
||||
</Flex>
|
||||
);
|
||||
}) }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex className={ 'w-100 justify-content-' + (isOwnChat ? 'end' : 'start') } gap={ 2 } { ...rest }>
|
||||
<Base className="message-avatar flex-shrink-0">
|
||||
{ (group.type === GroupType.PRIVATE_CHAT && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ thread.participant.figure } direction={ 2 } />
|
||||
}
|
||||
{ (group.type === GroupType.GROUP_CHAT && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ GetGroupChatData(group.chats[0].extraData).figure } direction={ 2} />
|
||||
}
|
||||
</Base>
|
||||
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat ? 'right' : 'left') }>
|
||||
<Base className='fw-bold'>
|
||||
{ (isOwnChat) && GetSessionDataManager().userName }
|
||||
{ (!isOwnChat) && ((group.type === GroupType.GROUP_CHAT) ? GetGroupChatData(group.chats[0].extraData).username : thread.participant.name)
|
||||
}
|
||||
</Base>
|
||||
{ group.chats.map((chat, index) =><Base key={ index } className="text-break">{ chat.message }</Base>) }
|
||||
</Base>
|
||||
{ (isOwnChat) &&
|
||||
<Base className="message-avatar flex-shrink-0">
|
||||
<LayoutAvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
|
||||
</Base> }
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{ (thread.groups.length > 0) && thread.groups.map((group, index) => <FriendsMessengerThreadGroup key={ index } thread={ thread } group={ group } />) }
|
||||
</>
|
||||
);
|
||||
}
|
@ -4,14 +4,14 @@ import { FC, KeyboardEvent, useEffect, useRef, useState } from 'react';
|
||||
import { AddEventLinkTracker, GetUserProfile, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../../../api';
|
||||
import { Base, Button, ButtonGroup, Column, Flex, Grid, LayoutAvatarImageView, LayoutBadgeImageView, LayoutGridItem, LayoutItemCountView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
||||
import { useMessenger } from '../../../../hooks';
|
||||
import { FriendsMessengerThreadView } from './FriendsMessengerThreadView';
|
||||
import { FriendsMessengerThreadView } from './messenger-thread/FriendsMessengerThreadView';
|
||||
|
||||
export const FriendsMessengerView: FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState(false);
|
||||
const [ lastThreadId, setLastThreadId ] = useState(-1);
|
||||
const [ messageText, setMessageText ] = useState('');
|
||||
const { visibleThreads = [], activeThread = null, getMessageThread = null, sendMessage = null, setActiveThread = null, closeThread = null } = useMessenger();
|
||||
const { visibleThreads = [], activeThread = null, getMessageThread = null, sendMessage = null, setActiveThreadId = null, closeThread = null } = useMessenger();
|
||||
const messagesBox = useRef<HTMLDivElement>();
|
||||
|
||||
const followFriend = () => (activeThread && activeThread.participant && SendMessageComposer(new FollowFriendMessageComposer(activeThread.participant.id)));
|
||||
@ -54,7 +54,7 @@ export const FriendsMessengerView: FC<{}> = props =>
|
||||
|
||||
if(!thread) return;
|
||||
|
||||
setActiveThread(thread);
|
||||
setActiveThreadId(thread.threadId);
|
||||
setIsVisible(true);
|
||||
}
|
||||
}
|
||||
@ -65,14 +65,7 @@ export const FriendsMessengerView: FC<{}> = props =>
|
||||
AddEventLinkTracker(linkTracker);
|
||||
|
||||
return () => RemoveLinkEventTracker(linkTracker);
|
||||
}, [ getMessageThread, setActiveThread ]);
|
||||
|
||||
// useEffect(() =>
|
||||
// {
|
||||
// if(!isVisible || activeThread || !visibleThreads || !visibleThreads.length) return;
|
||||
|
||||
// setActiveThread(visibleThreads[0]);
|
||||
// }, [ isVisible, visibleThreads, activeThread, setActiveThread ]);
|
||||
}, [ getMessageThread, setActiveThreadId ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
@ -83,23 +76,26 @@ export const FriendsMessengerView: FC<{}> = props =>
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!activeThread) return;
|
||||
|
||||
return () =>
|
||||
if(isVisible && !activeThread)
|
||||
{
|
||||
if(lastThreadId > 0)
|
||||
{
|
||||
setActiveThreadId(lastThreadId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(visibleThreads.length > 0) setActiveThreadId(visibleThreads[0].threadId);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isVisible && activeThread)
|
||||
{
|
||||
console.log('set last thread id', activeThread.threadId);
|
||||
setLastThreadId(activeThread.threadId);
|
||||
setActiveThreadId(-1);
|
||||
}
|
||||
}, [ activeThread ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
console.log('clear thread')
|
||||
setActiveThread(null);
|
||||
}
|
||||
}, [ setActiveThread ]);
|
||||
}, [ isVisible, activeThread, lastThreadId, visibleThreads, setActiveThreadId ]);
|
||||
|
||||
if(!isVisible) return null;
|
||||
|
||||
@ -114,7 +110,7 @@ export const FriendsMessengerView: FC<{}> = props =>
|
||||
{ visibleThreads && (visibleThreads.length > 0) && visibleThreads.map(thread =>
|
||||
{
|
||||
return (
|
||||
<LayoutGridItem key={ thread.threadId } itemActive={ (activeThread === thread) } onClick={ event => setActiveThread(thread) }>
|
||||
<LayoutGridItem key={ thread.threadId } itemActive={ (activeThread === thread) } onClick={ event => setActiveThreadId(thread.threadId) }>
|
||||
{ thread.unread &&
|
||||
<LayoutItemCountView count={ thread.unreadCount } /> }
|
||||
<Flex fullWidth alignItems="center" gap={ 1 }>
|
||||
|
@ -0,0 +1,72 @@
|
||||
import { FC, useMemo } from 'react';
|
||||
import { GetGroupChatData, GetSessionDataManager, GroupType, LocalizeText, MessengerThread, MessengerThreadChat, MessengerThreadChatGroup } from '../../../../../api';
|
||||
import { Base, Flex, LayoutAvatarImageView } from '../../../../../common';
|
||||
|
||||
export const FriendsMessengerThreadGroup: FC<{ thread: MessengerThread, group: MessengerThreadChatGroup }> = props =>
|
||||
{
|
||||
const { thread = null, group = null } = props;
|
||||
|
||||
const groupChatData = useMemo(() => ((group.type === GroupType.GROUP_CHAT) && GetGroupChatData(group.chats[0].extraData)), [ group ]);
|
||||
|
||||
const isOwnChat = useMemo(() =>
|
||||
{
|
||||
if(!thread || !group) return false;
|
||||
|
||||
if((group.type === GroupType.PRIVATE_CHAT) && (group.userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
if(groupChatData && group.chats.length && (groupChatData.userId === GetSessionDataManager().userId)) return true;
|
||||
|
||||
return false;
|
||||
}, [ thread, group, groupChatData ]);
|
||||
|
||||
if(!thread || !group) return null;
|
||||
|
||||
if(!group.userId)
|
||||
{
|
||||
return (
|
||||
<>
|
||||
{ group.chats.map((chat, index) =>
|
||||
{
|
||||
return (
|
||||
<Flex key={ index } fullWidth gap={ 2 } justifyContent="start">
|
||||
<Base className="w-100 text-break">
|
||||
{ (chat.type === MessengerThreadChat.SECURITY_NOTIFICATION) &&
|
||||
<Flex gap={ 2 } alignItems="center" className="bg-light rounded mb-2 px-2 py-1 small text-muted">
|
||||
<Base className="nitro-friends-spritesheet icon-warning flex-shrink-0" />
|
||||
<Base>{ chat.message }</Base>
|
||||
</Flex> }
|
||||
{ (chat.type === MessengerThreadChat.ROOM_INVITE) &&
|
||||
<Flex gap={ 2 } alignItems="center" className="bg-light rounded mb-2 px-2 py-1 small text-black">
|
||||
<Base className="messenger-notification-icon flex-shrink-0" />
|
||||
<Base>{ (LocalizeText('messenger.invitation') + ' ') }{ chat.message }</Base>
|
||||
</Flex> }
|
||||
</Base>
|
||||
</Flex>
|
||||
);
|
||||
}) }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex fullWidth justifyContent={ isOwnChat ? 'end' : 'start' } gap={ 2 }>
|
||||
<Base shrink className="message-avatar">
|
||||
{ ((group.type === GroupType.PRIVATE_CHAT) && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ thread.participant.figure } direction={ 2 } /> }
|
||||
{ (groupChatData && !isOwnChat) &&
|
||||
<LayoutAvatarImageView figure={ groupChatData.figure } direction={ 2} /> }
|
||||
</Base>
|
||||
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat ? 'right' : 'left') }>
|
||||
<Base className='fw-bold'>
|
||||
{ isOwnChat && GetSessionDataManager().userName }
|
||||
{ !isOwnChat && (groupChatData ? groupChatData.username : thread.participant.name) }
|
||||
</Base>
|
||||
{ group.chats.map((chat, index) => <Base key={ index } className="text-break">{ chat.message }</Base>) }
|
||||
</Base>
|
||||
{ isOwnChat &&
|
||||
<Base shrink className="message-avatar">
|
||||
<LayoutAvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
|
||||
</Base> }
|
||||
</Flex>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import { FC } from 'react';
|
||||
import { MessengerThread } from '../../../../../api';
|
||||
import { FriendsMessengerThreadGroup } from './FriendsMessengerThreadGroup';
|
||||
|
||||
export const FriendsMessengerThreadView: FC<{ thread: MessengerThread }> = props =>
|
||||
{
|
||||
const { thread = null } = props;
|
||||
|
||||
thread.setRead();
|
||||
|
||||
return (
|
||||
<>
|
||||
{ (thread.groups.length > 0) && thread.groups.map((group, index) => <FriendsMessengerThreadGroup key={ index } thread={ thread } group={ group } />) }
|
||||
</>
|
||||
);
|
||||
}
|
@ -2,8 +2,8 @@ import { IRoomSession, RoomObjectVariable, RoomPreviewer, Vector3d } from '@nitr
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { attemptItemPlacement, FurniCategory, GetRoomEngine, GetSessionDataManager, GroupItem, LocalizeText, UnseenItemCategory } from '../../../../api';
|
||||
import { AutoGrid, Button, Column, Grid, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomPreviewerView, Text } from '../../../../common';
|
||||
import { useInventoryFurni, useInventoryUnseenTracker } from '../../../../hooks';
|
||||
import { attemptPlaceMarketplaceOffer } from '../../../../hooks/inventory/common';
|
||||
import { CatalogPostMarketplaceOfferEvent } from '../../../../events';
|
||||
import { DispatchUiEvent, useInventoryFurni, useInventoryUnseenTracker } from '../../../../hooks';
|
||||
import { InventoryCategoryEmptyView } from '../InventoryCategoryEmptyView';
|
||||
import { InventoryFurnitureItemView } from './InventoryFurnitureItemView';
|
||||
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
||||
@ -14,6 +14,17 @@ interface InventoryFurnitureViewProps
|
||||
roomPreviewer: RoomPreviewer;
|
||||
}
|
||||
|
||||
const attemptPlaceMarketplaceOffer = (groupItem: GroupItem) =>
|
||||
{
|
||||
const item = groupItem.getLastItem();
|
||||
|
||||
if(!item) return false;
|
||||
|
||||
if(!item.sellable) return false;
|
||||
|
||||
DispatchUiEvent(new CatalogPostMarketplaceOfferEvent(item));
|
||||
}
|
||||
|
||||
export const InventoryFurnitureView: FC<InventoryFurnitureViewProps> = props =>
|
||||
{
|
||||
const { roomSession = null, roomPreviewer = null } = props;
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { IObjectData, TradingListAddItemComposer, TradingListAddItemsComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { FurniCategory, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../../api';
|
||||
import { FurniCategory, getGuildFurniType, GroupItem, IFurnitureItem, LocalizeText, NotificationAlertType, NotificationUtilities, SendMessageComposer, TradeState } from '../../../../api';
|
||||
import { AutoGrid, Base, Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../../common';
|
||||
import { useInventoryTrade } from '../../../../hooks';
|
||||
import { getGuildFurniType } from '../../../../hooks/inventory/common/TradingUtilities';
|
||||
import { InventoryFurnitureSearchView } from './InventoryFurnitureSearchView';
|
||||
|
||||
interface InventoryTradeViewProps
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { RoomObjectCategory } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { LocalizeText, MessengerRequest } from '../../../../api';
|
||||
import { Base, Button, Column, Flex, Text } from '../../../../common';
|
||||
import { useFriends } from '../../../../hooks';
|
||||
import { ObjectLocationView } from '../object-location/ObjectLocationView';
|
||||
|
||||
export const FriendRequestDialogView: FC<{ roomIndex: number, request: MessengerRequest, hideFriendRequest: (userId: number) => void }> = props =>
|
||||
{
|
||||
const { roomIndex = -1, request = null, hideFriendRequest = null } = props;
|
||||
const { requestResponse = null } = useFriends();
|
||||
|
||||
return (
|
||||
<ObjectLocationView objectId={ roomIndex } category={ RoomObjectCategory.UNIT }>
|
||||
<Base className="nitro-friend-request-dialog nitro-context-menu p-2">
|
||||
<Column>
|
||||
<Flex alignItems="center" justifyContent="between" gap={ 2 }>
|
||||
<Text variant="white" fontSize={ 6 }>{ LocalizeText('widget.friendrequest.from', [ 'username' ], [ request.name ]) }</Text>
|
||||
<FontAwesomeIcon icon="times" className="cursor-pointer" onClick={ event => hideFriendRequest(request.requesterUserId) } />
|
||||
</Flex>
|
||||
<Flex justifyContent="end" gap={ 1 }>
|
||||
<Button variant="danger" onClick={ event => requestResponse(request.requesterUserId, false) }>{ LocalizeText('widget.friendrequest.decline') }</Button>
|
||||
<Button variant="success" onClick={ event => requestResponse(request.requesterUserId, true) }>{ LocalizeText('widget.friendrequest.accept') }</Button>
|
||||
</Flex>
|
||||
</Column>
|
||||
</Base>
|
||||
</ObjectLocationView>
|
||||
);
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { LocalizeText, MessengerRequest, RoomWidgetUpdateRoomObjectEvent } from '../../../../api';
|
||||
import { Base, Button, Column, Flex, Text } from '../../../../common';
|
||||
import { MessengerRequest, RoomWidgetUpdateRoomObjectEvent } from '../../../../api';
|
||||
import { UseEventDispatcherHook, useFriends } from '../../../../hooks';
|
||||
import { useRoomContext } from '../../RoomContext';
|
||||
import { ObjectLocationView } from '../object-location/ObjectLocationView';
|
||||
import { FriendRequestDialogView } from './FriendRequestDialogView';
|
||||
|
||||
export const FriendRequestWidgetView: FC<{}> = props =>
|
||||
{
|
||||
const [ displayedRequests, setDisplayedRequests ] = useState<{ roomIndex: number, request: MessengerRequest }[]>([]);
|
||||
const [ dismissedRequestIds, setDismissedRequestIds ] = useState<number[]>([]);
|
||||
const { roomSession = null, eventDispatcher = null } = useRoomContext();
|
||||
const { requests = [], requestResponse = null } = useFriends();
|
||||
const { requests = [] } = useFriends();
|
||||
|
||||
const hideFriendRequest = (userId: number) =>
|
||||
{
|
||||
@ -89,35 +87,13 @@ export const FriendRequestWidgetView: FC<{}> = props =>
|
||||
|
||||
if(!requests.length) return null;
|
||||
|
||||
const FriendRequestDialogView: FC<{ roomIndex: number, request: MessengerRequest }> = props =>
|
||||
{
|
||||
const { roomIndex = -1, request = null } = props;
|
||||
|
||||
return (
|
||||
<ObjectLocationView objectId={ roomIndex } category={ RoomObjectCategory.UNIT }>
|
||||
<Base className="nitro-friend-request-dialog nitro-context-menu p-2">
|
||||
<Column>
|
||||
<Flex alignItems="center" justifyContent="between" gap={ 2 }>
|
||||
<Text variant="white" fontSize={ 6 }>{ LocalizeText('widget.friendrequest.from', [ 'username' ], [ request.name ]) }</Text>
|
||||
<FontAwesomeIcon icon="times" className="cursor-pointer" onClick={ event => hideFriendRequest(request.requesterUserId) } />
|
||||
</Flex>
|
||||
<Flex justifyContent="end" gap={ 1 }>
|
||||
<Button variant="danger" onClick={ event => requestResponse(request.requesterUserId, false) }>{ LocalizeText('widget.friendrequest.decline') }</Button>
|
||||
<Button variant="success" onClick={ event => requestResponse(request.requesterUserId, true) }>{ LocalizeText('widget.friendrequest.accept') }</Button>
|
||||
</Flex>
|
||||
</Column>
|
||||
</Base>
|
||||
</ObjectLocationView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{ displayedRequests.map((request, index) =>
|
||||
{
|
||||
if(dismissedRequestIds.indexOf(request.request.requesterUserId) >= 0) return null;
|
||||
|
||||
return <FriendRequestDialogView key={ index } roomIndex={ request.roomIndex } request={ request.request } />;
|
||||
return <FriendRequestDialogView key={ index } roomIndex={ request.roomIndex } request={ request.request } hideFriendRequest={ hideFriendRequest } />;
|
||||
}) }
|
||||
</>
|
||||
);
|
||||
|
@ -72,13 +72,13 @@ const useFriendsState = () =>
|
||||
if(!canRequestFriend(userId)) return false;
|
||||
|
||||
setSentRequests(prevValue =>
|
||||
{
|
||||
const newSentRequests = [ ...prevValue ];
|
||||
{
|
||||
const newSentRequests = [ ...prevValue ];
|
||||
|
||||
newSentRequests.push(userId);
|
||||
newSentRequests.push(userId);
|
||||
|
||||
return newSentRequests;
|
||||
});
|
||||
return newSentRequests;
|
||||
});
|
||||
|
||||
SendMessageComposer(new RequestFriendComposer(userName));
|
||||
}, [ canRequestFriend ]);
|
||||
@ -94,25 +94,25 @@ const useFriendsState = () =>
|
||||
else
|
||||
{
|
||||
setRequests(prevValue =>
|
||||
{
|
||||
const newRequests = [ ...prevValue ];
|
||||
const index = newRequests.findIndex(request => (request.id === requestId));
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
|
||||
if(flag)
|
||||
{
|
||||
const newRequests = [ ...prevValue ];
|
||||
const index = newRequests.findIndex(request => (request.id === requestId));
|
||||
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
|
||||
}
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
newRequests.splice(index, 1);
|
||||
|
||||
if(flag)
|
||||
{
|
||||
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
|
||||
}
|
||||
|
||||
newRequests.splice(index, 1);
|
||||
|
||||
return newRequests;
|
||||
});
|
||||
return newRequests;
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
@ -136,21 +136,21 @@ const useFriendsState = () =>
|
||||
const parser = event.getParser();
|
||||
|
||||
setFriends(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const friend of parser.fragment)
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
|
||||
for(const friend of parser.fragment)
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
if(index > -1) newValue[index] = newFriend;
|
||||
else newValue.push(newFriend);
|
||||
}
|
||||
|
||||
if(index > -1) newValue[index] = newFriend;
|
||||
else newValue.push(newFriend);
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FriendListFragmentEvent, onFriendsFragmentEvent);
|
||||
@ -160,39 +160,39 @@ const useFriendsState = () =>
|
||||
const parser = event.getParser();
|
||||
|
||||
setFriends(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
const processUpdate = (friend: FriendParser) =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
|
||||
const processUpdate = (friend: FriendParser) =>
|
||||
if(index === -1)
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === friend.id));
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
|
||||
if(index === -1)
|
||||
{
|
||||
const newFriend = new MessengerFriend();
|
||||
newFriend.populate(friend);
|
||||
|
||||
newValue.unshift(newFriend);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue[index].populate(friend);
|
||||
}
|
||||
newValue.unshift(newFriend);
|
||||
}
|
||||
|
||||
for(const friend of parser.addedFriends) processUpdate(friend);
|
||||
|
||||
for(const friend of parser.updatedFriends) processUpdate(friend);
|
||||
|
||||
for(const removedFriendId of parser.removedFriendIds)
|
||||
else
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === removedFriendId));
|
||||
|
||||
if(index > -1) newValue.splice(index);
|
||||
newValue[index].populate(friend);
|
||||
}
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
for(const friend of parser.addedFriends) processUpdate(friend);
|
||||
|
||||
for(const friend of parser.updatedFriends) processUpdate(friend);
|
||||
|
||||
for(const removedFriendId of parser.removedFriendIds)
|
||||
{
|
||||
const index = newValue.findIndex(existingFriend => (existingFriend.id === removedFriendId));
|
||||
|
||||
if(index > -1) newValue.splice(index, 1);
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FriendListUpdateEvent, onFriendsUpdateEvent);
|
||||
@ -202,29 +202,29 @@ const useFriendsState = () =>
|
||||
const parser = event.getParser();
|
||||
|
||||
setRequests(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const request of parser.requests)
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||
|
||||
for(const request of parser.requests)
|
||||
if(index > 0)
|
||||
{
|
||||
const index = newValue.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||
|
||||
if(index > 0)
|
||||
{
|
||||
newValue[index] = CloneObject(newValue[index]);
|
||||
newValue[index].populate(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
const newRequest = new MessengerRequest();
|
||||
newRequest.populate(request);
|
||||
|
||||
newValue.push(newRequest);
|
||||
}
|
||||
newValue[index] = CloneObject(newValue[index]);
|
||||
newValue[index].populate(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
const newRequest = new MessengerRequest();
|
||||
newRequest.populate(request);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
newValue.push(newRequest);
|
||||
}
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FriendRequestsEvent, onFriendRequestsEvent);
|
||||
@ -235,21 +235,21 @@ const useFriendsState = () =>
|
||||
const request = parser.request;
|
||||
|
||||
setRequests(prevValue =>
|
||||
{
|
||||
const newRequests = [ ...prevValue ];
|
||||
|
||||
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||
|
||||
if(index === -1)
|
||||
{
|
||||
const newRequests = [ ...prevValue ];
|
||||
const newRequest = new MessengerRequest();
|
||||
newRequest.populate(request);
|
||||
|
||||
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
|
||||
newRequests.push(newRequest);
|
||||
}
|
||||
|
||||
if(index === -1)
|
||||
{
|
||||
const newRequest = new MessengerRequest();
|
||||
newRequest.populate(request);
|
||||
|
||||
newRequests.push(newRequest);
|
||||
}
|
||||
|
||||
return newRequests;
|
||||
});
|
||||
return newRequests;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(NewFriendRequestEvent, onNewFriendRequestEvent);
|
||||
|
@ -29,70 +29,42 @@ const useMessengerState = () =>
|
||||
thread = new MessengerThread(friend);
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
newValue.push(thread);
|
||||
newValue.push(thread);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return newValue;
|
||||
});
|
||||
|
||||
setHiddenThreadIds(prevValue =>
|
||||
{
|
||||
const index = prevValue.indexOf(thread.threadId);
|
||||
{
|
||||
const index = prevValue.indexOf(thread.threadId);
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
if(index === -1) return prevValue;
|
||||
|
||||
const newValue = [ ...prevValue ];
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
newValue.splice(index, 1);
|
||||
newValue.splice(index, 1);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return newValue;
|
||||
});
|
||||
|
||||
return thread;
|
||||
}, [ messageThreads, getFriend ]);
|
||||
|
||||
const setActiveThread = useCallback((thread: MessengerThread) =>
|
||||
{
|
||||
if(!thread)
|
||||
{
|
||||
setActiveThreadId(-1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
|
||||
const newThread = CloneObject(newValue[index]);
|
||||
|
||||
newValue[index] = newThread;
|
||||
|
||||
newThread.setRead();
|
||||
|
||||
return newValue;
|
||||
});
|
||||
|
||||
setActiveThreadId(thread.threadId);
|
||||
}, []);
|
||||
|
||||
const closeThread = (threadId: number) =>
|
||||
{
|
||||
setHiddenThreadIds(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
if(newValue.indexOf(threadId) >= 0) return prevValue;
|
||||
if(newValue.indexOf(threadId) >= 0) return prevValue;
|
||||
|
||||
newValue.push(threadId);
|
||||
newValue.push(threadId);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
|
||||
const sendMessage = (thread: MessengerThread, text: string) =>
|
||||
@ -104,81 +76,103 @@ const useMessengerState = () =>
|
||||
if((messageThreads.length === 1) && (thread.groups.length === 1)) PlaySound(SoundNames.MESSENGER_NEW_THREAD);
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
if(index === -1) return prevValue;
|
||||
|
||||
const newThread = CloneObject(newValue[index]);
|
||||
newValue[index] = CloneObject(newValue[index]);
|
||||
|
||||
newValue[index] = newThread;
|
||||
thread = newValue[index];
|
||||
|
||||
newThread.addMessage(GetSessionDataManager().userId, text, 0, null, MessengerThreadChat.CHAT);
|
||||
thread.addMessage(GetSessionDataManager().userId, text, 0, null, MessengerThreadChat.CHAT);
|
||||
|
||||
if(activeThreadId === newThread.threadId) newThread.setRead();
|
||||
if(activeThreadId === thread.threadId) thread.setRead();
|
||||
|
||||
return newValue;
|
||||
});
|
||||
return newValue;
|
||||
});
|
||||
}
|
||||
|
||||
const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const thread = getMessageThread(parser.senderId);
|
||||
|
||||
if(!thread) return;
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
let existingIndex = newValue.findIndex(newThread => (newThread.participant && (newThread.participant.id === parser.senderId)));
|
||||
let thread: MessengerThread = null;
|
||||
|
||||
if(existingIndex === -1)
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
const friend = getFriend(parser.senderId);
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
if(friend)
|
||||
{
|
||||
thread = new MessengerThread(friend);
|
||||
|
||||
const newThread = CloneObject(newValue[index]);
|
||||
newValue.push(thread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue[existingIndex] = CloneObject(newValue[existingIndex]);
|
||||
|
||||
newValue[index] = newThread;
|
||||
thread = newValue[existingIndex];
|
||||
}
|
||||
|
||||
newThread.addMessage(parser.senderId, parser.messageText, parser.secondsSinceSent, parser.extraData);
|
||||
thread.addMessage(parser.senderId, parser.messageText, parser.secondsSinceSent, parser.extraData);
|
||||
|
||||
if(activeThreadId === newThread.threadId) newThread.setRead();
|
||||
if(activeThreadId === thread.threadId) thread.setRead();
|
||||
|
||||
if(newThread.unreadCount > 0) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
|
||||
if(thread.unreadCount > 0) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, [ activeThreadId, getMessageThread ]);
|
||||
return newValue;
|
||||
});
|
||||
}, [ activeThreadId, getFriend ]);
|
||||
|
||||
UseMessageEventHook(NewConsoleMessageEvent, onNewConsoleMessageEvent);
|
||||
|
||||
const onRoomInviteEvent = useCallback((event: RoomInviteEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const thread = getMessageThread(parser.senderId);
|
||||
|
||||
if(!thread) return;
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
let existingIndex = newValue.findIndex(newThread => (newThread.participant && (newThread.participant.id === parser.senderId)));
|
||||
let thread: MessengerThread = null;
|
||||
|
||||
if(existingIndex === -1)
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const index = newValue.findIndex(newThread => (newThread.threadId === thread.threadId));
|
||||
const friend = getFriend(parser.senderId);
|
||||
|
||||
if(index === -1) return prevValue;
|
||||
if(friend)
|
||||
{
|
||||
thread = new MessengerThread(friend);
|
||||
|
||||
const newThread = CloneObject(newValue[index]);
|
||||
newValue.push(thread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue[existingIndex] = CloneObject(newValue[existingIndex]);
|
||||
|
||||
newValue[index] = newThread;
|
||||
thread = newValue[existingIndex];
|
||||
}
|
||||
|
||||
newThread.addMessage(null, parser.messageText, 0, null, MessengerThreadChat.ROOM_INVITE);
|
||||
thread.addMessage(null, parser.messageText, 0, null, MessengerThreadChat.ROOM_INVITE);
|
||||
|
||||
if(activeThreadId === newThread.threadId) newThread.setRead();
|
||||
if(activeThreadId === thread.threadId) thread.setRead();
|
||||
|
||||
if(newThread.unreadCount > 0) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
|
||||
if(thread.unreadCount > 0) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, [ activeThreadId, getMessageThread ]);
|
||||
return newValue;
|
||||
});
|
||||
}, [ activeThreadId, getFriend ]);
|
||||
|
||||
UseMessageEventHook(RoomInviteEvent, onRoomInviteEvent);
|
||||
|
||||
@ -192,31 +186,51 @@ const useMessengerState = () =>
|
||||
|
||||
UseMessageEventHook(RoomInviteErrorEvent, onRoomInviteErrorEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(activeThreadId <= 0) return;
|
||||
|
||||
setMessageThreads(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
let existingIndex = newValue.findIndex(newThread => (newThread.threadId === activeThreadId));
|
||||
|
||||
if(existingIndex === -1) return;
|
||||
|
||||
newValue[existingIndex] = CloneObject(newValue[existingIndex]);
|
||||
|
||||
newValue[existingIndex].setRead();
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, [ activeThreadId ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setIconState(prevValue =>
|
||||
{
|
||||
if(!visibleThreads.length) return MessengerIconState.HIDDEN;
|
||||
|
||||
let isUnread = false;
|
||||
|
||||
for(const thread of visibleThreads)
|
||||
{
|
||||
if(!visibleThreads.length) return MessengerIconState.HIDDEN;
|
||||
|
||||
let isUnread = false;
|
||||
|
||||
for(const thread of visibleThreads)
|
||||
if(thread.unreadCount > 0)
|
||||
{
|
||||
if(thread.unreadCount > 0)
|
||||
{
|
||||
isUnread = true;
|
||||
isUnread = true;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isUnread) return MessengerIconState.UNREAD;
|
||||
if(isUnread) return MessengerIconState.UNREAD;
|
||||
|
||||
return MessengerIconState.SHOW;
|
||||
});
|
||||
return MessengerIconState.SHOW;
|
||||
});
|
||||
}, [ visibleThreads ]);
|
||||
|
||||
return { messageThreads, activeThread, iconState, visibleThreads, getMessageThread, setActiveThread, closeThread, sendMessage };
|
||||
return { messageThreads, activeThread, iconState, visibleThreads, getMessageThread, setActiveThreadId, closeThread, sendMessage };
|
||||
}
|
||||
|
||||
export const useMessenger = () => useBetween(useMessengerState);
|
||||
|
@ -1,3 +0,0 @@
|
||||
export * from './FurnitureUtilities';
|
||||
export * from './PetUtilities';
|
||||
export * from './TradingUtilities';
|
@ -1,4 +1,3 @@
|
||||
export * from './common';
|
||||
export * from './useInventoryBadges';
|
||||
export * from './useInventoryBots';
|
||||
export * from './useInventoryFurni';
|
||||
|
@ -3,9 +3,8 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { useInventoryUnseenTracker } from '.';
|
||||
import { UseMessageEventHook } from '..';
|
||||
import { attemptItemPlacement, cancelRoomObjectPlacement, CloneObject, CreateLinkEvent, FurnitureItem, getPlacingItemId, GroupItem, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||
import { addFurnitureItem, attemptItemPlacement, cancelRoomObjectPlacement, CloneObject, CreateLinkEvent, FurnitureItem, getAllItemIds, getPlacingItemId, GroupItem, mergeFurniFragments, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||
import { useSharedVisibility } from '../useSharedVisibility';
|
||||
import { addFurnitureItem, getAllItemIds, mergeFurniFragments } from './common';
|
||||
|
||||
let furniMsgFragments: Map<number, FurnitureListItemParser>[] = null;
|
||||
|
||||
|
@ -3,10 +3,8 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { useInventoryUnseenTracker } from '.';
|
||||
import { UseMessageEventHook } from '..';
|
||||
import { SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||
import { IPetItem } from '../../api/inventory/IPetItem';
|
||||
import { addSinglePetItem, IPetItem, mergePetFragments, processPetFragment, removePetItemById, SendMessageComposer, UnseenItemCategory } from '../../api';
|
||||
import { useSharedVisibility } from '../useSharedVisibility';
|
||||
import { addSinglePetItem, mergePetFragments, processPetFragment, removePetItemById } from './common';
|
||||
|
||||
let petMsgFragments: Map<number, PetData>[] = null;
|
||||
|
||||
|
@ -3,10 +3,9 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { useInventoryFurni } from '.';
|
||||
import { UseMessageEventHook } from '..';
|
||||
import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, NotificationUtilities, SendMessageComposer, TradeState, TradeUserData, TradingNotificationMessage, TradingNotificationType } from '../../api';
|
||||
import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, NotificationUtilities, parseTradeItems, SendMessageComposer, TradeState, TradeUserData, TradingNotificationMessage, TradingNotificationType } from '../../api';
|
||||
import { InventoryTradeRequestEvent } from '../../events';
|
||||
import { UseUiEvent } from '../events';
|
||||
import { parseTradeItems } from './common';
|
||||
|
||||
const useInventoryTradeState = () =>
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user