mirror of
https://github.com/duckietm/Nitro-Cool-UI.git
synced 2025-06-21 22:36:58 +00:00
⚠️ WiP Group badges
This commit is contained in:
parent
313c814b1e
commit
2269b20f35
@ -1,4 +1,3 @@
|
||||
|
||||
export class GroupBadgePart
|
||||
{
|
||||
public static BASE: string = 'b';
|
||||
|
@ -47,15 +47,10 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
|
||||
|
||||
newStyle.backgroundImage = `url(${ badgeUrl })`;
|
||||
|
||||
// Remove inline width and height to let SCSS control the size
|
||||
// newStyle.width = imageElement.width;
|
||||
// newStyle.height = imageElement.height;
|
||||
|
||||
if(scale !== 1)
|
||||
{
|
||||
newStyle.transform = `scale(${ scale })`;
|
||||
if(!(scale % 1)) newStyle.imageRendering = 'pixelated';
|
||||
// If scaling, adjust the dimensions in SCSS instead
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +106,8 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
|
||||
// Fallback: Try fetching directly from session data
|
||||
let texture = isGroup ? GetSessionDataManager().getGroupBadgeImage(badgeCode) : GetSessionDataManager().getBadgeImage(badgeCode);
|
||||
|
||||
console.log('LayoutBadgeImageView: getGroupBadgeImage result', { badgeCode, texture: texture ? 'exists' : 'null', isGroup });
|
||||
|
||||
if(texture)
|
||||
{
|
||||
const sprite = new NitroSprite(texture);
|
||||
@ -162,6 +159,12 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
|
||||
return null; // Optionally render a loading placeholder
|
||||
}
|
||||
|
||||
if(!imageElement)
|
||||
{
|
||||
console.log('LayoutBadgeImageView: Rendering fallback placeholder', { badgeCode, isGroup });
|
||||
return <Base classNames={ getClassNames } style={ { ...style, backgroundColor: '#d3d3d3' } } { ...rest } />; // Gray square as fallback
|
||||
}
|
||||
|
||||
console.log('LayoutBadgeImageView: Rendering badge', { badgeCode, hasImage: !!imageElement, isGroup });
|
||||
|
||||
return (
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GroupPurchasedEvent, GroupSettingsComposer, ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||
import { GroupPurchasedEvent, ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { AddEventLinkTracker, RemoveLinkEventTracker, SendMessageComposer, TryVisitRoom } from '../../api';
|
||||
import { useGroup, useMessageEvent } from '../../hooks';
|
||||
@ -10,8 +10,15 @@ import { GroupMembersView } from './views/GroupMembersView';
|
||||
export const GroupsView: FC<{}> = props =>
|
||||
{
|
||||
const [ isCreatorVisible, setCreatorVisible ] = useState<boolean>(false);
|
||||
const [ currentBadgeCode, setCurrentBadgeCode ] = useState<string>(''); // State to hold the current badge code
|
||||
const {} = useGroup();
|
||||
|
||||
// Callback to receive the updated badge code from GroupCreatorView
|
||||
const handleBadgeCodeUpdate = (badgeCode: string) => {
|
||||
console.log('GroupsView: Received updated badge code', { badgeCode });
|
||||
setCurrentBadgeCode(badgeCode);
|
||||
};
|
||||
|
||||
useMessageEvent<GroupPurchasedEvent>(GroupPurchasedEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
@ -53,11 +60,11 @@ export const GroupsView: FC<{}> = props =>
|
||||
return (
|
||||
<>
|
||||
{ isCreatorVisible &&
|
||||
<GroupCreatorView onClose={ () => setCreatorVisible(false) } /> }
|
||||
<GroupCreatorView onClose={ () => setCreatorVisible(false) } onBadgeCodeUpdate={ handleBadgeCodeUpdate } /> }
|
||||
{ !isCreatorVisible &&
|
||||
<GroupManagerView /> }
|
||||
<GroupMembersView />
|
||||
<GroupInformationStandaloneView />
|
||||
<GroupInformationStandaloneView badgeCode={ currentBadgeCode } isCreating={ isCreatorVisible } />
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { Dispatch, FC, SetStateAction, useState } from 'react';
|
||||
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react';
|
||||
import { FaPlus, FaTimes } from 'react-icons/fa';
|
||||
import { GroupBadgePart } from '../../../api';
|
||||
import { Base, Column, Flex, Grid, LayoutBadgeImageView } from '../../../common';
|
||||
@ -6,15 +6,16 @@ import { useGroup } from '../../../hooks';
|
||||
|
||||
interface GroupBadgeCreatorViewProps
|
||||
{
|
||||
badgeParts: GroupBadgePart[];
|
||||
badgeParts: GroupBadgePart[] | null;
|
||||
setBadgeParts: Dispatch<SetStateAction<GroupBadgePart[]>>;
|
||||
onBadgeCodeUpdate?: (badgeCode: string) => void;
|
||||
}
|
||||
|
||||
const POSITIONS: number[] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
|
||||
|
||||
export const GroupBadgeCreatorView: FC<GroupBadgeCreatorViewProps> = props =>
|
||||
{
|
||||
const { badgeParts = [], setBadgeParts = null } = props;
|
||||
const { badgeParts = [], setBadgeParts = null, onBadgeCodeUpdate = null } = props;
|
||||
const [ selectedIndex, setSelectedIndex ] = useState<number>(-1);
|
||||
const { groupCustomize = null } = useGroup();
|
||||
|
||||
@ -27,23 +28,61 @@ export const GroupBadgeCreatorView: FC<GroupBadgeCreatorViewProps> = props =>
|
||||
setBadgeParts(newBadgeParts);
|
||||
|
||||
if(property === 'key') setSelectedIndex(-1);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to generate a full group badge code with all parts
|
||||
const getFullBadgeCode = (index: number): string => {
|
||||
if (!badgeParts) return '';
|
||||
|
||||
let badgeCode = '';
|
||||
|
||||
badgeParts.forEach(part => {
|
||||
if (part.code && part.code.length > 0) {
|
||||
badgeCode += part.code;
|
||||
}
|
||||
// Exclude unset symbols (key: 0) from the badge code
|
||||
});
|
||||
|
||||
console.log('GroupBadgeCreatorView: Computed full badge code', { badgeCode });
|
||||
|
||||
return badgeCode;
|
||||
};
|
||||
|
||||
// Debug the contents of badgeBases and badgeSymbols
|
||||
console.log('GroupBadgeCreatorView: badgeBases', groupCustomize?.badgeBases);
|
||||
console.log('GroupBadgeCreatorView: badgeSymbols', groupCustomize?.badgeSymbols);
|
||||
|
||||
// Compute the full badge code
|
||||
const fullBadgeCode = getFullBadgeCode(0);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('GroupBadgeCreatorView: useEffect triggered', { fullBadgeCode, hasOnBadgeCodeUpdate: !!onBadgeCodeUpdate });
|
||||
if (onBadgeCodeUpdate && fullBadgeCode) {
|
||||
console.log('GroupBadgeCreatorView: Propagating badge code to parent', { fullBadgeCode });
|
||||
onBadgeCodeUpdate(fullBadgeCode);
|
||||
}
|
||||
}, [fullBadgeCode, onBadgeCodeUpdate]);
|
||||
|
||||
// Early return after all hooks are called
|
||||
if (!badgeParts || !badgeParts.length) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ ((selectedIndex < 0) && badgeParts && (badgeParts.length > 0)) && badgeParts.map((part, index) =>
|
||||
{
|
||||
const badgeCode = badgeParts[index].code;
|
||||
console.log('GroupBadgeCreatorView: Rendering badge part', { index, badgeCode, fullBadgeCode, part });
|
||||
|
||||
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) &&
|
||||
{ (badgeCode && badgeCode.length > 0) ? (
|
||||
<LayoutBadgeImageView badgeCode={ badgeCode } isGroup={ true } />
|
||||
) : (
|
||||
<Flex center className="badge-image group-badge">
|
||||
<FaPlus className="fa-icon" />
|
||||
</Flex> }
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
{ (part.type !== GroupBadgePart.BASE) &&
|
||||
<Grid gap={ 1 } columnCount={ 3 }>
|
||||
@ -71,13 +110,16 @@ export const GroupBadgeCreatorView: FC<GroupBadgeCreatorViewProps> = props =>
|
||||
</Column> }
|
||||
{ ((badgeParts[selectedIndex].type === GroupBadgePart.BASE) ? groupCustomize.badgeBases : groupCustomize.badgeSymbols).map((item, index) =>
|
||||
{
|
||||
const badgeCode = GroupBadgePart.getCode(badgeParts[selectedIndex].type, item.id, badgeParts[selectedIndex].color, 4);
|
||||
console.log('GroupBadgeCreatorView: Rendering template badge', { type: badgeParts[selectedIndex].type, id: item.id, badgeCode, color: badgeParts[selectedIndex].color, position: badgeParts[selectedIndex].position, item });
|
||||
|
||||
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 } />
|
||||
<LayoutBadgeImageView badgeCode={ badgeCode } isGroup={ true } />
|
||||
</Column>
|
||||
);
|
||||
}) }
|
||||
</Grid> }
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
@ -11,18 +11,20 @@ import { GroupTabIdentityView } from './tabs/GroupTabIdentityView';
|
||||
interface GroupCreatorViewProps
|
||||
{
|
||||
onClose: () => void;
|
||||
onBadgeCodeUpdate?: (badgeCode: string) => void; // Callback to propagate badge code to parent
|
||||
}
|
||||
|
||||
const TABS: number[] = [ 1, 2, 3, 4 ];
|
||||
|
||||
export const GroupCreatorView: FC<GroupCreatorViewProps> = props =>
|
||||
{
|
||||
const { onClose = null } = props;
|
||||
const { onClose = null, onBadgeCodeUpdate = null } = props;
|
||||
const [ currentTab, setCurrentTab ] = useState<number>(1);
|
||||
const [ closeAction, setCloseAction ] = useState<{ action: () => boolean }>(null);
|
||||
const [ groupData, setGroupData ] = useState<IGroupData>(null);
|
||||
const [ availableRooms, setAvailableRooms ] = useState<{ id: number, name: string }[]>(null);
|
||||
const [ purchaseCost, setPurchaseCost ] = useState<number>(0);
|
||||
const [ currentBadgeCode, setCurrentBadgeCode ] = useState<string>(''); // State to hold the current badge code
|
||||
|
||||
const onCloseClose = () =>
|
||||
{
|
||||
@ -85,6 +87,16 @@ export const GroupCreatorView: FC<GroupCreatorViewProps> = props =>
|
||||
setCurrentTab(value => (value === 4 ? value : value + 1));
|
||||
}
|
||||
|
||||
// Callback to receive the updated badge code from GroupTabBadgeView
|
||||
const handleBadgeCodeUpdate = (badgeCode: string) => {
|
||||
console.log('GroupCreatorView: Received updated badge code', { badgeCode });
|
||||
setCurrentBadgeCode(badgeCode);
|
||||
// Propagate the badge code to the parent
|
||||
if (onBadgeCodeUpdate) {
|
||||
onBadgeCodeUpdate(badgeCode);
|
||||
}
|
||||
};
|
||||
|
||||
useMessageEvent<GroupBuyDataEvent>(GroupBuyDataEvent, event =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
@ -143,7 +155,7 @@ export const GroupCreatorView: FC<GroupCreatorViewProps> = props =>
|
||||
{ (currentTab === 1) &&
|
||||
<GroupTabIdentityView groupData={ groupData } setGroupData={ setGroupData } setCloseAction={ setCloseAction } onClose={ null } isCreator={ true } availableRooms={ availableRooms } /> }
|
||||
{ (currentTab === 2) &&
|
||||
<GroupTabBadgeView groupData={ groupData } setGroupData={ setGroupData } setCloseAction={ setCloseAction } /> }
|
||||
<GroupTabBadgeView groupData={ groupData } setGroupData={ setGroupData } setCloseAction={ setCloseAction } onBadgeCodeUpdate={ handleBadgeCodeUpdate } /> }
|
||||
{ (currentTab === 3) &&
|
||||
<GroupTabColorsView groupData={ groupData } setGroupData={ setGroupData } setCloseAction={ setCloseAction } /> }
|
||||
{ (currentTab === 4) &&
|
||||
|
@ -5,24 +5,34 @@ import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../
|
||||
import { useMessageEvent } from '../../../hooks';
|
||||
import { GroupInformationView } from './GroupInformationView';
|
||||
|
||||
export const GroupInformationStandaloneView: FC<{}> = props =>
|
||||
interface GroupInformationStandaloneViewProps
|
||||
{
|
||||
badgeCode?: string;
|
||||
isCreating?: boolean;
|
||||
}
|
||||
|
||||
export const GroupInformationStandaloneView: FC<GroupInformationStandaloneViewProps> = props =>
|
||||
{
|
||||
const { badgeCode = null, isCreating = false } = props;
|
||||
const [ groupInformation, setGroupInformation ] = useState<GroupInformationParser>(null);
|
||||
|
||||
useMessageEvent<GroupInformationEvent>(GroupInformationEvent, event =>
|
||||
{
|
||||
// Skip updates during group creation
|
||||
if (isCreating) return;
|
||||
|
||||
const parser = event.getParser();
|
||||
|
||||
if((groupInformation && (groupInformation.id === parser.id)) || parser.flag) setGroupInformation(parser);
|
||||
});
|
||||
|
||||
if(!groupInformation) return null;
|
||||
if(!groupInformation && !isCreating) return null;
|
||||
|
||||
return (
|
||||
<NitroCardView className="nitro-group-information-standalone" theme="primary-slim">
|
||||
<NitroCardHeaderView headerText={ LocalizeText('group.window.title') } onCloseClick={ event => setGroupInformation(null) } />
|
||||
<NitroCardContentView>
|
||||
<GroupInformationView groupInformation={ groupInformation } onClose={ () => setGroupInformation(null) } />
|
||||
<GroupInformationView groupInformation={ groupInformation } onClose={ () => setGroupInformation(null) } badgeCode={ badgeCode } />
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
|
@ -11,11 +11,12 @@ interface GroupInformationViewProps extends GridProps
|
||||
groupInformation: GroupInformationParser;
|
||||
onJoin?: () => void;
|
||||
onClose?: () => void;
|
||||
badgeCode?: string; // Optional badge code prop
|
||||
}
|
||||
|
||||
export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
{
|
||||
const { groupInformation = null, onClose = null, overflow = 'hidden', ...rest } = props;
|
||||
const { groupInformation = null, onClose = null, badgeCode = null, overflow = 'hidden', ...rest } = props;
|
||||
const { showConfirm = null } = useNotification();
|
||||
|
||||
const isRealOwner = (groupInformation && (groupInformation.ownerName === GetSessionDataManager().userName));
|
||||
@ -99,11 +100,16 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
|
||||
if(!groupInformation) return null;
|
||||
|
||||
// Use badgeCode if provided (during group creation), otherwise fall back to groupInformation.badge
|
||||
const displayBadgeCode = badgeCode || groupInformation.badge;
|
||||
|
||||
return (
|
||||
<Grid overflow={ overflow } { ...rest }>
|
||||
<Column center size={ 3 } overflow="hidden">
|
||||
<Flex alignItems="center" overflow="hidden" className="group-badge">
|
||||
<LayoutBadgeImageView badgeCode={ groupInformation.badge } isGroup={ true } scale={ 2 } />
|
||||
{ displayBadgeCode && (
|
||||
<LayoutBadgeImageView badgeCode={ displayBadgeCode } isGroup={ true } scale={ 2 } />
|
||||
)}
|
||||
</Flex>
|
||||
<Column alignItems="center" gap={ 1 }>
|
||||
<Text small underline pointer onClick={ () => handleAction('members') }>{ LocalizeText('group.membercount', [ 'totalMembers' ], [ groupInformation.membersCount.toString() ]) }</Text>
|
||||
|
@ -11,13 +11,14 @@ interface GroupTabBadgeViewProps
|
||||
setCloseAction: Dispatch<SetStateAction<{ action: () => boolean }>>;
|
||||
groupData: IGroupData;
|
||||
setGroupData: Dispatch<SetStateAction<IGroupData>>;
|
||||
onBadgeCodeUpdate?: (badgeCode: string) => void;
|
||||
}
|
||||
|
||||
export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
|
||||
{
|
||||
const { groupData = null, setGroupData = null, setCloseAction = null, skipDefault = null } = props;
|
||||
const [ badgeParts, setBadgeParts ] = useState<GroupBadgePart[]>(null);
|
||||
const { groupData = null, setGroupData = null, setCloseAction = null, skipDefault = null, onBadgeCodeUpdate = null } = props;
|
||||
const { groupCustomize = null } = useGroup();
|
||||
const [ badgeParts, setBadgeParts ] = useState<GroupBadgePart[]>(groupData?.groupBadgeParts || []);
|
||||
|
||||
const getModifiedBadgeCode = () =>
|
||||
{
|
||||
@ -25,10 +26,17 @@ export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
|
||||
|
||||
let badgeCode = '';
|
||||
|
||||
badgeParts.forEach(part => (part.code && (badgeCode += part.code)));
|
||||
badgeParts.forEach(part => {
|
||||
if (part.code && part.code.length > 0) {
|
||||
badgeCode += part.code;
|
||||
}
|
||||
// Exclude unset symbols (key: 0) from the badge code
|
||||
});
|
||||
|
||||
console.log('GroupTabBadgeView: Computed badge code', { badgeCode, badgeParts });
|
||||
|
||||
return badgeCode;
|
||||
}
|
||||
};
|
||||
|
||||
const saveBadge = useCallback(() =>
|
||||
{
|
||||
@ -88,14 +96,14 @@ export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
console.log('GroupTabBadgeView: Setting badgeParts', { groupData, groupBadgeParts: groupData?.groupBadgeParts });
|
||||
if (groupData.groupId <= 0)
|
||||
{
|
||||
setBadgeParts(groupData.groupBadgeParts ? [ ...groupData.groupBadgeParts ] : null);
|
||||
|
||||
setBadgeParts(groupData.groupBadgeParts ? [ ...groupData.groupBadgeParts ] : []);
|
||||
return;
|
||||
}
|
||||
|
||||
setBadgeParts(groupData.groupBadgeParts);
|
||||
setBadgeParts(groupData.groupBadgeParts || []);
|
||||
}, [ groupData ]);
|
||||
|
||||
useEffect(() =>
|
||||
@ -106,14 +114,18 @@ export const GroupTabBadgeView: FC<GroupTabBadgeViewProps> = props =>
|
||||
}, [ setCloseAction, saveBadge ]);
|
||||
|
||||
return (
|
||||
<Grid overflow="hidden" gap={ 1 }>
|
||||
<Grid gap={ 1 } overflow="hidden">
|
||||
<Column size={ 2 }>
|
||||
<Flex center className="bg-muted rounded p-1">
|
||||
{ getModifiedBadgeCode() ? (
|
||||
<LayoutBadgeImageView badgeCode={ getModifiedBadgeCode() } isGroup={ true } />
|
||||
) : (
|
||||
<div style={{ width: 45, height: 45 }} /> // Placeholder to maintain layout
|
||||
)}
|
||||
</Flex>
|
||||
</Column>
|
||||
<Column size={ 10 } overflow="auto">
|
||||
<GroupBadgeCreatorView badgeParts={ badgeParts } setBadgeParts={ setBadgeParts } />
|
||||
<Column overflow="auto" size={ 10 }>
|
||||
<GroupBadgeCreatorView badgeParts={ badgeParts } setBadgeParts={ setBadgeParts } onBadgeCodeUpdate={ onBadgeCodeUpdate } />
|
||||
</Column>
|
||||
</Grid>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user