mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-26 23:50:52 +01:00
Groups updates
This commit is contained in:
parent
dcf18449b8
commit
820a147120
7
src/api/groups/TryJoinGroup.ts
Normal file
7
src/api/groups/TryJoinGroup.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { GroupJoinComposer } from '@nitrots/nitro-renderer';
|
||||||
|
import { SendMessageHook } from '../../hooks';
|
||||||
|
|
||||||
|
export function TryJoinGroup(groupId: number): void
|
||||||
|
{
|
||||||
|
SendMessageHook(new GroupJoinComposer(groupId));
|
||||||
|
}
|
@ -4,6 +4,7 @@ import { CatalogLayoutDefaultView } from './default/CatalogLayoutDefaultView';
|
|||||||
import { CatalogLayoutFrontpage4View } from './frontpage4/CatalogLayoutFrontpage4View';
|
import { CatalogLayoutFrontpage4View } from './frontpage4/CatalogLayoutFrontpage4View';
|
||||||
import { CatalogLayouGuildCustomFurniView } from './guild-custom-furni/CatalogLayoutGuildCustomFurniView';
|
import { CatalogLayouGuildCustomFurniView } from './guild-custom-furni/CatalogLayoutGuildCustomFurniView';
|
||||||
import { CatalogLayouGuildForumView } from './guild-forum/CatalogLayoutGuildForumView';
|
import { CatalogLayouGuildForumView } from './guild-forum/CatalogLayoutGuildForumView';
|
||||||
|
import { CatalogLayouGuildFrontpageView } from './guild-frontpage/CatalogLayoutGuildFrontpageView';
|
||||||
import { CatalogLayoutInfoLoyaltyView } from './info-loyalty/CatalogLayoutInfoLoyaltyView';
|
import { CatalogLayoutInfoLoyaltyView } from './info-loyalty/CatalogLayoutInfoLoyaltyView';
|
||||||
import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView';
|
import { CatalogLayoutPetView } from './pets/CatalogLayoutPetView';
|
||||||
import { CatalogLayoutPets2View } from './pets2/CatalogLayoutPets2View';
|
import { CatalogLayoutPets2View } from './pets2/CatalogLayoutPets2View';
|
||||||
@ -30,7 +31,7 @@ export const GetCatalogLayout = (pageParser: CatalogPageMessageParser, roomPrevi
|
|||||||
case 'vip_buy':
|
case 'vip_buy':
|
||||||
return <CatalogLayoutVipBuyView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
|
return <CatalogLayoutVipBuyView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
|
||||||
case 'guild_frontpage':
|
case 'guild_frontpage':
|
||||||
return null;
|
return <CatalogLayouGuildFrontpageView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
|
||||||
case 'guild_forum':
|
case 'guild_forum':
|
||||||
return <CatalogLayouGuildForumView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
|
return <CatalogLayouGuildForumView roomPreviewer={ roomPreviewer } pageParser={ pageParser } />;
|
||||||
case 'guild_custom_furni':
|
case 'guild_custom_furni':
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { CatalogGroupsComposer } from '@nitrots/nitro-renderer';
|
import { CatalogGroupsComposer, StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { LocalizeText } from '../../../../../../api';
|
import { LocalizeText } from '../../../../../../api';
|
||||||
import { SendMessageHook } from '../../../../../../hooks/messages';
|
import { SendMessageHook } from '../../../../../../hooks/messages';
|
||||||
|
import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView';
|
||||||
import { GetOfferName } from '../../../../common/CatalogUtilities';
|
import { GetOfferName } from '../../../../common/CatalogUtilities';
|
||||||
import { useCatalogContext } from '../../../../context/CatalogContext';
|
import { useCatalogContext } from '../../../../context/CatalogContext';
|
||||||
import { CatalogRoomPreviewerView } from '../../../catalog-room-previewer/CatalogRoomPreviewerView';
|
import { CatalogRoomPreviewerView } from '../../../catalog-room-previewer/CatalogRoomPreviewerView';
|
||||||
@ -18,11 +19,32 @@ export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutGuildCustomFurniV
|
|||||||
|
|
||||||
const product = ((activeOffer && activeOffer.products[0]) || null);
|
const product = ((activeOffer && activeOffer.products[0]) || null);
|
||||||
|
|
||||||
|
const [ selectedGroupIndex, setSelectedGroupIndex ] = useState<number>(0);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new CatalogGroupsComposer());
|
SendMessageHook(new CatalogGroupsComposer());
|
||||||
}, [ pageParser ]);
|
}, [ pageParser ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(!groups[selectedGroupIndex]) return;
|
||||||
|
|
||||||
|
const productData = [];
|
||||||
|
productData.push('0');
|
||||||
|
productData.push(groups[selectedGroupIndex].groupId);
|
||||||
|
productData.push(groups[selectedGroupIndex].badgeCode);
|
||||||
|
productData.push(groups[selectedGroupIndex].colorA);
|
||||||
|
productData.push(groups[selectedGroupIndex].colorB);
|
||||||
|
|
||||||
|
const stringDataType = new StringDataType();
|
||||||
|
stringDataType.setValue(productData);
|
||||||
|
|
||||||
|
roomPreviewer.updateObjectStuffData(stringDataType);
|
||||||
|
}, [ selectedGroupIndex, activeOffer ]);
|
||||||
|
|
||||||
|
if(!groups) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row h-100 nitro-catalog-layout-guild-custom-furni">
|
<div className="row h-100 nitro-catalog-layout-guild-custom-furni">
|
||||||
<div className="d-flex flex-column col-7 h-100">
|
<div className="d-flex flex-column col-7 h-100">
|
||||||
@ -30,13 +52,30 @@ export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutGuildCustomFurniV
|
|||||||
</div>
|
</div>
|
||||||
{ product &&
|
{ product &&
|
||||||
<div className="col position-relative d-flex flex-column">
|
<div className="col position-relative d-flex flex-column">
|
||||||
|
{ groups[selectedGroupIndex] && <div className="position-absolute" style={{ width: '50px', height: '50px', zIndex: 1 }}>
|
||||||
|
<BadgeImageView badgeCode={ groups[selectedGroupIndex].badgeCode } isGroup={ true } />
|
||||||
|
</div> }
|
||||||
<CatalogRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
<CatalogRoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
||||||
<div className="fs-6 text-black mt-1 overflow-hidden">{ GetOfferName(activeOffer) }</div>
|
<div className="fs-6 text-black mt-1 overflow-hidden">{ GetOfferName(activeOffer) }</div>
|
||||||
{ groups.length === 0 && <div className="bg-muted text-center rounded p-1 text-black mt-auto">
|
{ groups.length === 0 && <div className="bg-muted text-center rounded p-1 text-black mt-auto">
|
||||||
{ LocalizeText('catalog.guild_selector.members_only') }
|
{ LocalizeText('catalog.guild_selector.members_only') }
|
||||||
<button className="btn btn-sm btn-primary mt-1">{ LocalizeText('catalog.guild_selector.find_groups') }</button>
|
<button className="btn btn-sm btn-primary mt-1">{ LocalizeText('catalog.guild_selector.find_groups') }</button>
|
||||||
</div> }
|
</div> }
|
||||||
{ groups.length > 0 && <CatalogPurchaseView offer={ activeOffer } pageId={ pageParser.pageId } /> }
|
{ groups.length > 0 && <>
|
||||||
|
<div className="d-flex mb-2">
|
||||||
|
<div className="rounded d-flex overflow-hidden me-1 border">
|
||||||
|
<div className="h-100" style={{ width: '20px', backgroundColor: '#' + groups[selectedGroupIndex].colorA }}></div>
|
||||||
|
<div className="h-100" style={{ width: '20px', backgroundColor: '#' + groups[selectedGroupIndex].colorB }}></div>
|
||||||
|
</div>
|
||||||
|
<select className="form-select form-select-sm" value={ selectedGroupIndex } onChange={ (e) => setSelectedGroupIndex(parseInt(e.target.value)) }>
|
||||||
|
{ groups.map((group, index) =>
|
||||||
|
{
|
||||||
|
return <option key={ index } value={ index }>{ group.groupName }</option>;
|
||||||
|
}) }
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<CatalogPurchaseView offer={ activeOffer } pageId={ pageParser.pageId } extra={ groups[selectedGroupIndex] ? groups[selectedGroupIndex].groupId.toString() : '' } />
|
||||||
|
</> }
|
||||||
</div> }
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { CreateLinkEvent, LocalizeText } from '../../../../../../api';
|
||||||
|
import { GetCatalogPageImage, GetCatalogPageText } from '../../../../common/CatalogUtilities';
|
||||||
|
import { useCatalogContext } from '../../../../context/CatalogContext';
|
||||||
|
import { CatalogLayoutGuildFrontpageViewProps } from './CatalogLayoutGuildFrontpageView.types';
|
||||||
|
|
||||||
|
export const CatalogLayouGuildFrontpageView: FC<CatalogLayoutGuildFrontpageViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { pageParser = null } = props;
|
||||||
|
|
||||||
|
const { catalogState = null, dispatchCatalogState = null } = useCatalogContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row h-100 nitro-catalog-layout-guild-custom-furni">
|
||||||
|
<div className="col-7 overflow-auto h-100 d-flex flex-column bg-muted rounded py-1 px-2 text-black">
|
||||||
|
<div dangerouslySetInnerHTML={ { __html: GetCatalogPageText(pageParser, 2) } } />
|
||||||
|
<div dangerouslySetInnerHTML={ { __html: GetCatalogPageText(pageParser, 0) } } />
|
||||||
|
<div dangerouslySetInnerHTML={ { __html: GetCatalogPageText(pageParser, 1) } } />
|
||||||
|
<div className="d-block mb-2">
|
||||||
|
<img alt="" src={ GetCatalogPageImage(pageParser, 1) } />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col position-relative d-flex flex-column justify-content-center" onClick={ () => CreateLinkEvent('groups/create') }>
|
||||||
|
<button className="btn btn-sm btn-primary mt-1">{ LocalizeText('catalog.start.guild.purchase.button') }</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
import { CatalogLayoutProps } from '../CatalogLayout.types';
|
||||||
|
|
||||||
|
export interface CatalogLayoutGuildFrontpageViewProps extends CatalogLayoutProps
|
||||||
|
{}
|
27
src/views/groups/GroupsMessageHandler.tsx
Normal file
27
src/views/groups/GroupsMessageHandler.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { GroupBadgePartsEvent } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, useCallback } from 'react';
|
||||||
|
import { CreateMessageHook } from '../../hooks';
|
||||||
|
import { useGroupsContext } from './context/GroupsContext';
|
||||||
|
import { GroupsActions } from './context/GroupsContext.types';
|
||||||
|
|
||||||
|
export const GroupsMessageHandler: FC<{}> = props =>
|
||||||
|
{
|
||||||
|
const { groupsState = null, dispatchGroupsState = null } = useGroupsContext();
|
||||||
|
|
||||||
|
const onGroupBadgePartsEvent = useCallback((event: GroupBadgePartsEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
dispatchGroupsState({
|
||||||
|
type: GroupsActions.SET_BADGE_PARTS,
|
||||||
|
payload: {
|
||||||
|
arrayMaps: [ parser.bases, parser.symbols ],
|
||||||
|
stringMaps: [ parser.partColors, parser.colorsA, parser.colorsB ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [ dispatchGroupsState ]);
|
||||||
|
|
||||||
|
CreateMessageHook(GroupBadgePartsEvent, onGroupBadgePartsEvent);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
@ -1,11 +1,50 @@
|
|||||||
import { FC } from 'react';
|
import { GroupBadgePartsComposer, ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||||
import { GroupInformationBoxView } from './views/information-standalone/GroupInformationStandaloneView';
|
import { FC, useCallback, useEffect, useReducer } from 'react';
|
||||||
|
import { AddEventLinkTracker, RemoveLinkEventTracker } from '../../api';
|
||||||
|
import { SendMessageHook } from '../../hooks';
|
||||||
|
import { GroupsContextProvider } from './context/GroupsContext';
|
||||||
|
import { GroupsReducer, initialGroups } from './context/GroupsContext.types';
|
||||||
|
import { GroupsMessageHandler } from './GroupsMessageHandler';
|
||||||
|
import { GroupInformationStandaloneView } from './views/information-standalone/GroupInformationStandaloneView';
|
||||||
|
|
||||||
export const GroupsView: FC<{}> = props =>
|
export const GroupsView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
|
const [ groupsState, dispatchGroupsState ] = useReducer(GroupsReducer, initialGroups);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
SendMessageHook(new GroupBadgePartsComposer());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const linkReceived = useCallback((url: string) =>
|
||||||
|
{
|
||||||
|
const parts = url.split('/');
|
||||||
|
|
||||||
|
if(parts.length < 2) return;
|
||||||
|
|
||||||
|
switch(parts[1])
|
||||||
|
{
|
||||||
|
case 'create':
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const linkTracker: ILinkEventTracker = {
|
||||||
|
linkReceived,
|
||||||
|
eventUrlPrefix: 'groups/'
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEventLinkTracker(linkTracker);
|
||||||
|
|
||||||
|
return () => RemoveLinkEventTracker(linkTracker);
|
||||||
|
}, [ linkReceived ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<GroupsContextProvider value={ { groupsState, dispatchGroupsState } }>
|
||||||
<GroupInformationBoxView />
|
<GroupsMessageHandler />
|
||||||
</>
|
<GroupInformationStandaloneView />
|
||||||
|
</GroupsContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
14
src/views/groups/context/GroupsContext.tsx
Normal file
14
src/views/groups/context/GroupsContext.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { createContext, FC, useContext } from 'react';
|
||||||
|
import { GroupsContextProps, IGroupsContext } from './GroupsContext.types';
|
||||||
|
|
||||||
|
const GroupsContext = createContext<IGroupsContext>({
|
||||||
|
groupsState: null,
|
||||||
|
dispatchGroupsState: null
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GroupsContextProvider: FC<GroupsContextProps> = props =>
|
||||||
|
{
|
||||||
|
return <GroupsContext.Provider value={ props.value }>{ props.children }</GroupsContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGroupsContext = () => useContext(GroupsContext);
|
61
src/views/groups/context/GroupsContext.types.ts
Normal file
61
src/views/groups/context/GroupsContext.types.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Dispatch, ProviderProps, Reducer } from 'react';
|
||||||
|
|
||||||
|
export interface IGroupsContext
|
||||||
|
{
|
||||||
|
groupsState: IGroupsState;
|
||||||
|
dispatchGroupsState: Dispatch<IGroupsAction>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GroupsContextProps extends ProviderProps<IGroupsContext>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGroupsState
|
||||||
|
{
|
||||||
|
badgeBases: Map<number, string[]>;
|
||||||
|
badgeSymbols: Map<number, string[]>;
|
||||||
|
badgePartColors: Map<number, string>;
|
||||||
|
groupColorsA: Map<number, string>;
|
||||||
|
groupColorsB: Map<number, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGroupsAction
|
||||||
|
{
|
||||||
|
type: string;
|
||||||
|
payload: {
|
||||||
|
arrayMaps?: Map<number, string[]>[];
|
||||||
|
stringMaps?: Map<number, string>[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GroupsActions
|
||||||
|
{
|
||||||
|
public static SET_BADGE_PARTS: string = 'GA_SET_BADGE_PARTS';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialGroups: IGroupsState = {
|
||||||
|
badgeBases: null,
|
||||||
|
badgeSymbols: null,
|
||||||
|
badgePartColors: null,
|
||||||
|
groupColorsA: null,
|
||||||
|
groupColorsB: null
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GroupsReducer: Reducer<IGroupsState, IGroupsAction> = (state, action) =>
|
||||||
|
{
|
||||||
|
switch(action.type)
|
||||||
|
{
|
||||||
|
case GroupsActions.SET_BADGE_PARTS: {
|
||||||
|
const badgeBases = (action.payload.arrayMaps[0] || state.badgeBases || null);
|
||||||
|
const badgeSymbols = (action.payload.arrayMaps[1] || state.badgeSymbols || null);
|
||||||
|
const badgePartColors = (action.payload.stringMaps[0] || state.badgePartColors || null);
|
||||||
|
const groupColorsA = (action.payload.stringMaps[1] || state.groupColorsA || null);
|
||||||
|
const groupColorsB = (action.payload.stringMaps[2] || state.groupColorsB || null);
|
||||||
|
|
||||||
|
return { ...state, badgeBases, badgeSymbols, badgePartColors, groupColorsA, groupColorsB };
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ import { CreateMessageHook } from '../../../../hooks';
|
|||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||||
import { GroupInformationView } from '../information/GroupInformationView';
|
import { GroupInformationView } from '../information/GroupInformationView';
|
||||||
|
|
||||||
export const GroupInformationBoxView: FC<{}> = props =>
|
export const GroupInformationStandaloneView: FC<{}> = props =>
|
||||||
{
|
{
|
||||||
const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null);
|
const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null);
|
||||||
|
|
||||||
@ -15,10 +15,9 @@ export const GroupInformationBoxView: FC<{}> = props =>
|
|||||||
|
|
||||||
if(!parser.flag) return;
|
if(!parser.flag) return;
|
||||||
|
|
||||||
if(groupInformation) setGroupInformation(null);
|
setGroupInformation(null);
|
||||||
|
|
||||||
setGroupInformation(parser);
|
setGroupInformation(parser);
|
||||||
}, [ groupInformation ]);
|
}, []);
|
||||||
|
|
||||||
CreateMessageHook(GroupInformationEvent, onGroupInformationEvent);
|
CreateMessageHook(GroupInformationEvent, onGroupInformationEvent);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { GroupDeleteComposer, GroupInformationComposer, GroupJoinComposer, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
import { GroupDeleteComposer, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback } from 'react';
|
import { FC, useCallback } from 'react';
|
||||||
import { CreateLinkEvent, GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../../api';
|
import { CreateLinkEvent, GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../../api';
|
||||||
|
import { TryJoinGroup } from '../../../../api/groups/TryJoinGroup';
|
||||||
import { SendMessageHook } from '../../../../hooks';
|
import { SendMessageHook } from '../../../../hooks';
|
||||||
import { CatalogPageName } from '../../../catalog/common/CatalogPageName';
|
import { CatalogPageName } from '../../../catalog/common/CatalogPageName';
|
||||||
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
|
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
|
||||||
@ -12,18 +13,16 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
|||||||
{
|
{
|
||||||
const { groupInformation = null, onClose = null } = props;
|
const { groupInformation = null, onClose = null } = props;
|
||||||
|
|
||||||
const tryJoinGroup = useCallback(() =>
|
const joinGroup = useCallback(() =>
|
||||||
{
|
{
|
||||||
if(!groupInformation) return;
|
if(!groupInformation) return;
|
||||||
|
|
||||||
SendMessageHook(new GroupJoinComposer(groupInformation.id));
|
TryJoinGroup(groupInformation.id);
|
||||||
SendMessageHook(new GroupInformationComposer(groupInformation.id, false));
|
|
||||||
}, [ groupInformation ]);
|
}, [ groupInformation ]);
|
||||||
|
|
||||||
const tryLeaveGroup = useCallback(() =>
|
const leaveGroup = useCallback(() =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
||||||
SendMessageHook(new GroupInformationComposer(groupInformation.id, false));
|
|
||||||
if(onClose) onClose();
|
if(onClose) onClose();
|
||||||
}, [ groupInformation, onClose ]);
|
}, [ groupInformation, onClose ]);
|
||||||
|
|
||||||
@ -67,10 +66,10 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
|||||||
{
|
{
|
||||||
if(groupInformation.type === GroupType.PRIVATE && groupInformation.membershipType === GroupMembershipType.NOT_MEMBER) return;
|
if(groupInformation.type === GroupType.PRIVATE && groupInformation.membershipType === GroupMembershipType.NOT_MEMBER) return;
|
||||||
|
|
||||||
if(groupInformation.membershipType === GroupMembershipType.MEMBER) return tryLeaveGroup();
|
if(groupInformation.membershipType === GroupMembershipType.MEMBER) return leaveGroup();
|
||||||
|
|
||||||
return tryJoinGroup();
|
return joinGroup();
|
||||||
}, [ groupInformation, tryLeaveGroup, tryJoinGroup ]);
|
}, [ groupInformation, leaveGroup, joinGroup ]);
|
||||||
|
|
||||||
const handleAction = useCallback((action: string) =>
|
const handleAction = useCallback((action: string) =>
|
||||||
{
|
{
|
||||||
|
@ -3,5 +3,6 @@ import { GroupInformationParser } from '@nitrots/nitro-renderer';
|
|||||||
export interface GroupInformationViewProps
|
export interface GroupInformationViewProps
|
||||||
{
|
{
|
||||||
groupInformation: GroupInformationParser;
|
groupInformation: GroupInformationParser;
|
||||||
|
onJoin?: () => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,9 @@ export const GroupRoomInformationView: FC<{}> = props =>
|
|||||||
|
|
||||||
const getButtonText = useCallback(() =>
|
const getButtonText = useCallback(() =>
|
||||||
{
|
{
|
||||||
if(groupInformation.type === GroupType.PRIVATE) return '';
|
if(isRealOwner()) return 'group.manage';
|
||||||
|
|
||||||
if(isRealOwner()) return 'group.youareowner';
|
if(groupInformation.type === GroupType.PRIVATE) return '';
|
||||||
|
|
||||||
if(groupInformation.membershipType === GroupMembershipType.MEMBER) return 'group.leave';
|
if(groupInformation.membershipType === GroupMembershipType.MEMBER) return 'group.leave';
|
||||||
|
|
||||||
@ -112,8 +112,8 @@ export const GroupRoomInformationView: FC<{}> = props =>
|
|||||||
{ groupInformation.title }
|
{ groupInformation.title }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ groupInformation.type !== GroupType.PRIVATE && !isRealOwner() &&
|
{ (groupInformation.type !== GroupType.PRIVATE || isRealOwner()) &&
|
||||||
<button className="btn btn-sm btn-primary w-100 mt-1" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING || isRealOwner() } onClick={ handleButtonClick }>
|
<button className="btn btn-sm btn-primary w-100 mt-1" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING } onClick={ handleButtonClick }>
|
||||||
{ LocalizeText(getButtonText()) }
|
{ LocalizeText(getButtonText()) }
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { RoomMuteComposer, RoomSettingsComposer, RoomStaffPickComposer, SecurityLevel, UserHomeRoomComposer } from '@nitrots/nitro-renderer';
|
import { RoomMuteComposer, RoomSettingsComposer, RoomStaffPickComposer, SecurityLevel, UserHomeRoomComposer } from '@nitrots/nitro-renderer';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { GetConfiguration, GetSessionDataManager, LocalizeText } from '../../../../api';
|
import { GetConfiguration, GetGroupInformation, GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||||
import { NavigatorEvent } from '../../../../events';
|
import { NavigatorEvent } from '../../../../events';
|
||||||
import { RoomWidgetThumbnailEvent } from '../../../../events/room-widgets/thumbnail';
|
import { RoomWidgetThumbnailEvent } from '../../../../events/room-widgets/thumbnail';
|
||||||
import { dispatchUiEvent } from '../../../../hooks/events';
|
import { dispatchUiEvent } from '../../../../hooks/events';
|
||||||
@ -82,6 +82,7 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
|
|||||||
dispatchUiEvent(new RoomWidgetThumbnailEvent(RoomWidgetThumbnailEvent.TOGGLE_THUMBNAIL));
|
dispatchUiEvent(new RoomWidgetThumbnailEvent(RoomWidgetThumbnailEvent.TOGGLE_THUMBNAIL));
|
||||||
return;
|
return;
|
||||||
case 'open_group_info':
|
case 'open_group_info':
|
||||||
|
GetGroupInformation(roomInfoData.enteredGuestRoom.habboGroupId);
|
||||||
return;
|
return;
|
||||||
case 'toggle_room_link':
|
case 'toggle_room_link':
|
||||||
dispatchUiEvent(new NavigatorEvent(NavigatorEvent.TOGGLE_ROOM_LINK));
|
dispatchUiEvent(new NavigatorEvent(NavigatorEvent.TOGGLE_ROOM_LINK));
|
||||||
@ -137,7 +138,7 @@ export const NavigatorRoomInfoView: FC<NavigatorRoomInfoViewProps> = props =>
|
|||||||
</div>
|
</div>
|
||||||
<div>{ roomInfoData.enteredGuestRoom.description }</div>
|
<div>{ roomInfoData.enteredGuestRoom.description }</div>
|
||||||
<div className="room-thumbnail border mt-1 mb-2">
|
<div className="room-thumbnail border mt-1 mb-2">
|
||||||
<i className="icon icon-camera-small position-absolute b-0 r-0 m-1 cursor-pointer" onClick={ () => processAction('open_room_thumbnail_camera') } />
|
{ hasPermission('settings') && <i className="icon icon-camera-small position-absolute b-0 r-0 m-1 cursor-pointer" onClick={ () => processAction('open_room_thumbnail_camera') } /> }
|
||||||
{ roomThumbnail && <img alt="" src={ roomThumbnail } /> }
|
{ roomThumbnail && <img alt="" src={ roomThumbnail } /> }
|
||||||
</div>
|
</div>
|
||||||
{ roomInfoData.enteredGuestRoom.habboGroupId > 0 && <div className="d-flex align-items-center mb-2 cursor-pointer" onClick={ () => processAction('open_group_info') }>
|
{ roomInfoData.enteredGuestRoom.habboGroupId > 0 && <div className="d-flex align-items-center mb-2 cursor-pointer" onClick={ () => processAction('open_group_info') }>
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { ContextMenuEnum, RoomEngineTriggerWidgetEvent, RoomObjectCategory } from '@nitrots/nitro-renderer';
|
import { ContextMenuEnum, FurnitureGroupInfoComposer, GroupFurniContextMenuInfoMessageParser, RoomEngineTriggerWidgetEvent, RoomObjectCategory, RoomObjectVariable } from '@nitrots/nitro-renderer';
|
||||||
|
import { GroupFurniContextMenuInfoMessageEvent } from '@nitrots/nitro-renderer/src/nitro/communication/messages/incoming/room/furniture/GroupFurniContextMenuInfoMessageEvent';
|
||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { GetRoomEngine, IsOwnerOfFurniture, LocalizeText, RoomWidgetFurniActionMessage } from '../../../../../api';
|
import { GetRoomEngine, IsOwnerOfFurniture, LocalizeText, RoomWidgetFurniActionMessage, TryVisitRoom } from '../../../../../api';
|
||||||
|
import { TryJoinGroup } from '../../../../../api/groups/TryJoinGroup';
|
||||||
|
import { CreateMessageHook, SendMessageHook } from '../../../../../hooks';
|
||||||
import { useRoomEngineEvent } from '../../../../../hooks/events';
|
import { useRoomEngineEvent } from '../../../../../hooks/events';
|
||||||
import { useRoomContext } from '../../../context/RoomContext';
|
import { useRoomContext } from '../../../context/RoomContext';
|
||||||
import { ContextMenuView } from '../../context-menu/ContextMenuView';
|
import { ContextMenuView } from '../../context-menu/ContextMenuView';
|
||||||
@ -18,6 +21,9 @@ export const FurnitureContextMenuView: FC<{}> = props =>
|
|||||||
const [ mode, setMode ] = useState<string>(null);
|
const [ mode, setMode ] = useState<string>(null);
|
||||||
const [ confirmMode, setConfirmMode ] = useState<string>(null);
|
const [ confirmMode, setConfirmMode ] = useState<string>(null);
|
||||||
const [ confirmingObjectId, setConfirmingObjectId ] = useState(-1);
|
const [ confirmingObjectId, setConfirmingObjectId ] = useState(-1);
|
||||||
|
const [ groupData, setGroupData ] = useState<GroupFurniContextMenuInfoMessageParser>(null);
|
||||||
|
const [ isGroupMember, setIsGroupMember ] = useState<boolean>(false);
|
||||||
|
|
||||||
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
const { roomSession = null, widgetHandler = null } = useRoomContext();
|
||||||
|
|
||||||
const close = useCallback(() =>
|
const close = useCallback(() =>
|
||||||
@ -71,6 +77,9 @@ export const FurnitureContextMenuView: FC<{}> = props =>
|
|||||||
case ContextMenuEnum.PURCHASABLE_CLOTHING:
|
case ContextMenuEnum.PURCHASABLE_CLOTHING:
|
||||||
if(IsOwnerOfFurniture(object)) setMode(ContextMenuEnum.PURCHASABLE_CLOTHING);
|
if(IsOwnerOfFurniture(object)) setMode(ContextMenuEnum.PURCHASABLE_CLOTHING);
|
||||||
return;
|
return;
|
||||||
|
case ContextMenuEnum.GROUP_FURNITURE:
|
||||||
|
SendMessageHook(new FurnitureGroupInfoComposer(object.id, object.model.getValue<number>(RoomObjectVariable.FURNITURE_GUILD_CUSTOMIZED_GUILD_ID)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -85,6 +94,18 @@ export const FurnitureContextMenuView: FC<{}> = props =>
|
|||||||
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_MONSTERPLANT_SEED_PLANT_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
|
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_MONSTERPLANT_SEED_PLANT_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
|
||||||
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PURCHASABLE_CLOTHING_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
|
useRoomEngineEvent(RoomEngineTriggerWidgetEvent.REQUEST_PURCHASABLE_CLOTHING_CONFIRMATION_DIALOG, onRoomEngineTriggerWidgetEvent);
|
||||||
|
|
||||||
|
const onGroupFurniContextMenuInfoMessageEvent = useCallback((event: GroupFurniContextMenuInfoMessageEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setGroupData(null);
|
||||||
|
setGroupData(parser);
|
||||||
|
setIsGroupMember(parser.userIsMember);
|
||||||
|
setMode(ContextMenuEnum.GROUP_FURNITURE);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
CreateMessageHook(GroupFurniContextMenuInfoMessageEvent, onGroupFurniContextMenuInfoMessageEvent);
|
||||||
|
|
||||||
const processAction = useCallback((name: string) =>
|
const processAction = useCallback((name: string) =>
|
||||||
{
|
{
|
||||||
if(name)
|
if(name)
|
||||||
@ -105,11 +126,18 @@ export const FurnitureContextMenuView: FC<{}> = props =>
|
|||||||
setConfirmMode(PURCHASABLE_CLOTHING_CONFIRMATION);
|
setConfirmMode(PURCHASABLE_CLOTHING_CONFIRMATION);
|
||||||
setConfirmingObjectId(objectId);
|
setConfirmingObjectId(objectId);
|
||||||
break;
|
break;
|
||||||
|
case 'join_group':
|
||||||
|
TryJoinGroup(groupData.guildId);
|
||||||
|
setIsGroupMember(true);
|
||||||
|
return;
|
||||||
|
case 'go_to_group_homeroom':
|
||||||
|
if(groupData) TryVisitRoom(groupData.guildHomeRoomId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close();
|
close();
|
||||||
}, [ roomSession, widgetHandler, objectId, close ]);
|
}, [ roomSession, widgetHandler, objectId, groupData, close ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -153,6 +181,18 @@ export const FurnitureContextMenuView: FC<{}> = props =>
|
|||||||
{ LocalizeText('widget.generic_usable.button.use') }
|
{ LocalizeText('widget.generic_usable.button.use') }
|
||||||
</ContextMenuListItemView>
|
</ContextMenuListItemView>
|
||||||
</> }
|
</> }
|
||||||
|
{ (mode === ContextMenuEnum.GROUP_FURNITURE) && groupData &&
|
||||||
|
<>
|
||||||
|
<ContextMenuHeaderView>
|
||||||
|
{ groupData.guildName }
|
||||||
|
</ContextMenuHeaderView>
|
||||||
|
{ !isGroupMember && <ContextMenuListItemView onClick={ event => processAction('join_group') }>
|
||||||
|
{ LocalizeText('widget.furniture.button.join.group') }
|
||||||
|
</ContextMenuListItemView> }
|
||||||
|
<ContextMenuListItemView onClick={ event => processAction('go_to_group_homeroom') }>
|
||||||
|
{ LocalizeText('widget.furniture.button.go.to.group.home.room') }
|
||||||
|
</ContextMenuListItemView>
|
||||||
|
</> }
|
||||||
</ContextMenuView> }
|
</ContextMenuView> }
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { CrackableDataType, RoomControllerLevel, RoomObjectCategory, RoomObjectVariable, RoomWidgetEnumItemExtradataParameter, RoomWidgetFurniInfoUsagePolicyEnum, SetObjectDataMessageComposer, StringDataType, UserProfileComposer } from '@nitrots/nitro-renderer';
|
import { CrackableDataType, GroupInformationComposer, GroupInformationEvent, RoomControllerLevel, RoomObjectCategory, RoomObjectVariable, RoomWidgetEnumItemExtradataParameter, RoomWidgetFurniInfoUsagePolicyEnum, SetObjectDataMessageComposer, StringDataType } from '@nitrots/nitro-renderer';
|
||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { CreateLinkEvent, GetRoomEngine, LocalizeText, RoomWidgetFurniActionMessage } from '../../../../../../api';
|
import { CreateLinkEvent, GetGroupInformation, GetRoomEngine, LocalizeText, RoomWidgetFurniActionMessage } from '../../../../../../api';
|
||||||
import { SendMessageHook } from '../../../../../../hooks';
|
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks';
|
||||||
import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView';
|
import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView';
|
||||||
import { LimitedEditionCompactPlateView } from '../../../../../shared/limited-edition/compact-plate/LimitedEditionCompactPlateView';
|
import { LimitedEditionCompactPlateView } from '../../../../../shared/limited-edition/compact-plate/LimitedEditionCompactPlateView';
|
||||||
import { RarityLevelView } from '../../../../../shared/rarity-level/RarityLevelView';
|
import { RarityLevelView } from '../../../../../shared/rarity-level/RarityLevelView';
|
||||||
@ -31,6 +31,7 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
|
|||||||
const [ crackableHits, setCrackableHits ] = useState(0);
|
const [ crackableHits, setCrackableHits ] = useState(0);
|
||||||
const [ crackableTarget, setCrackableTarget ] = useState(0);
|
const [ crackableTarget, setCrackableTarget ] = useState(0);
|
||||||
const [ godMode, setGodMode ] = useState(false);
|
const [ godMode, setGodMode ] = useState(false);
|
||||||
|
const [ groupName, setGroupName ] = useState<string>(null);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -128,12 +129,23 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
|
|||||||
setCrackableHits(crackableHits);
|
setCrackableHits(crackableHits);
|
||||||
setCrackableTarget(crackableTarget);
|
setCrackableTarget(crackableTarget);
|
||||||
setGodMode(godMode);
|
setGodMode(godMode);
|
||||||
|
setGroupName(null);
|
||||||
|
|
||||||
|
if(furniData.groupId) SendMessageHook(new GroupInformationComposer(furniData.groupId, false));
|
||||||
}, [ roomSession, furniData ]);
|
}, [ roomSession, furniData ]);
|
||||||
|
|
||||||
const openFurniGroupInfo = useCallback(() =>
|
const onGroupInformationEvent = useCallback((event: GroupInformationEvent) =>
|
||||||
{
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
}, []);
|
if(!furniData || furniData.groupId !== parser.id || parser.flag) return;
|
||||||
|
|
||||||
|
if(groupName) setGroupName(null);
|
||||||
|
|
||||||
|
setGroupName(parser.title);
|
||||||
|
}, [ furniData, groupName ]);
|
||||||
|
|
||||||
|
CreateMessageHook(GroupInformationEvent, onGroupInformationEvent);
|
||||||
|
|
||||||
const onFurniSettingChange = useCallback((index: number, value: string) =>
|
const onFurniSettingChange = useCallback((index: number, value: string) =>
|
||||||
{
|
{
|
||||||
@ -223,9 +235,13 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
|
|||||||
widgetHandler.processWidgetMessage(new RoomWidgetFurniActionMessage(messageType, furniData.id, furniData.category, furniData.purchaseOfferId, objectData));
|
widgetHandler.processWidgetMessage(new RoomWidgetFurniActionMessage(messageType, furniData.id, furniData.category, furniData.purchaseOfferId, objectData));
|
||||||
}, [ widgetHandler, furniData, pickupMode, customKeys, customValues, getFurniSettingsAsString ]);
|
}, [ widgetHandler, furniData, pickupMode, customKeys, customValues, getFurniSettingsAsString ]);
|
||||||
|
|
||||||
const openProfile = useCallback(() =>
|
const getGroupBadgeCode = useCallback(() =>
|
||||||
{
|
{
|
||||||
SendMessageHook(new UserProfileComposer(furniData.ownerId));
|
const stringDataType = (furniData.stuffData as StringDataType);
|
||||||
|
|
||||||
|
if(!stringDataType || !(stringDataType instanceof StringDataType)) return null;
|
||||||
|
|
||||||
|
return stringDataType.getValue(2);
|
||||||
}, [ furniData ]);
|
}, [ furniData ]);
|
||||||
|
|
||||||
if(!furniData) return null;
|
if(!furniData) return null;
|
||||||
@ -258,11 +274,12 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
|
|||||||
<hr className="m-0 my-1" />
|
<hr className="m-0 my-1" />
|
||||||
<div className="small text-wrap">{ LocalizeText('infostand.crackable_furni.hits_remaining', [ 'hits', 'target' ], [ crackableHits.toString(), crackableTarget.toString() ]) }</div>
|
<div className="small text-wrap">{ LocalizeText('infostand.crackable_furni.hits_remaining', [ 'hits', 'target' ], [ crackableHits.toString(), crackableTarget.toString() ]) }</div>
|
||||||
</> }
|
</> }
|
||||||
{ (furniData.groupId > 0) &&
|
{ furniData.groupId > 0 &&
|
||||||
<>
|
<>
|
||||||
<hr className="m-0 my-1" />
|
<hr className="m-0 my-1" />
|
||||||
<div className="badge badge-secondary mb-0" onClick={ openFurniGroupInfo }>
|
<div className="d-flex align-items-center cursor-pointer text-decoration-underline gap-2" onClick={ () => GetGroupInformation(furniData.groupId) }>
|
||||||
<BadgeImageView badgeCode={ (furniData.stuffData as StringDataType).getValue(2) } />
|
<BadgeImageView badgeCode={ getGroupBadgeCode() } isGroup={ true } />
|
||||||
|
<div>{ groupName }</div>
|
||||||
</div>
|
</div>
|
||||||
</> }
|
</> }
|
||||||
{ godMode &&
|
{ godMode &&
|
||||||
|
Loading…
Reference in New Issue
Block a user