Add eslint formatting

This commit is contained in:
Bill 2022-04-01 13:33:08 -04:00
parent 95621e95eb
commit d7b00756bf
192 changed files with 2494 additions and 2323 deletions

View File

@ -1,86 +0,0 @@
module.exports = {
'extends': [
'react-app',
'react-app/jest'
],
'rules': {
'linebreak-style': [
'off'
],
'quotes': [
'error',
'single'
],
'brace-style': [
'error',
'allman',
{
'allowSingleLine': true
}
],
'object-curly-spacing': [
'error',
'always'
],
'keyword-spacing': [
'error',
{
'overrides': {
'if': {
'after': false
},
'for': {
'after': false
},
'while': {
'after': false
},
'switch': {
'after': false
}
}
}
],
'@typescript-eslint/no-explicit-any': [
'off'
],
'@typescript-eslint/ban-ts-comment': [
'off'
],
'@typescript-eslint/no-empty-function': [
'error',
{
'allow': [
'functions',
'arrowFunctions',
'generatorFunctions',
'methods',
'generatorMethods',
'constructors'
]
}
],
'@typescript-eslint/no-unused-vars': [
'off'
],
'@typescript-eslint/ban-types': [
'error',
{
'types': {
'String': true,
'Boolean': true,
'Number': true,
'Symbol': true,
'{}': false,
'Object': false,
'object': false,
'Function': false
},
'extendDefaults': true
}
],
'no-switch-case-fall-through': [
'off'
]
}
}

34
.eslintrc.json Normal file
View File

@ -0,0 +1,34 @@
{
"settings": {
"react": {
"pragma": "React",
"version": "17.0.2"
}
},
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended",
"plugin:react/jsx-runtime"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"react",
"@typescript-eslint"
],
"rules": {
"indent": ["error", 4, {"SwitchCase": 1}],
"array-bracket-spacing": ["error", "always"],
"brace-style": ["error", "allman"],
"react/prop-types": ["off"]
}
}

View File

@ -1 +0,0 @@
*.scss

View File

@ -14,5 +14,7 @@
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"editor.wordWrap": "on",
"emmet.showExpandedAbbreviation": "never"
"emmet.showExpandedAbbreviation": "never",
"eslint.validate": [ "javascript", "javascriptreact", "html", "typescriptreact" ],
"eslint.workingDirectories": [ "./src" ]
}

View File

@ -7,7 +7,8 @@
"build": "cross-env GENERATE_SOURCEMAP=false IMAGE_INLINE_SIZE_LIMIT=100000 craco build",
"build:prod": "npx browserslist@latest --update-db && yarn build",
"test": "craco test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"eslint": "eslint src --ext .ts,.tsx"
},
"dependencies": {
"@craco/craco": "^6.3.0",
@ -41,7 +42,13 @@
"@types/react-slider": "^1.3.1",
"@types/react-transition-group": "^4.4.2",
"@types/react-virtualized": "^9.21.13",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"eslint": "^8.12.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.4.0",
"react-error-overlay": "6.0.9"
}
}

View File

@ -14,8 +14,8 @@ export const App: FC<{}> = props =>
{
const [ isReady, setIsReady ] = useState(false);
const [ isError, setIsError ] = useState(false);
const [message, setMessage] = useState('Getting Ready');
const [percent, setPercent] = useState(0);
const [ message, setMessage ] = useState('Getting Ready');
const [ percent, setPercent ] = useState(0);
//@ts-ignore
if(!NitroConfig) throw new Error('NitroConfig is not defined!');
@ -68,24 +68,24 @@ export const App: FC<{}> = props =>
return;
case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKING:
loadPercent();
return;
case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED:
return;
case NitroCommunicationDemoEvent.CONNECTION_HANDSHAKE_FAILED:
setIsError(true);
setMessage('Handshake Failed');
return;
case NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED:
return;
case NitroCommunicationDemoEvent.CONNECTION_AUTHENTICATED:
loadPercent();
GetNitroInstance().init();
if(LegacyExternalInterface.available) LegacyExternalInterface.call('legacyTrack', 'authentication', 'authok', []);
return;
case NitroCommunicationDemoEvent.CONNECTION_ERROR:
return;
case NitroCommunicationDemoEvent.CONNECTION_ERROR:
setIsError(true);
setMessage('Connection Error');
return;
case NitroCommunicationDemoEvent.CONNECTION_CLOSED:
//if(GetNitroInstance().roomEngine) GetNitroInstance().roomEngine.dispose();
return;
case NitroCommunicationDemoEvent.CONNECTION_CLOSED:
//if(GetNitroInstance().roomEngine) GetNitroInstance().roomEngine.dispose();
//setIsError(true);
setMessage('Connection Error');

View File

@ -34,7 +34,7 @@ export class ProductImageUtility
}
break;
case CatalogPageMessageProductData.E:
// fx_icon_furniClassId_png
// fx_icon_furniClassId_png
break;
}

View File

@ -10,5 +10,6 @@ export class TradeUserData
public itemCount: number = 0,
public creditsCount: number = 0,
public accepts: boolean = false,
public canTrade: boolean = false) {}
public canTrade: boolean = false)
{}
}

View File

@ -37,40 +37,40 @@ export class FurniChooserWidgetHandler extends RoomWidgetHandler
const floorItems = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.FLOOR);
wallItems.forEach(roomObject =>
{
let name = roomObject.type;
if(name.startsWith('poster'))
{
let name = roomObject.type;
if(name.startsWith('poster'))
{
name = LocalizeText(`poster_${ name.replace('poster', '') }_name`);
}
else
{
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
const furniData = GetSessionDataManager().getWallItemData(typeId);
if(furniData && furniData.name.length) name = furniData.name;
}
items.push(new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name));
});
floorItems.forEach(roomObject =>
name = LocalizeText(`poster_${ name.replace('poster', '') }_name`);
}
else
{
let name = roomObject.type;
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
const furniData = GetSessionDataManager().getFloorItemData(typeId);
const furniData = GetSessionDataManager().getWallItemData(typeId);
if(furniData && furniData.name.length) name = furniData.name;
}
items.push(new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name));
});
items.push(new RoomObjectItem(roomObject.id, RoomObjectCategory.WALL, name));
});
floorItems.forEach(roomObject =>
{
let name = roomObject.type;
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
const furniData = GetSessionDataManager().getFloorItemData(typeId);
if(furniData && furniData.name.length) name = furniData.name;
items.push(new RoomObjectItem(roomObject.id, RoomObjectCategory.FLOOR, name));
});
items.sort((a, b) =>
{
return (a.name < b.name) ? -1 : 1;
});
{
return (a.name < b.name) ? -1 : 1;
});
this.container.eventDispatcher.dispatchEvent(new RoomWidgetChooserContentEvent(RoomWidgetChooserContentEvent.FURNI_CHOOSER_CONTENT, items));
}

View File

@ -43,7 +43,7 @@ export class FurnitureInternalLinkHandler extends RoomWidgetHandler
public get eventTypes(): string[]
{
return [RoomEngineTriggerWidgetEvent.REQUEST_INTERNAL_LINK];
return [ RoomEngineTriggerWidgetEvent.REQUEST_INTERNAL_LINK ];
}
public get messageTypes(): string[]

View File

@ -49,7 +49,7 @@ export class FurnitureRoomLinkHandler extends RoomWidgetHandler
public get eventTypes(): string[]
{
return [RoomEngineTriggerWidgetEvent.REQUEST_ROOM_LINK];
return [ RoomEngineTriggerWidgetEvent.REQUEST_ROOM_LINK ];
}
public get messageTypes(): string[]

View File

@ -63,11 +63,11 @@ export class PollWidgetHandler extends RoomWidgetHandler
public get eventTypes(): string[]
{
return [RoomSessionPollEvent.OFFER, RoomSessionPollEvent.ERROR, RoomSessionPollEvent.CONTENT];
return [ RoomSessionPollEvent.OFFER, RoomSessionPollEvent.ERROR, RoomSessionPollEvent.CONTENT ];
}
public get messageTypes(): string[]
{
return [RoomWidgetPollMessage.ANSWER, RoomWidgetPollMessage.REJECT, RoomWidgetPollMessage.START];
return [ RoomWidgetPollMessage.ANSWER, RoomWidgetPollMessage.REJECT, RoomWidgetPollMessage.START ];
}
}

View File

@ -50,7 +50,7 @@ export class RoomWidgetAvatarInfoHandler extends RoomWidgetHandler
this.processOwnCharacterInfo();
break;
case RoomWidgetUserActionMessage.START_NAME_CHANGE:
// habbo help - start name change
// habbo help - start name change
break;
case RoomWidgetUserActionMessage.REQUEST_PET_UPDATE:
break;

View File

@ -101,7 +101,7 @@ export class RoomWidgetChatHandler extends RoomWidgetHandler implements IAvatarI
text = LocalizeText('widget.chatbubble.pettreat', [ 'petname' ], [ username ]);
break;
case RoomSessionChatEvent.CHAT_TYPE_HAND_ITEM_RECEIVED:
text = LocalizeText('widget.chatbubble.handitem', [ 'username', 'handitem' ], [ username, LocalizeText(('handitem' + chatEvent.extraParam))]);
text = LocalizeText('widget.chatbubble.handitem', [ 'username', 'handitem' ], [ username, LocalizeText(('handitem' + chatEvent.extraParam)) ]);
break;
case RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING: {
const hours = ((chatEvent.extraParam > 0) ? Math.floor((chatEvent.extraParam / 3600)) : 0).toString();

View File

@ -141,10 +141,10 @@ export class RoomWidgetChatInputHandler extends RoomWidgetHandler
if(this.container.roomSession.isRoomOwner || GetSessionDataManager().isModerator)
{
NotificationUtilities.confirm(LocalizeText('room.confirm.pick_all'), () =>
{
GetSessionDataManager().sendSpecialCommandMessage(':pickall');
},
null, null, null, LocalizeText('generic.alert.title'));
{
GetSessionDataManager().sendSpecialCommandMessage(':pickall');
},
null, null, null, LocalizeText('generic.alert.title'));
}
return null;

View File

@ -35,13 +35,13 @@ export class UserChooserWidgetHandler extends RoomWidgetHandler
const userItems = GetRoomEngine().getRoomObjects(roomId, RoomObjectCategory.UNIT);
userItems.forEach(roomObject =>
{
const userData = this.container.roomSession.userDataManager.getUserDataByIndex(roomObject.id);
{
const userData = this.container.roomSession.userDataManager.getUserDataByIndex(roomObject.id);
if(!userData) return;
if(!userData) return;
items.push(new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name));
});
items.push(new RoomObjectItem(userData.roomIndex, RoomObjectCategory.UNIT, userData.name));
});
items.sort((a, b) =>
{

View File

@ -64,7 +64,7 @@ export class WordQuizWidgetHandler extends RoomWidgetHandler
public get eventTypes(): string[]
{
return [RoomSessionWordQuizEvent.ANSWERED, RoomSessionWordQuizEvent.FINISHED, RoomSessionWordQuizEvent.QUESTION];
return [ RoomSessionWordQuizEvent.ANSWERED, RoomSessionWordQuizEvent.FINISHED, RoomSessionWordQuizEvent.QUESTION ];
}
public get messageTypes(): string[]

View File

@ -4,7 +4,7 @@ export class RoomWidgetDanceMessage extends RoomWidgetMessage
{
public static DANCE: string = 'RWDM_MESSAGE_DANCE';
public static NORMAL_STYLE: number = 0;
public static CLUB_STYLE: number[] = [2, 3, 4];
public static CLUB_STYLE: number[] = [ 2, 3, 4 ];
private _style: number = 0;

View File

@ -157,7 +157,7 @@ export class NotificationUtilities
public static handleHotelClosedMessage(open: number, minute: number, thrownOut: boolean): void
{
this.simpleAlert( LocalizeText(('opening.hours.' + (thrownOut ? 'disconnected' : 'closed')), [ 'h', 'm'], [ this.getTimeZeroPadded(open), this.getTimeZeroPadded(minute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
this.simpleAlert( LocalizeText(('opening.hours.' + (thrownOut ? 'disconnected' : 'closed')), [ 'h', 'm' ], [ this.getTimeZeroPadded(open), this.getTimeZeroPadded(minute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
}
public static handleHotelMaintenanceMessage(minutesUntilMaintenance: number, duration: number): void

View File

@ -26,16 +26,16 @@ allowedColours.set('pink', 'pink');
function encodeHTML(str: string)
{
return str.replace(/([\u00A0-\u9999<>&])(.|$)/g, function(full, char, next)
{
if(char !== '&' || next !== '#')
{
if(/[\u00A0-\u9999<>&]/.test(next))
next = '&#' + next.charCodeAt(0) + ';';
{
if(char !== '&' || next !== '#')
{
if(/[\u00A0-\u9999<>&]/.test(next))
next = '&#' + next.charCodeAt(0) + ';';
return '&#' + char.charCodeAt(0) + ';' + next;
}
return '&#' + char.charCodeAt(0) + ';' + next;
}
return full;
return full;
});
}

View File

@ -45,26 +45,26 @@ export const NitroCardAccordionSetView: FC<NitroCardAccordionSetViewProps> = pro
const closeFunction = close;
setClosers(prevValue =>
{
const newClosers = [ ...prevValue ];
{
const newClosers = [ ...prevValue ];
newClosers.push(closeFunction);
newClosers.push(closeFunction);
return newClosers;
});
return newClosers;
});
return () =>
{
setClosers(prevValue =>
{
const newClosers = [ ...prevValue ];
{
const newClosers = [ ...prevValue ];
const index = newClosers.indexOf(closeFunction);
const index = newClosers.indexOf(closeFunction);
if(index >= 0) newClosers.splice(index, 1);
if(index >= 0) newClosers.splice(index, 1);
return newClosers;
});
return newClosers;
});
}
}, [ close, setClosers ]);

View File

@ -261,8 +261,8 @@ export const DraggableWindow: FC<DraggableWindowProps> = props =>
return (
createPortal(
<Base position="absolute" innerRef={ elementRef } className="draggable-window" onMouseDownCapture={ onMouseDown } onTouchStartCapture={ onTouchStart } style={ dragStyle }>
{ children }
</Base>, document.getElementById('draggable-windows-container'))
<Base position="absolute" innerRef={ elementRef } className="draggable-window" onMouseDownCapture={ onMouseDown } onTouchStartCapture={ onTouchStart } style={ dragStyle }>
{ children }
</Base>, document.getElementById('draggable-windows-container'))
);
}

View File

@ -67,7 +67,8 @@ export const LayoutAvatarImageView: FC<LayoutAvatarImageViewProps> = props =>
setRandomValue(Math.random());
},
dispose: () => {},
dispose: () =>
{},
disposed: false
}, null);

View File

@ -31,7 +31,7 @@ export const LayoutGiftTagView: FC<LayoutGiftTagViewProps> = props =>
{ editable && (onChange !== null) &&
<textarea className="gift-message h-100" maxLength={ 140 } value={ message } onChange={ (e) => onChange(e.target.value) } placeholder={ LocalizeText('catalog.gift_wrapping_new.message_hint') }></textarea> }
{ userName &&
<Text italics textEnd className="pe-1">{ LocalizeText('catalog.gift_wrapping_new.message_from', ['name'], [userName]) }</Text> }
<Text italics textEnd className="pe-1">{ LocalizeText('catalog.gift_wrapping_new.message_from', [ 'name' ], [ userName ]) }</Text> }
</Column>
</Flex>
</Flex>

View File

@ -15,7 +15,7 @@ export const LayoutNotificationAlertView: FC<LayoutNotificationAlertViewProps> =
const getClassNames = useMemo(() =>
{
const newClassNames: string[] = ['nitro-alert'];
const newClassNames: string[] = [ 'nitro-alert' ];
newClassNames.push('nitro-alert-' + type);

View File

@ -35,11 +35,11 @@ export const LayoutNotificationBubbleView: FC<LayoutNotificationBubbleViewProps>
if(!fadesOut) return;
const timeout = setTimeout(() =>
{
setIsVisible(false);
{
setIsVisible(false);
setTimeout(() => close(), 300);
}, timeoutMs);
setTimeout(() => close(), 300);
}, timeoutMs);
return () => clearTimeout(timeout);
}, [ fadesOut, timeoutMs, close ]);

View File

@ -74,15 +74,15 @@ export const LayoutRoomPreviewerView: FC<LayoutRoomPreviewerViewProps> = props =
GetNitroInstance().ticker.add(update);
const resizeObserver = new ResizeObserver(() =>
{
if(!roomPreviewer || !elementRef.current) return;
{
if(!roomPreviewer || !elementRef.current) return;
const width = elementRef.current.parentElement.offsetWidth;
const width = elementRef.current.parentElement.offsetWidth;
roomPreviewer.modifyRoomCanvas(width, height);
roomPreviewer.modifyRoomCanvas(width, height);
update(-1);
});
update(-1);
});
resizeObserver.observe(elementRef.current);

