Friend List

This commit is contained in:
MyNameIsBatman 2021-09-08 01:03:48 -03:00
parent 6f8aabbcea
commit 2c35c31226
21 changed files with 330 additions and 83 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

View File

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

View File

@ -119,6 +119,12 @@
height: 34px; height: 34px;
} }
&.icon-cog {
background: url('../images/icons/icon_cog.png');
width: 14px;
height: 15px;
}
&.icon-joinroom { &.icon-joinroom {
background-image: url('../images/toolbar/icons/joinroom.png'); background-image: url('../images/toolbar/icons/joinroom.png');
width: 21px; width: 21px;
@ -147,6 +153,18 @@
} }
} }
&.icon-deny {
background: url('../images/icons/deny.png');
width: 13px;
height: 14px;
}
&.icon-accept {
background: url('../images/icons/accept.png');
width: 13px;
height: 14px;
}
&.icon-wired-trigger { &.icon-wired-trigger {
background-image: url('../images/wired/icon_trigger.png'); background-image: url('../images/wired/icon_trigger.png');
width: 13px; width: 13px;
@ -531,6 +549,12 @@
height: 10px; height: 10px;
} }
&.icon-relationship-none {
background: url('../images/friendlist/icons/icon_relationship_none.png');
width: 16px;
height: 14px;
}
&.icon-relationship-heart { &.icon-relationship-heart {
background: url('../images/profile/icons/heart.png'); background: url('../images/profile/icons/heart.png');
width: 16px; width: 16px;
@ -615,18 +639,6 @@
height: 13px; height: 13px;
} }
&.icon-group-remove-member {
background: url('../images/groups/icons/group_icon_remove_member.png');
width: 13px;
height: 14px;
}
&.icon-group-accept-member {
background: url('../images/groups/icons/group_icon_accept_member.png');
width: 13px;
height: 14px;
}
&.icon-group-small-owner { &.icon-group-small-owner {
background: url('../images/groups/icons/group_icon_small_owner.png'); background: url('../images/groups/icons/group_icon_small_owner.png');
width: 13px; width: 13px;
@ -663,6 +675,18 @@
height: 11px; height: 11px;
} }
&.icon-friendlist-follow {
background: url('../images/friendlist/icons/icon_follow.png');
width: 16px;
height: 14px;
}
&.icon-friendlist-chat {
background: url('../images/friendlist/icons/icon_chat.png');
width: 17px;
height: 16px;
}
&.spin { &.spin {
animation: rotating 1s linear infinite; animation: rotating 1s linear infinite;
} }

View File

@ -3,13 +3,7 @@
border-bottom: 1px solid rgba($black, 0.2); border-bottom: 1px solid rgba($black, 0.2);
} }
&.active {
> .nitro-card-accordion-item-header {
background: rgba($white, 0.5);
}
}
.nitro-card-accordion-item-content { .nitro-card-accordion-item-content {
background: rgba($black, 0.1); background: rgba($white, 0.5);
} }
} }

View File

@ -1,4 +1,4 @@
import { FriendListFragmentEvent, FriendListUpdateEvent, GetFriendRequestsComposer, MessengerInitEvent } from '@nitrots/nitro-renderer'; import { FriendListFragmentEvent, FriendListUpdateEvent, FriendRequestsEvent, GetFriendRequestsComposer, MessengerInitEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event';
import { MessengerSettings } from './common/MessengerSettings'; import { MessengerSettings } from './common/MessengerSettings';
@ -52,9 +52,22 @@ export const FriendListMessageHandler: FC<FriendListMessageHandlerProps> = props
}); });
}, [ dispatchFriendListState ]); }, [ dispatchFriendListState ]);
const onFriendRequestsEvent = useCallback((event: FriendRequestsEvent) =>
{
const parser = event.getParser();
dispatchFriendListState({
type: FriendListActions.PROCESS_REQUESTS,
payload: {
requests: parser.requests
}
});
}, [ dispatchFriendListState ]);
CreateMessageHook(MessengerInitEvent, onMessengerInitEvent); CreateMessageHook(MessengerInitEvent, onMessengerInitEvent);
CreateMessageHook(FriendListFragmentEvent, onFriendListFragmentEvent); CreateMessageHook(FriendListFragmentEvent, onFriendListFragmentEvent);
CreateMessageHook(FriendListUpdateEvent, onFriendListUpdateEvent); CreateMessageHook(FriendListUpdateEvent, onFriendListUpdateEvent);
CreateMessageHook(FriendRequestsEvent, onFriendRequestsEvent);
return null; return null;
} }

