Groups updates

This commit is contained in:
MyNameIsBatman 2021-09-03 16:02:05 -03:00
parent 02dfb4150c
commit 13753e8b42
15 changed files with 101 additions and 16 deletions

View File

@ -22,6 +22,8 @@
"generic.asset.url": "${asset.url}/bundled/generic/%libname%.nitro", "generic.asset.url": "${asset.url}/bundled/generic/%libname%.nitro",
"badge.asset.url": "${image.library.url}album1584/%badgename%.gif", "badge.asset.url": "${image.library.url}album1584/%badgename%.gif",
"badge.asset.group.url": "https://cdn.ironhotel.biz/group-badge/%badgedata%.gif", "badge.asset.group.url": "https://cdn.ironhotel.biz/group-badge/%badgedata%.gif",
"badge.asset.group.external.url": "",
"badge.asset.grouparts.url": "https://cdn.ironhotel.biz/static_iron_active/c_images/Badgeparts/badgepart_%part%.png",
"furni.rotation.bounce.steps": 20, "furni.rotation.bounce.steps": 20,
"furni.rotation.bounce.height": 0.0625, "furni.rotation.bounce.height": 0.0625,
"enable.avatar.arrow": false, "enable.avatar.arrow": false,

View File

@ -522,7 +522,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
} }
event.groupId = parseInt(userData.guildId); event.groupId = parseInt(userData.guildId);
//event._Str_5235 = GetSessionDataManager()._Str_17173(int(userData._Str_4592)); event.groupBadgeId = GetSessionDataManager().getGroupBadge(event.groupId);
event.groupName = userData.groupName; event.groupName = userData.groupName;
event.badges = this.container.roomSession.userDataManager.getUserBadges(userData.webID); event.badges = this.container.roomSession.userDataManager.getUserBadges(userData.webID);
event.figure = userData.figure; event.figure = userData.figure;

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

View File

