Merge branch 'dev' into feature/furni-widget-externalimage

This commit is contained in:
Bill 2021-08-15 01:41:28 -04:00
commit 243c0dc6dc
372 changed files with 4517 additions and 3544 deletions

3844
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,29 +3,16 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@testing-library/jest-dom": "^5.14.1", "@nitrots/nitro-renderer": "file:../nitro-renderer",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"@types/jest": "^26.0.24",
"@types/node": "^12.20.16",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"animate.css": "^4.1.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"immutable": "^4.0.0-rc.14",
"nitro-renderer": "file:../nitro-renderer",
"node-sass": "^5.0.0", "node-sass": "^5.0.0",
"rc-slider": "^9.7.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^2.0.0-alpha.2", "react-bootstrap": "^2.0.0-alpha.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-draggable": "^4.4.3",
"react-google-recaptcha": "^2.1.0",
"react-input-autosize": "^3.0.0",
"react-redux": "^7.2.4",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"react-slider": "^1.3.1", "react-slider": "^1.3.1",
"react-transition-group": "^4.4.2", "react-transition-group": "^4.4.2",
"react-virtualized": "^9.22.3",
"typescript": "^4.3.5", "typescript": "^4.3.5",
"web-vitals": "^1.1.2" "web-vitals": "^1.1.2"
}, },
@ -60,7 +47,15 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"@types/jest": "^26.0.24",
"@types/node": "^12.20.19",
"@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9",
"@types/react-slider": "^1.3.1", "@types/react-slider": "^1.3.1",
"@types/react-transition-group": "^4.4.2" "@types/react-transition-group": "^4.4.2",
"@types/react-virtualized": "^9.21.13"
} }
} }

View File

