mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-30 00:50:50 +01:00
Updates
This commit is contained in:
parent
ced2e2540e
commit
77cb36be44
@ -6,7 +6,7 @@ export const GetAchievementCategoryTotalUnseen = (category: IAchievementCategory
|
||||
|
||||
let unseen = 0;
|
||||
|
||||
for(const achievement of category.achievements) unseen += achievement.unseen;
|
||||
for(const achievement of category.achievements) ((achievement.unseen > 0) && unseen++);
|
||||
|
||||
return unseen;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './ProductImageUtility';
|
@ -1,13 +1,13 @@
|
||||
export * from './achievements';
|
||||
export * from './campaign';
|
||||
export * from './catalog';
|
||||
export * from './common';
|
||||
export * from './core';
|
||||
export * from './friends';
|
||||
export * from './GetRendererVersion';
|
||||
export * from './GetUIVersion';
|
||||
export * from './groups';
|
||||
export * from './inventory';
|
||||
export * from './inventory/unseen';
|
||||
export * from './navigator';
|
||||
export * from './nitro';
|
||||
export * from './nitro/avatar';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionFavoriteGroupUpdateEvent, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomSessionUserFigureUpdateEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionFavoriteGroupUpdateEvent, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomSessionUserFigureUpdateEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, TradingOpenComposer, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { SendMessageComposer } from '../../..';
|
||||
import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
|
||||
import { PetSupplementEnum } from '../../../../../components/room/widgets/avatar-info/common/PetSupplementEnum';
|
||||
import { HelpReportUserEvent, InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events';
|
||||
import { HelpReportUserEvent, WiredSelectObjectEvent } from '../../../../../events';
|
||||
import { DispatchUiEvent } from '../../../../../hooks';
|
||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||
import { RoomWidgetObjectNameEvent, RoomWidgetUpdateChatInputContentEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent } from '../events';
|
||||
@ -119,7 +119,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
|
||||
this.container.roomSession.sendTakeRightsMessage((message as RoomWidgetUserActionMessage).userId);
|
||||
break;
|
||||
case RoomWidgetUserActionMessage.START_TRADING:
|
||||
DispatchUiEvent(new InventoryTradeRequestEvent(userData.roomIndex, userData.name));
|
||||
SendMessageComposer(new TradingOpenComposer(userData.roomIndex));
|
||||
break;
|
||||
// case RoomWidgetUserActionMessage.RWUAM_OPEN_HOME_PAGE:
|
||||
// this._container.sessionDataManager._Str_21275((message as RoomWidgetUserActionMessage).userId, _local_3.name);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CatalogPageMessageProductData } from '@nitrots/nitro-renderer';
|
||||
import { GetRoomEngine } from '..';
|
||||
import { FurniCategory } from '../../components/catalog/common/FurniCategory';
|
||||
import { FurniCategory } from '../inventory';
|
||||
import { GetRoomEngine } from '../nitro';
|
||||
|
||||
export class ProductImageUtility
|
||||
{
|
@ -6,6 +6,7 @@ export * from './LocalizeFormattedNumber';
|
||||
export * from './LocalizeShortNumber';
|
||||
export * from './LocalizeText';
|
||||
export * from './PlaySound';
|
||||
export * from './ProductImageUtility';
|
||||
export * from './Randomizer';
|
||||
export * from './RoomChatFormatter';
|
||||
export * from './SoundNames';
|
||||
|
@ -1,177 +1,27 @@
|
||||
import { AchievementData, AchievementEvent, AchievementsEvent, AchievementsScoreEvent, ILinkEventTracker, RequestAchievementsMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { AchievementCategory, AddEventLinkTracker, CloneObject, GetAchievementCategoryImageUrl, GetAchievementIsIgnored, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api';
|
||||
import { ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { AddEventLinkTracker, GetAchievementCategoryImageUrl, LocalizeText, RemoveLinkEventTracker } from '../../api';
|
||||
import { Base, Column, LayoutImage, LayoutProgressBar, NitroCardContentView, NitroCardHeaderView, NitroCardSubHeaderView, NitroCardView, Text } from '../../common';
|
||||
import { AchievementsUIUnseenCountEvent } from '../../events';
|
||||
import { DispatchUiEvent, UseMessageEventHook } from '../../hooks';
|
||||
import { useAchievements } from '../../hooks';
|
||||
import { AchievementCategoryView } from './views/AchievementCategoryView';
|
||||
import { AchievementsCategoryListView } from './views/category-list/AchievementsCategoryListView';
|
||||
|
||||
export const AchievementsView: FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState(false);
|
||||
const [ isInitalized, setIsInitalized ] = useState(false);
|
||||
const [ achievementCategories, setAchievementCategories ] = useState<AchievementCategory[]>([]);
|
||||
const [ selectedCategoryCode, setSelectedCategoryCode ] = useState<string>(null);
|
||||
const [ achievementScore, setAchievementScore ] = useState(0);
|
||||
const { achievementCategories = [], selectedCategoryCode = null, setSelectedCategoryCode = null, selectedAchievementId = -1, setSelectedAchievementId = null, achievementScore = 0, getProgress = 0, getMaxProgress = 0, setAchievementSeen = null } = useAchievements();
|
||||
|
||||
const onAchievementEvent = useCallback((event: AchievementEvent) =>
|
||||
const selectedCategory = useMemo(() =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const achievement = parser.achievement;
|
||||
const categoryName = achievement.category;
|
||||
if(selectedCategoryCode === null) return null;
|
||||
|
||||
setAchievementCategories(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const categoryIndex = newValue.findIndex(existing => (existing.code === categoryName));
|
||||
|
||||
if(categoryIndex === -1)
|
||||
{
|
||||
const category = new AchievementCategory(categoryName);
|
||||
|
||||
category.achievements.push(achievement);
|
||||
|
||||
newValue.push(category);
|
||||
}
|
||||
else
|
||||
{
|
||||
const category = CloneObject(newValue[categoryIndex]);
|
||||
const newAchievements = [ ...category.achievements ];
|
||||
const achievementIndex = newAchievements.findIndex(existing => (existing.achievementId === achievement.achievementId));
|
||||
let previousAchievement: AchievementData = null;
|
||||
|
||||
if(achievementIndex === -1)
|
||||
{
|
||||
newAchievements.push(achievement);
|
||||
}
|
||||
else
|
||||
{
|
||||
previousAchievement = newAchievements[achievementIndex];
|
||||
|
||||
newAchievements[achievementIndex] = achievement;
|
||||
}
|
||||
|
||||
if(!GetAchievementIsIgnored(achievement))
|
||||
{
|
||||
achievement.unseen++;
|
||||
|
||||
if(previousAchievement) achievement.unseen += previousAchievement.unseen;
|
||||
}
|
||||
|
||||
category.achievements = newAchievements;
|
||||
|
||||
newValue[categoryIndex] = category;
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementEvent, onAchievementEvent);
|
||||
|
||||
const onAchievementsEvent = useCallback((event: AchievementsEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
const categories: AchievementCategory[] = [];
|
||||
|
||||
for(const achievement of parser.achievements)
|
||||
{
|
||||
const categoryName = achievement.category;
|
||||
|
||||
let existing = categories.find(category => (category.code === categoryName));
|
||||
|
||||
if(!existing)
|
||||
{
|
||||
existing = new AchievementCategory(categoryName);
|
||||
|
||||
categories.push(existing);
|
||||
}
|
||||
|
||||
existing.achievements.push(achievement);
|
||||
}
|
||||
|
||||
setAchievementCategories(categories);
|
||||
setIsInitalized(true);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementsEvent, onAchievementsEvent);
|
||||
|
||||
const onAchievementsScoreEvent = useCallback((event: AchievementsScoreEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setAchievementScore(parser.score);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementsScoreEvent, onAchievementsScoreEvent);
|
||||
|
||||
const getTotalUnseen = useMemo(() =>
|
||||
{
|
||||
let unseen = 0;
|
||||
|
||||
for(const category of achievementCategories)
|
||||
{
|
||||
for(const achievement of category.achievements) unseen += achievement.unseen;
|
||||
}
|
||||
|
||||
return unseen;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const getProgress = useMemo(() =>
|
||||
{
|
||||
let progress = 0;
|
||||
|
||||
for(const category of achievementCategories) progress += category.getProgress();
|
||||
|
||||
return progress;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const getMaxProgress = useMemo(() =>
|
||||
{
|
||||
let progress = 0;
|
||||
|
||||
for(const category of achievementCategories) progress += category.getMaxProgress();
|
||||
|
||||
return progress;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const scaledProgressPercent = useMemo(() =>
|
||||
{
|
||||
return ~~((((getProgress - 0) * (100 - 0)) / (getMaxProgress - 0)) + 0);
|
||||
}, [ getProgress, getMaxProgress ]);
|
||||
|
||||
const getSelectedCategory = useMemo(() =>
|
||||
{
|
||||
if(!achievementCategories || !achievementCategories.length) return null;
|
||||
|
||||
return achievementCategories.find(existing => (existing.code === selectedCategoryCode));
|
||||
return achievementCategories.find(category => (category.code === selectedCategoryCode));
|
||||
}, [ achievementCategories, selectedCategoryCode ]);
|
||||
|
||||
const setAchievementSeen = useCallback((code: string, achievementId: number) =>
|
||||
useEffect(() =>
|
||||
{
|
||||
setAchievementCategories(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const category of newValue)
|
||||
{
|
||||
if(category.code !== code) continue;
|
||||
|
||||
for(const achievement of category.achievements)
|
||||
{
|
||||
if(achievement.achievementId !== achievementId) continue;
|
||||
|
||||
achievement.unseen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const linkReceived = useCallback((url: string) =>
|
||||
const linkTracker: ILinkEventTracker = {
|
||||
linkReceived: (url: string) =>
|
||||
{
|
||||
const parts = url.split('/');
|
||||
|
||||
@ -189,48 +39,31 @@ export const AchievementsView: FC<{}> = props =>
|
||||
setIsVisible(prevValue => !prevValue);
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const linkTracker: ILinkEventTracker = {
|
||||
linkReceived,
|
||||
},
|
||||
eventUrlPrefix: 'achievements/'
|
||||
};
|
||||
|
||||
AddEventLinkTracker(linkTracker);
|
||||
|
||||
return () => RemoveLinkEventTracker(linkTracker);
|
||||
}, [ linkReceived ]);
|
||||
}, []);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!isVisible || isInitalized) return;
|
||||
|
||||
SendMessageComposer(new RequestAchievementsMessageComposer());
|
||||
}, [ isVisible, isInitalized ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
DispatchUiEvent(new AchievementsUIUnseenCountEvent(getTotalUnseen));
|
||||
}, [ getTotalUnseen ]);
|
||||
|
||||
if(!isVisible || !isInitalized) return null;
|
||||
if(!isVisible) return null;
|
||||
|
||||
return (
|
||||
<NitroCardView uniqueKey="achievements" className="nitro-achievements" theme="primary-slim">
|
||||
<NitroCardHeaderView headerText={ LocalizeText('inventory.achievements') } onCloseClick={ event => setIsVisible(false) } />
|
||||
{ getSelectedCategory &&
|
||||
{ selectedCategory &&
|
||||
<NitroCardSubHeaderView position="relative" className="justify-content-center align-items-center cursor-pointer" gap={ 3 }>
|
||||
<Base onClick={ event => setSelectedCategoryCode(null) } className="nitro-achievements-back-arrow" />
|
||||
<Column grow gap={ 0 }>
|
||||
<Text fontSize={ 4 } fontWeight="bold" className="text-small">{ LocalizeText(`quests.${ getSelectedCategory.code }.name`) }</Text>
|
||||
<Text>{ LocalizeText('achievements.details.categoryprogress', [ 'progress', 'limit' ], [ getSelectedCategory.getProgress().toString(), getSelectedCategory.getMaxProgress().toString() ]) }</Text>
|
||||
<Text fontSize={ 4 } fontWeight="bold" className="text-small">{ LocalizeText(`quests.${ selectedCategory.code }.name`) }</Text>
|
||||
<Text>{ LocalizeText('achievements.details.categoryprogress', [ 'progress', 'limit' ], [ selectedCategory.getProgress().toString(), selectedCategory.getMaxProgress().toString() ]) }</Text>
|
||||
</Column>
|
||||
<LayoutImage imageUrl={ GetAchievementCategoryImageUrl(getSelectedCategory, null,true) } />
|
||||
<LayoutImage imageUrl={ GetAchievementCategoryImageUrl(selectedCategory, null,true) } />
|
||||
</NitroCardSubHeaderView> }
|
||||
<NitroCardContentView gap={ 1 }>
|
||||
{ !getSelectedCategory &&
|
||||
{ !selectedCategory &&
|
||||
<>
|
||||
<AchievementsCategoryListView categories={ achievementCategories } selectedCategoryCode={ selectedCategoryCode } setSelectedCategoryCode={ setSelectedCategoryCode } />
|
||||
<Column grow justifyContent="end" gap={ 1 }>
|
||||
@ -238,8 +71,8 @@ export const AchievementsView: FC<{}> = props =>
|
||||
<LayoutProgressBar text={ LocalizeText('achievements.categories.totalprogress', [ 'progress', 'limit' ], [ getProgress.toString(), getMaxProgress.toString() ]) } progress={ getProgress } maxProgress={ getMaxProgress } />
|
||||
</Column>
|
||||
</> }
|
||||
{ getSelectedCategory &&
|
||||
<AchievementCategoryView category={ getSelectedCategory } setAchievementSeen={ setAchievementSeen } /> }
|
||||
{ selectedCategory &&
|
||||
<AchievementCategoryView category={ selectedCategory } selectedAchievementId={ selectedAchievementId } setSelectedAchievementId={ setSelectedAchievementId } setAchievementSeen={ setAchievementSeen } /> }
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FC, useEffect, useMemo, useState } from 'react';
|
||||
import { Dispatch, FC, SetStateAction, useEffect, useMemo } from 'react';
|
||||
import { AchievementCategory } from '../../../api';
|
||||
import { Column } from '../../../common';
|
||||
import { AchievementListView } from './achievement-list/AchievementListView';
|
||||
@ -7,40 +7,44 @@ import { AchievementDetailsView } from './AchievementDetailsView';
|
||||
interface AchievementCategoryViewProps
|
||||
{
|
||||
category: AchievementCategory;
|
||||
selectedAchievementId: number;
|
||||
setSelectedAchievementId: Dispatch<SetStateAction<number>>;
|
||||
setAchievementSeen: (code: string, achievementId: number) => void;
|
||||
}
|
||||
|
||||
export const AchievementCategoryView: FC<AchievementCategoryViewProps> = props =>
|
||||
{
|
||||
const { category = null, setAchievementSeen = null } = props;
|
||||
const [ selectedAchievementId, setSelectedAchievementId ] = useState(0);
|
||||
const { category = null, selectedAchievementId = -1, setSelectedAchievementId = null, setAchievementSeen = null } = props;
|
||||
|
||||
const getSelectedAchievement = useMemo(() =>
|
||||
const selectedAchievement = useMemo(() =>
|
||||
{
|
||||
if(!category || !category.achievements.length) return null;
|
||||
if(selectedAchievementId === -1) return null;
|
||||
|
||||
return category.achievements.find(existing => (existing.achievementId === selectedAchievementId));
|
||||
return category.achievements.find(achievement => (achievement.achievementId === selectedAchievementId));
|
||||
}, [ category, selectedAchievementId ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setSelectedAchievementId((!category || !category.achievements.length) ? 0 : category.achievements[0].achievementId);
|
||||
}, [ category ]);
|
||||
if(!selectedAchievement)
|
||||
{
|
||||
if(category.achievements.length) setSelectedAchievementId(category.achievements[0].achievementId);
|
||||
}
|
||||
}, [ selectedAchievement, category, setSelectedAchievementId ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!getSelectedAchievement || !getSelectedAchievement.unseen) return;
|
||||
if(!selectedAchievement) return;
|
||||
|
||||
setAchievementSeen(category.code, getSelectedAchievement.achievementId);
|
||||
}, [ category, getSelectedAchievement, setAchievementSeen ]);
|
||||
setAchievementSeen(category.code, selectedAchievement.achievementId);
|
||||
}, [ selectedAchievement, category, setAchievementSeen ]);
|
||||
|
||||
if(!category) return null;
|
||||
|
||||
return (
|
||||
<Column fullHeight justifyContent="between">
|
||||
<AchievementListView achievements={ category.achievements } selectedAchievementId={ selectedAchievementId } setSelectedAchievementId={ setSelectedAchievementId } />
|
||||
{ getSelectedAchievement &&
|
||||
<AchievementDetailsView achievement={ getSelectedAchievement } /> }
|
||||
{ !!selectedAchievement &&
|
||||
<AchievementDetailsView achievement={ selectedAchievement } /> }
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
@ -11,12 +11,12 @@ interface AchievementDetailsViewProps
|
||||
|
||||
export const AchievementDetailsView: FC<AchievementDetailsViewProps> = props =>
|
||||
{
|
||||
const { achievement = null } = props;
|
||||
const { achievement = null, children = null, ...rest } = props;
|
||||
|
||||
if(!achievement) return null;
|
||||
|
||||
return (
|
||||
<Flex shrink className="bg-muted rounded p-2 text-black" gap={ 2 } overflow="hidden">
|
||||
<Flex shrink className="bg-muted rounded p-2 text-black" gap={ 2 } overflow="hidden" { ...rest }>
|
||||
<Column center gap={ 1 }>
|
||||
<AchievementBadgeView className="nitro-achievements-badge-image" achievement={ achievement } scale={ 2 } />
|
||||
<Text fontWeight="bold">
|
||||
@ -48,6 +48,7 @@ export const AchievementDetailsView: FC<AchievementDetailsViewProps> = props =>
|
||||
<LayoutProgressBar text={ LocalizeText('achievements.details.progress', [ 'progress', 'limit' ], [ (achievement.currentPoints + achievement.scoreAtStartOfLevel).toString(), (achievement.scoreLimit + achievement.scoreAtStartOfLevel).toString() ]) } progress={ (achievement.currentPoints + achievement.scoreAtStartOfLevel) } maxProgress={ (achievement.scoreLimit + achievement.scoreAtStartOfLevel) } /> }
|
||||
</Column> }
|
||||
</Column>
|
||||
{ children }
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
@ -1,21 +1,23 @@
|
||||
import { AchievementData } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { LayoutGridItem, LayoutGridItemProps } from '../../../../common';
|
||||
import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { LayoutGridItem } from '../../../../common';
|
||||
import { AchievementBadgeView } from '../AchievementBadgeView';
|
||||
|
||||
interface AchievementListItemViewProps extends LayoutGridItemProps
|
||||
interface AchievementListItemViewProps
|
||||
{
|
||||
achievement: AchievementData;
|
||||
selectedAchievementId: number;
|
||||
setSelectedAchievementId: Dispatch<SetStateAction<number>>;
|
||||
}
|
||||
|
||||
export const AchievementListItemView: FC<AchievementListItemViewProps> = props =>
|
||||
{
|
||||
const { achievement = null, children = null, ...rest } = props;
|
||||
const { achievement = null, selectedAchievementId = -1, setSelectedAchievementId = null, children = null, ...rest } = props;
|
||||
|
||||
if(!achievement) return null;
|
||||
|
||||
return (
|
||||
<LayoutGridItem itemCount={ achievement.unseen } itemCountMinimum={ 0 } { ...rest }>
|
||||
<LayoutGridItem itemActive={ (selectedAchievementId === achievement.achievementId) } itemUnseen={ (achievement.unseen > 0) } onClick={ event => setSelectedAchievementId(achievement.achievementId) } { ...rest }>
|
||||
<AchievementBadgeView achievement={ achievement } />
|
||||
{ children }
|
||||
</LayoutGridItem>
|
||||
|
@ -3,7 +3,7 @@ import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { AutoGrid } from '../../../../common';
|
||||
import { AchievementListItemView } from './AchievementListItemView';
|
||||
|
||||
export interface AchievementListViewProps
|
||||
interface AchievementListViewProps
|
||||
{
|
||||
achievements: AchievementData[];
|
||||
selectedAchievementId: number;
|
||||
@ -12,11 +12,11 @@ export interface AchievementListViewProps
|
||||
|
||||
export const AchievementListView: FC<AchievementListViewProps> = props =>
|
||||
{
|
||||
const { achievements = null, selectedAchievementId = 0, setSelectedAchievementId = null, children = null } = props;
|
||||
const { achievements = null, selectedAchievementId = -1, setSelectedAchievementId = null, children = null, ...rest } = props;
|
||||
|
||||
return (
|
||||
<AutoGrid columnCount={ 6 } columnMinWidth={ 50 } columnMinHeight={ 50 }>
|
||||
{ achievements && (achievements.length > 0) && achievements.map((achievement, index) => <AchievementListItemView key={ index } achievement={ achievement } itemActive={ (selectedAchievementId === achievement.achievementId) } itemUnseen={ (achievement.unseen > 0) } onClick={ event => setSelectedAchievementId(achievement.achievementId) } />) }
|
||||
<AutoGrid columnCount={ 6 } columnMinWidth={ 50 } columnMinHeight={ 50 } { ...rest }>
|
||||
{ achievements && (achievements.length > 0) && achievements.map((achievement, index) => <AchievementListItemView key={ index } achievement={ achievement } selectedAchievementId={ selectedAchievementId } setSelectedAchievementId={ setSelectedAchievementId } />) }
|
||||
{ children }
|
||||
</AutoGrid>
|
||||
);
|
||||
|
@ -1,15 +1,19 @@
|
||||
import { FC } from 'react';
|
||||
import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { GetAchievementCategoryImageUrl, GetAchievementCategoryMaxProgress, GetAchievementCategoryProgress, GetAchievementCategoryTotalUnseen, IAchievementCategory, LocalizeText } from '../../../../api';
|
||||
import { LayoutBackgroundImage, LayoutGridItem, LayoutGridItemProps, Text } from '../../../../common';
|
||||
import { LayoutBackgroundImage, LayoutGridItem, Text } from '../../../../common';
|
||||
|
||||
export interface AchievementCategoryListItemViewProps extends LayoutGridItemProps
|
||||
interface AchievementCategoryListItemViewProps
|
||||
{
|
||||
category: IAchievementCategory;
|
||||
selectedCategoryCode: string;
|
||||
setSelectedCategoryCode: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export const AchievementsCategoryListItemView: FC<AchievementCategoryListItemViewProps> = props =>
|
||||
{
|
||||
const { category = null, children = null, ...rest } = props;
|
||||
const { category = null, selectedCategoryCode = null, setSelectedCategoryCode = null, children = null, ...rest } = props;
|
||||
|
||||
if(!category) return null;
|
||||
|
||||
const progress = GetAchievementCategoryProgress(category);
|
||||
const maxProgress = GetAchievementCategoryMaxProgress(category);
|
||||
@ -17,9 +21,9 @@ export const AchievementsCategoryListItemView: FC<AchievementCategoryListItemVie
|
||||
const getTotalUnseen = GetAchievementCategoryTotalUnseen(category);
|
||||
|
||||
return (
|
||||
<LayoutGridItem itemCount={ getTotalUnseen } itemCountMinimum={ 0 } gap={ 1 } { ...rest }>
|
||||
<Text fullWidth center className="small pt-1">{ LocalizeText(`quests.${ category.code }.name`) }</Text>
|
||||
<LayoutBackgroundImage className="position-relative" imageUrl={ getCategoryImage }>
|
||||
<LayoutGridItem itemActive={ (selectedCategoryCode === category.code) } itemCount={ getTotalUnseen } itemCountMinimum={ 0 } gap={ 1 } onClick={ event => setSelectedCategoryCode(category.code) } { ...rest }>
|
||||
<Text fullWidth center small className="pt-1">{ LocalizeText(`quests.${ category.code }.name`) }</Text>
|
||||
<LayoutBackgroundImage position="relative" imageUrl={ getCategoryImage }>
|
||||
<Text fullWidth center position="absolute" variant="white" style={ { fontSize: 12, bottom: 9 } }>{ progress } / { maxProgress }</Text>
|
||||
</LayoutBackgroundImage>
|
||||
{ children }
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { IAchievementCategory } from '../../../../api';
|
||||
import { AutoGrid, AutoGridProps } from '../../../../common';
|
||||
import { AutoGrid } from '../../../../common';
|
||||
import { AchievementsCategoryListItemView } from './AchievementsCategoryListItemView';
|
||||
|
||||
export interface AchievementsCategoryListViewProps extends AutoGridProps
|
||||
interface AchievementsCategoryListViewProps
|
||||
{
|
||||
categories: IAchievementCategory[];
|
||||
selectedCategoryCode: string;
|
||||
@ -12,11 +12,11 @@ export interface AchievementsCategoryListViewProps extends AutoGridProps
|
||||
|
||||
export const AchievementsCategoryListView: FC<AchievementsCategoryListViewProps> = props =>
|
||||
{
|
||||
const { categories = null, selectedCategoryCode = null, setSelectedCategoryCode = null, columnCount = 3, columnMinWidth = 90, columnMinHeight = 100, children = null, ...rest } = props;
|
||||
const { categories = null, selectedCategoryCode = null, setSelectedCategoryCode = null, children = null, ...rest } = props;
|
||||
|
||||
return (
|
||||
<AutoGrid columnCount={ columnCount } columnMinWidth={ columnMinWidth } columnMinHeight={ columnMinHeight } { ...rest }>
|
||||
{ categories && (categories.length > 0) && categories.map((category, index) => <AchievementsCategoryListItemView key={ index } category={ category } itemActive={ (selectedCategoryCode === category.code) } onClick={ event => setSelectedCategoryCode(category.code) } /> ) }
|
||||
<AutoGrid columnCount={ 3 } columnMinWidth={ 90 } columnMinHeight={ 100 } { ...rest }>
|
||||
{ categories && (categories.length > 0) && categories.map((category, index) => <AchievementsCategoryListItemView key={ index } category={ category } selectedCategoryCode={ selectedCategoryCode } setSelectedCategoryCode={ setSelectedCategoryCode } /> ) }
|
||||
{ children }
|
||||
</AutoGrid>
|
||||
);
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraStorageUrlMessageEvent, PublishPhotoMessageComposer, PurchasePhotoMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { GetConfiguration, GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api';
|
||||
import { CreateLinkEvent, GetConfiguration, GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../api';
|
||||
import { Button, Column, Flex, LayoutCurrencyIcon, LayoutImage, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../../../common';
|
||||
import { InventoryEvent } from '../../../../events';
|
||||
import { DispatchUiEvent, UseMessageEventHook } from '../../../../hooks';
|
||||
import { UseMessageEventHook } from '../../../../hooks';
|
||||
|
||||
export interface CameraWidgetCheckoutViewProps
|
||||
{
|
||||
@ -122,7 +121,7 @@ export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props
|
||||
{ (picturesBought > 0) &&
|
||||
<Text>
|
||||
<Text bold>{ LocalizeText('camera.purchase.count.info') }</Text> { picturesBought }
|
||||
<u className="ms-1 cursor-pointer" onClick={ () => DispatchUiEvent(new InventoryEvent(InventoryEvent.SHOW_INVENTORY)) }>{ LocalizeText('camera.open.inventory') }</u>
|
||||
<u className="ms-1 cursor-pointer" onClick={ () => CreateLinkEvent('inventory/open') }>{ LocalizeText('camera.open.inventory') }</u>
|
||||
</Text> }
|
||||
</Column>
|
||||
<Flex alignItems="center">
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { BadgesEvent, ClubGiftInfoEvent, FigureUpdateEvent, FriendlyTime, GetClubGiftInfo, ILinkEventTracker, RequestBadgesComposer, ScrGetKickbackInfoMessageComposer, ScrKickbackData, ScrSendKickbackInfoMessageEvent, UserInfoEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer';
|
||||
import { BadgesEvent, ClubGiftInfoEvent, FriendlyTime, GetClubGiftInfo, ILinkEventTracker, RequestBadgesComposer, ScrGetKickbackInfoMessageComposer, ScrKickbackData, ScrSendKickbackInfoMessageEvent, UserSubscriptionEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import { AddEventLinkTracker, CreateLinkEvent, GetConfiguration, LocalizeText, RemoveLinkEventTracker, SendMessageComposer } from '../../api';
|
||||
import { Base, Button, Column, Flex, LayoutAvatarImageView, LayoutBadgeImageView, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common';
|
||||
import { HcCenterEvent } from '../../events';
|
||||
import { UseMessageEventHook, UseUiEvent } from '../../hooks';
|
||||
import { UseMessageEventHook, useSessionInfo } from '../../hooks';
|
||||
import { BadgeResolver } from './common/BadgeResolver';
|
||||
import { ClubStatus } from './common/ClubStatus';
|
||||
|
||||
@ -12,7 +11,6 @@ import { ClubStatus } from './common/ClubStatus';
|
||||
export const HcCenterView: FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState(false);
|
||||
const [ userFigure, setUserFigure ] = useState<string>(null);
|
||||
const [ kickbackData, setKickbackData ] = useState<ScrKickbackData>(null);
|
||||
const [ clubDays, setClubDays ] = useState(0);
|
||||
const [ pastClubDays, setPastClubDays ] = useState(0);
|
||||
@ -21,6 +19,7 @@ export const HcCenterView: FC<{}> = props =>
|
||||
const [ clubStatus, setClubStatus ] = useState(ClubStatus.NONE);
|
||||
const [ unclaimedGifts, setUnclaimedGifts ] = useState(0);
|
||||
const [ badgeCode, setBadgeCode ] = useState(BadgeResolver.default_badge);
|
||||
const { userFigure = null } = useSessionInfo();
|
||||
|
||||
const getClubText = () =>
|
||||
{
|
||||
@ -64,36 +63,6 @@ export const HcCenterView: FC<{}> = props =>
|
||||
return LocalizeText('hccenter.special.sum', [ 'credits' ], [ (kickbackData.creditRewardForStreakBonus + kickbackData.creditRewardForMonthlySpent).toString() ]);
|
||||
}
|
||||
|
||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserFigure(parser.userInfo.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(UserInfoEvent, onUserInfoEvent);
|
||||
|
||||
const onUserFigureEvent = useCallback((event: FigureUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserFigure(parser.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FigureUpdateEvent, onUserFigureEvent);
|
||||
|
||||
const onHcCenterEvent = useCallback((event: HcCenterEvent) =>
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case HcCenterEvent.TOGGLE_HC_CENTER:
|
||||
setIsVisible(!isVisible);
|
||||
break;
|
||||
}
|
||||
}, [ isVisible ]);
|
||||
|
||||
UseUiEvent(HcCenterEvent.TOGGLE_HC_CENTER, onHcCenterEvent);
|
||||
|
||||
const onClubGiftInfoEvent = useCallback((event: ClubGiftInfoEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
@ -265,7 +234,7 @@ export const HcCenterView: FC<{}> = props =>
|
||||
<h5 className="ms-2 mb-1 bolder">{LocalizeText('hccenter.special.amount.title')}</h5>
|
||||
<div className="d-flex flex-column">
|
||||
<div className="w-100 text-center ms-4n">{getHcPaydayAmount()}</div>
|
||||
<OverlayTrigger trigger="hover" placement="left" overlay={popover}>
|
||||
<OverlayTrigger trigger={ [ 'hover', 'focus' ] } placement="left" overlay={popover}>
|
||||
<div className="btn btn-link align-self-end text-primary">
|
||||
{LocalizeText('hccenter.breakdown.infolink')}
|
||||
</div>
|
||||
|
@ -1,36 +1,16 @@
|
||||
import { FigureUpdateEvent, RoomSessionEvent, UserInfoDataParser, UserInfoEvent } from '@nitrots/nitro-renderer';
|
||||
import { RoomSessionEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { GetConfiguration, GetConfigurationManager } from '../../api';
|
||||
import { LayoutAvatarImageView } from '../../common';
|
||||
import { UseMessageEventHook, UseRoomSessionManagerEvent } from '../../hooks';
|
||||
import { UseRoomSessionManagerEvent, useSessionInfo } from '../../hooks';
|
||||
import { WidgetSlotView } from './views/widgets/WidgetSlotView';
|
||||
|
||||
const widgetSlotCount = 7;
|
||||
|
||||
export const HotelView: FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState(true);
|
||||
const widgetSlotCount = 7;
|
||||
const [ userFigure, setUserFigure ] = useState<string>(null);
|
||||
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
|
||||
|
||||
|
||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserInfo(parser.userInfo);
|
||||
setUserFigure(parser.userInfo.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(UserInfoEvent, onUserInfoEvent);
|
||||
|
||||
const onUserFigureEvent = useCallback((event: FigureUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserFigure(parser.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FigureUpdateEvent, onUserFigureEvent);
|
||||
|
||||
const { userFigure = null } = useSessionInfo();
|
||||
|
||||
const onRoomSessionEvent = useCallback((event: RoomSessionEvent) =>
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ export const InventoryBadgeView: FC<{}> = props =>
|
||||
{
|
||||
const [ isVisible, setIsVisible ] = useState(false);
|
||||
const { badgeCodes = [], activeBadgeCodes = [], selectedBadgeCode = null, isWearingBadge = null, canWearBadges = null, toggleBadge = null, getBadgeId = null, activate = null, deactivate = null } = useInventoryBadges();
|
||||
const { getCount = null, resetCategory = null, isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
||||
const { isUnseen = null, removeUnseen = null } = useInventoryUnseenTracker();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
|
@ -70,9 +70,9 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
|
||||
<Flex gap={2} overflow="hidden">
|
||||
<LayoutRoomThumbnailView roomId={roomData.roomId} customUrl={roomData.officialRoomPicRef} className="d-flex flex-column align-items-center justify-content-end mb-1">
|
||||
{roomData.habboGroupId > 0 && (
|
||||
<LayoutBadgeImageView badgeCode={roomData.groupBadgeCode} isGroup={true} className={"position-absolute top-0 start-0 m-1 "}/>)}
|
||||
<LayoutBadgeImageView badgeCode={roomData.groupBadgeCode} isGroup={true} className={'position-absolute top-0 start-0 m-1 '}/>)}
|
||||
{roomData.doorMode !== RoomDataParser.OPEN_STATE && (
|
||||
<i className={"position-absolute end-0 mb-1 me-1 icon icon-navigator-room-" + (roomData.doorMode === RoomDataParser.DOORBELL_STATE ? "locked" : roomData.doorMode === RoomDataParser.PASSWORD_STATE ? "password" : roomData.doorMode === RoomDataParser.INVISIBLE_STATE ? "invisible" : "")}/> )}
|
||||
<i className={'position-absolute end-0 mb-1 me-1 icon icon-navigator-room-' + (roomData.doorMode === RoomDataParser.DOORBELL_STATE ? 'locked' : roomData.doorMode === RoomDataParser.PASSWORD_STATE ? 'password' : roomData.doorMode === RoomDataParser.INVISIBLE_STATE ? 'invisible' : '')}/> )}
|
||||
</LayoutRoomThumbnailView>
|
||||
<Column gap={1}>
|
||||
<Text bold truncate className="flex-grow-1" style={{ maxHeight: 13 }}>
|
||||
@ -80,7 +80,7 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
|
||||
</Text>
|
||||
<Flex gap={1}>
|
||||
<Text italics variant="muted">
|
||||
{LocalizeText("navigator.roomownercaption")}
|
||||
{LocalizeText('navigator.roomownercaption')}
|
||||
</Text>
|
||||
<UserProfileIconView
|
||||
userId={roomData.ownerId}
|
||||
@ -90,7 +90,7 @@ export const NavigatorSearchResultItemInfoView: FC<NavigatorSearchResultItemInfo
|
||||
<Text className="flex-grow-1">
|
||||
{roomData.description}
|
||||
</Text>
|
||||
<Flex className={"badge p-1 position-absolute m-1 bottom-0 end-0 m-2 " + getUserCounterColor()} gap={1}>
|
||||
<Flex className={'badge p-1 position-absolute m-1 bottom-0 end-0 m-2 ' + getUserCounterColor()} gap={1}>
|
||||
<FontAwesomeIcon icon="user" />
|
||||
{roomData.userCount}
|
||||
</Flex>
|
||||
|
@ -2,7 +2,7 @@ import { ActivityPointNotificationMessageEvent, FriendlyTime, HabboClubLevelEnum
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { CreateLinkEvent, GetConfiguration, LocalizeText, PlaySound, SendMessageComposer, SoundNames } from '../../api';
|
||||
import { Column, Flex, Grid, LayoutCurrencyIcon, Text } from '../../common';
|
||||
import { HcCenterEvent, UserSettingsUIEvent } from '../../events';
|
||||
import { UserSettingsUIEvent } from '../../events';
|
||||
import { DispatchUiEvent, UseMessageEventHook } from '../../hooks';
|
||||
import { IPurse } from './common/IPurse';
|
||||
import { Purse } from './common/Purse';
|
||||
@ -179,7 +179,7 @@ export const PurseView: FC<{}> = props =>
|
||||
{ getCurrencyElements(0, 2) }
|
||||
</Column>
|
||||
{ !hcDisabled &&
|
||||
<Column center pointer size={ 4 } gap={ 1 } className="nitro-purse-subscription rounded" onClick={ event => DispatchUiEvent(new HcCenterEvent(HcCenterEvent.TOGGLE_HC_CENTER)) }>
|
||||
<Column center pointer size={ 4 } gap={ 1 } className="nitro-purse-subscription rounded" onClick={ event => CreateLinkEvent('habboUI/open/hccenter') }>
|
||||
<LayoutCurrencyIcon type="hc" />
|
||||
<Text variant="white">{ getClubText }</Text>
|
||||
</Column> }
|
||||
|
@ -1,44 +1,24 @@
|
||||
import { Dispose, DropBounce, EaseOut, FigureUpdateEvent, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, UserInfoDataParser, UserInfoEvent, Wait } from '@nitrots/nitro-renderer';
|
||||
import { Dispose, DropBounce, EaseOut, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { CreateLinkEvent, GetSessionDataManager, MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api';
|
||||
import { Base, Flex, LayoutAvatarImageView, LayoutItemCountView, TransitionAnimation, TransitionAnimationTypes } from '../../common';
|
||||
import { AchievementsUIUnseenCountEvent, ModToolsEvent } from '../../events';
|
||||
import { DispatchUiEvent, useFriends, useInventoryUnseenTracker, UseMessageEventHook, useMessenger, UseRoomEngineEvent, UseUiEvent } from '../../hooks';
|
||||
import { ModToolsEvent } from '../../events';
|
||||
import { DispatchUiEvent, useAchievements, useFriends, useInventoryUnseenTracker, UseMessageEventHook, useMessenger, UseRoomEngineEvent, useSessionInfo } from '../../hooks';
|
||||
import { ToolbarMeView } from './ToolbarMeView';
|
||||
|
||||
export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
||||
{
|
||||
const { isInRoom } = props;
|
||||
|
||||
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
|
||||
const [ userFigure, setUserFigure ] = useState<string>(null);
|
||||
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
||||
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
||||
const [ unseenAchievementCount, setUnseenAchievementCount ] = useState(0);
|
||||
const { getFullCount = null } = useInventoryUnseenTracker();
|
||||
const { userFigure = null } = useSessionInfo();
|
||||
const { getFullCount = 0 } = useInventoryUnseenTracker();
|
||||
const { getTotalUnseen = 0 } = useAchievements();
|
||||
const { requests = [] } = useFriends();
|
||||
const { iconState = MessengerIconState.HIDDEN } = useMessenger();
|
||||
const isMod = GetSessionDataManager().isModerator;
|
||||
|
||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserInfo(parser.userInfo);
|
||||
setUserFigure(parser.userInfo.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(UserInfoEvent, onUserInfoEvent);
|
||||
|
||||
const onUserFigureEvent = useCallback((event: FigureUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserFigure(parser.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FigureUpdateEvent, onUserFigureEvent);
|
||||
|
||||
const onPerkAllowancesMessageEvent = useCallback((event: PerkAllowancesMessageEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
@ -48,13 +28,6 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
||||
|
||||
UseMessageEventHook(PerkAllowancesMessageEvent, onPerkAllowancesMessageEvent);
|
||||
|
||||
const onAchievementsUIUnseenCountEvent = useCallback((event: AchievementsUIUnseenCountEvent) =>
|
||||
{
|
||||
setUnseenAchievementCount(event.count);
|
||||
}, []);
|
||||
|
||||
UseUiEvent(AchievementsUIUnseenCountEvent.UNSEEN_COUNT, onAchievementsUIUnseenCountEvent);
|
||||
|
||||
const animationIconToToolbar = useCallback((iconName: string, image: HTMLImageElement, x: number, y: number) =>
|
||||
{
|
||||
const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement);
|
||||
@ -96,20 +69,18 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
||||
|
||||
UseRoomEngineEvent(NitroToolbarAnimateIconEvent.ANIMATE_ICON, onNitroToolbarAnimateIconEvent);
|
||||
|
||||
const unseenInventoryCount = getFullCount();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ isMeExpanded } timeout={ 300 }>
|
||||
<ToolbarMeView useGuideTool={ useGuideTool } unseenAchievementCount={ unseenAchievementCount } setMeExpanded={ setMeExpanded } />
|
||||
<ToolbarMeView useGuideTool={ useGuideTool } unseenAchievementCount={ getTotalUnseen } setMeExpanded={ setMeExpanded } />
|
||||
</TransitionAnimation>
|
||||
<Flex alignItems="center" justifyContent="between" gap={ 2 } className="nitro-toolbar py-1 px-3">
|
||||
<Flex gap={ 2 } alignItems="center">
|
||||
<Flex alignItems="center" gap={ 2 }>
|
||||
<Flex center pointer className={ 'navigation-item item-avatar ' + (isMeExpanded ? 'active ' : '') } onClick={ event => setMeExpanded(!isMeExpanded) }>
|
||||
<LayoutAvatarImageView figure={ userFigure } direction={ 2 } />
|
||||
{ (unseenAchievementCount > 0) &&
|
||||
<LayoutItemCountView count={ unseenAchievementCount } /> }
|
||||
{ (getTotalUnseen > 0) &&
|
||||
<LayoutItemCountView count={ getTotalUnseen } /> }
|
||||
</Flex>
|
||||
{ isInRoom &&
|
||||
<Base pointer className="navigation-item icon icon-habbo" onClick={ event => VisitDesktop() } /> }
|
||||
@ -118,8 +89,8 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
||||
<Base pointer className="navigation-item icon icon-rooms" onClick={ event => CreateLinkEvent('navigator/toggle') } />
|
||||
<Base pointer className="navigation-item icon icon-catalog" onClick={ event => CreateLinkEvent('catalog/toggle') } />
|
||||
<Base pointer className="navigation-item icon icon-inventory" onClick={ event => CreateLinkEvent('inventory/toggle') }>
|
||||
{ (unseenInventoryCount > 0) &&
|
||||
<LayoutItemCountView count={ unseenInventoryCount } /> }
|
||||
{ (getFullCount > 0) &&
|
||||
<LayoutItemCountView count={ getFullCount } /> }
|
||||
</Base>
|
||||
{ isInRoom &&
|
||||
<Base pointer className="navigation-item icon icon-camera" onClick={ event => CreateLinkEvent('camera/toggle') } /> }
|
||||
|
@ -1,20 +0,0 @@
|
||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||
|
||||
export class AchievementsUIUnseenCountEvent extends NitroEvent
|
||||
{
|
||||
public static UNSEEN_COUNT: string = 'AUUCE_UNSEEN_COUNT';
|
||||
|
||||
private _count: number;
|
||||
|
||||
constructor(count: number)
|
||||
{
|
||||
super(AchievementsUIUnseenCountEvent.UNSEEN_COUNT);
|
||||
|
||||
this._count = count;
|
||||
}
|
||||
|
||||
public get count(): number
|
||||
{
|
||||
return this._count;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './AchievementsUIUnseenCountEvent';
|
@ -1,48 +0,0 @@
|
||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||
|
||||
export class FriendEnteredRoomEvent extends NitroEvent
|
||||
{
|
||||
public static ENTERED: string = 'FERE_ENTERED';
|
||||
|
||||
private _roomIndex: number;
|
||||
private _category: number;
|
||||
private _id: number;
|
||||
private _name: string;
|
||||
private _userType: number;
|
||||
|
||||
constructor(roomIndex: number, category: number, id: number, name: string, userType: number)
|
||||
{
|
||||
super(FriendEnteredRoomEvent.ENTERED);
|
||||
|
||||
this._roomIndex = roomIndex;
|
||||
this._category = category;
|
||||
this._id = id;
|
||||
this._name = name;
|
||||
this._userType = userType;
|
||||
}
|
||||
|
||||
public get roomIndex(): number
|
||||
{
|
||||
return this._roomIndex;
|
||||
}
|
||||
|
||||
public get category(): number
|
||||
{
|
||||
return this._category;
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get name(): string
|
||||
{
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get userType(): number
|
||||
{
|
||||
return this._userType;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './FriendEnteredRoomEvent';
|
@ -1,6 +0,0 @@
|
||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||
|
||||
export class HcCenterEvent extends NitroEvent
|
||||
{
|
||||
public static TOGGLE_HC_CENTER: string = 'HCC_TOGGLE';
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './HcCenterEvent';
|
@ -1,11 +1,7 @@
|
||||
export * from './achievements';
|
||||
export * from './catalog';
|
||||
export * from './floorplan-editor';
|
||||
export * from './friends';
|
||||
export * from './guide-tool';
|
||||
export * from './hc-center';
|
||||
export * from './help';
|
||||
export * from './inventory';
|
||||
export * from './mod-tools';
|
||||
export * from './notification-center';
|
||||
export * from './room-widgets';
|
||||
|
@ -1,8 +0,0 @@
|
||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
||||
|
||||
export class InventoryEvent extends NitroEvent
|
||||
{
|
||||
public static SHOW_INVENTORY: string = 'IE_SHOW_INVENTORY';
|
||||
public static HIDE_INVENTORY: string = 'IE_HIDE_INVENTORY';
|
||||
public static TOGGLE_INVENTORY: string = 'IE_TOGGLE_INVENTORY';
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
import { InventoryEvent } from './InventoryEvent';
|
||||
|
||||
export class InventoryTradeRequestEvent extends InventoryEvent
|
||||
{
|
||||
public static REQUEST_TRADE: string = 'ITSE_REQUEST_TRADE';
|
||||
|
||||
private _objectId: number;
|
||||
private _username: string;
|
||||
|
||||
constructor(objectId: number, username: string)
|
||||
{
|
||||
super(InventoryTradeRequestEvent.REQUEST_TRADE);
|
||||
|
||||
this._objectId = objectId;
|
||||
this._username = username;
|
||||
}
|
||||
|
||||
public get objectId(): number
|
||||
{
|
||||
return this._objectId;
|
||||
}
|
||||
|
||||
public get username(): string
|
||||
{
|
||||
return this._username;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import { TradeUserData } from '../../api';
|
||||
import { InventoryEvent } from './InventoryEvent';
|
||||
|
||||
export class InventoryTradeStartEvent extends InventoryEvent
|
||||
{
|
||||
public static START_TRADE: string = 'ITSE_START_TRADE';
|
||||
|
||||
private _ownUserTradeData: TradeUserData;
|
||||
private _otherUserTradeData: TradeUserData;
|
||||
|
||||
constructor(ownUserTradeData: TradeUserData, otherUserTradeData: TradeUserData)
|
||||
{
|
||||
super(InventoryTradeStartEvent.START_TRADE);
|
||||
|
||||
this._ownUserTradeData = ownUserTradeData;
|
||||
this._otherUserTradeData = otherUserTradeData;
|
||||
}
|
||||
|
||||
public get ownUserTradeData(): TradeUserData
|
||||
{
|
||||
return this._ownUserTradeData;
|
||||
}
|
||||
|
||||
public get otherUserTradeData(): TradeUserData
|
||||
{
|
||||
return this._otherUserTradeData;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export * from './InventoryEvent';
|
||||
export * from './InventoryTradeRequestEvent';
|
||||
export * from './InventoryTradeStartEvent';
|
1
src/hooks/achievements/index.ts
Normal file
1
src/hooks/achievements/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './useAchievements';
|
169
src/hooks/achievements/useAchievements.ts
Normal file
169
src/hooks/achievements/useAchievements.ts
Normal file
@ -0,0 +1,169 @@
|
||||
import { AchievementData, AchievementEvent, AchievementsEvent, AchievementsScoreEvent, RequestAchievementsMessageComposer } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { AchievementCategory, CloneObject, GetAchievementCategoryTotalUnseen, GetAchievementIsIgnored, SendMessageComposer } from '../../api';
|
||||
import { UseMessageEventHook } from '../messages';
|
||||
|
||||
const useAchievementsState = () =>
|
||||
{
|
||||
const [ needsUpdate, setNeedsUpdate ] = useState<boolean>(true);
|
||||
const [ achievementCategories, setAchievementCategories ] = useState<AchievementCategory[]>([]);
|
||||
const [ selectedCategoryCode, setSelectedCategoryCode ] = useState<string>(null);
|
||||
const [ selectedAchievementId, setSelectedAchievementId ] = useState<number>(-1);
|
||||
const [ achievementScore, setAchievementScore ] = useState<number>(0);
|
||||
|
||||
const getTotalUnseen = useMemo(() =>
|
||||
{
|
||||
let unseen = 0;
|
||||
|
||||
achievementCategories.forEach(category => unseen += GetAchievementCategoryTotalUnseen(category));
|
||||
|
||||
return unseen;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const getProgress = useMemo(() =>
|
||||
{
|
||||
let progress = 0;
|
||||
|
||||
achievementCategories.forEach(category => (progress += category.getProgress()));
|
||||
|
||||
return progress;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const getMaxProgress = useMemo(() =>
|
||||
{
|
||||
let progress = 0;
|
||||
|
||||
achievementCategories.forEach(category => (progress += category.getMaxProgress()));
|
||||
|
||||
return progress;
|
||||
}, [ achievementCategories ]);
|
||||
|
||||
const scaledProgressPercent = useMemo(() =>
|
||||
{
|
||||
return ~~((((getProgress - 0) * (100 - 0)) / (getMaxProgress - 0)) + 0);
|
||||
}, [ getProgress, getMaxProgress ]);
|
||||
|
||||
const setAchievementSeen = useCallback((categoryCode: string, achievementId: number) =>
|
||||
{
|
||||
setAchievementCategories(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
|
||||
for(const category of newValue)
|
||||
{
|
||||
if(category.code !== categoryCode) continue;
|
||||
|
||||
for(const achievement of category.achievements)
|
||||
{
|
||||
if(achievement.achievementId !== achievementId) continue;
|
||||
|
||||
achievement.unseen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onAchievementEvent = useCallback((event: AchievementEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const achievement = parser.achievement;
|
||||
|
||||
setAchievementCategories(prevValue =>
|
||||
{
|
||||
const newValue = [ ...prevValue ];
|
||||
const categoryIndex = newValue.findIndex(existing => (existing.code === achievement.category));
|
||||
|
||||
if(categoryIndex === -1)
|
||||
{
|
||||
const category = new AchievementCategory(achievement.category);
|
||||
|
||||
category.achievements.push(achievement);
|
||||
|
||||
newValue.push(category);
|
||||
}
|
||||
else
|
||||
{
|
||||
const category = CloneObject(newValue[categoryIndex]);
|
||||
const newAchievements = [ ...category.achievements ];
|
||||
const achievementIndex = newAchievements.findIndex(existing => (existing.achievementId === achievement.achievementId));
|
||||
let previousAchievement: AchievementData = null;
|
||||
|
||||
if(achievementIndex === -1)
|
||||
{
|
||||
newAchievements.push(achievement);
|
||||
}
|
||||
else
|
||||
{
|
||||
previousAchievement = newAchievements[achievementIndex];
|
||||
|
||||
newAchievements[achievementIndex] = achievement;
|
||||
}
|
||||
|
||||
if(!GetAchievementIsIgnored(achievement))
|
||||
{
|
||||
achievement.unseen++;
|
||||
|
||||
if(previousAchievement) achievement.unseen += previousAchievement.unseen;
|
||||
}
|
||||
|
||||
category.achievements = newAchievements;
|
||||
|
||||
newValue[categoryIndex] = category;
|
||||
}
|
||||
|
||||
return newValue;
|
||||
});
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementEvent, onAchievementEvent);
|
||||
|
||||
const onAchievementsEvent = useCallback((event: AchievementsEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
const categories: AchievementCategory[] = [];
|
||||
|
||||
for(const achievement of parser.achievements)
|
||||
{
|
||||
const categoryName = achievement.category;
|
||||
|
||||
let existing = categories.find(category => (category.code === categoryName));
|
||||
|
||||
if(!existing)
|
||||
{
|
||||
existing = new AchievementCategory(categoryName);
|
||||
|
||||
categories.push(existing);
|
||||
}
|
||||
|
||||
existing.achievements.push(achievement);
|
||||
}
|
||||
|
||||
setAchievementCategories(categories);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementsEvent, onAchievementsEvent);
|
||||
|
||||
const onAchievementsScoreEvent = useCallback((event: AchievementsScoreEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setAchievementScore(parser.score);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(AchievementsScoreEvent, onAchievementsScoreEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!needsUpdate) return;
|
||||
|
||||
SendMessageComposer(new RequestAchievementsMessageComposer());
|
||||
|
||||
setNeedsUpdate(false);
|
||||
}, [ needsUpdate ]);
|
||||
|
||||
return { achievementCategories, selectedCategoryCode, setSelectedCategoryCode, selectedAchievementId, setSelectedAchievementId, achievementScore, getTotalUnseen, getProgress, getMaxProgress, scaledProgressPercent, setAchievementSeen };
|
||||
}
|
||||
|
||||
export const useAchievements = useAchievementsState;
|
@ -1,3 +1,4 @@
|
||||
export * from './achievements';
|
||||
export * from './events';
|
||||
export * from './events/core';
|
||||
export * from './events/nitro';
|
||||
@ -6,5 +7,6 @@ export * from './friends';
|
||||
export * from './inventory';
|
||||
export * from './messages';
|
||||
export * from './navigator';
|
||||
export * from './session';
|
||||
export * from './UseMountEffect';
|
||||
export * from './useSharedVisibility';
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { AdvancedMap, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListItemEvent, TradingListItemRemoveComposer, TradingNotOpenEvent, TradingOpenComposer, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent } from '@nitrots/nitro-renderer';
|
||||
import { AdvancedMap, TradingAcceptComposer, TradingAcceptEvent, TradingCancelComposer, TradingCloseComposer, TradingCloseEvent, TradingCloseParser, TradingCompletedEvent, TradingConfirmationComposer, TradingConfirmationEvent, TradingListItemEvent, TradingListItemRemoveComposer, TradingNotOpenEvent, TradingOpenEvent, TradingOpenFailedEvent, TradingOtherNotAllowedEvent, TradingUnacceptComposer, TradingYouAreNotAllowedEvent } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { useInventoryFurni } from '.';
|
||||
import { UseMessageEventHook } from '..';
|
||||
import { CloneObject, GetRoomSession, GetSessionDataManager, GroupItem, LocalizeText, NotificationUtilities, parseTradeItems, SendMessageComposer, TradeState, TradeUserData, TradingNotificationMessage, TradingNotificationType } from '../../api';
|
||||
import { InventoryTradeRequestEvent } from '../../events';
|
||||
import { UseUiEvent } from '../events';
|
||||
|
||||
const useInventoryTradeState = () =>
|
||||
{
|
||||
@ -66,20 +64,6 @@ const useInventoryTradeState = () =>
|
||||
}
|
||||
}
|
||||
|
||||
const onInventoryTradeRequestEvent = useCallback((event: InventoryTradeRequestEvent) =>
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case InventoryTradeRequestEvent.REQUEST_TRADE: {
|
||||
const tradeEvent = (event as InventoryTradeRequestEvent);
|
||||
|
||||
SendMessageComposer(new TradingOpenComposer(tradeEvent.objectId));
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
UseUiEvent(InventoryTradeRequestEvent.REQUEST_TRADE, onInventoryTradeRequestEvent);
|
||||
|
||||
const onTradingAcceptEvent = useCallback((event: TradingAcceptEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { UnseenItemsEvent, UnseenResetCategoryComposer, UnseenResetItemsComposer } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { UseMessageEventHook } from '..';
|
||||
import { SendMessageComposer } from '../../api';
|
||||
@ -10,17 +10,17 @@ const sendResetItemsMessage = (category: number, itemIds: number[]) => SendMessa
|
||||
const useInventoryUnseenTrackerState = () =>
|
||||
{
|
||||
const [ unseenItems, setUnseenItems ] = useState<Map<number, number[]>>(new Map());
|
||||
const getIds = (category: number) => unseenItems.get(category);
|
||||
const getCount = (category: number) => (unseenItems.get(category)?.length || 0);
|
||||
|
||||
const getFullCount = () =>
|
||||
const getCount = useCallback((category: number) => (unseenItems.get(category)?.length || 0), [ unseenItems ]);
|
||||
|
||||
const getFullCount = useMemo(() =>
|
||||
{
|
||||
let count = 0;
|
||||
|
||||
for(const key of unseenItems.keys()) count += getCount(key);
|
||||
|
||||
return count;
|
||||
}
|
||||
}, [ unseenItems, getCount ]);
|
||||
|
||||
const resetCategory = useCallback((category: number) =>
|
||||
{
|
||||
@ -128,7 +128,7 @@ const useInventoryUnseenTrackerState = () =>
|
||||
|
||||
UseMessageEventHook(UnseenItemsEvent, onUnseenItemsEvent);
|
||||
|
||||
return { getIds, getCount, getFullCount, resetCategory, resetItems, isUnseen, removeUnseen };
|
||||
return { getCount, getFullCount, resetCategory, resetItems, isUnseen, removeUnseen };
|
||||
}
|
||||
|
||||
export const useInventoryUnseenTracker = () => useBetween(useInventoryUnseenTrackerState);
|
||||
|
1
src/hooks/session/index.ts
Normal file
1
src/hooks/session/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './useSessionInfo';
|
33
src/hooks/session/useSessionInfo.ts
Normal file
33
src/hooks/session/useSessionInfo.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { FigureUpdateEvent, UserInfoDataParser, UserInfoEvent } from '@nitrots/nitro-renderer';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useBetween } from 'use-between';
|
||||
import { UseMessageEventHook } from '../messages';
|
||||
|
||||
const useSessionInfoState = () =>
|
||||
{
|
||||
const [ userInfo, setUserInfo ] = useState<UserInfoDataParser>(null);
|
||||
const [ userFigure, setUserFigure ] = useState<string>(null);
|
||||
|
||||
const onUserInfoEvent = useCallback((event: UserInfoEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserInfo(parser.userInfo);
|
||||
setUserFigure(parser.userInfo.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(UserInfoEvent, onUserInfoEvent);
|
||||
|
||||
const onUserFigureEvent = useCallback((event: FigureUpdateEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setUserFigure(parser.figure);
|
||||
}, []);
|
||||
|
||||
UseMessageEventHook(FigureUpdateEvent, onUserFigureEvent);
|
||||
|
||||
return { userInfo, userFigure };
|
||||
}
|
||||
|
||||
export const useSessionInfo = () => useBetween(useSessionInfoState);
|
Loading…
Reference in New Issue
Block a user