Add AvatarImageView

This commit is contained in:
Bill 2021-04-14 17:47:12 -04:00
parent 37225d3261
commit 3770bf81cb
5 changed files with 149 additions and 0 deletions

View File

@ -1,3 +1,4 @@
@import './avatar-image/AvatarImage.scss';
@import './hotel-view/HotelView.scss'; @import './hotel-view/HotelView.scss';
@import './loading/LoadingView.scss'; @import './loading/LoadingView.scss';
@import './main//MainView.scss'; @import './main//MainView.scss';

View File

@ -0,0 +1,8 @@
.avatar-image {
position: relative;
width: 90px;
height: 130px;
background-repeat: no-repeat;
background-position-x: center;
background-position-y: -8px !important;
}

View File

@ -0,0 +1,111 @@
import { AdvancedMap } from 'nitro-renderer';
import { AvatarScaleType } from 'nitro-renderer/src/nitro/avatar/enum/AvatarScaleType';
import { AvatarSetType } from 'nitro-renderer/src/nitro/avatar/enum/AvatarSetType';
import { IAvatarImageListener } from 'nitro-renderer/src/nitro/avatar/IAvatarImageListener';
import { Nitro } from 'nitro-renderer/src/nitro/Nitro';
import { Component } from 'react';
import { AvatarImageViewProps, AvatarImageViewState } from './AvatarImageView.types';
export class AvatarImageView extends Component<AvatarImageViewProps, AvatarImageViewState> implements IAvatarImageListener
{
private static _maxAvatarCacheSize = 10;
private static _avatarCache: AdvancedMap<string, string> = new AdvancedMap();
private static defaultProps: AvatarImageViewProps = {
figure: '',
gender: 'M',
headOnly: false,
direction: 0,
scale: 1
};
constructor(props: AvatarImageViewProps)
{;
super(props);
this.state = {
avatarUrl: null
};
}
public dispose(): void
{
}
public componentDidMount(): void
{
this.buildAvatar();
}
private buildAvatar(): void
{
const imageUrl = this.getUserImageUrl();
if(imageUrl && imageUrl.length) this.setState({ avatarUrl: imageUrl });
}
private getUserImageUrl(): string
{
const build = this.getAvatarBuildString();
let existing = AvatarImageView._avatarCache.getValue(build);
if(!existing)
{
const avatarImage = Nitro.instance.avatar.createAvatarImage(this.props.figure, AvatarScaleType.LARGE, this.props.gender, this, null);
if(avatarImage)
{
let setType = AvatarSetType.FULL;
if(this.props.headOnly) setType = AvatarSetType.HEAD;
avatarImage.setDirection(setType, this.props.direction);
const image = avatarImage.getCroppedImage(setType);
if(image) existing = image.src;
avatarImage.dispose();
}
if(existing) this.putInCache(build, existing);
}
return existing;
}
public resetFigure(figure: string): void
{
AvatarImageView._avatarCache.remove(this.getAvatarBuildString());
this.buildAvatar();
}
public getAvatarBuildString(): string
{
return (`${ this.props.figure }:${ this.props.gender }:${ this.props.direction }:${ this.props.headOnly }`);
}
private putInCache(build: string, url: string): void
{
if(AvatarImageView._avatarCache.length === AvatarImageView._maxAvatarCacheSize) AvatarImageView._avatarCache.remove(AvatarImageView._avatarCache.getKey(0));
AvatarImageView._avatarCache.add(build, url);
}
public render(): JSX.Element
{
const url = `url('${ this.state.avatarUrl }')`;
return (
<div className="avatar-image" style={ (url && url.length) ? { backgroundImage: url } : {} }></div>
);
}
public get disposed(): boolean
{
return false;
}
}

View File

@ -0,0 +1,13 @@
export interface AvatarImageViewProps
{
figure: string;
gender?: string;
headOnly?: boolean;
direction?: number;
scale?: number;
}
export interface AvatarImageViewState
{
avatarUrl: string;
}

View File

@ -1,14 +1,29 @@
import { UserInfoEvent } from 'nitro-renderer/src/nitro/communication/messages/incoming/user/data/UserInfoEvent';
import { UserInfoDataParser } from 'nitro-renderer/src/nitro/communication/messages/parser/user/data/UserInfoDataParser';
import { useState } from 'react'; import { useState } from 'react';
import { CreateMessageHook } from '../../hooks/messages/message-event';
import { AvatarImageView } from '../avatar-image/AvatarImageView';
import { ToolbarViewProps } from './ToolbarView.types'; import { ToolbarViewProps } from './ToolbarView.types';
export function ToolbarView(props: ToolbarViewProps): JSX.Element export function ToolbarView(props: ToolbarViewProps): JSX.Element
{ {
const [ isInRoom, setIsInRoom ] = useState(false); const [ isInRoom, setIsInRoom ] = useState(false);
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
const unseenInventoryCount = 0; const unseenInventoryCount = 0;
const unseenFriendListCount = 0; const unseenFriendListCount = 0;
const unseenAchievementsCount = 0; const unseenAchievementsCount = 0;
const onUserInfoEvent = (event: UserInfoEvent) =>
{
const parser = event.getParser();
setUserInfo(parser.userInfo);
};
CreateMessageHook(new UserInfoEvent(onUserInfoEvent));
return ( return (
<div className="nitro-toolbar"> <div className="nitro-toolbar">
<div className="card p-0 overflow-hidden"> <div className="card p-0 overflow-hidden">
@ -38,6 +53,7 @@ export function ToolbarView(props: ToolbarViewProps): JSX.Element
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenFriendListCount }</div>) } <div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenFriendListCount }</div>) }
</li> </li>
<li className="list-group-item avatar-image"> <li className="list-group-item avatar-image">
{ userInfo && <AvatarImageView figure={ userInfo.figure } direction={ 2 } headOnly={ true } /> }
{ (unseenAchievementsCount > 0) && ( { (unseenAchievementsCount > 0) && (
<div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenAchievementsCount }</div>) } <div className="position-absolute bg-danger px-1 py-0 rounded shadow count">{ unseenAchievementsCount }</div>) }
</li> </li>