@ -591,6 +591,18 @@
height: 20px; height: 20px;
} }
&.icon-group-favorite {
background: url('../images/groups/icons/group_favorite.png');
width: 14px;
height: 14px;
}
&.icon-group-not-favorite {
background: url('../images/groups/icons/group_notfavorite.png');
width: 14px;
height: 14px;
}
&.icon-navigator-info { &.icon-navigator-info {
background: url('../images/navigator/icons/info.png'); background: url('../images/navigator/icons/info.png');
width: 18px; width: 18px;

View File

@ -1,6 +1,7 @@
import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, RoomSessionUserBadgesEvent, UserRelationshipsComposer } from '@nitrots/nitro-renderer'; import { RelationshipStatusInfoEvent, RelationshipStatusInfoMessageParser, RoomSessionUserBadgesEvent, UserRelationshipsComposer } from '@nitrots/nitro-renderer';
import classNames from 'classnames';
import { FC, FocusEvent, KeyboardEvent, useCallback, useEffect, useState } from 'react'; import { FC, FocusEvent, KeyboardEvent, useCallback, useEffect, useState } from 'react';
import { LocalizeText, RoomWidgetChangeMottoMessage, RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api'; import { GetGroupInformation, LocalizeText, RoomWidgetChangeMottoMessage, RoomWidgetUpdateInfostandUserEvent } from '../../../../../../api';
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks';
import { CreateEventDispatcherHook } from '../../../../../../hooks/events'; import { CreateEventDispatcherHook } from '../../../../../../hooks/events';
import { AvatarImageView } from '../../../../../shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../../../shared/avatar-image/AvatarImageView';
@ -82,7 +83,7 @@ export const InfoStandWidgetUserView: FC<InfoStandWidgetUserViewProps> = props =
return ( return (
<div className="d-flex flex-column nitro-card nitro-infostand rounded"> <div className="d-flex flex-column nitro-card nitro-infostand rounded">
<div className="container-fluid content-area"> <div className="container-fluid content-area overflow-visible">
<div className="d-flex justify-content-between align-items-center"> <div className="d-flex justify-content-between align-items-center">
<div className="small text-wrap"> <div className="small text-wrap">
<UserProfileIconView userId={ userData.webID } /> <UserProfileIconView userId={ userData.webID } />
@ -98,26 +99,26 @@ export const InfoStandWidgetUserView: FC<InfoStandWidgetUserViewProps> = props =
<div> <div>
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<div className="badge-image"> <div className="badge-image">
{ badges[0] && <BadgeImageView badgeCode={ badges[0] } /> } { badges[0] && <BadgeImageView badgeCode={ badges[0] } showInfo={ true } /> }
</div> </div>
<div className="badge-image"> <div className={ 'badge-image' + classNames({ ' cursor-pointer': userData.groupId > 0 }) } onClick={ () => GetGroupInformation(userData.groupId) }>
{ userData.groupId > 0 && <BadgeImageView badgeCode={ userData.groupBadgeId } isGroup={ true } /> } { userData.groupId > 0 && <BadgeImageView badgeCode={ userData.groupBadgeId } isGroup={ true } showInfo={ true } customTitle={ userData.groupName } /> }
</div> </div>
</div> </div>
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<div className="badge-image"> <div className="badge-image">
{ badges[1] && <BadgeImageView badgeCode={ badges[1] } /> } { badges[1] && <BadgeImageView badgeCode={ badges[1] } showInfo={ true } /> }
</div> </div>
<div className="badge-image"> <div className="badge-image">
{ badges[2] && <BadgeImageView badgeCode={ badges[2] } /> } { badges[2] && <BadgeImageView badgeCode={ badges[2] } showInfo={ true } /> }
</div> </div>
</div> </div>
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<div className="badge-image"> <div className="badge-image">
{ badges[3] && <BadgeImageView badgeCode={ badges[3] } /> } { badges[3] && <BadgeImageView badgeCode={ badges[3] } showInfo={ true } /> }
</div> </div>
<div className="badge-image"> <div className="badge-image">
{ badges[4] && <BadgeImageView badgeCode={ badges[4] } /> } { badges[4] && <BadgeImageView badgeCode={ badges[4] } showInfo={ true } /> }
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,4 +4,16 @@
height: 100%; height: 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
.badge-information {
display: none;
}
&:hover {
.badge-information {
display: block;
}
}
@import './badge-info/BadgeInformationView';
} }

View File

@ -1,10 +1,11 @@
import { FC } from 'react'; import { FC } from 'react';
import { GetConfiguration } from '../../../api'; import { GetConfiguration, LocalizeBadgeDescription, LocalizeBadgeName, LocalizeText } from '../../../api';
import { BadgeInformationView } from './badge-info/BadgeInformationView';
import { BadgeImageViewProps } from './BadgeImageView.types'; import { BadgeImageViewProps } from './BadgeImageView.types';
export const BadgeImageView: FC<BadgeImageViewProps> = props => export const BadgeImageView: FC<BadgeImageViewProps> = props =>
{ {
const { badgeCode = null, isGroup = false } = props; const { badgeCode = null, isGroup = false, showInfo = false, customTitle = null } = props;
function getBadgeUrl(): string function getBadgeUrl(): string
{ {
@ -20,5 +21,7 @@ export const BadgeImageView: FC<BadgeImageViewProps> = props =>
const url = `url('${ getBadgeUrl() }')`; const url = `url('${ getBadgeUrl() }')`;
return <div className="badge-image" style={ (url && url.length) ? { backgroundImage: url } : {} }></div>; return <div className="badge-image" style={ (url && url.length) ? { backgroundImage: url } : {} }>
{ showInfo && <BadgeInformationView title={ isGroup ? customTitle : LocalizeBadgeName(badgeCode) } description={ isGroup ? LocalizeText('group.badgepopup.body') : LocalizeBadgeDescription(badgeCode) } /> }
</div>;
} }

View File

@ -2,4 +2,6 @@ export interface BadgeImageViewProps
{ {
badgeCode: string; badgeCode: string;
isGroup?: boolean; isGroup?: boolean;
showInfo?: boolean;
customTitle?: string;
} }

View File

@ -0,0 +1,22 @@
.badge-information {
position: absolute;
pointer-events: none;
user-select: none;
width: 260px;
border-radius: $border-radius;
background: $white;
left: -270px;
z-index: 100;
&:before {
position: absolute;
content: ' ';
width: 0;
height: 0;
border-left: 10px solid $white;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
top: 10px;
right: -10px;
}
}

View File

@ -0,0 +1,14 @@
import { FC } from 'react';
import { BadgeInformationViewProps } from './BadgeInformationView.types';
export const BadgeInformationView: FC<BadgeInformationViewProps> = props =>
{
const { title = null, description = null } = props;
return (
<div className="badge-information text-black py-1 px-2 small">
<div className="fw-bold mb-2">{ title }</div>
<div>{ description }</div>
</div>
);
};

View File

@ -0,0 +1,5 @@
export interface BadgeInformationViewProps
{
title: string;
description: string;
}

View File

@ -13,5 +13,11 @@
border-color: $grid-active-border-color !important; border-color: $grid-active-border-color !important;
background-color: $grid-active-bg-color !important; background-color: $grid-active-bg-color !important;
} }
.icon {
z-index: 1;
top: 0px;
right: 0px;
}
} }
} }

