From 3770bf81cb2e3951a87dac17aecb3d72d487e20c Mon Sep 17 00:00:00 2001 From: Bill Date: Wed, 14 Apr 2021 17:47:12 -0400 Subject: [PATCH] Add AvatarImageView --- src/views/Styles.scss | 1 + src/views/avatar-image/AvatarImage.scss | 8 ++ src/views/avatar-image/AvatarImageView.tsx | 111 ++++++++++++++++++ .../avatar-image/AvatarImageView.types.ts | 13 ++ src/views/toolbar/ToolbarView.tsx | 16 +++ 5 files changed, 149 insertions(+) create mode 100644 src/views/avatar-image/AvatarImage.scss create mode 100644 src/views/avatar-image/AvatarImageView.tsx create mode 100644 src/views/avatar-image/AvatarImageView.types.ts diff --git a/src/views/Styles.scss b/src/views/Styles.scss index 9e55c939..23cf1ea0 100644 --- a/src/views/Styles.scss +++ b/src/views/Styles.scss @@ -1,3 +1,4 @@ +@import './avatar-image/AvatarImage.scss'; @import './hotel-view/HotelView.scss'; @import './loading/LoadingView.scss'; @import './main//MainView.scss'; diff --git a/src/views/avatar-image/AvatarImage.scss b/src/views/avatar-image/AvatarImage.scss new file mode 100644 index 00000000..c1d05822 --- /dev/null +++ b/src/views/avatar-image/AvatarImage.scss @@ -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; +} diff --git a/src/views/avatar-image/AvatarImageView.tsx b/src/views/avatar-image/AvatarImageView.tsx new file mode 100644 index 00000000..a0fb615b --- /dev/null +++ b/src/views/avatar-image/AvatarImageView.tsx @@ -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 implements IAvatarImageListener +{ + private static _maxAvatarCacheSize = 10; + private static _avatarCache: AdvancedMap = 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 ( +
+ ); + } + + public get disposed(): boolean + { + return false; + } +} diff --git a/src/views/avatar-image/AvatarImageView.types.ts b/src/views/avatar-image/AvatarImageView.types.ts new file mode 100644 index 00000000..8c0e01e8 --- /dev/null +++ b/src/views/avatar-image/AvatarImageView.types.ts @@ -0,0 +1,13 @@ +export interface AvatarImageViewProps +{ + figure: string; + gender?: string; + headOnly?: boolean; + direction?: number; + scale?: number; +} + +export interface AvatarImageViewState +{ + avatarUrl: string; +} diff --git a/src/views/toolbar/ToolbarView.tsx b/src/views/toolbar/ToolbarView.tsx index 9eb76ef3..9ed795b9 100644 --- a/src/views/toolbar/ToolbarView.tsx +++ b/src/views/toolbar/ToolbarView.tsx @@ -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 { CreateMessageHook } from '../../hooks/messages/message-event'; +import { AvatarImageView } from '../avatar-image/AvatarImageView'; import { ToolbarViewProps } from './ToolbarView.types'; export function ToolbarView(props: ToolbarViewProps): JSX.Element { const [ isInRoom, setIsInRoom ] = useState(false); + const [ userInfo, setUserInfo ] = useState(null); + const unseenInventoryCount = 0; const unseenFriendListCount = 0; const unseenAchievementsCount = 0; + const onUserInfoEvent = (event: UserInfoEvent) => + { + const parser = event.getParser(); + + setUserInfo(parser.userInfo); + }; + + CreateMessageHook(new UserInfoEvent(onUserInfoEvent)); + return (
@@ -38,6 +53,7 @@ export function ToolbarView(props: ToolbarViewProps): JSX.Element
{ unseenFriendListCount }
) }
  • + { userInfo && } { (unseenAchievementsCount > 0) && (
    { unseenAchievementsCount }
    ) }