View File

@ -8,15 +8,11 @@ interface LayoutLimitedEditionStyledNumberViewProps
export const LayoutLimitedEditionStyledNumberView: FC<LayoutLimitedEditionStyledNumberViewProps> = props =>
{
const { value = 0 } = props;
const numbers = value.toString().split('');
return (
<>
{ numbers.map((number, index) =>
{
return <i key={ index } className={ 'limited-edition-number n-' + number } />;
})}
{ numbers.map((number, index) => <i key={ index } className={ 'limited-edition-number n-' + number } />) }
</>
);
}

View File

@ -22,50 +22,50 @@ export const AchievementsView: FC<{}> = props =>
const categoryName = achievement.category;
setAchievementCategories(prevValue =>
{
const newValue = [ ...prevValue ];
const categoryIndex = newValue.findIndex(existing => (existing.code === categoryName));
if(categoryIndex === -1)
{
const newValue = [ ...prevValue ];
const categoryIndex = newValue.findIndex(existing => (existing.code === categoryName));
const category = new AchievementCategory(categoryName);
if(categoryIndex === -1)
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)
{
const category = new AchievementCategory(categoryName);
category.achievements.push(achievement);
newValue.push(category);
newAchievements.push(achievement);
}
else
{
const category = CloneObject(newValue[categoryIndex]);
const newAchievements = [ ...category.achievements ];
const achievementIndex = newAchievements.findIndex(existing => (existing.achievementId === achievement.achievementId));
let previousAchievement: AchievementData = null;
previousAchievement = newAchievements[achievementIndex];
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;
newAchievements[achievementIndex] = achievement;
}
return newValue;
});
if(!GetAchievementIsIgnored(achievement))
{
achievement.unseen++;
if(previousAchievement) achievement.unseen += previousAchievement.unseen;
}
category.achievements = newAchievements;
newValue[categoryIndex] = category;
}
return newValue;
});
}, []);
UseMessageEventHook(AchievementEvent, onAchievementEvent);
@ -155,23 +155,23 @@ export const AchievementsView: FC<{}> = props =>
const setAchievementSeen = useCallback((code: string, achievementId: number) =>
{
setAchievementCategories(prevValue =>
{
const newValue = [ ...prevValue ];
for(const category of newValue)
{
const newValue = [ ...prevValue ];
if(category.code !== code) continue;
for(const category of newValue)
for(const achievement of category.achievements)
{
if(category.code !== code) continue;
if(achievement.achievementId !== achievementId) continue;
for(const achievement of category.achievements)
{
if(achievement.achievementId !== achievementId) continue;
achievement.unseen = 0;
}
achievement.unseen = 0;
}
}
return newValue;
});
return newValue;
});
}, []);
const linkReceived = useCallback((url: string) =>

View File

@ -288,15 +288,15 @@ export const AvatarEditorView: FC<{}> = props =>
<NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView>
{ categories && (categories.size > 0) && Array.from(categories.keys()).map(category =>
{
const isActive = (activeCategory && (activeCategory.name === category));
{
const isActive = (activeCategory && (activeCategory.name === category));
return (
<NitroCardTabsItemView key={ category } isActive={ isActive } onClick={ event => selectCategory(category) }>
{ LocalizeText(`avatareditor.category.${ category }`) }
</NitroCardTabsItemView>
);
})}
return (
<NitroCardTabsItemView key={ category } isActive={ isActive } onClick={ event => selectCategory(category) }>
{ LocalizeText(`avatareditor.category.${ category }`) }
</NitroCardTabsItemView>
);
})}
<NitroCardTabsItemView isActive={ isWardrobeVisible } onClick={ event => setIsWardrobeVisible(true) }>
{ LocalizeText('avatareditor.category.wardrobe') }
</NitroCardTabsItemView>

View File

@ -5,7 +5,7 @@ import { FigureData } from './FigureData';
export class AvatarEditorGridPartItem implements IAvatarImageListener
{
private static ALPHA_FILTER: NitroAlphaFilter = new NitroAlphaFilter(0.2);
private static THUMB_DIRECTIONS: number[] = [2, 6, 0, 4, 3, 1];
private static THUMB_DIRECTIONS: number[] = [ 2, 6, 0, 4, 3, 1 ];
private static DRAW_ORDER: string[] = [
AvatarFigurePartType.LEFT_HAND_ITEM,
AvatarFigurePartType.LEFT_HAND,

View File

@ -26,11 +26,11 @@ function getRandomPartSet(setType: SetType, gender: string, clubLevel: number =
if(!setType) return null;
const options = setType.partSets.getValues().filter(option =>
{
if(!option.isSelectable || ((option.gender !== 'U') && (option.gender !== gender)) || (option.clubLevel > clubLevel) || (option.isSellable && (figureSetIds.indexOf(option.id) === -1))) return null;
{
if(!option.isSelectable || ((option.gender !== 'U') && (option.gender !== gender)) || (option.clubLevel > clubLevel) || (option.isSellable && (figureSetIds.indexOf(option.id) === -1))) return null;
return option;
});
return option;
});
if(!options || !options.length) return null;
@ -42,11 +42,11 @@ function getRandomColors(palette: IPalette, partSet: IFigurePartSet, clubLevel:
if(!palette) return [];
const options = palette.colors.getValues().filter(option =>
{
if(!option.isSelectable || (option.clubLevel > clubLevel)) return null;
{
if(!option.isSelectable || (option.clubLevel > clubLevel)) return null;
return option;
});
return option;
});
if(!options || !options.length) return null;

View File

@ -68,15 +68,15 @@ export const AvatarEditorModelView: FC<AvatarEditorModelViewProps> = props =>
</Flex>
</> }
{ !model.canSetGender && model.categories && (model.categories.size > 0) && Array.from(model.categories.keys()).map(name =>
{
const category = model.categories.get(name);
{
const category = model.categories.get(name);
return (
<Flex center pointer key={ name } className="category-item" onClick={ event => selectCategory(name) }>
<AvatarEditorIcon icon={ category.name } selected={ (activeCategory === category) } />
</Flex>
);
})}
return (
<Flex center pointer key={ name } className="category-item" onClick={ event => selectCategory(name) }>
<AvatarEditorIcon icon={ category.name } selected={ (activeCategory === category) } />
</Flex>
);
})}
</Column>
<Column size={ 5 } overflow="hidden">
<AvatarEditorFigureSetView model={ model } category={ activeCategory } setMaxPaletteCount={ setMaxPaletteCount } />

View File

@ -47,25 +47,25 @@ export const AvatarEditorWardrobeView: FC<AvatarEditorWardrobeViewProps> = props
const items: JSX.Element[] = [];
savedFigures.forEach(([ figureContainer, gender ], index) =>
{
let clubLevel = 0;
{
let clubLevel = 0;
if(figureContainer) clubLevel = GetAvatarRenderManager().getFigureClubLevel(figureContainer, gender);
if(figureContainer) clubLevel = GetAvatarRenderManager().getFigureClubLevel(figureContainer, gender);
items.push(
<LayoutGridItem key={ index } position="relative" overflow="hidden" className="nitro-avatar-editor-wardrobe-figure-preview">
{ figureContainer &&
items.push(
<LayoutGridItem key={ index } position="relative" overflow="hidden" className="nitro-avatar-editor-wardrobe-figure-preview">
{ figureContainer &&
<LayoutAvatarImageView figure={ figureContainer.getFigureString() } gender={ gender } direction={ 2 } /> }
<Base className="avatar-shadow" />
{ (clubLevel > 0) && <LayoutCurrencyIcon className="position-absolute top-1 start-1" type="hc" /> }
<Flex gap={ 1 } className="button-container">
<Button variant="link" fullWidth onClick={ event => saveFigureAtWardrobeIndex(index) }>{ LocalizeText('avatareditor.wardrobe.save') }</Button>
{ figureContainer &&
<Base className="avatar-shadow" />
{ (clubLevel > 0) && <LayoutCurrencyIcon className="position-absolute top-1 start-1" type="hc" /> }
<Flex gap={ 1 } className="button-container">
<Button variant="link" fullWidth onClick={ event => saveFigureAtWardrobeIndex(index) }>{ LocalizeText('avatareditor.wardrobe.save') }</Button>
{ figureContainer &&
<Button variant="link" fullWidth onClick={ event => wearFigureAtIndex(index) } disabled={ (clubLevel > GetClubMemberLevel()) }>{ LocalizeText('generic_usable.button.use') }</Button> }
</Flex>
</LayoutGridItem>
);
});
</Flex>
</LayoutGridItem>
);
});
return items;
}, [ savedFigures, saveFigureAtWardrobeIndex, wearFigureAtIndex ]);

View File

@ -70,13 +70,13 @@ export const CameraWidgetView: FC<{}> = props =>
return;
case 'delete':
setCameraRoll(prevValue =>
{
const clone = [ ...prevValue ];
{
const clone = [ ...prevValue ];
clone.splice(selectedPictureIndex, 1);
clone.splice(selectedPictureIndex, 1);
return clone;
});
return clone;
});
return;
case 'editor_cancel':
setMode(MODE_CAPTURE);
@ -106,10 +106,10 @@ export const CameraWidgetView: FC<{}> = props =>
return;
case 'toggle':
setMode(prevValue =>
{
if(!prevValue) return MODE_CAPTURE;
else return MODE_NONE;
});
{
if(!prevValue) return MODE_CAPTURE;
else return MODE_NONE;
});
return;
}
}, []);

View File

@ -4,5 +4,6 @@ export class CameraPicture
{
constructor(
public texture: NitroTexture,
public imageUrl: string) {}
public imageUrl: string)
{}
}

View File

@ -2,5 +2,6 @@ export class CameraPictureThumbnail
{
constructor(
public effectName: string,
public thumbnailUrl: string) {}
public thumbnailUrl: string)
{}
}

View File

@ -80,9 +80,9 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
{ (cameraRoll.length > 0) &&
<Flex gap={ 2 } justifyContent="center" className="camera-roll d-flex justify-content-center py-2">
{ cameraRoll.map((picture, index) =>
{
return <img alt="" key={ index } src={ picture.imageUrl } onClick={ event => setSelectedPictureIndex(index) } />;
}) }
{
return <img alt="" key={ index } src={ picture.imageUrl } onClick={ event => setSelectedPictureIndex(index) } />;
}) }
</Flex> }
</Column>
</DraggableWindow>

View File

@ -76,14 +76,14 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
if(index === -1) return;
setSelectedEffects(prevValue =>
{
const clone = [ ...prevValue ];
const currentEffect = clone[index];
{
const clone = [ ...prevValue ];
const currentEffect = clone[index];
clone[getCurrentEffectIndex] = new RoomCameraWidgetSelectedEffect(currentEffect.effect, alpha);
clone[getCurrentEffectIndex] = new RoomCameraWidgetSelectedEffect(currentEffect.effect, alpha);
return clone;
});
return clone;
});
}, [ getCurrentEffectIndex, setSelectedEffects ]);
const getCurrentPictureUrl = useMemo(() =>
@ -117,9 +117,9 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
if(!effect) return;
setSelectedEffects(prevValue =>
{
return [ ...prevValue, new RoomCameraWidgetSelectedEffect(effect, 1) ];
});
{
return [ ...prevValue, new RoomCameraWidgetSelectedEffect(effect, 1) ];
});
setSelectedEffectName(effect.name);
return;
@ -130,13 +130,13 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
if(existingIndex === -1) return;
setSelectedEffects(prevValue =>
{
const clone = [ ...prevValue ];
{
const clone = [ ...prevValue ];
clone.splice(existingIndex, 1);
clone.splice(existingIndex, 1);
return clone;
});
return clone;
});
if(selectedEffectName === effectName) setSelectedEffectName(null);
return;
@ -177,9 +177,9 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
<NitroCardHeaderView headerText={ LocalizeText('camera.editor.button.text') } onCloseClick={ event => processAction('close') } />
<NitroCardTabsView>
{ TABS.map(tab =>
{
return <NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ event => processAction('change_tab', tab) }><i className={ 'icon icon-camera-' + tab }></i></NitroCardTabsItemView>
}) }
{
return <NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ event => processAction('change_tab', tab) }><i className={ 'icon icon-camera-' + tab }></i></NitroCardTabsItemView>
}) }
</NitroCardTabsView>
<NitroCardContentView>
<Grid>

View File

@ -20,12 +20,12 @@ export const CameraWidgetEffectListView: FC<CameraWidgetEffectListViewProps> = p
return (
<AutoGrid columnCount={ 2 } columnMinHeight={ 60 }>
{ effects && (effects.length > 0) && effects.map((effect, index) =>
{
const thumbnailUrl = (thumbnails.find(thumbnail => (thumbnail.effectName === effect.name)));
const isActive = (selectedEffects.findIndex(selectedEffect => (selectedEffect.effect.name === effect.name)) > -1);
{
const thumbnailUrl = (thumbnails.find(thumbnail => (thumbnail.effectName === effect.name)));
const isActive = (selectedEffects.findIndex(selectedEffect => (selectedEffect.effect.name === effect.name)) > -1);
return <CameraWidgetEffectListItemView key={ index } effect={ effect } thumbnailUrl={ ((thumbnailUrl && thumbnailUrl.thumbnailUrl) || null) } isActive={ isActive } isLocked={ (effect.minLevel > myLevel) } selectEffect={ () => processAction('select_effect', effect.name) } removeEffect={ () => processAction('remove_effect', effect.name) } />
}) }
return <CameraWidgetEffectListItemView key={ index } effect={ effect } thumbnailUrl={ ((thumbnailUrl && thumbnailUrl.thumbnailUrl) || null) } isActive={ isActive } isLocked={ (effect.minLevel > myLevel) } selectEffect={ () => processAction('select_effect', effect.name) } removeEffect={ () => processAction('remove_effect', effect.name) } />
}) }
</AutoGrid>
);
}

View File

@ -104,7 +104,7 @@ export const CalendarView: FC<CalendarViewProps> = props =>
<Column size={ 10 }>
<Flex justifyContent="between" alignItems="center" gap={ 1 }>
<Column gap={ 1 }>
<Text fontSize={ 3 }>{ LocalizeText('campaign.calendar.heading.day', ['number'], [(selectedDay + 1).toString()]) }</Text>
<Text fontSize={ 3 }>{ LocalizeText('campaign.calendar.heading.day', [ 'number' ], [ (selectedDay + 1).toString() ]) }</Text>
<Text>{ dayMessage(selectedDay) }</Text>
</Column>
<div>
@ -121,16 +121,16 @@ export const CalendarView: FC<CalendarViewProps> = props =>
</Flex>
<Column center fullWidth>
<Grid fit columnCount={ TOTAL_SHOWN_ITEMS } gap={ 1 }>
{ [...Array(TOTAL_SHOWN_ITEMS)].map((e, i) =>
{
const day = (index + i);
{ [ ...Array(TOTAL_SHOWN_ITEMS) ].map((e, i) =>
{
const day = (index + i);
return (
<Column key={ i } overflow="hidden">
<CalendarItemView itemId={ day } state={ getDayState(day) } active={ (selectedDay === day) } product={ receivedProducts.has(day) ? receivedProducts.get(day) : null } onClick={ onClickItem } />
</Column>
);
}) }
return (
<Column key={ i } overflow="hidden">
<CalendarItemView itemId={ day } state={ getDayState(day) } active={ (selectedDay === day) } product={ receivedProducts.has(day) ? receivedProducts.get(day) : null } onClick={ onClickItem } />
</Column>
);
}) }
</Grid>
</Column>
<Flex center>

View File