@ -1,57 +1,10 @@
{ {
"image.library.notifications.url": "${image.library.url}notifications/%image%.png", "image.library.notifications.url": "${image.library.url}notifications/%image%.png",
"achievements.images.url": "${image.library.url}Quests/%image%.png", "achievements.images.url": "${image.library.url}Quests/%image%.png",
"camera.url": "https://nitro.nitrots.co/camera",
"thumbnails.url": "https://nitro.nitrots.co/camera/thumbnail/%thumbnail%.png", "thumbnails.url": "https://nitro.nitrots.co/camera/thumbnail/%thumbnail%.png",
"url.prefix": "http://localhost:3000", "url.prefix": "http://localhost:3000",
"chat.viewer.height.percentage": 0.40, "chat.viewer.height.percentage": 0.40,
"auth.system.enabled": true,
"auth.system.http.enabled": true,
"auth.system.http.endpoint.login": "https://reqres.in/api/posts",
"auth.system.http.endpoint.register": "https://reqres.in/api/posts",
"auth.system.sso_field_name": "username",
"auth.system.recaptcha.public_key": "",
"auth.system.recaptcha.field_name": "recaptcha",
"auth.system.login.fields": [
{
"name": "username",
"label": "Username",
"type": "text",
"col": 12
},
{
"name": "password",
"label": "Password",
"type": "password",
"col": 12
}
],
"auth.system.register.enabled": true,
"auth.system.register.fields": [
{
"name": "username",
"label": "Username",
"type": "text",
"col": 12
},
{
"name": "email",
"label": "Email Address",
"type": "email",
"col": 12
},
{
"name": "password",
"label": "Password",
"type": "password",
"col": 6
},
{
"name": "confirm_password",
"label": "Confirm Password",
"type": "password",
"col": 6
}
],
"navigator.slider.enabled": true, "navigator.slider.enabled": true,
"navigator.slider.content": [ "navigator.slider.content": [
{ {

View File

@ -1,11 +1,10 @@
import { ConfigurationEvent, LegacyExternalInterface, Nitro, NitroCommunicationDemoEvent, NitroEvent, NitroLocalizationEvent, RoomEngineEvent, WebGL } from 'nitro-renderer'; import { ConfigurationEvent, LegacyExternalInterface, Nitro, NitroCommunicationDemoEvent, NitroEvent, NitroLocalizationEvent, NitroVersion, RoomEngineEvent, WebGL } from '@nitrots/nitro-renderer';
import { FC, useCallback, useState } from 'react'; import { FC, useCallback, useState } from 'react';
import { GetCommunication, GetConfiguration, GetNitroInstance } from './api'; import { GetCommunication, GetConfiguration, GetNitroInstance } from './api';
import { useConfigurationEvent } from './hooks/events/core/configuration/configuration-event'; import { useConfigurationEvent } from './hooks/events/core/configuration/configuration-event';
import { useLocalizationEvent } from './hooks/events/nitro/localization/localization-event'; import { useLocalizationEvent } from './hooks/events/nitro/localization/localization-event';
import { dispatchMainEvent, useMainEvent } from './hooks/events/nitro/main-event'; import { dispatchMainEvent, useMainEvent } from './hooks/events/nitro/main-event';
import { useRoomEngineEvent } from './hooks/events/nitro/room/room-engine-event'; import { useRoomEngineEvent } from './hooks/events/nitro/room/room-engine-event';
import { AuthView } from './views/auth/AuthView';
import { LoadingView } from './views/loading/LoadingView'; import { LoadingView } from './views/loading/LoadingView';
import { MainView } from './views/main/MainView'; import { MainView } from './views/main/MainView';
@ -13,13 +12,16 @@ export const App: FC<{}> = props =>
{ {
const [ isReady, setIsReady ] = useState(false); const [ isReady, setIsReady ] = useState(false);
const [ isError, setIsError ] = useState(false); const [ isError, setIsError ] = useState(false);
const [ isAuth, setIsAuth ] = useState(false);
const [ message, setMessage ] = useState('Getting Ready'); const [ message, setMessage ] = useState('Getting Ready');
//@ts-ignore //@ts-ignore
if(!NitroConfig) throw new Error('NitroConfig is not defined!'); if(!NitroConfig) throw new Error('NitroConfig is not defined!');
if(!GetNitroInstance()) Nitro.bootstrap(); if(!GetNitroInstance())
{
NitroVersion.UI_VERSION = '2.0.0';
Nitro.bootstrap();
}
const getPreloadAssetUrls = useCallback(() => const getPreloadAssetUrls = useCallback(() =>
{ {
@ -58,17 +60,8 @@ export const App: FC<{}> = props =>
case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKING: case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKING:
return; return;
case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED: case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED:
const authEnabled = (GetConfiguration('auth.system.enabled') as boolean); setIsError(true);
setMessage('Handshake Failed');
if(authEnabled)
{
setIsAuth(true);
}
else
{
setIsError(true);
setMessage('Handshake Failed');
}
return; return;
case NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED: case NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED:
setMessage('Finishing Up'); setMessage('Finishing Up');
@ -132,9 +125,8 @@ export const App: FC<{}> = props =>
return ( return (
<div className="nitro-app"> <div className="nitro-app">
{ (!isReady || isError) && !isAuth && <LoadingView isError={ isError } message={ message } /> } { (!isReady || isError) && <LoadingView isError={ isError } message={ message } /> }
{ (isReady && !isError && !isAuth) && <MainView /> } { (isReady && !isError) && <MainView /> }
{ isAuth && <AuthView /> }
</div> </div>
); );
} }

View File

@ -1,4 +1,4 @@
import { IConfigurationManager } from 'nitro-renderer'; import { IConfigurationManager } from '@nitrots/nitro-renderer';
import { GetNitroCore } from './GetNitroCore'; import { GetNitroCore } from './GetNitroCore';
export function GetConfigurationManager(): IConfigurationManager export function GetConfigurationManager(): IConfigurationManager

View File

@ -1,4 +1,4 @@
import { INitroCore } from 'nitro-renderer'; import { INitroCore } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../nitro'; import { GetNitroInstance } from '../nitro';
export function GetNitroCore(): INitroCore export function GetNitroCore(): INitroCore

View File

@ -1,4 +1,4 @@
import { RoomInfoComposer } from 'nitro-renderer'; import { RoomInfoComposer } from '@nitrots/nitro-renderer';
import { SendMessageHook } from '../../hooks/messages/message-event'; import { SendMessageHook } from '../../hooks/messages/message-event';
export function TryVisitRoom(roomId: number): void export function TryVisitRoom(roomId: number): void

View File

@ -1,6 +0,0 @@
import { GetRoomSessionManager } from '../nitro';
export function VisitRoom(roomId: number, password: string = null): void
{
GetRoomSessionManager().createSession(roomId, password);
}

View File

@ -1,4 +1,4 @@
import { ILinkEventTracker } from 'nitro-renderer'; import { ILinkEventTracker } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from './GetNitroInstance'; import { GetNitroInstance } from './GetNitroInstance';
export function AddEventLinkTracker(tracker: ILinkEventTracker): void export function AddEventLinkTracker(tracker: ILinkEventTracker): void

View File

@ -1,4 +1,4 @@
import { INitroCommunicationManager } from 'nitro-renderer'; import { INitroCommunicationManager } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from './GetNitroInstance'; import { GetNitroInstance } from './GetNitroInstance';
export function GetCommunication(): INitroCommunicationManager export function GetCommunication(): INitroCommunicationManager

View File

@ -1,4 +1,4 @@
import { IConnection } from 'nitro-renderer'; import { IConnection } from '@nitrots/nitro-renderer';
import { GetCommunication } from './GetCommunication'; import { GetCommunication } from './GetCommunication';
export function GetConnection(): IConnection export function GetConnection(): IConnection

View File

@ -1,4 +1,4 @@
import { INitro, Nitro } from 'nitro-renderer'; import { INitro, Nitro } from '@nitrots/nitro-renderer';
export function GetNitroInstance(): INitro export function GetNitroInstance(): INitro
{ {

View File

@ -1,4 +1,4 @@
import { ILinkEventTracker } from 'nitro-renderer'; import { ILinkEventTracker } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from './GetNitroInstance'; import { GetNitroInstance } from './GetNitroInstance';
export function RemoveLinkEventTracker(tracker: ILinkEventTracker): void export function RemoveLinkEventTracker(tracker: ILinkEventTracker): void

View File

@ -1,4 +1,4 @@
import { IPalette } from 'nitro-renderer'; import { IPalette } from '@nitrots/nitro-renderer';
import { GetAvatarRenderManager } from './GetAvatarRenderManager'; import { GetAvatarRenderManager } from './GetAvatarRenderManager';
export function GetAvatarPalette(paletteId: number): IPalette export function GetAvatarPalette(paletteId: number): IPalette

View File

@ -1,4 +1,4 @@
import { IAvatarRenderManager } from 'nitro-renderer'; import { IAvatarRenderManager } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../GetNitroInstance'; import { GetNitroInstance } from '../GetNitroInstance';
export function GetAvatarRenderManager(): IAvatarRenderManager export function GetAvatarRenderManager(): IAvatarRenderManager

View File

@ -1,4 +1,4 @@
import { ISetType } from 'nitro-renderer'; import { ISetType } from '@nitrots/nitro-renderer';
import { GetAvatarRenderManager } from './GetAvatarRenderManager'; import { GetAvatarRenderManager } from './GetAvatarRenderManager';
export function GetAvatarSetType(setType: string): ISetType export function GetAvatarSetType(setType: string): ISetType

View File

@ -1,4 +1,4 @@
import { IRoomCameraWidgetManager } from 'nitro-renderer/src/nitro/camera/IRoomCameraWidgetManager'; import { IRoomCameraWidgetManager } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../GetNitroInstance'; import { GetNitroInstance } from '../GetNitroInstance';
export function GetRoomCameraWidgetManager(): IRoomCameraWidgetManager export function GetRoomCameraWidgetManager(): IRoomCameraWidgetManager

View File

@ -1,4 +1,4 @@
import { MouseEventType } from 'nitro-renderer'; import { MouseEventType } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from './GetRoomEngine'; import { GetRoomEngine } from './GetRoomEngine';
import { SetActiveRoomId } from './SetActiveRoomId'; import { SetActiveRoomId } from './SetActiveRoomId';

View File

@ -1,4 +1,4 @@
import { MouseEventType, TouchEventType } from 'nitro-renderer'; import { MouseEventType, TouchEventType } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from './GetRoomEngine'; import { GetRoomEngine } from './GetRoomEngine';
let didMouseMove = false; let didMouseMove = false;

View File

@ -1,4 +1,4 @@
import { IRoomObjectController, RoomObjectCategory } from 'nitro-renderer'; import { IRoomObjectController, RoomObjectCategory } from '@nitrots/nitro-renderer';
import { GetRoomSession, GetSessionDataManager } from '../session'; import { GetRoomSession, GetSessionDataManager } from '../session';
import { GetRoomEngine } from './GetRoomEngine'; import { GetRoomEngine } from './GetRoomEngine';

View File

@ -1,4 +1,4 @@
import { IRoomEngine } from 'nitro-renderer'; import { IRoomEngine } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../GetNitroInstance'; import { GetNitroInstance } from '../GetNitroInstance';
export function GetRoomEngine(): IRoomEngine export function GetRoomEngine(): IRoomEngine

View File

@ -1,4 +1,4 @@
import { NitroRectangle } from 'nitro-renderer'; import { NitroRectangle } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from './GetRoomEngine'; import { GetRoomEngine } from './GetRoomEngine';
export function GetRoomObjectBounds(roomId: number, objectId: number, category: number, canvasId = 1): NitroRectangle export function GetRoomObjectBounds(roomId: number, objectId: number, category: number, canvasId = 1): NitroRectangle

View File

@ -1,4 +1,4 @@
import { RoomEngineObjectEvent, RoomObjectVariable } from 'nitro-renderer'; import { RoomEngineObjectEvent, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from '../..'; import { GetSessionDataManager } from '../..';
import { GetRoomEngine } from './GetRoomEngine'; import { GetRoomEngine } from './GetRoomEngine';

View File

@ -1,4 +1,4 @@
import { IRoomSession, RoomControllerLevel } from 'nitro-renderer'; import { IRoomSession, RoomControllerLevel } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from '../..'; import { GetSessionDataManager } from '../..';
import { GetRoomEngine } from '../room/GetRoomEngine'; import { GetRoomEngine } from '../room/GetRoomEngine';
import { IsOwnerOfFurniture } from './IsOwnerOfFurniture'; import { IsOwnerOfFurniture } from './IsOwnerOfFurniture';

View File

@ -0,0 +1,6 @@
import { GetRoomSessionManager } from './GetRoomSessionManager';
export function CreateRoomSession(roomId: number, password: string = null): void
{
GetRoomSessionManager().createSession(roomId, password);
}

View File

@ -1,4 +1,4 @@
import { AvatarAction, RoomObjectVariable } from 'nitro-renderer'; import { AvatarAction, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetOwnRoomObject } from '../room'; import { GetOwnRoomObject } from '../room';
export function GetCanStandUp(): string export function GetCanStandUp(): string

View File

@ -1,4 +1,4 @@
import { RoomObjectVariable } from 'nitro-renderer'; import { RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetOwnRoomObject } from '../room'; import { GetOwnRoomObject } from '../room';
export function GetCanUseExpression(): boolean export function GetCanUseExpression(): boolean

View File

@ -1,4 +1,4 @@
import { CatalogProductOfferData, FurnitureType, IFurnitureData } from 'nitro-renderer'; import { CatalogProductOfferData, FurnitureType, IFurnitureData } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from './GetSessionDataManager'; import { GetSessionDataManager } from './GetSessionDataManager';
export function GetFurnitureDataForProductOffer(offer: CatalogProductOfferData): IFurnitureData export function GetFurnitureDataForProductOffer(offer: CatalogProductOfferData): IFurnitureData

View File

@ -1,4 +1,4 @@
import { IFurnitureData, RoomObjectCategory, RoomObjectVariable } from 'nitro-renderer'; import { IFurnitureData, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from '../room'; import { GetRoomEngine } from '../room';
import { GetSessionDataManager } from './GetSessionDataManager'; import { GetSessionDataManager } from './GetSessionDataManager';

View File

@ -1,4 +1,4 @@
import { AvatarAction, RoomObjectVariable } from 'nitro-renderer'; import { AvatarAction, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetOwnRoomObject } from '../room'; import { GetOwnRoomObject } from '../room';
export function GetOwnPosture(): string export function GetOwnPosture(): string

View File

@ -1,4 +1,4 @@
import { IProductData } from 'nitro-renderer'; import { IProductData } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from './GetSessionDataManager'; import { GetSessionDataManager } from './GetSessionDataManager';
export function GetProductDataForLocalization(localizationId: string): IProductData export function GetProductDataForLocalization(localizationId: string): IProductData

View File

@ -1,4 +1,4 @@
import { IRoomSession } from 'nitro-renderer'; import { IRoomSession } from '@nitrots/nitro-renderer';
import { GetRoomSessionManager } from './GetRoomSessionManager'; import { GetRoomSessionManager } from './GetRoomSessionManager';
export function GetRoomSession(): IRoomSession export function GetRoomSession(): IRoomSession

View File

@ -1,4 +1,4 @@
import { IRoomSessionManager } from 'nitro-renderer'; import { IRoomSessionManager } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../GetNitroInstance'; import { GetNitroInstance } from '../GetNitroInstance';
export function GetRoomSessionManager(): IRoomSessionManager export function GetRoomSessionManager(): IRoomSessionManager

View File

@ -1,4 +1,4 @@
import { ISessionDataManager } from 'nitro-renderer'; import { ISessionDataManager } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../GetNitroInstance'; import { GetNitroInstance } from '../GetNitroInstance';
export function GetSessionDataManager(): ISessionDataManager export function GetSessionDataManager(): ISessionDataManager

View File

@ -0,0 +1,7 @@
import { DesktopViewComposer } from '@nitrots/nitro-renderer';
import { SendMessageHook } from '../../../hooks';
export function GoToDesktop(): void
{
SendMessageHook(new DesktopViewComposer());
}

View File

@ -1,4 +1,4 @@
import { HabboClubLevelEnum } from 'nitro-renderer'; import { HabboClubLevelEnum } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from './GetSessionDataManager'; import { GetSessionDataManager } from './GetSessionDataManager';
export function HasHabboClub(): boolean export function HasHabboClub(): boolean

View File

@ -1,4 +1,4 @@
import { HabboClubLevelEnum } from 'nitro-renderer'; import { HabboClubLevelEnum } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from './GetSessionDataManager'; import { GetSessionDataManager } from './GetSessionDataManager';
export function HasHabboVip(): boolean export function HasHabboVip(): boolean

View File

@ -1,4 +1,4 @@
import { IRoomObject, RoomObjectVariable } from 'nitro-renderer'; import { IRoomObject, RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from '../../../api'; import { GetSessionDataManager } from '../../../api';
export function IsOwnerOfFurniture(roomObject: IRoomObject): boolean export function IsOwnerOfFurniture(roomObject: IRoomObject): boolean

View File

@ -1,4 +1,4 @@
import { RoomObjectVariable } from 'nitro-renderer'; import { RoomObjectVariable } from '@nitrots/nitro-renderer';
import { GetOwnRoomObject } from '../room'; import { GetOwnRoomObject } from '../room';
export function IsRidingHorse(): boolean export function IsRidingHorse(): boolean

View File

@ -1,4 +1,4 @@
import { IRoomSession } from 'nitro-renderer'; import { IRoomSession } from '@nitrots/nitro-renderer';
import { GetRoomSessionManager } from './GetRoomSessionManager'; import { GetRoomSessionManager } from './GetRoomSessionManager';
export function StartRoomSession(session: IRoomSession): void export function StartRoomSession(session: IRoomSession): void

View File

@ -1,4 +1,5 @@
export * from './CanManipulateFurniture'; export * from './CanManipulateFurniture';
export * from './CreateRoomSession';
export * from './GetCanStandUp'; export * from './GetCanStandUp';
export * from './GetCanUseExpression'; export * from './GetCanUseExpression';
export * from './GetClubMemberLevel'; export * from './GetClubMemberLevel';
@ -9,6 +10,7 @@ export * from './GetProductDataForLocalization';
export * from './GetRoomSession'; export * from './GetRoomSession';
export * from './GetRoomSessionManager'; export * from './GetRoomSessionManager';
export * from './GetSessionDataManager'; export * from './GetSessionDataManager';
export * from './GoToDesktop';
export * from './HasHabboClub'; export * from './HasHabboClub';
export * from './HasHabboVip'; export * from './HasHabboVip';
export * from './IsOwnerOfFurniture'; export * from './IsOwnerOfFurniture';

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

View File

@ -82,6 +82,8 @@ $pale-sky: #677181 !default;
$oslo-gray: #8F9297 !default; $oslo-gray: #8F9297 !default;
$ghost: #c8cad0 !default; $ghost: #c8cad0 !default;
$gray-chateau: #a3a7b1 !default; $gray-chateau: #a3a7b1 !default;
$gable-green: #1C323F !default;
$william: #3d5f6e !default;
$success: $green !default; $success: $green !default;
$info: $cyan !default; $info: $cyan !default;
$warning: $yellow !default; $warning: $yellow !default;

View File

@ -476,13 +476,13 @@
&.icon-camera-colormatrix { &.icon-camera-colormatrix {
background: url('../images/icons/camera-colormatrix.png'); background: url('../images/icons/camera-colormatrix.png');
width: 32px; width: 32px;
height: 14px; height: 21px;
} }
&.icon-camera-composite { &.icon-camera-composite {
background: url('../images/icons/camera-composite.png'); background: url('../images/icons/camera-composite.png');
width: 32px; width: 32px;
height: 14px; height: 21px;
} }
&.icon-user-profile { &.icon-user-profile {

View File

@ -1,5 +1,6 @@
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 0.5rem; width: 0.5rem;
height: 0.5rem;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class AchievementsUIEvent extends NitroEvent export class AchievementsUIEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class AvatarEditorEvent extends NitroEvent export class AvatarEditorEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class CatalogEvent extends NitroEvent export class CatalogEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { CatalogPurchaseData } from 'nitro-renderer'; import { CatalogPurchaseData } from '@nitrots/nitro-renderer';
import { CatalogEvent } from './CatalogEvent'; import { CatalogEvent } from './CatalogEvent';
export class CatalogPurchasedEvent extends CatalogEvent export class CatalogPurchasedEvent extends CatalogEvent

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class FriendListEvent extends NitroEvent export class FriendListEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class InventoryBadgesRequestEvent extends NitroEvent export class InventoryBadgesRequestEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class InventoryBadgesUpdatedEvent extends NitroEvent export class InventoryBadgesUpdatedEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class InventoryEvent extends NitroEvent export class InventoryEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class UnseenItemTrackerUpdateEvent extends NitroEvent export class UnseenItemTrackerUpdateEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class ModToolsEvent extends NitroEvent export class ModToolsEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class NavigatorEvent extends NitroEvent export class NavigatorEvent extends NitroEvent
{ {

View File

@ -0,0 +1,27 @@
import { NitroEvent, RoomDataParser } from '@nitrots/nitro-renderer';
export class UpdateDoorStateEvent extends NitroEvent
{
public static START_DOORBELL: string = 'UDSE_START_DOORBELL';
public static START_PASSWORD: string = 'UDSE_START_PASSWORD';
public static STATE_PENDING_SERVER: string = 'UDSE_STATE_PENDING_SERVER';
public static UPDATE_STATE: string = 'UDSE_UPDATE_STATE';
public static STATE_WAITING: string = 'UDSE_STATE_WAITING';
public static STATE_NO_ANSWER: string = 'UDSE_STATE_NO_ANSWER';
public static STATE_WRONG_PASSWORD: string = 'UDSE_STATE_WRONG_PASSWORD';
public static STATE_ACCEPTED: string = 'UDSE_STATE_ACCEPTED';
private _roomData: RoomDataParser
constructor(type: string, roomData: RoomDataParser = null)
{
super(type);
this._roomData = roomData;
}
public get roomData(): RoomDataParser
{
return this._roomData;
}
}

View File

@ -1 +1,2 @@
export * from './NavigatorEvent'; export * from './NavigatorEvent';
export * from './UpdateDoorStateEvent';

View File

@ -1,4 +1,4 @@
import { NitroNotification } from '../../views/notification-center/utils/Notification'; import { NitroNotification } from '../../views/notification-center/common/Notification';
import { NotificationCenterEvent } from './NotificationCenterEvent'; import { NotificationCenterEvent } from './NotificationCenterEvent';
export class NotificationCenterAddNotificationEvent extends NotificationCenterEvent export class NotificationCenterAddNotificationEvent extends NotificationCenterEvent

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class NotificationCenterAlertEvent extends NitroEvent export class NotificationCenterAlertEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class NotificationCenterEvent extends NitroEvent export class NotificationCenterEvent extends NitroEvent
{ {

View File

@ -1 +1,2 @@
export * from './camera'; export * from './camera';
export * from './thumbnail';

View File

@ -0,0 +1,8 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
export class UserSettingsUIEvent extends NitroEvent
{
public static SHOW_USER_SETTINGS: string = 'NE_SHOW_USER_SETTINGS';
public static HIDE_USER_SETTINGS: string = 'NE_HIDE_USER_SETTINGS';
public static TOGGLE_USER_SETTINGS: string = 'NE_TOGGLE_USER_SETTINGS';
}

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class WiredEvent extends NitroEvent export class WiredEvent extends NitroEvent
{ {

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetCommunication } from '../../../../api'; import { GetCommunication } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetConfigurationManager } from '../../../../api'; import { GetConfigurationManager } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { IEventDispatcher, NitroEvent } from 'nitro-renderer'; import { IEventDispatcher, NitroEvent } from '@nitrots/nitro-renderer';
import { useEffect } from 'react'; import { useEffect } from 'react';
export function CreateEventDispatcherHook(type: string, eventDispatcher: IEventDispatcher, handler: (event: NitroEvent) => void): void export function CreateEventDispatcherHook(type: string, eventDispatcher: IEventDispatcher, handler: (event: NitroEvent) => void): void

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetAvatarRenderManager } from '../../../../api'; import { GetAvatarRenderManager } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../../../../api'; import { GetNitroInstance } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../../../../api'; import { GetNitroInstance } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetNitroInstance } from '../../../api'; import { GetNitroInstance } from '../../../api';
import { CreateEventDispatcherHook, DispatchEventHook } from '../event-dispatcher.base'; import { CreateEventDispatcherHook, DispatchEventHook } from '../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from '../../../../api'; import { GetRoomEngine } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetRoomSessionManager } from '../../../../api'; import { GetRoomSessionManager } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { NitroEvent } from 'nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
import { GetSessionDataManager } from '../../../../api'; import { GetSessionDataManager } from '../../../../api';
import { CreateEventDispatcherHook } from '../../event-dispatcher.base'; import { CreateEventDispatcherHook } from '../../event-dispatcher.base';

View File

@ -1,4 +1,4 @@
import { EventDispatcher, IEventDispatcher, NitroEvent } from 'nitro-renderer'; import { EventDispatcher, IEventDispatcher, NitroEvent } from '@nitrots/nitro-renderer';
import { CreateEventDispatcherHook, DispatchEventHook } from '../event-dispatcher.base'; import { CreateEventDispatcherHook, DispatchEventHook } from '../event-dispatcher.base';
const uiEventDispatcher: IEventDispatcher = new EventDispatcher(); const uiEventDispatcher: IEventDispatcher = new EventDispatcher();

View File

@ -1,4 +1,4 @@
import { IMessageComposer, IMessageEvent, MessageEvent } from 'nitro-renderer'; import { IMessageComposer, IMessageEvent, MessageEvent } from '@nitrots/nitro-renderer';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { GetCommunication, GetConnection } from '../../api'; import { GetCommunication, GetConnection } from '../../api';

View File

@ -1,6 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Ubuntu+Condensed:wght@300;400;500&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Ubuntu+Condensed:wght@300;400;500&display=swap');
@import '../node_modules/animate.css/animate.css';
@import '../node_modules/rc-slider/assets/index.css';
@import './assets/styles'; @import './assets/styles';
html, html,

View File

@ -5,12 +5,12 @@ import { NitroCardViewProps } from './NitroCardView.types';
export const NitroCardView: FC<NitroCardViewProps> = props => export const NitroCardView: FC<NitroCardViewProps> = props =>
{ {
const { className = '', disableDrag = false, simple = false, theme = 'primary', children = null } = props; const { className = '', simple = false, theme = 'primary', children = null, ...rest } = props;
return ( return (
<NitroCardContextProvider value={ { theme, simple } }> <NitroCardContextProvider value={ { theme, simple } }>
<div className="nitro-card-responsive"> <div className="nitro-card-responsive">
<DraggableWindow handle=".drag-handler" disableDrag= { disableDrag }> <DraggableWindow { ...rest }>
<div className={ 'nitro-card d-flex flex-column rounded border shadow overflow-hidden ' + className }> <div className={ 'nitro-card d-flex flex-column rounded border shadow overflow-hidden ' + className }>
{ children } { children }
</div> </div>

View File

@ -1,7 +1,8 @@
export interface NitroCardViewProps import { DraggableWindowProps } from '../draggable-window';
export interface NitroCardViewProps extends DraggableWindowProps
{ {
className?: string; className?: string;
disableDrag?: boolean;
simple?: boolean; simple?: boolean;
theme?: string; theme?: string;
} }

View File

@ -1,19 +1,27 @@
import { FC, MouseEvent, useCallback, useEffect, useMemo, useRef } from 'react'; import { MouseEventType } from '@nitrots/nitro-renderer';
import Draggable from 'react-draggable'; import { FC, Key, MouseEvent as ReactMouseEvent, useCallback, useEffect, useRef, useState } from 'react';
import { DraggableWindowProps } from './DraggableWindow.types'; import { DraggableWindowPosition, DraggableWindowProps } from './DraggableWindow.types';
const currentWindows: HTMLDivElement[] = []; const CURRENT_WINDOWS: HTMLElement[] = [];
const POS_MEMORY: Map<Key, { x: number, y: number }> = new Map();
const BOUNDS_THRESHOLD_TOP: number = 0;
const BOUNDS_THRESHOLD_LEFT: number = 0;
export const DraggableWindow: FC<DraggableWindowProps> = props => export const DraggableWindow: FC<DraggableWindowProps> = props =>
{ {
const { disableDrag = false, noCenter = false, handle = '.drag-handler', draggableOptions = {}, children = null } = props; const { uniqueKey = null, handleSelector = '.drag-handler', position = DraggableWindowPosition.CENTER, disableDrag = false, children = null } = props;
const [ delta, setDelta ] = useState<{ x: number, y: number }>(null);
const [ offset, setOffset ] = useState<{ x: number, y: number }>(null);
const [ start, setStart ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
const [ isDragging, setIsDragging ] = useState(false);
const [ dragHandler, setDragHandler ] = useState<HTMLElement>(null);
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
const bringToTop = useCallback(() => const bringToTop = useCallback(() =>
{ {
let zIndex = 400; let zIndex = 400;
for(const existingWindow of currentWindows) for(const existingWindow of CURRENT_WINDOWS)
{ {
zIndex += 1; zIndex += 1;
@ -21,69 +29,170 @@ export const DraggableWindow: FC<DraggableWindowProps> = props =>
} }
}, []); }, []);
const onMouseDown = useCallback((event: MouseEvent) => const onMouseDown = useCallback((event: ReactMouseEvent) =>
{ {
const index = currentWindows.indexOf(elementRef.current); const index = CURRENT_WINDOWS.indexOf(elementRef.current);
if(index === -1) if(index === -1)
{ {
currentWindows.push(elementRef.current); CURRENT_WINDOWS.push(elementRef.current);
} }
else if(index === (currentWindows.length - 1)) return; else if(index === (CURRENT_WINDOWS.length - 1)) return;
else if(index >= 0) else if(index >= 0)
{ {
currentWindows.splice(index, 1); CURRENT_WINDOWS.splice(index, 1);
currentWindows.push(elementRef.current); CURRENT_WINDOWS.push(elementRef.current);
} }
bringToTop(); bringToTop();
}, [ bringToTop ]); }, [ bringToTop ]);
const onDragMouseDown = useCallback((event: MouseEvent) =>
{
setStart({ x: event.clientX, y: event.clientY });
setIsDragging(true);
}, []);
const onDragMouseMove = useCallback((event: MouseEvent) =>
{
setDelta({ x: (event.clientX - start.x), y: (event.clientY - start.y) });
}, [ start ]);
const onDragMouseUp = useCallback((event: MouseEvent) =>
{
if(!elementRef.current || !dragHandler) return;
let offsetX = (offset.x + delta.x);
let offsetY = (offset.y + delta.y);
const left = elementRef.current.offsetLeft + offsetX;
const top = elementRef.current.offsetTop + offsetY;
if(top < BOUNDS_THRESHOLD_TOP)
{
offsetY = -elementRef.current.offsetTop;
}
else if((top + dragHandler.offsetHeight) >= (document.body.offsetHeight - BOUNDS_THRESHOLD_TOP))
{
offsetY = (document.body.offsetHeight - elementRef.current.offsetHeight) - elementRef.current.offsetTop;
}
if((left + elementRef.current.offsetWidth) < BOUNDS_THRESHOLD_LEFT)
{
offsetX = -elementRef.current.offsetLeft;
}
else if(left >= (document.body.offsetWidth - BOUNDS_THRESHOLD_LEFT))
{
offsetX = (document.body.offsetWidth - elementRef.current.offsetWidth) - elementRef.current.offsetLeft;
}
setDelta({ x: 0, y: 0 });
setOffset({ x: offsetX, y: offsetY });
setIsDragging(false);
if(uniqueKey !== null) POS_MEMORY.set(uniqueKey, { x: offsetX, y: offsetY });
}, [ dragHandler, delta, offset, uniqueKey ]);
useEffect(() => useEffect(() =>
{ {
if(!elementRef) return; const element = (elementRef.current as HTMLElement);
const element = elementRef.current;
currentWindows.push(element); if(!element) return;
CURRENT_WINDOWS.push(element);
bringToTop(); bringToTop();
if(!noCenter) if(!disableDrag)
{ {
const left = ((document.body.clientWidth / 2) - (element.clientWidth / 2)); const handle = (element.querySelector(handleSelector) as HTMLElement);
const top = ((document.body.clientHeight / 2) - (element.clientHeight / 2));
element.style.left = `${ left }px`; if(handle) setDragHandler(handle);
element.style.top = `${ top }px`;
}
else
{
element.style.left = `0px`;
element.style.top = `0px`;
} }
element.style.visibility = 'visible'; let offsetX = 0;
let offsetY = 0;
switch(position)
{
case DraggableWindowPosition.TOP_CENTER:
element.style.top = '50px';
element.style.left = `calc(50vw - ${ (element.offsetWidth / 2) }px)`;
break;
case DraggableWindowPosition.CENTER:
element.style.top = `calc(50vh - ${ (element.offsetHeight / 2) }px)`;
element.style.left = `calc(50vw - ${ (element.offsetWidth / 2) }px)`;
break;
}
if(uniqueKey !== null)
{
const memory = POS_MEMORY.get(uniqueKey);
if(memory)
{
offsetX = memory.x;
offsetY = memory.y;
}
}
setDelta({ x: 0, y: 0});
setOffset({ x: offsetX, y: offsetY });
return () => return () =>
{ {
const index = currentWindows.indexOf(element); const index = CURRENT_WINDOWS.indexOf(element);
if(index >= 0) currentWindows.splice(index, 1); if(index >= 0) CURRENT_WINDOWS.splice(index, 1);
} }
}, [ elementRef, noCenter, bringToTop ]); }, [ handleSelector, position, uniqueKey, disableDrag, bringToTop ]);
const getWindowContent = useMemo(() => useEffect(() =>
{ {
return ( if(!offset && !delta) return;
<div ref={ elementRef } className="position-absolute draggable-window" onMouseDownCapture={ onMouseDown }>
{ children } const element = (elementRef.current as HTMLElement);
</div>
);
}, [ children, onMouseDown ]);
return disableDrag ? getWindowContent : <Draggable handle={ handle } { ...draggableOptions }>{ getWindowContent }</Draggable>; if(!element) return;
element.style.transform = `translate(${ offset.x + delta.x }px, ${ offset.y + delta.y }px)`;
element.style.visibility = 'visible';
}, [ offset, delta ]);
useEffect(() =>
{
if(!dragHandler) return;
dragHandler.addEventListener(MouseEventType.MOUSE_DOWN, onDragMouseDown);
return () =>
{
dragHandler.removeEventListener(MouseEventType.MOUSE_DOWN, onDragMouseDown);
}
}, [ dragHandler, onDragMouseDown ]);
useEffect(() =>
{
if(!isDragging) return;
document.addEventListener(MouseEventType.MOUSE_UP, onDragMouseUp);
document.addEventListener(MouseEventType.MOUSE_MOVE, onDragMouseMove);
return () =>
{
document.removeEventListener(MouseEventType.MOUSE_UP, onDragMouseUp);
document.removeEventListener(MouseEventType.MOUSE_MOVE, onDragMouseMove);
}
}, [ isDragging, onDragMouseUp, onDragMouseMove ]);
return (
<div ref={ elementRef } className="position-absolute draggable-window" onMouseDownCapture={ onMouseDown }>
{ children }
</div>
);
} }

View File

@ -1,11 +1,16 @@
import { ReactNode } from 'react'; import { Key } from 'react';
import { DraggableProps } from 'react-draggable';
export interface DraggableWindowProps export interface DraggableWindowProps
{ {
handle: string; uniqueKey?: Key;
draggableOptions?: Partial<DraggableProps>; handleSelector?: string;
position?: string;
disableDrag?: boolean; disableDrag?: boolean;
noCenter?: boolean; }
children?: ReactNode;
export class DraggableWindowPosition
{
public static CENTER: string = 'DWP_CENTER';
public static TOP_CENTER: string = 'DWP_TOP_CENTER';
public static NOTHING: string = 'DWP_NOTHING';
} }

View File

@ -1,5 +1,6 @@
export * from './card'; export * from './card';
export * from './draggable-window'; export * from './draggable-window';
export * from './loading-spinner'; export * from './loading-spinner';
export * from './mini-camera';
export * from './transitions'; export * from './transitions';
export * from './trophy'; export * from './trophy';

View File

@ -0,0 +1,38 @@
import { NitroRectangle } from '@nitrots/nitro-renderer';
import { FC, useCallback, useRef } from 'react';
import { GetRoomEngine } from '../../api';
import { LocalizeText } from '../../utils';
import { DraggableWindow } from '../draggable-window';
import { NitroLayoutMiniCameraViewProps } from './NitroLayoutMiniCameraView.types';
export const NitroLayoutMiniCameraView: FC<NitroLayoutMiniCameraViewProps> = props =>
{
const { roomId = -1, textureReceiver = null, onClose = null } = props;
const elementRef = useRef<HTMLDivElement>();
const getCameraBounds = useCallback(() =>
{
if(!elementRef || !elementRef.current) return null;
const frameBounds = elementRef.current.getBoundingClientRect();
return new NitroRectangle(Math.floor(frameBounds.x), Math.floor(frameBounds.y), Math.floor(frameBounds.width), Math.floor(frameBounds.height));
}, []);
const takePicture = useCallback(() =>
{
textureReceiver(GetRoomEngine().createTextureFromRoom(roomId, 1, getCameraBounds()));
}, [ roomId, getCameraBounds, textureReceiver ]);
return (
<DraggableWindow handleSelector=".nitro-room-thumbnail-camera">
<div className="nitro-room-thumbnail-camera px-2">
<div ref={ elementRef } className={ 'camera-frame' } />
<div className="d-flex align-items-end h-100 pb-2">
<button className="btn btn-sm btn-danger w-100 mb-1 me-2" onClick={ onClose }>{ LocalizeText('cancel') }</button>
<button className="btn btn-sm btn-success w-100 mb-1" onClick={ takePicture }>{ LocalizeText('navigator.thumbeditor.save') }</button>
</div>
</div>
</DraggableWindow>
);
};

View File

@ -0,0 +1,8 @@
import { NitroRenderTexture } from '@nitrots/nitro-renderer';
export interface NitroLayoutMiniCameraViewProps
{
roomId: number;
textureReceiver: (texture: NitroRenderTexture) => void;
onClose: () => void;
}

View File

@ -0,0 +1,2 @@
export * from './NitroLayoutMiniCameraView';
export * from './NitroLayoutMiniCameraView.types';

View File

@ -8,7 +8,7 @@ export const NitroLayoutTrophyView: FC<NitroLayoutTrophyViewProps> = props =>
const { color = '', message = '', date = '', senderName = '', onCloseClick = null } = props; const { color = '', message = '', date = '', senderName = '', onCloseClick = null } = props;
return ( return (
<DraggableWindow handle=".drag-handler"> <DraggableWindow handleSelector=".drag-handler">
<div className={ `nitro-layout-trophy trophy-${ color }` }> <div className={ `nitro-layout-trophy trophy-${ color }` }>
<div className="trophy-header drag-handler"> <div className="trophy-header drag-handler">
<div className="float-end trophy-close" onClick={ onCloseClick }></div> <div className="float-end trophy-close" onClick={ onCloseClick }></div>

28
src/utils/Randomizer.ts Normal file
View File

@ -0,0 +1,28 @@
export class Randomizer
{
public static getRandomNumber(count: number): number
{
return Math.floor(Math.random() * count);
}
public static getRandomElement<T>(elements: T[]): T
{
return elements[this.getRandomNumber(elements.length)];
}
public static getRandomElements<T>(elements: T[], count: number): T[]
{
const result: T[] = new Array(count);
let len = elements.length;
const taken = new Array(len);
while(count--)
{
var x = this.getRandomNumber(len);
result[count] = elements[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}
}

View File

@ -3,3 +3,4 @@ export * from './LocalizeBadgeDescription';
export * from './LocalizeBageName'; export * from './LocalizeBageName';
export * from './LocalizeShortNumber'; export * from './LocalizeShortNumber';
export * from './LocalizeText'; export * from './LocalizeText';
export * from './Randomizer';

View File

@ -1,5 +1,4 @@
@import './shared/Shared'; @import './shared/Shared';
@import './auth/AuthView';
@import './avatar-editor/AvatarEditorView'; @import './avatar-editor/AvatarEditorView';
@import './catalog/CatalogView'; @import './catalog/CatalogView';
@import './friend-list/FriendListView'; @import './friend-list/FriendListView';
@ -17,3 +16,4 @@
@import './wired/WiredView'; @import './wired/WiredView';
@import './mod-tools/ModToolsView'; @import './mod-tools/ModToolsView';
@import './achievements/AchievementsView'; @import './achievements/AchievementsView';
@import './user-settings/UserSettingsView';

View File

@ -1,10 +1,10 @@
import { AchievementEvent, AchievementsEvent, AchievementsScoreEvent } from 'nitro-renderer'; import { AchievementEvent, AchievementsEvent, AchievementsScoreEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { CreateMessageHook } from '../../hooks/messages'; import { CreateMessageHook } from '../../hooks/messages';
import { IAchievementsMessageHandlerProps } from './AchievementsMessageHandler.types'; import { IAchievementsMessageHandlerProps } from './AchievementsMessageHandler.types';
import { AchievementCategory } from './common/AchievementCategory';
import { useAchievementsContext } from './context/AchievementsContext'; import { useAchievementsContext } from './context/AchievementsContext';
import { AchievementsActions } from './reducers/AchievementsReducer'; import { AchievementsActions } from './reducers/AchievementsReducer';
import { AchievementCategory } from './utils/AchievementCategory';
export const AchievementsMessageHandler: FC<IAchievementsMessageHandlerProps> = props => export const AchievementsMessageHandler: FC<IAchievementsMessageHandlerProps> = props =>
{ {

View File

@ -1,6 +1,10 @@
.nitro-achievements { .nitro-achievements {
width: 650px; width: 650px;
height: 376px;
.content-area {
min-height: 376px;
height: 376px;
}
.score { .score {
border-color: $grid-border-color !important; border-color: $grid-border-color !important;
@ -8,15 +12,6 @@
} }
.category { .category {
border-color: $grid-border-color !important;
background-color: $grid-bg-color;
cursor: pointer;
&.active {
border-color: $grid-active-border-color !important;
background-color: $grid-active-bg-color;
}
.category-score { .category-score {
margin-top: 43.5px; margin-top: 43.5px;
} }

View File

@ -1,4 +1,4 @@
import { FC, useCallback, useEffect, useReducer, useState } from 'react'; import { FC, useCallback, useReducer, useState } from 'react';
import { AchievementsUIEvent } from '../../events/achievements'; import { AchievementsUIEvent } from '../../events/achievements';
import { useUiEvent } from '../../hooks/events'; import { useUiEvent } from '../../hooks/events';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
@ -7,8 +7,8 @@ import { AchievementsMessageHandler } from './AchievementsMessageHandler';
import { AchievementsViewProps } from './AchievementsView.types'; import { AchievementsViewProps } from './AchievementsView.types';
import { AchievementsContextProvider } from './context/AchievementsContext'; import { AchievementsContextProvider } from './context/AchievementsContext';
import { AchievementsReducer, initialAchievements } from './reducers/AchievementsReducer'; import { AchievementsReducer, initialAchievements } from './reducers/AchievementsReducer';
import { AchievementsListView } from './views/category-list/AchievementsListView';
import { AchievementCategoryView } from './views/category/AchievementCategoryView'; import { AchievementCategoryView } from './views/category/AchievementCategoryView';
import { AchievementsListView } from './views/list/AchievementsListView';
export const AchievementsView: FC<AchievementsViewProps> = props => export const AchievementsView: FC<AchievementsViewProps> = props =>
{ {
@ -35,18 +35,12 @@ export const AchievementsView: FC<AchievementsViewProps> = props =>
useUiEvent(AchievementsUIEvent.SHOW_ACHIEVEMENTS, onAchievementsEvent); useUiEvent(AchievementsUIEvent.SHOW_ACHIEVEMENTS, onAchievementsEvent);
useUiEvent(AchievementsUIEvent.HIDE_ACHIEVEMENTS, onAchievementsEvent); useUiEvent(AchievementsUIEvent.HIDE_ACHIEVEMENTS, onAchievementsEvent);
useUiEvent(AchievementsUIEvent.TOGGLE_ACHIEVEMENTS, onAchievementsEvent); useUiEvent(AchievementsUIEvent.TOGGLE_ACHIEVEMENTS, onAchievementsEvent);
useEffect(() =>
{
if(!isVisible) return;
}, [ isVisible ]);
return ( return (
<AchievementsContextProvider value={ { achievementsState, dispatchAchievementsState } }> <AchievementsContextProvider value={ { achievementsState, dispatchAchievementsState } }>
<AchievementsMessageHandler /> <AchievementsMessageHandler />
{ isVisible && { isVisible &&
<NitroCardView className="nitro-achievements"> <NitroCardView uniqueKey="achievements" className="nitro-achievements">
<NitroCardHeaderView headerText={ LocalizeText('inventory.achievements') } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText('inventory.achievements') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardContentView> <NitroCardContentView>
<div className="row"> <div className="row">

View File

@ -1,4 +1,4 @@
import { AchievementData } from 'nitro-renderer'; import { AchievementData } from '@nitrots/nitro-renderer';
export class AchievementCategory export class AchievementCategory
{ {

View File

@ -1,5 +1,5 @@
import { Reducer } from 'react'; import { Reducer } from 'react';
import { AchievementCategory } from '../utils/AchievementCategory'; import { AchievementCategory } from '../common/AchievementCategory';
export interface IAchievementsState export interface IAchievementsState
{ {

View File

@ -0,0 +1,65 @@
import { FC, useCallback, useMemo } from 'react';
import { GetConfiguration } from '../../../../api';
import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView';
import { useAchievementsContext } from '../../context/AchievementsContext';
import { AchievementsActions } from '../../reducers/AchievementsReducer';
import { AchievementCategoryListItemViewProps } from './AchievementCategoryListItemView.types';
export const AchievementCategoryListItemView: FC<AchievementCategoryListItemViewProps> = props =>
{
const { category = null, isActive = false } = props;
const { dispatchAchievementsState = null } = useAchievementsContext();
const categoryLevel = useMemo(() =>
{
let level = 0;
for(const achievement of category.achievements)
{
level = (level + (achievement.finalLevel ? achievement.level : (achievement.level - 1)));
}
return level;
}, [ category ]);
const getCategoryImage = useMemo(() =>
{
const level = categoryLevel;
const imageUrl = GetConfiguration<string>('achievements.images.url');
return imageUrl.replace('%image%', `achcategory_${ category.name }_${ ((level > 0) ? 'active' : 'inactive') }`);
}, [ category, categoryLevel ]);
const getCategoryProgress = useMemo(() =>
{
let completed = 0;
let total = 0;
for(const achievement of category.achievements)
{
if(!achievement) continue;
if(achievement.firstLevelAchieved) completed = (completed + ((achievement.finalLevel) ? achievement.level : (achievement.level - 1)));
total += achievement.scoreLimit;
}
return (completed + ' / ' + total);
}, [ category ]);
const selectCategory = useCallback((name: string) =>
{
dispatchAchievementsState({
type: AchievementsActions.SELECT_CATEGORY,
payload: {
selectedCategoryName: name
}
});
}, [ dispatchAchievementsState ]);
return (
<NitroCardGridItemView className="d-flex flex-column justify-content-center align-items-center category border border-2 rounded p-2" itemActive={ isActive } itemImage={ getCategoryImage } onClick={ event => selectCategory(category.name) }>
<div className="position-absolute category-score small">{ getCategoryProgress }</div>
</NitroCardGridItemView>
);
}

Some files were not shown because too many files have changed in this diff Show More