View File

@ -1,5 +1,5 @@
import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer'; import { MessengerInitComposer, RoomEngineObjectEvent, RoomObjectCategory, RoomObjectUserType } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useReducer, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { GetRoomSession, LocalizeText } from '../../api'; import { GetRoomSession, LocalizeText } from '../../api';
import { FriendEnteredRoomEvent, FriendListEvent } from '../../events'; import { FriendEnteredRoomEvent, FriendListEvent } from '../../events';
@ -8,20 +8,25 @@ import { FriendListSendFriendRequestEvent } from '../../events/friend-list/Frien
import { useRoomEngineEvent } from '../../hooks/events'; import { useRoomEngineEvent } from '../../hooks/events';
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 { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout'; import { NitroCardAccordionItemView, NitroCardAccordionView, NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout';
import { FriendListContextProvider } from './context/FriendListContext'; import { FriendListContextProvider } from './context/FriendListContext';
import { FriendListMessageHandler } from './FriendListMessageHandler'; import { FriendListMessageHandler } from './FriendListMessageHandler';
import { FriendListViewProps } from './FriendListView.types'; import { FriendListViewProps } from './FriendListView.types';
import { FriendListReducer, initialFriendList } from './reducers/FriendListReducer'; import { FriendListReducer, initialFriendList } from './reducers/FriendListReducer';
import { FriendBarView } from './views/friend-bar/FriendBarView'; import { FriendBarView } from './views/friend-bar/FriendBarView';
import { FriendListFriendsView } from './views/friends/FriendListFriendsView'; import { FriendListFriendsView } from './views/friends/FriendListFriendsView';
import { FriendListRequestsView } from './views/requests/FriendListRequestsView';
const TABS: string[] = ['friendlist.friends', 'generic.search'];
export const FriendListView: FC<FriendListViewProps> = props => export const FriendListView: FC<FriendListViewProps> = props =>
{ {
const [ friendListState, dispatchFriendListState ] = useReducer(FriendListReducer, initialFriendList);
const { friends = null, requests = null, settings = null } = friendListState;
const [ isVisible, setIsVisible ] = useState(false); const [ isVisible, setIsVisible ] = useState(false);
const [ isReady, setIsReady ] = useState(false); const [ isReady, setIsReady ] = useState(false);
const [ friendListState, dispatchFriendListState ] = useReducer(FriendListReducer, initialFriendList); const [ currentTab, setCurrentTab ] = useState<number>(0);
const { settings = null } = friendListState;
const onFriendListEvent = useCallback((event: FriendListEvent) => const onFriendListEvent = useCallback((event: FriendListEvent) =>
{ {
@ -37,7 +42,6 @@ export const FriendListView: FC<FriendListViewProps> = props =>
const requestEvent = (event as FriendListSendFriendRequestEvent); const requestEvent = (event as FriendListSendFriendRequestEvent);
return; return;
case FriendListEvent.REQUEST_FRIEND_LIST: case FriendListEvent.REQUEST_FRIEND_LIST:
console.log('requested');
dispatchUiEvent(new FriendListContentEvent(friendListState.friends)); dispatchUiEvent(new FriendListContentEvent(friendListState.friends));
return; return;
} }
@ -84,20 +88,49 @@ export const FriendListView: FC<FriendListViewProps> = props =>
SendMessageHook(new MessengerInitComposer()); SendMessageHook(new MessengerInitComposer());
}, []); }, []);
const onlineFriends = useMemo(() =>
{
if(!friends) return [];
return friends.filter(f => f.online);
}, [ friends ]);
const offlineFriends = useMemo(() =>
{
if(!friends) return [];
return friends.filter(f => !f.online);
}, [ friends ]);
return ( return (
<FriendListContextProvider value={ { friendListState, dispatchFriendListState } }> <FriendListContextProvider value={ { friendListState, dispatchFriendListState } }>
<FriendListMessageHandler /> <FriendListMessageHandler />
{ isReady && createPortal(<FriendBarView />, document.getElementById('toolbar-friend-bar-container')) } { isReady && createPortal(<FriendBarView />, document.getElementById('toolbar-friend-bar-container')) }
{ isVisible && { isVisible &&
<NitroCardView uniqueKey="friend-list" className="nitro-friend-list"> <NitroCardView className="nitro-friend-list">
<NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText('friendlist.friends') } onCloseClick={ () => setIsVisible(false) } />
<NitroCardContentView> <NitroCardContentView className="p-0">
<div className="text-black fw-bold">{ LocalizeText('friendlist.search.friendscaption') }</div> <NitroCardTabsView>
<FriendListFriendsView online={ true } /> { TABS.map((tab, index) =>
<div className="text-black fw-bold">{ LocalizeText('friendlist.search.friendscaption') }</div> {
<FriendListFriendsView online={ true } /> return (<NitroCardTabsItemView key={ index } isActive={ currentTab === index } onClick={ () => setCurrentTab(index) }>
<div className="text-black fw-bold">{ LocalizeText('friendlist.friends.offlinecaption') }</div> { LocalizeText(tab) }
<FriendListFriendsView online={ false } /> </NitroCardTabsItemView>);
}) }
</NitroCardTabsView>
<div className="text-black">
{ currentTab === 0 && <NitroCardAccordionView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends') + ` (${onlineFriends.length})` }>
<FriendListFriendsView list={ onlineFriends } />
</NitroCardAccordionItemView>
<NitroCardAccordionItemView headerText={ LocalizeText('friendlist.friends.offlinecaption') + ` (${offlineFriends.length})` }>
<FriendListFriendsView list={ offlineFriends } />
</NitroCardAccordionItemView>
{ requests.length > 0 && <NitroCardAccordionItemView headerText={ LocalizeText('friendlist.tab.friendrequests') + ` (${requests.length})` }>
<FriendListRequestsView list={ requests } />
</NitroCardAccordionItemView> }
</NitroCardAccordionView> }
</div>
</NitroCardContentView> </NitroCardContentView>
</NitroCardView> } </NitroCardView> }
</FriendListContextProvider> </FriendListContextProvider>

View File

@ -1,5 +1,12 @@
import { FriendParser } from '@nitrots/nitro-renderer';
export class MessengerFriend export class MessengerFriend
{ {
public static RELATIONSHIP_NONE: number = 0;
public static RELATIONSHIP_HEART: number = 1;
public static RELATIONSHIP_SMILE: number = 2;
public static RELATIONSHIP_BOBBA: number = 3;
public id: number = -1; public id: number = -1;
public name: string = null; public name: string = null;
public gender: number = 0; public gender: number = 0;
@ -15,4 +22,22 @@ export class MessengerFriend
public pocketHabboUser: boolean = false; public pocketHabboUser: boolean = false;
public relationshipStatus: number = -1; public relationshipStatus: number = -1;
public unread: number = 0; public unread: number = 0;
public populate(parser: FriendParser): void
{
this.id = parser.id;
this.name = parser.name;
this.gender = parser.gender;
this.online = parser.online;
this.followingAllowed = parser.followingAllowed;
this.figure = parser.figure;
this.categoryId = parser.categoryId;
this.motto = parser.motto;
this.realName = parser.realName;
this.lastAccess = parser.lastAccess;
this.persistedMessageUser = parser.persistedMessageUser;
this.vipMember = parser.vipMember;
this.pocketHabboUser = parser.pocketHabboUser;
this.relationshipStatus = parser.relationshipStatus;
}
} }

View File

@ -0,0 +1,41 @@
import { FriendRequestData } from '@nitrots/nitro-renderer';
export class MessengerRequest
{
private _id: number;
private _name: string;
private _requesterUserId: number;
private _figureString: string;
public populate(data: FriendRequestData): boolean
{
if(!data) return false;
this._id = data.requestId;
this._name = data.requesterName;
this._figureString = data.figureString;
this._requesterUserId = data.requesterUserId;
return true;
}
public get id(): number
{
return this._id;
}
public get name(): string
{
return this._name;
}
public get requesterUserId(): number
{
return this._requesterUserId;
}
public get figureString(): string
{
return this._figureString;
}
}

View File

@ -1,12 +1,21 @@
import { FriendListUpdateParser, FriendParser } from '@nitrots/nitro-renderer'; import { FriendListUpdateParser, FriendParser, FriendRequestData } from '@nitrots/nitro-renderer';
import { Reducer } from 'react'; import { Reducer } from 'react';
import { MessengerFriend } from '../common/MessengerFriend'; import { MessengerFriend } from '../common/MessengerFriend';
import { MessengerRequest } from '../common/MessengerRequest';
import { MessengerSettings } from '../common/MessengerSettings'; 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 IFriendListState export interface IFriendListState
{ {
settings: MessengerSettings; settings: MessengerSettings;
friends: MessengerFriend[]; friends: MessengerFriend[];
requests: MessengerRequest[];
} }
export interface IFriendListAction export interface IFriendListAction
@ -16,6 +25,7 @@ export interface IFriendListAction
settings?: MessengerSettings; settings?: MessengerSettings;
fragment?: FriendParser[]; fragment?: FriendParser[];
update?: FriendListUpdateParser; update?: FriendListUpdateParser;
requests?: FriendRequestData[];
} }
} }
@ -25,11 +35,13 @@ export class FriendListActions
public static UPDATE_SETTINGS: string = 'FLA_UPDATE_SETTINGS'; public static UPDATE_SETTINGS: string = 'FLA_UPDATE_SETTINGS';
public static PROCESS_FRAGMENT: string = 'FLA_PROCESS_FRAGMENT'; public static PROCESS_FRAGMENT: string = 'FLA_PROCESS_FRAGMENT';
public static PROCESS_UPDATE: string = 'FLA_PROCESS_UPDATE'; public static PROCESS_UPDATE: string = 'FLA_PROCESS_UPDATE';
public static PROCESS_REQUESTS: string = 'FLA_PROCESS_REQUESTS';
} }
export const initialFriendList: IFriendListState = { export const initialFriendList: IFriendListState = {
settings: null, settings: null,
friends: [] friends: [],
requests: []
} }
export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (state, action) => export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (state, action) =>
@ -69,6 +81,8 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
else friends.push(newFriend); else friends.push(newFriend);
} }
friends.sort(compareName);
return { ...state, friends }; return { ...state, friends };
} }
case FriendListActions.PROCESS_UPDATE: { case FriendListActions.PROCESS_UPDATE: {
@ -80,22 +94,9 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
const processUpdate = (friend: FriendParser) => const processUpdate = (friend: FriendParser) =>
{ {
const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id)); const index = friends.findIndex(existingFriend => (existingFriend.id === friend.id));
const newFriend = new MessengerFriend();
newFriend.id = friend.id; const newFriend = new MessengerFriend();
newFriend.name = friend.name; newFriend.populate(friend);
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; if(index > -1) friends[index] = newFriend;
else friends.unshift(newFriend); else friends.unshift(newFriend);
@ -113,8 +114,25 @@ export const FriendListReducer: Reducer<IFriendListState, IFriendListAction> = (
} }
} }
friends.sort(compareName);
return { ...state, friends }; return { ...state, friends };
} }
case FriendListActions.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: default:
return state; return state;
} }