@ -34,25 +34,25 @@ export const CampaignView: FC<{}> = props =>
BatchUpdates(() =>
{
setCalendarData(prev =>
{
const copy = prev.clone();
copy.openedDays.push(lastOpenAttempt);
{
const copy = prev.clone();
copy.openedDays.push(lastOpenAttempt);
return copy;
});
return copy;
});
setReceivedProducts(prev =>
{
const copy = new Map(prev);
copy.set(lastAttempt, new CalendarItem(parser.productName, parser.customImage,parser.furnitureClassName));
setReceivedProducts(prev =>
{
const copy = new Map(prev);
copy.set(lastAttempt, new CalendarItem(parser.productName, parser.customImage,parser.furnitureClassName));
return copy;
});
return copy;
});
});
}
setLastOpenAttempt(-1);
}, [lastOpenAttempt]);
}, [ lastOpenAttempt ]);
UseMessageEventHook(CampaignCalendarDoorOpenedMessageEvent, onCampaignCalendarDoorOpenedMessageEvent);
@ -71,7 +71,7 @@ export const CampaignView: FC<{}> = props =>
{
SendMessageComposer(new OpenCampaignCalendarDoorComposer(calendarData.campaignName, id));
}
}, [calendarData]);
}, [ calendarData ]);
const onCalendarClose = useCallback(() =>
{
@ -101,7 +101,7 @@ export const CampaignView: FC<{}> = props =>
{
RemoveLinkEventTracker(linkTracker);
}
}, [onLinkReceived]);
}, [ onLinkReceived ]);
return (
<>

View File

@ -155,13 +155,13 @@ export const CatalogMessageHandler: FC<{}> = props =>
if(offer.product && (offer.product.productType === ProductTypeEnum.WALL))
{
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraData =( offer.product.extraParam || null);
newValue.extraData =( offer.product.extraParam || null);
return newValue;
});
return newValue;
});
}
}
@ -174,27 +174,27 @@ export const CatalogMessageHandler: FC<{}> = props =>
const petPalette = new CatalogPetPalette(parser.productCode, parser.palettes.slice());
setCatalogOptions(prevValue =>
{
const petPalettes = [];
if(prevValue.petPalettes) petPalettes.push(...prevValue.petPalettes);
for(let i = 0; i < petPalettes.length; i++)
{
const petPalettes = [];
const palette = petPalettes[i];
if(prevValue.petPalettes) petPalettes.push(...prevValue.petPalettes);
for(let i = 0; i < petPalettes.length; i++)
if(palette.breed === petPalette.breed)
{
const palette = petPalettes[i];
petPalettes.splice(i, 1);
if(palette.breed === petPalette.breed)
{
petPalettes.splice(i, 1);
break;
}
break;
}
}
petPalettes.push(petPalette);
petPalettes.push(petPalette);
return { ...prevValue, petPalettes };
});
return { ...prevValue, petPalettes };
});
}, [ setCatalogOptions ]);
const onApproveNameMessageEvent = useCallback((event: ApproveNameMessageEvent) =>
@ -214,11 +214,11 @@ export const CatalogMessageHandler: FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const clubOffers = parser.offers;
{
const clubOffers = parser.offers;
return { ...prevValue, clubOffers };
});
return { ...prevValue, clubOffers };
});
}, [ setCatalogOptions ]);
const onGuildMembershipsMessageEvent = useCallback((event: GuildMembershipsMessageEvent) =>
@ -226,11 +226,11 @@ export const CatalogMessageHandler: FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const groups = parser.groups;
{
const groups = parser.groups;
return { ...prevValue, groups };
});
return { ...prevValue, groups };
});
}, [ setCatalogOptions ]);
const onUserSubscriptionEvent = useCallback((event: UserSubscriptionEvent) =>
@ -238,16 +238,16 @@ export const CatalogMessageHandler: FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const subscriptionInfo = new SubscriptionInfo(
Math.max(0, parser.daysToPeriodEnd),
Math.max(0, parser.periodsSubscribedAhead),
parser.isVip,
parser.pastClubDays,
parser.pastVipDays);
{
const subscriptionInfo = new SubscriptionInfo(
Math.max(0, parser.daysToPeriodEnd),
Math.max(0, parser.periodsSubscribedAhead),
parser.isVip,
parser.pastClubDays,
parser.pastVipDays);
return { ...prevValue, subscriptionInfo };
});
return { ...prevValue, subscriptionInfo };
});
}, [ setCatalogOptions ]);
const onGiftWrappingConfigurationEvent = useCallback((event: GiftWrappingConfigurationEvent) =>
@ -255,11 +255,11 @@ export const CatalogMessageHandler: FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const giftConfiguration = new GiftWrappingConfiguration(parser);
{
const giftConfiguration = new GiftWrappingConfiguration(parser);
return { ...prevValue, giftConfiguration };
});
return { ...prevValue, giftConfiguration };
});
}, [ setCatalogOptions ]);
const onMarketplaceMakeOfferResult = useCallback((event: MarketplaceMakeOfferResult) =>
@ -288,11 +288,11 @@ export const CatalogMessageHandler: FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const clubGifts = parser;
{
const clubGifts = parser;
return { ...prevValue, clubGifts };
});
return { ...prevValue, clubGifts };
});
}, [ setCatalogOptions ]);
UseMessageEventHook(CatalogPagesListEvent, onCatalogPagesListEvent);

View File

@ -183,31 +183,31 @@ export const CatalogView: FC<{}> = props =>
nodes.reverse();
setActiveNodes(prevValue =>
{
const isActive = (prevValue.indexOf(targetNode) >= 0);
const isOpen = targetNode.isOpen;
for(const existing of prevValue)
{
const isActive = (prevValue.indexOf(targetNode) >= 0);
const isOpen = targetNode.isOpen;
existing.deactivate();
for(const existing of prevValue)
{
existing.deactivate();
if(nodes.indexOf(existing) === -1) existing.close();
}
if(nodes.indexOf(existing) === -1) existing.close();
}
for(const n of nodes)
{
n.activate();
for(const n of nodes)
{
n.activate();
if(n.parent) n.open();
if(n.parent) n.open();
if((n === targetNode.parent) && n.children.length) n.open();
}
if((n === targetNode.parent) && n.children.length) n.open();
}
if(isActive && isOpen) targetNode.close();
else targetNode.open();
if(isActive && isOpen) targetNode.close();
else targetNode.open();
return nodes;
});
return nodes;
});
if(targetNode.pageId > -1) loadCatalogPage(targetNode.pageId, offerId);
}, [ setActiveNodes, loadCatalogPage ]);
@ -346,11 +346,11 @@ export const CatalogView: FC<{}> = props =>
return () =>
{
setRoomPreviewer(prevValue =>
{
prevValue.dispose();
{
prevValue.dispose();
return null;
});
return null;
});
}
}, []);
@ -415,23 +415,26 @@ export const CatalogView: FC<{}> = props =>
<CatalogMessageHandler />
{ isVisible &&
<NitroCardView uniqueKey="catalog" className="nitro-catalog">
<NitroCardHeaderView headerText={ LocalizeText('catalog.title') } onCloseClick={ event => { setIsVisible(false); } } />
<NitroCardHeaderView headerText={ LocalizeText('catalog.title') } onCloseClick={ event =>
{
setIsVisible(false);
} } />
<NitroCardTabsView>
{ rootNode && (rootNode.children.length > 0) && rootNode.children.map(child =>
{
if(!child.isVisible) return null;
{
if(!child.isVisible) return null;
return (
<NitroCardTabsItemView key={ child.pageId } isActive={ child.isActive } onClick={ event =>
{
if(searchResult) setSearchResult(null);
return (
<NitroCardTabsItemView key={ child.pageId } isActive={ child.isActive } onClick={ event =>
{
if(searchResult) setSearchResult(null);
activateNode(child);
} }>
{ child.localization }
</NitroCardTabsItemView>
);
}) }
activateNode(child);
} }>
{ child.localization }
</NitroCardTabsItemView>
);
}) }
</NitroCardTabsView>
<NitroCardContentView>
<Grid>
@ -446,8 +449,8 @@ export const CatalogView: FC<{}> = props =>
</Grid>
</NitroCardContentView>
</NitroCardView> }
<CatalogGiftView />
<MarketplacePostOfferView />
<CatalogGiftView />
<MarketplacePostOfferView />
</CatalogContextProvider>
);
}

View File

@ -5,5 +5,6 @@ export class CatalogPetPalette
constructor(
public readonly breed: string,
public readonly palettes: SellablePetPaletteData[]
) {}
)
{}
}

View File

@ -85,21 +85,21 @@ export function GetPetAvailableColors(petIndex: number, palettes: SellablePetPal
switch(petIndex)
{
case 0:
return [[16743226], [16750435], [16764339], [0xF59500], [16498012], [16704690], [0xEDD400], [16115545], [16513201], [8694111], [11585939], [14413767], [6664599], [9553845], [12971486], [8358322], [10002885], [13292268], [10780600], [12623573], [14403561], [12418717], [14327229], [15517403], [14515069], [15764368], [16366271], [0xABABAB], [0xD4D4D4], [0xFFFFFF], [14256481], [14656129], [15848130], [14005087], [14337152], [15918540], [15118118], [15531929], [9764857], [11258085]];
return [ [ 16743226 ], [ 16750435 ], [ 16764339 ], [ 0xF59500 ], [ 16498012 ], [ 16704690 ], [ 0xEDD400 ], [ 16115545 ], [ 16513201 ], [ 8694111 ], [ 11585939 ], [ 14413767 ], [ 6664599 ], [ 9553845 ], [ 12971486 ], [ 8358322 ], [ 10002885 ], [ 13292268 ], [ 10780600 ], [ 12623573 ], [ 14403561 ], [ 12418717 ], [ 14327229 ], [ 15517403 ], [ 14515069 ], [ 15764368 ], [ 16366271 ], [ 0xABABAB ], [ 0xD4D4D4 ], [ 0xFFFFFF ], [ 14256481 ], [ 14656129 ], [ 15848130 ], [ 14005087 ], [ 14337152 ], [ 15918540 ], [ 15118118 ], [ 15531929 ], [ 9764857 ], [ 11258085 ] ];
case 1:
return [[16743226], [16750435], [16764339], [0xF59500], [16498012], [16704690], [0xEDD400], [16115545], [16513201], [8694111], [11585939], [14413767], [6664599], [9553845], [12971486], [8358322], [10002885], [13292268], [10780600], [12623573], [14403561], [12418717], [14327229], [15517403], [14515069], [15764368], [16366271], [0xABABAB], [0xD4D4D4], [0xFFFFFF], [14256481], [14656129], [15848130], [14005087], [14337152], [15918540], [15118118], [15531929], [9764857], [11258085]];
return [ [ 16743226 ], [ 16750435 ], [ 16764339 ], [ 0xF59500 ], [ 16498012 ], [ 16704690 ], [ 0xEDD400 ], [ 16115545 ], [ 16513201 ], [ 8694111 ], [ 11585939 ], [ 14413767 ], [ 6664599 ], [ 9553845 ], [ 12971486 ], [ 8358322 ], [ 10002885 ], [ 13292268 ], [ 10780600 ], [ 12623573 ], [ 14403561 ], [ 12418717 ], [ 14327229 ], [ 15517403 ], [ 14515069 ], [ 15764368 ], [ 16366271 ], [ 0xABABAB ], [ 0xD4D4D4 ], [ 0xFFFFFF ], [ 14256481 ], [ 14656129 ], [ 15848130 ], [ 14005087 ], [ 14337152 ], [ 15918540 ], [ 15118118 ], [ 15531929 ], [ 9764857 ], [ 11258085 ] ];
case 2:
return [[16579283], [15378351], [8830016], [15257125], [9340985], [8949607], [6198292], [8703620], [9889626], [8972045], [12161285], [13162269], [8620113], [12616503], [8628101], [0xD2FF00], [9764857]];
return [ [ 16579283 ], [ 15378351 ], [ 8830016 ], [ 15257125 ], [ 9340985 ], [ 8949607 ], [ 6198292 ], [ 8703620 ], [ 9889626 ], [ 8972045 ], [ 12161285 ], [ 13162269 ], [ 8620113 ], [ 12616503 ], [ 8628101 ], [ 0xD2FF00 ], [ 9764857 ] ];
case 3:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD]];
return [ [ 0xFFFFFF ], [ 0xEEEEEE ], [ 0xDDDDDD ] ];
case 4:
return [[0xFFFFFF], [16053490], [15464440], [16248792], [15396319], [15007487]];
return [ [ 0xFFFFFF ], [ 16053490 ], [ 15464440 ], [ 16248792 ], [ 15396319 ], [ 15007487 ] ];
case 5:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD]];
return [ [ 0xFFFFFF ], [ 0xEEEEEE ], [ 0xDDDDDD ] ];
case 6:
return [[0xFFFFFF], [0xEEEEEE], [0xDDDDDD], [16767177], [16770205], [16751331]];
return [ [ 0xFFFFFF ], [ 0xEEEEEE ], [ 0xDDDDDD ], [ 16767177 ], [ 16770205 ], [ 16751331 ] ];
case 7:
return [[0xCCCCCC], [0xAEAEAE], [16751331], [10149119], [16763290], [16743786]];
return [ [ 0xCCCCCC ], [ 0xAEAEAE ], [ 16751331 ], [ 10149119 ], [ 16763290 ], [ 16743786 ] ];
default: {
const colors: number[][] = [];

View File

@ -6,6 +6,6 @@ export class SearchResult
constructor(
public readonly searchValue: string,
public readonly offers: IPurchasableOffer[],
public readonly filteredNodes: ICatalogNode[]
) {}
public readonly filteredNodes: ICatalogNode[])
{}
}

View File

@ -8,7 +8,8 @@ export class SubscriptionInfo
public readonly clubPeriods: number = 0,
public readonly isVip: boolean = false,
public readonly pastDays: number = 0,
public readonly pastVipDays: number = 0) {}
public readonly pastVipDays: number = 0)
{}
public get lastUpdated(): number
{

View File

@ -196,7 +196,7 @@ export const CatalogGiftView: FC<{}> = props =>
<Column gap={ 1 }>
<Text fontWeight="bold">{ LocalizeText(boxName) }</Text>
<Flex alignItems="center" gap={ 1 }>
{ LocalizeText(priceText, ['price'], [giftConfiguration.price.toString()]) }
{ LocalizeText(priceText, [ 'price' ], [ giftConfiguration.price.toString() ]) }
<LayoutCurrencyIcon type={ -1 } />
</Flex>
</Column>

View File

@ -14,11 +14,11 @@ export const CatalogNavigationSetView: FC<CatalogNavigationSetViewProps> = props
return (
<>
{ node && (node.children.length > 0) && node.children.map((n, index) =>
{
if(!n.isVisible) return null;
{
if(!n.isVisible) return null;
return <CatalogNavigationItemView key={ index } node={ n } />
}) }
return <CatalogNavigationItemView key={ index } node={ n } />
}) }
</>
);
}

View File

@ -42,7 +42,7 @@ export const CatalogLayoutBadgeDisplayView: FC<CatalogLayoutProps> = props =>
<Column grow gap={ 1 }>
<Text grow truncate>{ currentOffer.localizationName }</Text>
<Flex justifyContent="end">
<CatalogTotalPriceWidget alignItems="end" />
<CatalogTotalPriceWidget alignItems="end" />
</Flex>
<CatalogPurchaseWidgetView />
</Column>

View File

@ -21,13 +21,13 @@ export const CatalogLayoutTrophiesView: FC<CatalogLayoutProps> = props =>
if(!currentOffer) return;
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraData = trophyText;
newValue.extraData = trophyText;
return newValue;
});
return newValue;
});
}, [ currentOffer, trophyText, setPurchaseOptions ]);
return (

View File

@ -140,28 +140,28 @@ export const CatalogLayoutVipBuyView: FC<CatalogLayoutProps> = props =>
<Column fullHeight size={ 7 } overflow="hidden" justifyContent="between">
<AutoGrid columnCount={ 1 } className="nitro-catalog-layout-vip-buy-grid">
{ clubOffers && (clubOffers.length > 0) && clubOffers.map((offer, index) =>
{
return (
<LayoutGridItem key={ index } column={ false } center={ false } alignItems="center" justifyContent="between" itemActive={ pendingOffer === offer } className="p-1" onClick={ () => setOffer(offer) }>
<i className="icon-hc-banner" />
<Column justifyContent="end" gap={ 0 }>
<Text textEnd>{ getOfferText(offer) }</Text>
<Flex justifyContent="end" gap={ 1 }>
{ (offer.priceCredits > 0) &&
{
return (
<LayoutGridItem key={ index } column={ false } center={ false } alignItems="center" justifyContent="between" itemActive={ pendingOffer === offer } className="p-1" onClick={ () => setOffer(offer) }>
<i className="icon-hc-banner" />
<Column justifyContent="end" gap={ 0 }>
<Text textEnd>{ getOfferText(offer) }</Text>
<Flex justifyContent="end" gap={ 1 }>
{ (offer.priceCredits > 0) &&
<Flex alignItems="center" justifyContent="end" gap={ 1 }>
<Text>{ offer.priceCredits }</Text>
<LayoutCurrencyIcon type={ -1 } />
</Flex> }
{ (offer.priceActivityPoints > 0) &&
{ (offer.priceActivityPoints > 0) &&
<Flex alignItems="center" justifyContent="end" gap={ 1 }>
<Text>{ offer.priceActivityPoints }</Text>
<LayoutCurrencyIcon type={ offer.priceActivityPointsType } />
</Flex> }
</Flex>
</Column>
</LayoutGridItem>
);
}) }
</Flex>
</Column>
</LayoutGridItem>
);
}) }
</AutoGrid>
<Text center dangerouslySetInnerHTML={{ __html: LocalizeText('catalog.vip.buy.hccenter') }}></Text>
</Column>

View File

@ -64,7 +64,7 @@ export const GetCatalogLayout = (page: ICatalogPage, hideNavigation: () => void)
case 'badge_display':
return <CatalogLayoutBadgeDisplayView { ...layoutProps } />;
//case 'default_3x3_color_grouping':
//return <CatalogLayoutColorGroupingView { ...layoutProps } />;
//return <CatalogLayoutColorGroupingView { ...layoutProps } />;
case 'bots':
case 'default_3x3':
default:

View File

@ -44,8 +44,8 @@ export const CatalogLayoutMarketplaceItemView: FC<MarketplaceItemViewProps> = pr
text = hours + ' ' + LocalizeText('catalog.marketplace.offer.hours') + ' ' + text;
}
return LocalizeText('catalog.marketplace.offer.time_left', ['time'], [text] );
}, [offerData]);
return LocalizeText('catalog.marketplace.offer.time_left', [ 'time' ], [ text ] );
}, [ offerData ]);
return (
<LayoutGridItem shrink center={ false } column={ false } alignItems="center" className="p-1">
@ -59,8 +59,8 @@ export const CatalogLayoutMarketplaceItemView: FC<MarketplaceItemViewProps> = pr
</> }
{ (type === PUBLIC_OFFER) &&
<>
<Text>{ LocalizeText('catalog.marketplace.offer.price_public_item', ['price', 'average'], [offerData.price.toString(), offerData.averagePrice.toString() ]) }</Text>
<Text>{ LocalizeText('catalog.marketplace.offer_count', ['count'], [offerData.offerCount.toString()]) }</Text>
<Text>{ LocalizeText('catalog.marketplace.offer.price_public_item', [ 'price', 'average' ], [ offerData.price.toString(), offerData.averagePrice.toString() ]) }</Text>
<Text>{ LocalizeText('catalog.marketplace.offer_count', [ 'count' ], [ offerData.offerCount.toString() ]) }</Text>
</> }
</Column>
<Column gap={ 1 }>