View File

@ -1,4 +1,4 @@
import { GroupInformationComposer, GroupInformationEvent, GroupInformationParser } from '@nitrots/nitro-renderer'; import { GroupFavoriteComposer, GroupInformationComposer, GroupInformationEvent, GroupInformationParser } from '@nitrots/nitro-renderer';
import classNames from 'classnames'; import classNames from 'classnames';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { CreateMessageHook, SendMessageHook } from '../../../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../../../hooks';
@ -36,6 +36,11 @@ export const GroupsContainerView: FC<GroupsContainerViewProps> = props =>
if(selectedGroupId) SendMessageHook(new GroupInformationComposer(selectedGroupId, false)); if(selectedGroupId) SendMessageHook(new GroupInformationComposer(selectedGroupId, false));
}, [ selectedGroupId ]); }, [ selectedGroupId ]);
const favoriteGroup = useCallback((groupId: number) =>
{
SendMessageHook(new GroupFavoriteComposer(groupId));
}, []);
if(!groups) return null; if(!groups) return null;
return ( return (
@ -44,7 +49,8 @@ export const GroupsContainerView: FC<GroupsContainerViewProps> = props =>
<div className="h-100 overflow-auto d-flex flex-column gap-1"> <div className="h-100 overflow-auto d-flex flex-column gap-1">
{ groups.map((group, index) => { groups.map((group, index) =>
{ {
return <div key={ index } onClick={ () => setSelectedGroupId(group.id) } className={ 'profile-groups-item flex-shrink-0 d-flex align-items-center justify-content-center cursor-pointer' + classNames({ ' active': selectedGroupId === group.id }) }> return <div key={ index } onClick={ () => setSelectedGroupId(group.id) } className={ 'profile-groups-item position-relative flex-shrink-0 d-flex align-items-center justify-content-center cursor-pointer' + classNames({ ' active': selectedGroupId === group.id }) }>
<i className={ 'position-absolute icon icon-group-' + (group.ownerOrFavorite ? 'favorite' : 'not-favorite') } onClick={ () => favoriteGroup(group.id) } />
<BadgeImageView badgeCode={ group.badge } isGroup={ true } /> <BadgeImageView badgeCode={ group.badge } isGroup={ true } />
</div> </div>
}) } }) }

View File

@ -33,7 +33,7 @@ export const UserContainerView: FC<UserContainerViewProps> = props =>
<div className="col-sm-8"> <div className="col-sm-8">
<div className="user-info-container"> <div className="user-info-container">
<div className="fw-bold">{userProfile.username}</div> <div className="fw-bold">{userProfile.username}</div>
<div className="fst-italic">{userProfile.motto}</div> <div className="fst-italic text-break small">{userProfile.motto}</div>
<div dangerouslySetInnerHTML={{ __html: LocalizeText('extendedprofile.created', ['created'], [userProfile.registration]) }} /> <div dangerouslySetInnerHTML={{ __html: LocalizeText('extendedprofile.created', ['created'], [userProfile.registration]) }} />
<div dangerouslySetInnerHTML={{ __html: LocalizeText('extendedprofile.last.login', ['lastlogin'], [FriendlyTime.format(userProfile.secondsSinceLastVisit, '.ago', 2)]) }} /> <div dangerouslySetInnerHTML={{ __html: LocalizeText('extendedprofile.last.login', ['lastlogin'], [FriendlyTime.format(userProfile.secondsSinceLastVisit, '.ago', 2)]) }} />
<div><b>{LocalizeText('extendedprofile.achievementscore')}</b> {userProfile.achievementPoints}</div> <div><b>{LocalizeText('extendedprofile.achievementscore')}</b> {userProfile.achievementPoints}</div>