View File

@ -1,13 +1,63 @@
import { FC } from 'react'; import { FollowFriendComposer, SetRelationshipStatusComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react';
import { LocalizeText } from '../../../../api';
import { SendMessageHook } from '../../../../hooks';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
import { MessengerFriend } from '../../common/MessengerFriend';
import { FriendListFriendsItemViewProps } from './FriendListFriendsItemView.types'; import { FriendListFriendsItemViewProps } from './FriendListFriendsItemView.types';
export const FriendListFriendsItemView: FC<FriendListFriendsItemViewProps> = props => export const FriendListFriendsItemView: FC<FriendListFriendsItemViewProps> = props =>
{ {
const { friend = null } = props; const { friend = null } = props;
const [ isExpanded, setIsExpanded ] = useState<boolean>(false);
const followFriend = useCallback(() =>
{
if(!friend) return;
SendMessageHook(new FollowFriendComposer(friend.id));
}, [ friend ]);
const getCurrentRelationshipName = useCallback(() =>
{
if(!friend) return 'none';
switch(friend.relationshipStatus)
{
case MessengerFriend.RELATIONSHIP_HEART: return 'heart';
case MessengerFriend.RELATIONSHIP_SMILE: return 'smile';
case MessengerFriend.RELATIONSHIP_BOBBA: return 'bobba';
default: return 'none';
}
}, [ friend ]);
const updateRelationship = useCallback((type: number) =>
{
if(type !== friend.relationshipStatus) SendMessageHook(new SetRelationshipStatusComposer(friend.id, type));
setIsExpanded(false);
}, [ friend ]);
if(!friend) return null;
return ( return (
<div className="d-flex"> <div className="px-2 py-1 d-flex gap-1 align-items-center">
<div className="text-black">{ friend.name }</div> <UserProfileIconView userId={ friend.id } />
<div>{ friend.name }</div>
<div className="ms-auto d-flex align-items-center gap-1">
{ !isExpanded && <>
{ friend.followingAllowed && <i onClick={ followFriend } className="icon icon-friendlist-follow cursor-pointer" title={ LocalizeText('friendlist.tip.follow') } /> }
{ friend.online && <i className="icon icon-friendlist-chat cursor-pointer" title={ LocalizeText('friendlist.tip.im') } /> }
<i className={ 'icon cursor-pointer icon-relationship-' + getCurrentRelationshipName() } onClick={ () => setIsExpanded(true) } title={ LocalizeText('infostand.link.relationship') } />
</> }
{ isExpanded && <>
<i className="icon icon-relationship-heart cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_HEART) } />
<i className="icon icon-relationship-smile cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_SMILE) } />
<i className="icon icon-relationship-bobba cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_BOBBA) } />
<i className="icon icon-relationship-none cursor-pointer" onClick={ () => updateRelationship(MessengerFriend.RELATIONSHIP_NONE) } />
</> }
</div>
</div> </div>
); );
} }

View File

@ -1,35 +1,17 @@
import { FC, useMemo } from 'react'; import { FC } from 'react';
import { useFriendListContext } from '../../context/FriendListContext';
import { FriendListFriendsItemView } from '../friends-item/FriendListFriendsItemView'; import { FriendListFriendsItemView } from '../friends-item/FriendListFriendsItemView';
import { FriendListFriendsViewProps } from './FriendListFriendsView.types'; import { FriendListFriendsViewProps } from './FriendListFriendsView.types';
export const FriendListFriendsView: FC<FriendListFriendsViewProps> = props => export const FriendListFriendsView: FC<FriendListFriendsViewProps> = props =>
{ {
const { online = true } = props; const { list = null } = props;
const { friendListState = null } = useFriendListContext();
const { friends = null } = friendListState;
const getFriendElements = useMemo(() => if(!list) return null;
{
if(!friends || !friends.length) return null;
const elements: JSX.Element[] = []; return (<>
{ list.map((friend, index) =>
for(const friend of friends)
{ {
if(!friend || (friend.online !== online)) continue; return <FriendListFriendsItemView key={ index } friend={ friend } />
}) }
elements.push(<FriendListFriendsItemView key={ friend.id } friend={ friend } />) </>);
}
console.log(elements);
return elements;
}, [ friends, online ]);
return (
<div className="d-flex flex-column">
{ getFriendElements }
</div>
);
} }

View File

@ -1,4 +1,5 @@
import { MessengerFriend } from './../../common/MessengerFriend';
export interface FriendListFriendsViewProps export interface FriendListFriendsViewProps
{ {
online?: boolean; list: MessengerFriend[];
} }

View File

@ -0,0 +1,37 @@
import { AcceptFriendComposer, DeclineFriendComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react';
import { SendMessageHook } from '../../../../hooks/messages/message-event';
import { UserProfileIconView } from '../../../shared/user-profile-icon/UserProfileIconView';
import { FriendListRequestsItemViewProps } from './FriendListRequestsItemView.types';
export const FriendListRequestsItemView: FC<FriendListRequestsItemViewProps> = props =>
{
const { request = null } = props;
const accept = useCallback(() =>
{
if(!request) return;
SendMessageHook(new AcceptFriendComposer(request.id));
}, [ request ]);
const decline = useCallback(() =>
{
if(!request) return;
SendMessageHook(new DeclineFriendComposer(false, request.id));
}, [ request ]);
if(!request) return null;
return (
<div className="px-2 py-1 d-flex gap-1 align-items-center">
<UserProfileIconView userId={ request.id } />
<div>{ request.name }</div>
<div className="ms-auto d-flex align-items-center gap-1">
<i className="icon icon-accept cursor-pointer" onClick={ accept } />
<i className="icon icon-deny cursor-pointer" onClick={ decline } />
</div>
</div>
);
};

View File

@ -0,0 +1,6 @@
import { MessengerRequest } from './../../common/MessengerRequest';
export interface FriendListRequestsItemViewProps
{
request: MessengerRequest;
}

View File

@ -0,0 +1,17 @@
import { FC } from 'react';
import { FriendListRequestsItemView } from '../requests-item/FriendListRequestsItemView';
import { FriendListRequestsViewProps } from './FriendListRequestsView.types';
export const FriendListRequestsView: FC<FriendListRequestsViewProps> = props =>
{
const { list = null } = props;
if(!list) return null;
return (<>
{ list.map((request, index) =>
{
return <FriendListRequestsItemView key={ index } request={ request } />
}) }
</>);
};

View File

@ -0,0 +1,6 @@
import { MessengerRequest } from './../../common/MessengerRequest';
export interface FriendListRequestsViewProps
{
list: MessengerRequest[];
}

View File

@ -177,10 +177,10 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
<i className={ 'icon icon-group-small-' + classNames({ 'owner': member.rank === GroupRank.OWNER, 'admin': member.rank === GroupRank.ADMIN, 'not-admin': member.rank === GroupRank.MEMBER, 'cursor-pointer': pageData.admin }) } title={ LocalizeText(getRankDescription(member)) } onClick={ () => toggleAdmin(member) } /> <i className={ 'icon icon-group-small-' + classNames({ 'owner': member.rank === GroupRank.OWNER, 'admin': member.rank === GroupRank.ADMIN, 'not-admin': member.rank === GroupRank.MEMBER, 'cursor-pointer': pageData.admin }) } title={ LocalizeText(getRankDescription(member)) } onClick={ () => toggleAdmin(member) } />
</div> </div>
{ member.rank === GroupRank.REQUESTED && <div className="d-flex align-items-center"> { member.rank === GroupRank.REQUESTED && <div className="d-flex align-items-center">
<i className="icon cursor-pointer icon-group-accept-member" title={ LocalizeText('group.members.accept') } onClick={ () => acceptMembership(member) } /> <i className="icon cursor-pointer icon-accept" title={ LocalizeText('group.members.accept') } onClick={ () => acceptMembership(member) } />
</div> } </div> }
{ member.rank !== GroupRank.OWNER && pageData.admin && member.id !== GetSessionDataManager().userId &&<div className="d-flex align-items-center mt-1"> { member.rank !== GroupRank.OWNER && pageData.admin && member.id !== GetSessionDataManager().userId &&<div className="d-flex align-items-center mt-1">
<i className="icon cursor-pointer icon-group-remove-member" title={ LocalizeText(member.rank === GroupRank.REQUESTED ? 'group.members.reject' : 'group.members.kick') } onClick={ () => removeMemberOrDeclineMembership(member) } /> <i className="icon cursor-pointer icon-deny" title={ LocalizeText(member.rank === GroupRank.REQUESTED ? 'group.members.reject' : 'group.members.kick') } onClick={ () => removeMemberOrDeclineMembership(member) } />
</div> } </div> }
</div> </div>
</div> </div>