View File

@ -20,13 +20,13 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
if(!parser) return;
const offers = parser.offers.map(offer =>
{
const newOffer = new MarketplaceOfferData(offer.offerId, offer.furniId, offer.furniType, offer.extraData, offer.stuffData, offer.price, offer.status, offer.averagePrice, offer.offerCount);
{
const newOffer = new MarketplaceOfferData(offer.offerId, offer.furniId, offer.furniType, offer.extraData, offer.stuffData, offer.price, offer.status, offer.averagePrice, offer.offerCount);
newOffer.timeLeftMinutes = offer.timeLeftMinutes;
newOffer.timeLeftMinutes = offer.timeLeftMinutes;
return newOffer;
});
return newOffer;
});
BatchUpdates(() =>
{
@ -91,7 +91,7 @@ export const CatalogLayoutMarketplaceOwnItemsView: FC<CatalogLayoutProps> = prop
{ (creditsWaiting > 0) &&
<Column center gap={ 1 } className="bg-muted rounded p-2">
<Text>
{ LocalizeText('catalog.marketplace.redeem.get_credits', ['count', 'credits'], [ soldOffers.length.toString(), creditsWaiting.toString() ]) }
{ LocalizeText('catalog.marketplace.redeem.get_credits', [ 'count', 'credits' ], [ soldOffers.length.toString(), creditsWaiting.toString() ]) }
</Text>
<Button className="mt-1" onClick={ redeemSoldOffers }>
{ LocalizeText('catalog.marketplace.offer.redeem') }

View File

@ -11,9 +11,9 @@ import { IMarketplaceSearchOptions } from './common/IMarketplaceSearchOptions';
import { MarketplaceOfferData } from './common/MarketplaceOfferData';
import { MarketplaceSearchType } from './common/MarketplaceSearchType';
const SORT_TYPES_VALUE = [1, 2];
const SORT_TYPES_ACTIVITY = [3, 4, 5, 6];
const SORT_TYPES_ADVANCED = [1, 2, 3, 4, 5, 6];
const SORT_TYPES_VALUE = [ 1, 2 ];
const SORT_TYPES_ACTIVITY = [ 3, 4, 5, 6 ];
const SORT_TYPES_ADVANCED = [ 1, 2, 3, 4, 5, 6 ];
export interface CatalogLayoutMarketplacePublicItemsViewProps extends CatalogLayoutProps
{
@ -44,7 +44,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
return SORT_TYPES_ADVANCED;
}
return [];
}, [searchType]);
}, [ searchType ]);
const purchaseItem = useCallback((offerData: MarketplaceOfferData) =>
{
@ -55,10 +55,10 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
}
const offerId = offerData.offerId;
NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_header'), () =>
{
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId));
},
null, null, null, LocalizeText('catalog.marketplace.confirm_title'));
{
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(offerId));
},
null, null, null, LocalizeText('catalog.marketplace.confirm_title'));
},[]);
const onMarketPlaceOffersEvent = useCallback( (event: MarketPlaceOffersEvent) =>
@ -104,8 +104,8 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
NotificationUtilities.simpleAlert(LocalizeText('catalog.marketplace.not_available_header'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.marketplace.not_available_title'));
break;
case 3:
// our shit was updated
// todo: some dialogue modal
// our shit was updated
// todo: some dialogue modal
setOffers( prev =>
{
const newVal = new Map(prev);
@ -124,7 +124,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
});
NotificationUtilities.confirm(LocalizeText('catalog.marketplace.confirm_higher_header') +
'\n' + LocalizeText('catalog.marketplace.confirm_price', ['price'], [parser.newPrice.toString()]), () =>
'\n' + LocalizeText('catalog.marketplace.confirm_price', [ 'price' ], [ parser.newPrice.toString() ]), () =>
{
SendMessageComposer(new BuyMarketplaceOfferMessageComposer(parser.offerId));
},
@ -134,7 +134,7 @@ export const CatalogLayoutMarketplacePublicItemsView: FC<CatalogLayoutMarketplac
NotificationUtilities.simpleAlert(LocalizeText('catalog.alert.notenough.credits.description'), NotificationAlertType.DEFAULT, null, null, LocalizeText('catalog.alert.notenough.title'));
break;
}
}, [lastSearch, requestOffers]);
}, [ lastSearch, requestOffers ]);
UseMessageEventHook(MarketPlaceOffersEvent, onMarketPlaceOffersEvent);
UseMessageEventHook(MarketplaceBuyOfferResultEvent, onMarketplaceBuyOfferResultEvent);

View File

@ -46,7 +46,7 @@ export const SearchFormView: FC<SearchFormViewProps> = props =>
setSortType(sortType);
if(searchType === MarketplaceSearchType.BY_ACTIVITY || MarketplaceSearchType.BY_VALUE === searchType) onSearch({ minPrice: -1, maxPrice: -1, query: '', type: sortType });
}, [onSearch, searchType, sortTypes]);
}, [ onSearch, searchType, sortTypes ]);
return (
<Column gap={ 1 }>

View File

@ -18,13 +18,13 @@ export const MarketplacePostOfferView : FC<{}> = props =>
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.marketplaceConfiguration = parser;
newValue.marketplaceConfiguration = parser;
return newValue;
});
return newValue;
});
}, [ setCatalogOptions ]);
UseMessageEventHook(MarketplaceConfigurationEvent, onMarketplaceConfigurationEvent);
@ -60,11 +60,14 @@ export const MarketplacePostOfferView : FC<{}> = props =>
if(!item || (askingPrice <= marketplaceConfiguration.minimumPrice)) return;
NotificationUtilities.confirm(LocalizeText('inventory.marketplace.confirm_offer.info', [ 'furniname', 'price' ], [ getFurniTitle, askingPrice.toString() ]), () =>
{
SendMessageComposer(new MakeOfferMessageComposer(askingPrice, item.isWallItem ? 2 : 1, item.id));
setItem(null);
},
() => { setItem(null) }, null, null, LocalizeText('inventory.marketplace.confirm_offer.title'));
{
SendMessageComposer(new MakeOfferMessageComposer(askingPrice, item.isWallItem ? 2 : 1, item.id));
setItem(null);
},
() =>
{
setItem(null)
}, null, null, LocalizeText('inventory.marketplace.confirm_offer.title'));
}
return (
@ -82,7 +85,7 @@ export const MarketplacePostOfferView : FC<{}> = props =>
</Column>
<Column overflow="auto">
<Text italics>
{ LocalizeText('inventory.marketplace.make_offer.expiration_info', ['time'], [marketplaceConfiguration.offerTime.toString()]) }
{ LocalizeText('inventory.marketplace.make_offer.expiration_info', [ 'time' ], [ marketplaceConfiguration.offerTime.toString() ]) }
</Text>
<div className="input-group has-validation">
<input className="form-control form-control-sm" type="number" min={ 0 } value={ askingPrice } onChange={ event => setAskingPrice(parseInt(event.target.value)) } placeholder={ LocalizeText('inventory.marketplace.make_offer.price_request') } />

View File

@ -212,13 +212,13 @@ export const CatalogLayoutPetView: FC<CatalogLayoutProps> = props =>
<Column size={ 7 } overflow="hidden">
<AutoGrid columnCount={ 5 }>
{ !colorsShowing && (sellablePalettes.length > 0) && sellablePalettes.map((palette, index) =>
{
return (
<LayoutGridItem key={ index } itemActive={ (selectedPaletteIndex === index) } onClick={ event => setSelectedPaletteIndex(index) }>
<LayoutPetImageView typeId={ petIndex } paletteId={ palette.paletteId } direction={ 2 } headOnly={ true } />
</LayoutGridItem>
);
})}
{
return (
<LayoutGridItem key={ index } itemActive={ (selectedPaletteIndex === index) } onClick={ event => setSelectedPaletteIndex(index) }>
<LayoutPetImageView typeId={ petIndex } paletteId={ palette.paletteId } direction={ 2 } headOnly={ true } />
</LayoutGridItem>
);
})}
{ colorsShowing && (sellableColors.length > 0) && sellableColors.map((colorSet, index) => <LayoutGridItem itemHighlight key={ index } itemActive={ (selectedColorIndex === index) } itemColor={ ColorConverter.int2rgb(colorSet[0]) } className="clear-bg" onClick={ event => setSelectedColorIndex(index) } />) }
</AutoGrid>
</Column>

View File

@ -27,16 +27,16 @@ export const CatalogLayoutVipGiftsView: FC<CatalogLayoutProps> = props =>
const selectGift = useCallback((localizationId: string) =>
{
NotificationUtilities.confirm(LocalizeText('catalog.club_gift.confirm'), () =>
{
SendMessageComposer(new SelectClubGiftComposer(localizationId));
setCatalogOptions(prevValue =>
{
SendMessageComposer(new SelectClubGiftComposer(localizationId));
prevValue.clubGifts.giftsAvailable--;
setCatalogOptions(prevValue =>
{
prevValue.clubGifts.giftsAvailable--;
return { ...prevValue };
});
}, null);
return { ...prevValue };
});
}, null);
}, [ setCatalogOptions ]);
return (

View File

@ -21,7 +21,7 @@ export const VipGiftItem : FC<VipGiftItemViewProps> = props =>
const productData = offer.products[0];
return ProductImageUtility.getProductImageUrl(productData.productType, productData.furniClassId, productData.extraParam);
}, [offer]);
}, [ offer ]);
const getItemTitle = useCallback(() =>
{
@ -32,7 +32,7 @@ export const VipGiftItem : FC<VipGiftItemViewProps> = props =>
const localizationKey = ProductImageUtility.getProductCategory(productData.productType, productData.furniClassId) === 2 ? 'wallItem.name.' + productData.furniClassId : 'roomItem.name.' + productData.furniClassId;
return LocalizeText(localizationKey);
}, [offer]);
}, [ offer ]);
const getItemDesc = useCallback( () =>
{
@ -43,7 +43,7 @@ export const VipGiftItem : FC<VipGiftItemViewProps> = props =>
const localizationKey = ProductImageUtility.getProductCategory(productData.productType, productData.furniClassId) === 2 ? 'wallItem.desc.' + productData.furniClassId : 'roomItem.desc.' + productData.furniClassId ;
return LocalizeText(localizationKey);
}, [offer]);
}, [ offer ]);
return (
<LayoutGridItem center={ false } column={ false } alignItems="center" className="p-1">

View File

@ -34,27 +34,27 @@ export const CatalogBadgeSelectorWidgetView: FC<CatalogBadgeSelectorWidgetViewPr
if(!currentOffer) return;
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraParamRequired = true;
newValue.extraData = ((previewStuffData && previewStuffData.getValue(1)) || null);
newValue.previewStuffData = previewStuffData;
newValue.extraParamRequired = true;
newValue.extraData = ((previewStuffData && previewStuffData.getValue(1)) || null);
newValue.previewStuffData = previewStuffData;
return newValue;
});
return newValue;
});
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
return (
<AutoGrid columnCount={ columnCount } { ...rest }>
{ badgeCodes && (badgeCodes.length > 0) && badgeCodes.map((badgeCode, index) =>
{
return (
<LayoutGridItem key={ index } itemActive={ (currentBadgeCode === badgeCode) } onClick={ event => setCurrentBadgeCode(badgeCode) }>
<LayoutBadgeImageView badgeCode={ badgeCode } />
</LayoutGridItem>
);
}) }
{
return (
<LayoutGridItem key={ index } itemActive={ (currentBadgeCode === badgeCode) } onClick={ event => setCurrentBadgeCode(badgeCode) }>
<LayoutBadgeImageView badgeCode={ badgeCode } />
</LayoutGridItem>
);
}) }
</AutoGrid>
);
}

View File

@ -30,15 +30,15 @@ export const CatalogGuildSelectorWidgetView: FC<{}> = props =>
if(!currentOffer) return;
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraParamRequired = true;
newValue.extraData = ((previewStuffData && previewStuffData.getValue(1)) || null);
newValue.previewStuffData = previewStuffData;
newValue.extraParamRequired = true;
newValue.extraData = ((previewStuffData && previewStuffData.getValue(1)) || null);
newValue.previewStuffData = previewStuffData;
return newValue;
});
return newValue;
});
}, [ currentOffer, previewStuffData, setPurchaseOptions ]);
useEffect(() =>

View File

@ -28,13 +28,13 @@ export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = pro
if(offer.product && (offer.product.productType === ProductTypeEnum.WALL))
{
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraData = (offer.product.extraParam || null);
newValue.extraData = (offer.product.extraParam || null);
return newValue;
});
return newValue;
});
}
}

View File

@ -73,14 +73,14 @@ export const CatalogSpacesWidgetView: FC<CatalogSpacesWidgetViewProps> = props =
if((selectedGroupIndex === -1) || !selectedOfferForGroup || !currentOffer) return;
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.extraData = selectedOfferForGroup[selectedGroupIndex].product.extraParam;
newValue.extraParamRequired = true;
newValue.extraData = selectedOfferForGroup[selectedGroupIndex].product.extraParam;
newValue.extraParamRequired = true;
return newValue;
});
return newValue;
});
}, [ currentOffer, selectedGroupIndex, selectedOfferForGroup, setPurchaseOptions ]);
if(!groupedOffers || (selectedGroupIndex === -1)) return null;
@ -98,13 +98,13 @@ export const CatalogSpacesWidgetView: FC<CatalogSpacesWidgetViewProps> = props =
const setSelectedOffer = () =>
{
setSelectedOfferForGroup(prevValue =>
{
const newValue = [ ...prevValue ];
{
const newValue = [ ...prevValue ];
newValue[selectedGroupIndex] = offer;
newValue[selectedGroupIndex] = offer;
return newValue;
});
return newValue;
});
}
return <CatalogGridOfferView key={ index } itemActive={ (currentOffer && (currentOffer === offer)) } offer={ offer } onClick={ setSelectedOffer } />;

View File

@ -23,13 +23,13 @@ export const CatalogSpinnerWidgetView: FC<{}> = props =>
if(value === quantity) return;
setPurchaseOptions(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.quantity = value;
newValue.quantity = value;
return newValue;
});
return newValue;
});
}
if(!currentOffer || !currentOffer.bundlePurchaseAllowed) return null;

View File

@ -15,7 +15,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
{
const { chatHistoryState = null, roomHistoryState = null } = useChatHistoryContext();
const [needsRoomInsert, setNeedsRoomInsert ] = useState(false);
const [ needsRoomInsert, setNeedsRoomInsert ] = useState(false);
const addChatEntry = useCallback((entry: IChatEntry) =>
{
@ -32,7 +32,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
//dispatchUiEvent(new ChatHistoryEvent(ChatHistoryEvent.CHAT_HISTORY_CHANGED));
}, [chatHistoryState]);
}, [ chatHistoryState ]);
const addRoomHistoryEntry = useCallback((entry: IRoomHistoryEntry) =>
{
@ -45,7 +45,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
}
roomHistoryState.notify();
}, [roomHistoryState]);
}, [ roomHistoryState ]);
const onChatEvent = useCallback((event: RoomSessionChatEvent) =>
{
@ -62,7 +62,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
const entry: IChatEntry = { id: -1, entityId: userData.webID, name: userData.name, look: userData.figure, entityType: userData.type, message: event.message, timestamp: timeString, type: ChatEntryType.TYPE_CHAT, roomId: roomSession.roomId };
addChatEntry(entry);
}, [addChatEntry]);
}, [ addChatEntry ]);
UseRoomSessionManagerEvent(RoomSessionChatEvent.CHAT_EVENT, onChatEvent);
@ -74,7 +74,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
setNeedsRoomInsert(true);
break;
case RoomSessionEvent.ENDED:
//dispatchUiEvent(new ChatHistoryEvent(ChatHistoryEvent.HIDE_CHAT_HISTORY));
//dispatchUiEvent(new ChatHistoryEvent(ChatHistoryEvent.HIDE_CHAT_HISTORY));
break;
}
}, []);
@ -104,7 +104,7 @@ export const ChatHistoryMessageHandler: FC<{}> = props =>
setNeedsRoomInsert(false);
}
}, [addChatEntry, addRoomHistoryEntry, needsRoomInsert]);
}, [ addChatEntry, addRoomHistoryEntry, needsRoomInsert ]);
UseMessageEventHook(GetGuestRoomResultEvent, onGetGuestRoomResultEvent);

View File

@ -118,19 +118,19 @@ export const ChatHistoryView: FC<{}> = props =>
<NitroCardContentView>
<AutoSizer defaultWidth={ 300 } defaultHeight={ 200 } onResize={ onResize }>
{ ({ height, width }) =>
{
return (
<List
ref={ elementRef }
width={ width }
height={ height }
rowCount={ chatHistoryState.chats.length }
rowHeight={ cache.rowHeight }
className={ 'chat-history-list' }
rowRenderer={ RowRenderer }
deferredMeasurementCache={ cache } />
)
} }
{
return (
<List
ref={ elementRef }
width={ width }
height={ height }
rowCount={ chatHistoryState.chats.length }
rowHeight={ cache.rowHeight }
className={ 'chat-history-list' }
rowRenderer={ RowRenderer }
deferredMeasurementCache={ cache } />
)
} }
</AutoSizer>
</NitroCardContentView>
</NitroCardView> }

View File

@ -20,7 +20,7 @@ export const FloorplanEditorView: FC<{}> = props =>
const [ originalFloorplanSettings, setOriginalFloorplanSettings ] = useState<IFloorplanSettings>({
tilemap: '',
reservedTiles: [],
entryPoint: [0, 0],
entryPoint: [ 0, 0 ],
entryPointDir: 2,
wallHeight: -1,
thicknessWall: 1,
@ -65,23 +65,23 @@ export const FloorplanEditorView: FC<{}> = props =>
const parser = event.getParser();
setOriginalFloorplanSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.tilemap = parser.model;
newValue.wallHeight = (parser.wallHeight + 1);
newValue.tilemap = parser.model;
newValue.wallHeight = (parser.wallHeight + 1);
return newValue;
});
return newValue;
});
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.wallHeight = (parser.wallHeight + 1);
newValue.wallHeight = (parser.wallHeight + 1);
return newValue;
});
return newValue;
});
}, []);
UseMessageEventHook(FloorHeightMapEvent, onFloorHeightMapEvent);
@ -91,24 +91,24 @@ export const FloorplanEditorView: FC<{}> = props =>
const parser = event.getParser();
setOriginalFloorplanSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.thicknessFloor = convertSettingToNumber(parser.thicknessFloor);
newValue.thicknessWall = convertSettingToNumber(parser.thicknessWall);
newValue.thicknessFloor = convertSettingToNumber(parser.thicknessFloor);
newValue.thicknessWall = convertSettingToNumber(parser.thicknessWall);
return newValue;
});
return newValue;
});
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.thicknessFloor = convertSettingToNumber(parser.thicknessFloor);
newValue.thicknessWall = convertSettingToNumber(parser.thicknessWall);
newValue.thicknessFloor = convertSettingToNumber(parser.thicknessFloor);
newValue.thicknessWall = convertSettingToNumber(parser.thicknessWall);
return newValue;
});
return newValue;
});
}, []);
UseMessageEventHook(RoomVisualizationSettingsEvent, onRoomVisualizationSettingsEvent);

View File

@ -151,7 +151,7 @@ export class FloorplanEditor extends PixiApplicationProxy
{
if(this._isHolding)
{
const [realX, realY] = getTileFromScreenPosition(tileStartX, tileStartY);
const [ realX, realY ] = getTileFromScreenPosition(tileStartX, tileStartY);
if(isClick)
{
@ -246,7 +246,7 @@ export class FloorplanEditor extends PixiApplicationProxy
if(tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED;
//if((tile.height === 'x') || tile.height === 'X') continue;
const [positionX, positionY] = getScreenPositionForTile(x, y);
const [ positionX, positionY ] = getScreenPositionForTile(x, y);
this._tilemapRenderer.tile(this._assetCollection.getTexture(`floor_editor_${ assetName }`), positionX, positionY);
}

View File

@ -7,7 +7,7 @@ export const getScreenPositionForTile = (x: number, y: number): [number , number
positionX = positionX + 1024; // center the map in the canvas
return [positionX, positionY];
return [ positionX, positionY ];
}
export const getTileFromScreenPosition = (x: number, y: number): [number, number] =>
@ -17,7 +17,7 @@ export const getTileFromScreenPosition = (x: number, y: number): [number, number
const realX = ((translatedX /(TILE_SIZE / 2)) + (y / (TILE_SIZE / 4))) / 2;
const realY = ((y /(TILE_SIZE / 4)) - (translatedX / (TILE_SIZE / 2))) / 2;
return [realX, realY];
return [ realX, realY ];
}
export const convertNumbersForSaving = (value: number): number =>

View File

@ -28,15 +28,15 @@ export const FloorplanCanvasView: FC<FloorplanCanvasViewProps> = props =>
let newFloorPlanSettings: IFloorplanSettings = null;
setOriginalFloorplanSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.reservedTiles = parser.blockedTilesMap;
newValue.reservedTiles = parser.blockedTilesMap;
newFloorPlanSettings = newValue;
newFloorPlanSettings = newValue;
return newValue;
});
return newValue;
});
FloorplanEditor.instance.setTilemap(newFloorPlanSettings.tilemap, parser.blockedTilesMap);
@ -52,23 +52,23 @@ export const FloorplanCanvasView: FC<FloorplanCanvasViewProps> = props =>
const parser = event.getParser();
setOriginalFloorplanSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.entryPoint = [ parser.x, parser.y ];
newValue.entryPointDir = parser.direction;
newValue.entryPoint = [ parser.x, parser.y ];
newValue.entryPointDir = parser.direction;
return newValue;
});
return newValue;
});
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.entryPointDir = parser.direction;
newValue.entryPointDir = parser.direction;
return newValue;
});
return newValue;
});
FloorplanEditor.instance.doorLocation = new NitroPoint(parser.x, parser.y);
@ -107,14 +107,14 @@ export const FloorplanCanvasView: FC<FloorplanCanvasViewProps> = props =>
FloorplanEditor.instance.clear();
setVisualizationSettings(prevValue =>
{
return {
wallHeight: originalFloorplanSettings.wallHeight,
thicknessWall: originalFloorplanSettings.thicknessWall,
thicknessFloor: originalFloorplanSettings.thicknessFloor,
entryPointDir: prevValue.entryPointDir
}
});
{
return {
wallHeight: originalFloorplanSettings.wallHeight,
thicknessWall: originalFloorplanSettings.thicknessWall,
thicknessFloor: originalFloorplanSettings.thicknessFloor,
entryPointDir: prevValue.entryPointDir
}
});
}
}, [ originalFloorplanSettings.thicknessFloor, originalFloorplanSettings.thicknessWall, originalFloorplanSettings.wallHeight, setVisualizationSettings ]);

View File

@ -29,20 +29,20 @@ export const FloorplanOptionsView: FC<{}> = props =>
const changeDoorDirection = () =>
{
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
if(newValue.entryPointDir < 7)
{
const newValue = { ...prevValue };
++newValue.entryPointDir;
}
else
{
newValue.entryPointDir = 0;
}
if(newValue.entryPointDir < 7)
{
++newValue.entryPointDir;
}
else
{
newValue.entryPointDir = 0;
}
return newValue;
});
return newValue;
});
}
const onFloorHeightChange = (value: number) =>
@ -71,13 +71,13 @@ export const FloorplanOptionsView: FC<{}> = props =>
const onWallThicknessChange = (value: number) =>
{
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.thicknessWall = value;
newValue.thicknessWall = value;
return newValue;
});
return newValue;
});
}
const onWallHeightChange = (value: number) =>
@ -87,13 +87,13 @@ export const FloorplanOptionsView: FC<{}> = props =>
if(value > MAX_WALL_HEIGHT) value = MAX_WALL_HEIGHT;
setVisualizationSettings(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.wallHeight = value;
newValue.wallHeight = value;
return newValue;
});
return newValue;
});
}
const increaseWallHeight = () =>

View File

@ -53,13 +53,13 @@ export const FriendsView: FC<{}> = props =>
if(!canRequestFriend(userId)) return false;
setSentRequests(prevValue =>
{
const newSentRequests = [ ...prevValue ];
{
const newSentRequests = [ ...prevValue ];
newSentRequests.push(userId);
newSentRequests.push(userId);
return newSentRequests;
});
return newSentRequests;
});
SendMessageComposer(new RequestFriendComposer(userName));
}, [ sentRequests, canRequestFriend ]);
@ -67,6 +67,37 @@ export const FriendsView: FC<{}> = props =>
const acceptFriend = useCallback((userId: number) =>
{
setRequests(prevValue =>
{
const newRequests: MessengerRequest[] = [ ...prevValue ];
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
if(index >= 0)
{
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.ACCEPTED, userId));
newRequests.splice(index, 1);
}
return newRequests;
});
}, []);
const declineFriend = useCallback((userId: number, declineAll: boolean = false) =>
{
setRequests(prevValue =>
{
if(declineAll)
{
SendMessageComposer(new DeclineFriendMessageComposer(true));
for(const request of prevValue) DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, request.requesterUserId));
return [];
}
else
{
const newRequests: MessengerRequest[] = [ ...prevValue ];
@ -74,47 +105,16 @@ export const FriendsView: FC<{}> = props =>
if(index >= 0)
{
SendMessageComposer(new AcceptFriendMessageComposer(newRequests[index].id));
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.ACCEPTED, userId));
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, userId));
newRequests.splice(index, 1);
}
return newRequests;
});
}, []);
const declineFriend = useCallback((userId: number, declineAll: boolean = false) =>
{
setRequests(prevValue =>
{
if(declineAll)
{
SendMessageComposer(new DeclineFriendMessageComposer(true));
for(const request of prevValue) DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, request.requesterUserId));
return [];
}
else
{
const newRequests: MessengerRequest[] = [ ...prevValue ];
const index = newRequests.findIndex(request => (request.requesterUserId === userId));
if(index >= 0)
{
SendMessageComposer(new DeclineFriendMessageComposer(false, newRequests[index].id));
DispatchUiEvent(new FriendRequestEvent(FriendRequestEvent.DECLINED, userId));
newRequests.splice(index, 1);
}
return newRequests;
}
});
}
});
}, []);
const onMessengerInitEvent = useCallback((event: MessengerInitEvent) =>
@ -137,22 +137,22 @@ export const FriendsView: FC<{}> = props =>
const parser = event.getParser();
setFriends(prevValue =>
{
const newFriends = [ ...prevValue ];
for(const friend of parser.fragment)
{
const newFriends = [ ...prevValue ];
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
const newFriend = new MessengerFriend();
for(const friend of parser.fragment)
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
const newFriend = new MessengerFriend();
newFriend.populate(friend);
newFriend.populate(friend);
if(index > -1) newFriends[index] = newFriend;
else newFriends.push(newFriend);
}
if(index > -1) newFriends[index] = newFriend;
else newFriends.push(newFriend);
}
return newFriends;
});
return newFriends;
});
}, []);
UseMessageEventHook(FriendListFragmentEvent, onFriendsFragmentEvent);
@ -162,39 +162,39 @@ export const FriendsView: FC<{}> = props =>
const parser = event.getParser();
setFriends(prevValue =>
{
const newFriends = [ ...prevValue ];
const processUpdate = (friend: FriendParser) =>
{
const newFriends = [ ...prevValue ];
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
const processUpdate = (friend: FriendParser) =>
if(index === -1)
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === friend.id));
const newFriend = new MessengerFriend();
newFriend.populate(friend);
if(index === -1)
{
const newFriend = new MessengerFriend();
newFriend.populate(friend);
newFriends.unshift(newFriend);
}
else
{
newFriends[index].populate(friend);
}
newFriends.unshift(newFriend);
}
for(const friend of parser.addedFriends) processUpdate(friend);
for(const friend of parser.updatedFriends) processUpdate(friend);
for(const removedFriendId of parser.removedFriendIds)
else
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === removedFriendId));
if(index > -1) newFriends.splice(index);
newFriends[index].populate(friend);
}
}
return newFriends;
});
for(const friend of parser.addedFriends) processUpdate(friend);
for(const friend of parser.updatedFriends) processUpdate(friend);
for(const removedFriendId of parser.removedFriendIds)
{
const index = newFriends.findIndex(existingFriend => (existingFriend.id === removedFriendId));
if(index > -1) newFriends.splice(index);
}
return newFriends;
});
}, []);
UseMessageEventHook(FriendListUpdateEvent, onFriendsUpdateEvent);
@ -204,23 +204,23 @@ export const FriendsView: FC<{}> = props =>
const parser = event.getParser();
setRequests(prevValue =>
{
const newRequests = [ ...prevValue ];
for(const request of parser.requests)
{
const newRequests = [ ...prevValue ];
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
for(const request of parser.requests)
{
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
if(index > 0) continue;
if(index > 0) continue;
const newRequest = new MessengerRequest();
newRequest.populate(request);
const newRequest = new MessengerRequest();
newRequest.populate(request);
newRequests.push(newRequest);
}
newRequests.push(newRequest);
}
return newRequests;
});
return newRequests;
});
}, []);
UseMessageEventHook(FriendRequestsEvent, onFriendRequestsEvent);
@ -231,21 +231,21 @@ export const FriendsView: FC<{}> = props =>
const request = parser.request;
setRequests(prevValue =>
{
const newRequests = [ ...prevValue ];
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
if(index === -1)
{
const newRequests = [ ...prevValue ];
const newRequest = new MessengerRequest();
newRequest.populate(request);
const index = newRequests.findIndex(existing => (existing.requesterUserId === request.requesterUserId));
newRequests.push(newRequest);
}
if(index === -1)
{
const newRequest = new MessengerRequest();
newRequest.populate(request);
newRequests.push(newRequest);
}
return newRequests;
});
return newRequests;
});
}, []);
UseMessageEventHook(NewFriendRequestEvent, onNewFriendRequestEvent);

View File

@ -6,5 +6,6 @@ export class MessengerSettings
public userFriendLimit: number = 0,
public normalFriendLimit: number = 0,
public extendedFriendLimit: number = 0,
public categories: FriendCategoryData[] = []) {}
public categories: FriendCategoryData[] = [])
{}
}

View File

@ -37,9 +37,9 @@ export const FriendBarView: FC<FriendBarViewProps> = props =>
<FontAwesomeIcon icon="chevron-left" />
</Button>
{ Array.from(Array(maxDisplayCount), (e, i) =>
{
return <FriendBarItemView key={ i } friend={ (onlineFriends[ indexOffset + i ] || null) } />;
}) }
{
return <FriendBarItemView key={ i } friend={ (onlineFriends[ indexOffset + i ] || null) } />;
}) }
<Button variant="black" className="friend-bar-button" disabled={ !canIncreaseIndex } onClick={ event => setIndexOffset(indexOffset + 1) }>
<FontAwesomeIcon icon="chevron-right" />
</Button>

View File

@ -43,29 +43,29 @@ export const FriendsListView: FC<FriendsListViewProps> = props =>
}
return LocalizeText('friendlist.removefriendconfirm.userlist', [ 'user_names' ], [ userNames.join(', ') ]);
}, [offlineFriends, onlineFriends, selectedFriendsIds]);
}, [ offlineFriends, onlineFriends, selectedFriendsIds ]);
const selectFriend = useCallback((userId: number) =>
{
if(userId < 0) return;
setSelectedFriendsIds(prevValue =>
{
const newValue = [ ...prevValue ];
const existingUserIdIndex: number = newValue.indexOf(userId);
if(existingUserIdIndex > -1)
{
const newValue = [ ...prevValue ];
newValue.splice(existingUserIdIndex, 1)
}
else
{
newValue.push(userId);
}
const existingUserIdIndex: number = newValue.indexOf(userId);
if(existingUserIdIndex > -1)
{
newValue.splice(existingUserIdIndex, 1)
}
else
{
newValue.push(userId);
}
return newValue;
});
return newValue;
});
}, [ setSelectedFriendsIds ]);
const sendRoomInvite = (message: string) =>
@ -81,11 +81,11 @@ export const FriendsListView: FC<FriendsListViewProps> = props =>
if(selectedFriendsIds.length === 0) return;
setSelectedFriendsIds(prevValue =>
{
SendMessageComposer(new RemoveFriendComposer(...prevValue));
{
SendMessageComposer(new RemoveFriendComposer(...prevValue));
return [];
});
return [];
});
setShowRemoveFriendsConfirmation(false);
}

View File

@ -18,8 +18,8 @@ export const FriendsRemoveConfirmationView: FC<FriendsRemoveConfirmationViewProp
<NitroCardView className="nitro-friends-remove-confirmation" theme="primary-slim">
<NitroCardHeaderView headerText={ LocalizeText('friendlist.removefriendconfirm.title') } onCloseClick={ onCloseClick } />
<NitroCardContentView className="text-black">
<div>{ removeFriendsText }</div>
<Flex gap={ 1 }>
<div>{ removeFriendsText }</div>
<Flex gap={ 1 }>
<Button fullWidth variant="danger" disabled={ (selectedFriendsIds.length === 0) } onClick={ removeSelectedFriends }>{ LocalizeText('generic.ok') }</Button>
<Button fullWidth onClick={ onCloseClick }>{ LocalizeText('generic.cancel') }</Button>
</Flex>

View File

@ -59,20 +59,20 @@ export const FriendsSearchView: FC<FriendsSearchViewProps> = props =>
<hr className="mx-2 mt-0 mb-1 text-black" />
<Column gap={ 0 }>
{ friendResults.map(result =>
{
return (
<NitroCardAccordionItemView key={ result.avatarId } justifyContent="between" className="px-2 py-1">
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ result.avatarId } />
<div>{ result.avatarName }</div>
</Flex>
<Flex alignItems="center" gap={ 1 }>
{ result.isAvatarOnline &&
{
return (
<NitroCardAccordionItemView key={ result.avatarId } justifyContent="between" className="px-2 py-1">
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ result.avatarId } />
<div>{ result.avatarName }</div>
</Flex>
<Flex alignItems="center" gap={ 1 }>
{ result.isAvatarOnline &&
<Base className="nitro-friends-spritesheet icon-chat cursor-pointer" onClick={ event => OpenMessengerChat(result.avatarId) } title={ LocalizeText('friendlist.tip.im') } /> }
</Flex>
</NitroCardAccordionItemView>
)
}) }
</Flex>
</NitroCardAccordionItemView>
)
}) }
</Column>
</Column> }
</> }
@ -86,20 +86,20 @@ export const FriendsSearchView: FC<FriendsSearchViewProps> = props =>
<hr className="mx-2 mt-0 mb-1 text-black" />
<Column gap={ 0 }>
{ otherResults.map(result =>
{
return (
<NitroCardAccordionItemView key={ result.avatarId } justifyContent="between" className="px-2 py-1">
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ result.avatarId } />
<div>{ result.avatarName }</div>
</Flex>
<Flex alignItems="center" gap={ 1 }>
{ canRequestFriend(result.avatarId) &&
{
return (
<NitroCardAccordionItemView key={ result.avatarId } justifyContent="between" className="px-2 py-1">
<Flex alignItems="center" gap={ 1 }>
<UserProfileIconView userId={ result.avatarId } />
<div>{ result.avatarName }</div>
</Flex>
<Flex alignItems="center" gap={ 1 }>
{ canRequestFriend(result.avatarId) &&
<Base className="nitro-friends-spritesheet icon-add cursor-pointer" onClick={ event => requestFriend(result.avatarId, result.avatarName) } title={ LocalizeText('friendlist.tip.addfriend') } /> }
</Flex>
</NitroCardAccordionItemView>
)
}) }
</Flex>
</NitroCardAccordionItemView>
)
}) }
</Column>
</Column> }
</> }

View File

@ -26,47 +26,47 @@ export const FriendsMessengerThreadGroup: FC<FriendsMessengerThreadGroupProps> =
if( (group.type === GroupType.GROUP_CHAT) && (group.chats.length && getGroupChatData(group.chats[0].extraData).userId === GetSessionDataManager().userId)) return true;
return false;
}, [group, thread]);
}, [ group, thread ]);
if(!thread || !group) return null;
if(!group.userId)
{
return (
<>
<>
{ group.chats.map((chat, index) =>
{
return (
<div className="d-flex gap-2 w-100 justify-content-start">
<Base key={ index } className="w-100 text-break">
{ chat.type === MessengerThreadChat.SECURITY_NOTIFICATION &&
{
return (
<div key={ index } className="d-flex gap-2 w-100 justify-content-start">
<Base className="w-100 text-break">
{ chat.type === MessengerThreadChat.SECURITY_NOTIFICATION &&
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-muted align-items-center">
<Base className="nitro-friends-spritesheet icon-warning flex-shrink-0" />
<Base>{ chat.message }</Base>
</Base> }
{ chat.type === MessengerThreadChat.ROOM_INVITE &&
{ chat.type === MessengerThreadChat.ROOM_INVITE &&
<Base className="bg-light rounded mb-2 d-flex gap-2 px-2 py-1 small text-black align-items-center">
<Base className="messenger-notification-icon flex-shrink-0" />
<Base>{(LocalizeText('messenger.invitation') + ' ') }{ chat.message }</Base>
</Base> }
</Base>
</div>
);
}) }
<Base className="messenger-notification-icon flex-shrink-0" />
<Base>{(LocalizeText('messenger.invitation') + ' ') }{ chat.message }</Base>
</Base> }
</Base>
</div>
);
}) }
</>
);
}
return (
<Flex className={ 'w-100 justify-content-' + (isOwnChat ? 'end' : 'start') } gap={ 2 }>
<Base className="message-avatar flex-shrink-0">
<Base className="message-avatar flex-shrink-0">
{ (group.type === GroupType.PRIVATE_CHAT && !isOwnChat) &&
<LayoutAvatarImageView figure={ thread.participant.figure } direction={ 2 } />
}
{ (group.type === GroupType.GROUP_CHAT && !isOwnChat) &&
<LayoutAvatarImageView figure={ getGroupChatData(group.chats[0].extraData).figure } direction={ 2} />
}
</Base>
</Base>
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat ? 'right' : 'left') }>
<Base className='fw-bold'>
{ (isOwnChat) && GetSessionDataManager().userName }

View File

@ -14,9 +14,9 @@ export const FriendsMessengerThreadView: FC<FriendsMessengerThreadViewProps> = p
return (
<>
{ (thread.groups.length > 0) && thread.groups.map((group, index) =>
{
return <FriendsMessengerThreadGroup key={ index } thread={ thread } group={ group } />;
}) }
{
return <FriendsMessengerThreadGroup key={ index } thread={ thread } group={ group } />;
}) }
</>
);
}

View File

@ -12,29 +12,29 @@ import { FriendsMessengerThreadView } from './FriendsMessengerThreadView';
export const FriendsMessengerView: FC<{}> = props =>
{
const [isVisible, setIsVisible] = useState(false);
const [messageThreads, setMessageThreads] = useState<MessengerThread[]>([]);
const [activeThreadIndex, setActiveThreadIndex] = useState(-1);
const [hiddenThreadIndexes, setHiddenThreadIndexes] = useState<number[]>([]);
const [messageText, setMessageText] = useState('');
const [updateValue, setUpdateValue] = useState({});
const [ isVisible, setIsVisible ] = useState(false);
const [ messageThreads, setMessageThreads ] = useState<MessengerThread[]>([]);
const [ activeThreadIndex, setActiveThreadIndex ] = useState(-1);
const [ hiddenThreadIndexes, setHiddenThreadIndexes ] = useState<number[]>([]);
const [ messageText, setMessageText ] = useState('');
const [ updateValue, setUpdateValue ] = useState({});
const { friends = [] } = useFriendsContext();
const messagesBox = useRef<HTMLDivElement>();
const followFriend = useCallback(() =>
{
SendMessageComposer(new FollowFriendMessageComposer(messageThreads[activeThreadIndex].participant.id));
}, [messageThreads, activeThreadIndex]);
}, [ messageThreads, activeThreadIndex ]);
const openProfile = useCallback(() =>
{
GetUserProfile(messageThreads[activeThreadIndex].participant.id);
}, [messageThreads, activeThreadIndex]);
}, [ messageThreads, activeThreadIndex ]);
const getFriend = useCallback((userId: number) =>
{
return ((friends.find(friend => (friend.id === userId))) || null);
}, [friends]);
}, [ friends ]);
const visibleThreads = useMemo(() =>
{
@ -44,7 +44,7 @@ export const FriendsMessengerView: FC<{}> = props =>
return true;
});
}, [messageThreads, hiddenThreadIndexes]);
}, [ messageThreads, hiddenThreadIndexes ]);
const getMessageThreadWithIndex = useCallback<(userId: number) => [number, MessengerThread]>((userId: number) =>
{
@ -62,7 +62,7 @@ export const FriendsMessengerView: FC<{}> = props =>
{
setHiddenThreadIndexes(prevValue =>
{
const newIndexes = [...prevValue];
const newIndexes = [ ...prevValue ];
newIndexes.splice(hiddenIndex, 1);
@ -70,34 +70,34 @@ export const FriendsMessengerView: FC<{}> = props =>
});
}
return [i, thread];
return [ i, thread ];
}
}
}
const friend = getFriend(userId);
if(!friend) return [-1, null];
if(!friend) return [ -1, null ];
const thread = new MessengerThread(friend);
const newThreads = [...messageThreads, thread];
const newThreads = [ ...messageThreads, thread ];
setMessageThreads(newThreads);
return [(newThreads.length - 1), thread];
}, [messageThreads, hiddenThreadIndexes, getFriend]);
return [ (newThreads.length - 1), thread ];
}, [ messageThreads, hiddenThreadIndexes, getFriend ]);
const onNewConsoleMessageEvent = useCallback((event: NewConsoleMessageEvent) =>
{
const parser = event.getParser();
const [threadIndex, thread] = getMessageThreadWithIndex(parser.senderId);
const [ threadIndex, thread ] = getMessageThreadWithIndex(parser.senderId);
if((threadIndex === -1) || !thread) return;
thread.addMessage(parser.senderId, parser.messageText, parser.secondsSinceSent, parser.extraData);
setMessageThreads(prevValue => [...prevValue]);
}, [getMessageThreadWithIndex]);
setMessageThreads(prevValue => [ ...prevValue ]);
}, [ getMessageThreadWithIndex ]);
UseMessageEventHook(NewConsoleMessageEvent, onNewConsoleMessageEvent);
@ -105,14 +105,14 @@ export const FriendsMessengerView: FC<{}> = props =>
{
const parser = event.getParser();
const [threadIndex, thread] = getMessageThreadWithIndex(parser.senderId);
const [ threadIndex, thread ] = getMessageThreadWithIndex(parser.senderId);
if((threadIndex === -1) || !thread) return;
thread.addMessage(null, parser.messageText, 0, null, MessengerThreadChat.ROOM_INVITE);
setMessageThreads(prevValue => [...prevValue]);
}, [getMessageThreadWithIndex]);
setMessageThreads(prevValue => [ ...prevValue ]);
}, [ getMessageThreadWithIndex ]);
UseMessageEventHook(RoomInviteEvent, onRoomInviteEvent);
@ -144,17 +144,17 @@ export const FriendsMessengerView: FC<{}> = props =>
BatchUpdates(() =>
{
setMessageThreads(prevValue => [...prevValue]);
setMessageThreads(prevValue => [ ...prevValue ]);
setMessageText('');
});
}, [messageThreads, activeThreadIndex, messageText]);
}, [ messageThreads, activeThreadIndex, messageText ]);
const onKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) =>
{
if(event.key !== 'Enter') return;
sendMessage();
}, [sendMessage]);
}, [ sendMessage ]);
const linkReceived = useCallback((url: string) =>
{
@ -169,7 +169,7 @@ export const FriendsMessengerView: FC<{}> = props =>
return;
}
const [threadIndex] = getMessageThreadWithIndex(parseInt(parts[2]));
const [ threadIndex ] = getMessageThreadWithIndex(parseInt(parts[2]));
if(threadIndex === -1) return;
@ -178,13 +178,13 @@ export const FriendsMessengerView: FC<{}> = props =>
setActiveThreadIndex(threadIndex);
setIsVisible(true);
});
}, [getMessageThreadWithIndex]);
}, [ getMessageThreadWithIndex ]);
const closeThread = useCallback((threadIndex: number) =>
{
setHiddenThreadIndexes(prevValue =>
{
const values = [...prevValue];
const values = [ ...prevValue ];
if(values.indexOf(threadIndex) === -1) values.push(threadIndex);
@ -202,19 +202,19 @@ export const FriendsMessengerView: FC<{}> = props =>
AddEventLinkTracker(linkTracker);
return () => RemoveLinkEventTracker(linkTracker);
}, [linkReceived]);
}, [ linkReceived ]);
useEffect(() =>
{
if(!isVisible) return;
if(activeThreadIndex === -1) setActiveThreadIndex(0);
}, [isVisible, activeThreadIndex]);
}, [ isVisible, activeThreadIndex ]);
useEffect(() =>
{
if(hiddenThreadIndexes.indexOf(activeThreadIndex) >= 0) setActiveThreadIndex(0);
}, [activeThreadIndex, hiddenThreadIndexes]);
}, [ activeThreadIndex, hiddenThreadIndexes ]);
useEffect(() =>
{
@ -230,7 +230,7 @@ export const FriendsMessengerView: FC<{}> = props =>
activeThread.setRead();
setUpdateValue({});
}
}, [isVisible, messageThreads, activeThreadIndex]);
}, [ isVisible, messageThreads, activeThreadIndex ]);
useEffect(() =>
{
@ -258,13 +258,13 @@ export const FriendsMessengerView: FC<{}> = props =>
if(isUnread) PlaySound(SoundNames.MESSENGER_MESSAGE_RECEIVED);
DispatchUiEvent(new FriendsMessengerIconEvent(FriendsMessengerIconEvent.UPDATE_ICON, isUnread ? FriendsMessengerIconEvent.UNREAD_ICON : FriendsMessengerIconEvent.SHOW_ICON));
}, [visibleThreads, updateValue]);
}, [ visibleThreads, updateValue ]);
if(!isVisible) return null;
return (
<NitroCardView className="nitro-friends-messenger" uniqueKey="nitro-friends-messenger" theme="primary-slim">
<NitroCardHeaderView headerText={LocalizeText('messenger.window.title', ['OPEN_CHAT_COUNT'], [visibleThreads.length.toString()])} onCloseClick={event => setIsVisible(false)} />
<NitroCardHeaderView headerText={LocalizeText('messenger.window.title', [ 'OPEN_CHAT_COUNT' ], [ visibleThreads.length.toString() ])} onCloseClick={event => setIsVisible(false)} />
<NitroCardContentView>
<Grid overflow="hidden">
<Column size={ 4 }>

View File

@ -34,33 +34,33 @@ export const GroupBadgeCreatorView: FC<GroupBadgeCreatorViewProps> = props =>
return (
<>
{ ((selectedIndex < 0) && badgeParts && (badgeParts.length > 0)) && badgeParts.map((part, index) =>
{
return (
<Flex key={ index } alignItems="center" justifyContent="between" gap={ 2 } className="bg-muted rounded px-2 py-1">
<Flex pointer center className="bg-muted rounded p-1" onClick={ event => setSelectedIndex(index) }>
{ (badgeParts[index].code && (badgeParts[index].code.length > 0)) &&
{
return (
<Flex key={ index } alignItems="center" justifyContent="between" gap={ 2 } className="bg-muted rounded px-2 py-1">
<Flex pointer center className="bg-muted rounded p-1" onClick={ event => setSelectedIndex(index) }>
{ (badgeParts[index].code && (badgeParts[index].code.length > 0)) &&
<LayoutBadgeImageView badgeCode={ badgeParts[index].code } isGroup={ true } /> }
{ (!badgeParts[index].code || !badgeParts[index].code.length) &&
{ (!badgeParts[index].code || !badgeParts[index].code.length) &&
<Flex center className="badge-image group-badge">
<FontAwesomeIcon icon="plus" />
</Flex> }
</Flex>
{ (part.type !== GroupBadgePart.BASE) &&
</Flex>
{ (part.type !== GroupBadgePart.BASE) &&
<Grid gap={ 1 } columnCount={ 3 }>
{ POSITIONS.map((position, posIndex) =>
{
return <Base key={ posIndex } pointer className={ `group-badge-position-swatch ${ (badgeParts[index].position === position) ? 'active' : '' }` } onClick={ event => setPartProperty(index, 'position', position) }></Base>
}) }
</Grid> }
<Grid gap={ 1 } columnCount={ 8 }>
{ (groupCustomize.badgePartColors.length > 0) && groupCustomize.badgePartColors.map((item, colorIndex) =>
{
return <Base key={ colorIndex } pointer className={ `group-badge-color-swatch ${ (badgeParts[index].color === (colorIndex + 1)) ? 'active' : '' }` } style={{ backgroundColor: '#' + item.color }} onClick={ event => setPartProperty(index, 'color', (colorIndex + 1)) }></Base>
return <Base key={ posIndex } pointer className={ `group-badge-position-swatch ${ (badgeParts[index].position === position) ? 'active' : '' }` } onClick={ event => setPartProperty(index, 'position', position) }></Base>
}) }
</Grid>
</Flex>
);
}) }
</Grid> }
<Grid gap={ 1 } columnCount={ 8 }>
{ (groupCustomize.badgePartColors.length > 0) && groupCustomize.badgePartColors.map((item, colorIndex) =>
{
return <Base key={ colorIndex } pointer className={ `group-badge-color-swatch ${ (badgeParts[index].color === (colorIndex + 1)) ? 'active' : '' }` } style={{ backgroundColor: '#' + item.color }} onClick={ event => setPartProperty(index, 'color', (colorIndex + 1)) }></Base>
}) }
</Grid>
</Flex>
);
}) }
{ (selectedIndex >= 0) &&
<Grid gap={ 1 } columnCount={ 5 }>
{ (badgeParts[selectedIndex].type === GroupBadgePart.SYMBOL) &&
@ -70,13 +70,13 @@ export const GroupBadgeCreatorView: FC<GroupBadgeCreatorViewProps> = props =>
</Flex>
</Column> }
{ ((badgeParts[selectedIndex].type === GroupBadgePart.BASE) ? groupCustomize.badgeBases : groupCustomize.badgeSymbols).map((item, index) =>
{
return (
<Column key={ index } pointer center className="bg-muted rounded p-1" onClick={ event => setPartProperty(selectedIndex, 'key', item.id) }>
<LayoutBadgeImageView badgeCode={ GroupBadgePart.getCode(badgeParts[selectedIndex].type, item.id, badgeParts[selectedIndex].color, 4) } isGroup={ true } />
</Column>
);
}) }
{
return (
<Column key={ index } pointer center className="bg-muted rounded p-1" onClick={ event => setPartProperty(selectedIndex, 'key', item.id) }>
<LayoutBadgeImageView badgeCode={ GroupBadgePart.getCode(badgeParts[selectedIndex].type, item.id, badgeParts[selectedIndex].color, 4) } isGroup={ true } />
</Column>
);
}) }
</Grid> }
</>
);

View File

@ -132,13 +132,13 @@ export const GroupCreatorView: FC<GroupCreatorViewProps> = props =>
<NitroCardContentView>
<Flex center className="creator-tabs">
{ TABS.map((tab, index) =>
{
return (
<Flex center key={ index } className={ `tab tab-${ ((tab === 1) ? 'blue-flat' : (tab === 4) ? 'yellow' : 'blue-arrow') } ${ (currentTab === tab) ? 'active' : '' }` }>
<Text variant="white">{ LocalizeText(`group.create.steplabel.${ tab }`) }</Text>
</Flex>
);
}) }
{
return (
<Flex center key={ index } className={ `tab tab-${ ((tab === 1) ? 'blue-flat' : (tab === 4) ? 'yellow' : 'blue-arrow') } ${ (currentTab === tab) ? 'active' : '' }` }>
<Text variant="white">{ LocalizeText(`group.create.steplabel.${ tab }`) }</Text>
</Flex>
);
}) }
</Flex>
<Column overflow="hidden">
<Flex alignItems="center" gap={ 2 }>

View File

@ -26,11 +26,11 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
const leaveGroup = () =>
{
NotificationUtilities.confirm(LocalizeText('group.leaveconfirm.desc'), () =>
{
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
{
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
if(onClose) onClose();
}, null);
if(onClose) onClose();
}, null);
}
const getRoleIcon = () =>
@ -126,7 +126,7 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
<i className="icon icon-group-decorate" title={ LocalizeText('group.memberscandecorate') } /> }
</Flex>
</Flex>
<Text small>{ LocalizeText('group.created', ['date', 'owner'], [groupInformation.createdAt, groupInformation.ownerName]) }</Text>
<Text small>{ LocalizeText('group.created', [ 'date', 'owner' ], [ groupInformation.createdAt, groupInformation.ownerName ]) }</Text>
</Column>
<Text small overflow="auto" className="group-description">{ groupInformation.description }</Text>
</Column>

View File

@ -20,11 +20,11 @@ export const GroupManagerView: FC<{}> = props =>
const close = () =>
{
setCloseAction(prevValue =>
{
if(prevValue && prevValue.action) prevValue.action();
{
if(prevValue && prevValue.action) prevValue.action();
return null;
});
return null;
});
setGroupData(null);
}
@ -43,16 +43,16 @@ export const GroupManagerView: FC<{}> = props =>
if(!groupData || (groupData.groupId !== parser.id)) return;
setGroupData(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.groupName = parser.title;
newValue.groupDescription = parser.description;
newValue.groupState = parser.type;
newValue.groupCanMembersDecorate = parser.canMembersDecorate;
newValue.groupName = parser.title;
newValue.groupDescription = parser.description;
newValue.groupState = parser.type;
newValue.groupCanMembersDecorate = parser.canMembersDecorate;
return newValue;
});
return newValue;
});
}, [ groupData ]);
UseMessageEventHook(GroupInformationEvent, onGroupInformationEvent);
@ -94,11 +94,11 @@ export const GroupManagerView: FC<{}> = props =>
<NitroCardHeaderView headerText={ LocalizeText('group.window.title') } onCloseClick={ close } />
<NitroCardTabsView>
{ TABS.map(tab =>
{
return (<NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ () => changeTab(tab) }>
{ LocalizeText(`group.edit.tab.${tab}`) }
</NitroCardTabsItemView>);
}) }
{
return (<NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ () => changeTab(tab) }>
{ LocalizeText(`group.edit.tab.${tab}`) }
</NitroCardTabsItemView>);
}) }
</NitroCardTabsView>
<NitroCardContentView>
<Flex alignItems="center" gap={ 2 }>

View File

@ -91,11 +91,11 @@ export const GroupMembersView: FC<{}> = props =>
const parser = event.getParser();
NotificationUtilities.confirm(LocalizeText(((parser.furnitureCount > 0) ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc'), [ 'user', 'amount' ], [ removingMemberName, parser.furnitureCount.toString() ]), () =>
{
SendMessageComposer(new GroupRemoveMemberComposer(membersData.groupId, parser.userId));
{
SendMessageComposer(new GroupRemoveMemberComposer(membersData.groupId, parser.userId));
refreshMembers();
}, null);
refreshMembers();
}, null);
setRemovingMemberName(null);
}, [ membersData, removingMemberName, refreshMembers ]);
@ -160,7 +160,7 @@ export const GroupMembersView: FC<{}> = props =>
return (
<NitroCardView className="nitro-group-members" theme="primary-slim">
<NitroCardHeaderView headerText={ LocalizeText('group.members.title', ['groupName'], [ membersData ? membersData.groupTitle : '' ]) } onCloseClick={ event => setGroupId(-1) } />
<NitroCardHeaderView headerText={ LocalizeText('group.members.title', [ 'groupName' ], [ membersData ? membersData.groupTitle : '' ]) } onCloseClick={ event => setGroupId(-1) } />
<NitroCardContentView overflow="hidden">
<Flex gap={ 2 }>
<Flex center className="group-badge">
@ -177,41 +177,41 @@ export const GroupMembersView: FC<{}> = props =>
</Flex>
<Grid columnCount={ 2 } overflow="auto" className="nitro-group-members-list-grid">
{ membersData.result.map((member, index) =>
{
return (
<Flex key={ index } gap={ 2 } alignItems="center" overflow="hidden" className="member-list-item bg-white rounded p-2">
<div className="avatar-head cursor-pointer" onClick={ () => GetUserProfile(member.id) }>
<LayoutAvatarImageView figure={ member.figure } headOnly={ true } direction={ 2 } />
</div>
<Column grow gap={ 1 }>
<Text bold small pointer onClick={ event => GetUserProfile(member.id) }>{ member.name }</Text>
{ (member.rank !== GroupRank.REQUESTED) &&
{
return (
<Flex key={ index } gap={ 2 } alignItems="center" overflow="hidden" className="member-list-item bg-white rounded p-2">
<div className="avatar-head cursor-pointer" onClick={ () => GetUserProfile(member.id) }>
<LayoutAvatarImageView figure={ member.figure } headOnly={ true } direction={ 2 } />
</div>
<Column grow gap={ 1 }>
<Text bold small pointer onClick={ event => GetUserProfile(member.id) }>{ member.name }</Text>
{ (member.rank !== GroupRank.REQUESTED) &&
<Text small italics variant="muted">{ LocalizeText('group.members.since', [ 'date' ], [ member.joinedAt ]) }</Text> }
</Column>
<Column gap={ 1 }>
{ (member.rank !== GroupRank.REQUESTED) &&
</Column>
<Column gap={ 1 }>
{ (member.rank !== GroupRank.REQUESTED) &&
<Flex center>
<Base pointer={ membersData.admin } className={ `icon icon-group-small-${ ((member.rank === GroupRank.OWNER) ? 'owner' : (member.rank === GroupRank.ADMIN) ? 'admin' : (membersData.admin && (member.rank === GroupRank.MEMBER)) ? 'not-admin' : '') }` } title={ LocalizeText(getRankDescription(member)) } onClick={ event => toggleAdmin(member) } />
</Flex> }
{ membersData.admin && (member.rank === GroupRank.REQUESTED) &&
{ membersData.admin && (member.rank === GroupRank.REQUESTED) &&
<Flex alignItems="center">
<Base pointer className="nitro-friends-spritesheet icon-accept" title={ LocalizeText('group.members.accept') } onClick={ event => acceptMembership(member) }></Base>
</Flex> }
{ membersData.admin && (member.rank !== GroupRank.OWNER) && (member.id !== GetSessionDataManager().userId) &&
{ membersData.admin && (member.rank !== GroupRank.OWNER) && (member.id !== GetSessionDataManager().userId) &&
<Flex alignItems="center">
<Base pointer className="nitro-friends-spritesheet icon-deny" title={ LocalizeText(member.rank === GroupRank.REQUESTED ? 'group.members.reject' : 'group.members.kick') } onClick={ event => removeMemberOrDeclineMembership(member) }></Base>
</Flex> }
</Column>
</Flex>
);
}) }
</Column>
</Flex>
);
}) }
</Grid>
<Flex gap={ 1 } justifyContent="between" alignItems="center">
<Button disabled={ (membersData.pageIndex === 0) } onClick={ event => setPageId(prevValue => (prevValue - 1)) }>
<FontAwesomeIcon icon="chevron-left" />
</Button>
<Text small>
{ LocalizeText('group.members.pageinfo', ['amount', 'page', 'totalPages'], [membersData.totalMembersCount.toString(), (membersData.pageIndex + 1).toString(), totalPages.toString()]) }
{ LocalizeText('group.members.pageinfo', [ 'amount', 'page', 'totalPages' ], [ membersData.totalMembersCount.toString(), (membersData.pageIndex + 1).toString(), totalPages.toString() ]) }
</Text>
<Button disabled={ (membersData.pageIndex === (totalPages - 1)) } onClick={ event => setPageId(prevValue => (prevValue + 1)) }>
<FontAwesomeIcon icon="chevron-right" />

View File

@ -75,9 +75,9 @@ export const GroupRoomInformationView: FC<{}> = props =>
const leaveGroup = () =>
{
NotificationUtilities.confirm(LocalizeText('group.leaveconfirm.desc'), () =>
{
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
}, null);
{
SendMessageComposer(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
}, null);
}
const isRealOwner = (groupInformation && (groupInformation.ownerName === GetSessionDataManager().userName));
@ -134,7 +134,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
<Button fullWidth variant="success" disabled={ (groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING) } onClick={ handleButtonClick }>
{ LocalizeText(getButtonText()) }
</Button>
}
}
</> }
</Column>
</Base>

View File

@ -41,13 +41,13 @@ export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
if(groupData.groupId <= 0)
{
setGroupData(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.groupBadgeParts = badgeParts;
newValue.groupBadgeParts = badgeParts;
return newValue;
});
return newValue;
});
return true;
}
@ -81,11 +81,11 @@ export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
];
setGroupData(prevValue =>
{
const groupBadgeParts = badgeParts;
{
const groupBadgeParts = badgeParts;
return { ...prevValue, groupBadgeParts };
});
return { ...prevValue, groupBadgeParts };
});
}, [ groupData.groupBadgeParts, groupCustomize, setGroupData ]);
useEffect(() =>

View File

@ -29,13 +29,13 @@ export const GroupTabColorsView: FC<GroupTabColorsViewProps> = props =>
const selectColor = (colorIndex: number, colorId: number) =>
{
setColors(prevValue =>
{
const newColors = [ ...prevValue ];
{
const newColors = [ ...prevValue ];
newColors[colorIndex] = colorId;
newColors[colorIndex] = colorId;
return newColors;
});
return newColors;
});
}
const saveColors = useCallback(() =>
@ -47,13 +47,13 @@ export const GroupTabColorsView: FC<GroupTabColorsViewProps> = props =>
if(groupData.groupId <= 0)
{
setGroupData(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.groupColors = [ ...colors ];
newValue.groupColors = [ ...colors ];
return newValue;
});
return newValue;
});
return true;
}
@ -70,9 +70,9 @@ export const GroupTabColorsView: FC<GroupTabColorsViewProps> = props =>
const groupColors = [ groupCustomize.groupColorsA[0].id, groupCustomize.groupColorsB[0].id ];
setGroupData(prevValue =>
{
return { ...prevValue, groupColors };
});
{
return { ...prevValue, groupColors };
});
}, [ groupCustomize, groupData.groupColors, setGroupData ]);
useEffect(() =>
@ -110,18 +110,18 @@ export const GroupTabColorsView: FC<GroupTabColorsViewProps> = props =>
<Text bold>{ LocalizeText('group.edit.color.primary.color') }</Text>
<AutoGrid gap={ 1 } columnCount={ 7 } columnMinWidth={ 16 } columnMinHeight={ 16 }>
{ groupData.groupColors && groupCustomize.groupColorsA && groupCustomize.groupColorsA.map((item, index) =>
{
return <div key={ index } className={ 'group-badge-color-swatch cursor-pointer' + classNames({ ' active': (groupData.groupColors[0] === item.id) }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(0, item.id) }></div>
}) }
{
return <div key={ index } className={ 'group-badge-color-swatch cursor-pointer' + classNames({ ' active': (groupData.groupColors[0] === item.id) }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(0, item.id) }></div>
}) }
</AutoGrid>
</Column>
<Column size={ 5 } gap={ 1 } overflow="hidden">
<Text bold>{ LocalizeText('group.edit.color.secondary.color') }</Text>
<AutoGrid gap={ 1 } columnCount={ 7 } columnMinWidth={ 16 } columnMinHeight={ 16 }>
{ groupData.groupColors && groupCustomize.groupColorsB && groupCustomize.groupColorsB.map((item, index) =>
{
return <div key={ index } className={ 'group-badge-color-swatch cursor-pointer' + classNames({ ' active': (groupData.groupColors[1] === item.id) }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(1, item.id) }></div>
}) }
{
return <div key={ index } className={ 'group-badge-color-swatch cursor-pointer' + classNames({ ' active': (groupData.groupColors[1] === item.id) }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(1, item.id) }></div>
}) }
</AutoGrid>
</Column>
</Grid>

View File

@ -27,11 +27,11 @@ export const GroupTabIdentityView: FC<GroupTabIdentityViewProps> = props =>
if(!groupData || (groupData.groupId <= 0)) return;
NotificationUtilities.confirm(LocalizeText('group.deleteconfirm.desc'), () =>
{
SendMessageComposer(new GroupDeleteComposer(groupData.groupId));
{
SendMessageComposer(new GroupDeleteComposer(groupData.groupId));
if(close) close();
}, null, null, null, LocalizeText('group.deleteconfirm.title'));
if(close) close();
}, null, null, null, LocalizeText('group.deleteconfirm.title'));
}
const saveIdentity = useCallback(() =>
@ -45,15 +45,15 @@ export const GroupTabIdentityView: FC<GroupTabIdentityViewProps> = props =>
if(groupHomeroomId <= 0) return false;
setGroupData(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.groupName = groupName;
newValue.groupDescription = groupDescription;
newValue.groupHomeroomId = groupHomeroomId;
newValue.groupName = groupName;
newValue.groupDescription = groupDescription;
newValue.groupHomeroomId = groupHomeroomId;
return newValue;
});
return newValue;
});
return true;
}

View File

@ -30,14 +30,14 @@ export const GroupTabSettingsView: FC<GroupTabSettingsViewProps> = props =>
if(groupData.groupId <= 0)
{
setGroupData(prevValue =>
{
const newValue = { ...prevValue };
{
const newValue = { ...prevValue };
newValue.groupState = groupState;
newValue.groupCanMembersDecorate = groupDecorate;
newValue.groupState = groupState;
newValue.groupCanMembersDecorate = groupDecorate;
return newValue;
});
return newValue;
});
return true;
}
@ -67,20 +67,20 @@ export const GroupTabSettingsView: FC<GroupTabSettingsViewProps> = props =>
<Column overflow="auto">
<Column>
{ STATES.map((state, index) =>
{
return (
<Flex key={ index } alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="groupState" checked={ (groupState === index) } onChange={ event => setGroupState(index) } />
<Column gap={ 0 }>
<Flex gap={ 1 }>
<i className={ `icon icon-group-type-${ index }` } />
<Text bold>{ LocalizeText(`group.edit.settings.type.${ state }.label`) }</Text>
</Flex>
<Text>{ LocalizeText(`group.edit.settings.type.${ state }.help`) }</Text>
</Column>
</Flex>
);
}) }
{
return (
<Flex key={ index } alignItems="center" gap={ 1 }>
<input className="form-check-input" type="radio" name="groupState" checked={ (groupState === index) } onChange={ event => setGroupState(index) } />
<Column gap={ 0 }>
<Flex gap={ 1 }>
<i className={ `icon icon-group-type-${ index }` } />
<Text bold>{ LocalizeText(`group.edit.settings.type.${ state }.label`) }</Text>
</Flex>
<Text>{ LocalizeText(`group.edit.settings.type.${ state }.help`) }</Text>
</Column>
</Flex>
);
}) }
</Column>
<HorizontalRule />
<Flex alignItems="center" gap={ 1 }>

View File

@ -55,7 +55,7 @@ export const GuideToolView: FC<{}> = props =>
setNoCloseButton(true);
break;
case GuideSessionState.GUIDE_ONGOING:
setHeaderText(LocalizeText('guide.help.request.guide.ongoing.title', ['name'], [replacement]));
setHeaderText(LocalizeText('guide.help.request.guide.ongoing.title', [ 'name' ], [ replacement ]));
setNoCloseButton(true);
break;
case GuideSessionState.USER_CREATE:
@ -67,7 +67,7 @@ export const GuideToolView: FC<{}> = props =>
setNoCloseButton(true);
break;
case GuideSessionState.USER_ONGOING:
setHeaderText(LocalizeText('guide.help.request.user.ongoing.title', ['name'], [replacement]));
setHeaderText(LocalizeText('guide.help.request.user.ongoing.title', [ 'name' ], [ replacement ]));
setNoCloseButton(true);
break;
case GuideSessionState.USER_FEEDBACK:
@ -183,7 +183,7 @@ export const GuideToolView: FC<{}> = props =>
{
const parser = event.getParser();
const messageGroups = [...ongoingMessageGroups];
const messageGroups = [ ...ongoingMessageGroups ];
let lastGroup = messageGroups[messageGroups.length - 1];
@ -203,7 +203,7 @@ export const GuideToolView: FC<{}> = props =>
{
const parser = event.getParser();
const messageGroups = [...ongoingMessageGroups];
const messageGroups = [ ...ongoingMessageGroups ];
let lastGroup = messageGroups[messageGroups.length - 1];
@ -217,7 +217,7 @@ export const GuideToolView: FC<{}> = props =>
lastGroup.addChat(new GuideToolMessage(parser.roomName, parser.roomId));
setOngoingMessageGroups(messageGroups);
}, [isOnDuty, ongoingMessageGroups, ongoingUserId]);
}, [ isOnDuty, ongoingMessageGroups, ongoingUserId ]);
UseMessageEventHook(GuideSessionInvitedToGuideRoomMessageEvent, onGuideSessionInvitedToGuideRoomMessageEvent);
@ -270,7 +270,7 @@ export const GuideToolView: FC<{}> = props =>
switch(parts[1])
{
case 'tour':
//Create Tour Request
//Create Tour Request
return;
}
}, []);
@ -299,15 +299,15 @@ export const GuideToolView: FC<{}> = props =>
case 'toggle_duty':
if(!isHandlingBullyReports && !isHandlingGuideRequests && !isHandlingHelpRequests)
{
DispatchUiEvent(new NotificationAlertEvent([LocalizeText('guide.help.guide.tool.noqueueselected.message')], null, null, null, LocalizeText('guide.help.guide.tool.noqueueselected.caption'), null));
DispatchUiEvent(new NotificationAlertEvent([ LocalizeText('guide.help.guide.tool.noqueueselected.message') ], null, null, null, LocalizeText('guide.help.guide.tool.noqueueselected.caption'), null));
return;
}
setIsOnDuty(v =>
{
SendMessageComposer(new GuideSessionOnDutyUpdateMessageComposer(!v, v ? false : isHandlingGuideRequests, v ? false : isHandlingHelpRequests, v ? false : isHandlingBullyReports));
return !v;
});
{
SendMessageComposer(new GuideSessionOnDutyUpdateMessageComposer(!v, v ? false : isHandlingGuideRequests, v ? false : isHandlingHelpRequests, v ? false : isHandlingBullyReports));
return !v;
});
return;
case 'forum_link':
@ -315,7 +315,7 @@ export const GuideToolView: FC<{}> = props =>
window.open(url);
return;
}
}, [isHandlingBullyReports, isHandlingGuideRequests, isHandlingHelpRequests]);
}, [ isHandlingBullyReports, isHandlingGuideRequests, isHandlingHelpRequests ]);
if(!isVisible) return null;

View File

@ -24,8 +24,8 @@ export const GuideToolAcceptView: FC<GuideToolAcceptViewProps> = props =>
</Column>
<Column gap={ 1 }>
<Button variant="success" onClick={ event => answerRequest(true) }>
{ LocalizeText('guide.help.request.guide.accept.accept.button') }
</Button>
{ LocalizeText('guide.help.request.guide.accept.accept.button') }
</Button>
<Button variant="danger" onClick={ event => answerRequest(false) }>
{ LocalizeText('guide.help.request.guide.accept.skip.link') }
</Button>

View File

@ -83,27 +83,27 @@ export const GuideToolOngoingView: FC<GuideToolOngoingViewProps> = props =>
<Column overflow="hidden" gap={ 1 } className="bg-muted rounded chat-messages p-2">
<Column overflow="auto">
{ messageGroups.map((group, index) =>
{
return (
<Flex fullWidth justifyContent={ isOwnChat(group.userId) ? 'end' : 'start' } gap={ 2 }>
<Base shrink className="message-avatar">
{ (!isOwnChat(group.userId)) &&
{
return (
<Flex key={ index } fullWidth justifyContent={ isOwnChat(group.userId) ? 'end' : 'start' } gap={ 2 }>
<Base shrink className="message-avatar">
{ (!isOwnChat(group.userId)) &&
<LayoutAvatarImageView figure={ userFigure } direction={ 2 } /> }
</Base>
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat(group.userId) ? 'right' : 'left') }>
<Text bold>
{ (isOwnChat(group.userId)) && GetSessionDataManager().userName }
{ (!isOwnChat(group.userId)) && userName }
</Text>
{ group.messages.map((chat, index) => <Base key={ index } className="text-break">{ chat.message }</Base>) }
</Base>
{ (isOwnChat(group.userId)) &&
</Base>
<Base className={ 'bg-light text-black border-radius mb-2 rounded py-1 px-2 messages-group-' + (isOwnChat(group.userId) ? 'right' : 'left') }>
<Text bold>
{ (isOwnChat(group.userId)) && GetSessionDataManager().userName }
{ (!isOwnChat(group.userId)) && userName }
</Text>
{ group.messages.map((chat, index) => <Base key={ index } className="text-break">{ chat.message }</Base>) }
</Base>
{ (isOwnChat(group.userId)) &&
<Base className="message-avatar flex-shrink-0">
<LayoutAvatarImageView figure={ GetSessionDataManager().figure } direction={ 4 } />
</Base> }
</Flex>
);
}) }
</Flex>
);
}) }
</Column>
</Column>
<Column gap={ 1 }>

View File

@ -90,7 +90,7 @@ export const HcCenterView: FC<{}> = props =>
setIsVisible(!isVisible);
break;
}
}, [isVisible]);
}, [ isVisible ]);
UseUiEvent(HcCenterEvent.TOGGLE_HC_CENTER, onHcCenterEvent);
@ -169,7 +169,7 @@ export const HcCenterView: FC<{}> = props =>
AddEventLinkTracker(linkTracker);
return () => RemoveLinkEventTracker(linkTracker);
}, [ linkReceived]);
}, [ linkReceived ]);
useEffect(() =>
{
@ -201,14 +201,17 @@ export const HcCenterView: FC<{}> = props =>
<Popover id="popover-basic">
<Popover.Body className="text-black py-2 px-3">
<h5>{LocalizeText('hccenter.breakdown.title')}</h5>
<div>{LocalizeText('hccenter.breakdown.creditsspent', ['credits'], [kickbackData.totalCreditsSpent.toString()])}</div>
<div>{LocalizeText('hccenter.breakdown.paydayfactor.percent', ['percent'], [(kickbackData.kickbackPercentage * 100).toString()])}</div>
<div>{LocalizeText('hccenter.breakdown.streakbonus', ['credits'], [kickbackData.creditRewardForStreakBonus.toString()])}</div>
<div>{LocalizeText('hccenter.breakdown.creditsspent', [ 'credits' ], [ kickbackData.totalCreditsSpent.toString() ])}</div>
<div>{LocalizeText('hccenter.breakdown.paydayfactor.percent', [ 'percent' ], [ (kickbackData.kickbackPercentage * 100).toString() ])}</div>
<div>{LocalizeText('hccenter.breakdown.streakbonus', [ 'credits' ], [ kickbackData.creditRewardForStreakBonus.toString() ])}</div>
<hr className="w-100 text-black my-1" />
<div>{LocalizeText('hccenter.breakdown.total', ['credits', 'actual'], [getHcPaydayAmount(),
((((kickbackData.kickbackPercentage * kickbackData.totalCreditsSpent) + kickbackData.creditRewardForStreakBonus) * 100) / 100).toString()])}</div>
<div className="btn btn-link text-primary p-0" onClick={() => { CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage']) }}>{
LocalizeText('hccenter.special.infolink')}
<div>{LocalizeText('hccenter.breakdown.total', [ 'credits', 'actual' ], [ getHcPaydayAmount(),
((((kickbackData.kickbackPercentage * kickbackData.totalCreditsSpent) + kickbackData.creditRewardForStreakBonus) * 100) / 100).toString() ])}</div>
<div className="btn btn-link text-primary p-0" onClick={() =>
{
CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage'])
}}>{
LocalizeText('hccenter.special.infolink')}
</div>
</Popover.Body>
</Popover>
@ -221,7 +224,10 @@ export const HcCenterView: FC<{}> = props =>
<Column gap={ 1 }>
<div className="hc-logo" />
<Flex>
<Button variant="success" onClick={ event => { CreateLinkEvent('catalog/open/' + GetConfiguration('catalog.links')['hc.buy_hc']) } }>
<Button variant="success" onClick={ event =>
{
CreateLinkEvent('catalog/open/' + GetConfiguration('catalog.links')['hc.buy_hc'])
} }>
{ LocalizeText((clubStatus === ClubStatus.ACTIVE) ? 'hccenter.btn.extend' : 'hccenter.btn.buy') }
</Button>
</Flex>
@ -243,7 +249,10 @@ export const HcCenterView: FC<{}> = props =>
<Column className="rounded-start bg-primary p-2 payday-special mb-1">
<h4 className="mb-1">{LocalizeText('hccenter.special.title')}</h4>
<div>{LocalizeText('hccenter.special.info')}</div>
<div className="btn btn-link text-white p-0 mt-auto align-self-baseline" onClick={() => { CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage']) }}>{LocalizeText('hccenter.special.infolink')}</div>
<div className="btn btn-link text-white p-0 mt-auto align-self-baseline" onClick={() =>
{
CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['payday.habbopage'])
}}>{LocalizeText('hccenter.special.infolink')}</div>
</Column>
<div className="payday flex-shrink-0 p-2">
<h5 className="mb-2 ms-2">{LocalizeText('hccenter.special.time.title')}</h5>
@ -271,16 +280,22 @@ export const HcCenterView: FC<{}> = props =>
<div className="rounded bg-success p-2 d-flex flex-row mb-0">
<div>
<h4 className="mb-1">{LocalizeText('hccenter.gift.title')}</h4>
<div dangerouslySetInnerHTML={{ __html: unclaimedGifts > 0 ? LocalizeText('hccenter.unclaimedgifts', ['unclaimedgifts'], [unclaimedGifts.toString()]) : LocalizeText('hccenter.gift.info') }}></div>
<div dangerouslySetInnerHTML={{ __html: unclaimedGifts > 0 ? LocalizeText('hccenter.unclaimedgifts', [ 'unclaimedgifts' ], [ unclaimedGifts.toString() ]) : LocalizeText('hccenter.gift.info') }}></div>
</div>
<button className="btn btn-primary btn-lg align-self-center ms-auto" onClick={() => { CreateLinkEvent('catalog/open/' + GetConfiguration('catalog.links')['hc.hc_gifts']) }}>{LocalizeText(clubStatus === ClubStatus.ACTIVE ? 'hccenter.btn.gifts.redeem' : 'hccenter.btn.gifts.view')}</button>
<button className="btn btn-primary btn-lg align-self-center ms-auto" onClick={() =>
{
CreateLinkEvent('catalog/open/' + GetConfiguration('catalog.links')['hc.hc_gifts'])
}}>{LocalizeText(clubStatus === ClubStatus.ACTIVE ? 'hccenter.btn.gifts.redeem' : 'hccenter.btn.gifts.view')}</button>
</div>
}
{GetConfiguration('hc.center')['benefits.info'] &&
<div className="benefits text-black py-2">
<h5 className="mb-1 text-primary">{LocalizeText('hccenter.general.title')}</h5>
<div className="mb-2" dangerouslySetInnerHTML={{ __html: LocalizeText('hccenter.general.info') }} />
<button className="btn btn-link p-0 text-primary" onClick={() => { CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['benefits.habbopage']) }}>{LocalizeText('hccenter.general.infolink')}</button>
<button className="btn btn-link p-0 text-primary" onClick={() =>
{
CreateLinkEvent('habbopages/' + GetConfiguration('hc.center')['benefits.habbopage'])
}}>{LocalizeText('hccenter.general.infolink')}</button>
</div>
}
</NitroCardContentView>

View File

@ -2,7 +2,7 @@
export class BadgeResolver
{
public static default_badge: string = 'HC1';
public static badges: string[] = ['ACH_VipHC1', 'ACH_VipHC2', 'ACH_VipHC3', 'ACH_VipHC4', 'ACH_VipHC5', 'HC1', 'HC2', 'HC3', 'HC4', 'HC5'];
public static badges: string[] = [ 'ACH_VipHC1', 'ACH_VipHC2', 'ACH_VipHC3', 'ACH_VipHC4', 'ACH_VipHC5', 'HC1', 'HC2', 'HC3', 'HC4', 'HC5' ];
public static getClubBadge(k: string[]): string

View File

@ -104,7 +104,7 @@ export const HelpView: FC<{}> = props =>
}
return null;
}, [helpReportState.currentStep]);
}, [ helpReportState.currentStep ]);
return (
<HelpContextProvider value={ { helpReportState, setHelpReportState } }>

View File

@ -15,7 +15,7 @@ export const HelpIndexView: FC<{}> = props =>
const reportState = Object.assign({}, helpReportState );
reportState.currentStep = 1;
setHelpReportState(reportState);
},[helpReportState, setHelpReportState]);
},[ helpReportState, setHelpReportState ]);
const onRequestMySanctionStatusClick = useCallback(() =>
{

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