mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
fix(guild): show duplicated role in its final spot without flicker (#2109)
This commit is contained in:
1 parent
470e752fba
commit
82043ce2a8
2 files changed
+34
-12
No files matched your search
@@ -254,9 +254,16 @@ export async function updateVanityURL(guildId: string, code: string | null): Pro
|
||||
}
|
||||
}
|
||||
|
||||
export async function createRole(guildId: string, name: string): Promise<GuildRole> {
|
||||
export async function createRole(
|
||||
guildId: string,
|
||||
name: string,
|
||||
options?: {color?: number; permissions?: bigint},
|
||||
): Promise<GuildRole> {
|
||||
try {
|
||||
const response = await http.post<GuildRole>(Endpoints.GUILD_ROLES(guildId), {body: {name}});
|
||||
const body: {name: string; color?: number; permissions?: string} = {name};
|
||||
if (options?.color !== undefined) body.color = options.color;
|
||||
if (options?.permissions !== undefined) body.permissions = options.permissions.toString();
|
||||
const response = await http.post<GuildRole>(Endpoints.GUILD_ROLES(guildId), {body});
|
||||
logger.debug(`Created role "${name}" in guild ${guildId}`);
|
||||
return response.body;
|
||||
} catch (error) {
|
||||
|
||||
@@ -92,6 +92,7 @@ const GuildRolesTab: React.FC<{guildId: string}> = observer(({guildId}) => {
|
||||
const [mobileShowEditor, setMobileShowEditor] = useState(false);
|
||||
const [roleUpdates, setRoleUpdates] = useState<Map<string, RoleUpdate>>(new Map());
|
||||
const [pendingRoleOrder, setPendingRoleOrder] = useState<Array<string> | null>(null);
|
||||
const [optimisticRoleOrder, setOptimisticRoleOrder] = useState<Array<string> | null>(null);
|
||||
const [hoistOrderMode, setHoistOrderMode] = useState(false);
|
||||
const [pendingHoistOrder, setPendingHoistOrder] = useState<Array<string> | null>(null);
|
||||
const [permissionSearchQuery, setPermissionSearchQuery] = useState('');
|
||||
@@ -105,13 +106,16 @@ const GuildRolesTab: React.FC<{guildId: string}> = observer(({guildId}) => {
|
||||
if (!guild) return [];
|
||||
const rolesList = Object.values(guild.roles);
|
||||
const sorted = sortRolesByPosition(rolesList);
|
||||
if (pendingRoleOrder) {
|
||||
return pendingRoleOrder
|
||||
const order = pendingRoleOrder ?? optimisticRoleOrder;
|
||||
if (order) {
|
||||
const mapped = order
|
||||
.map((id: string) => sorted.find((r: GuildRole) => r.id === id))
|
||||
.filter((r): r is GuildRole => r != null);
|
||||
const missing = sorted.filter((r: GuildRole) => !order.includes(r.id));
|
||||
return [...mapped, ...missing];
|
||||
}
|
||||
return sorted;
|
||||
}, [guild, pendingRoleOrder]);
|
||||
}, [guild, pendingRoleOrder, optimisticRoleOrder]);
|
||||
useEffect(() => {
|
||||
if (!pendingRoleOrder || !guild) return;
|
||||
const sortedIds = sortRolesByPosition(Object.values(guild.roles)).map((role: GuildRole) => role.id);
|
||||
@@ -119,6 +123,13 @@ const GuildRolesTab: React.FC<{guildId: string}> = observer(({guildId}) => {
|
||||
const matches = pendingRoleOrder.every((id, index) => id === sortedIds[index]);
|
||||
if (matches) setPendingRoleOrder(null);
|
||||
}, [pendingRoleOrder, guild]);
|
||||
useEffect(() => {
|
||||
if (!optimisticRoleOrder || !guild) return;
|
||||
const sortedIds = sortRolesByPosition(Object.values(guild.roles)).map((role: GuildRole) => role.id);
|
||||
if (optimisticRoleOrder.length !== sortedIds.length) return;
|
||||
const matches = optimisticRoleOrder.every((id, index) => id === sortedIds[index]);
|
||||
if (matches) setOptimisticRoleOrder(null);
|
||||
}, [optimisticRoleOrder, guild]);
|
||||
const hoistedRoles = useMemo(() => {
|
||||
if (!guild) return [];
|
||||
const rolesList = Object.values(guild.roles).filter((role) => role.hoist && !role.isEveryone);
|
||||
@@ -357,18 +368,20 @@ const GuildRolesTab: React.FC<{guildId: string}> = observer(({guildId}) => {
|
||||
const grantablePermissions = sourceRole.permissions & currentUserPermissions;
|
||||
pendingRoleCreationRef.current = true;
|
||||
try {
|
||||
const createdRole = await GuildCommands.createRole(guild.id, copyName);
|
||||
await GuildCommands.updateRole(guild.id, createdRole.id, {
|
||||
const createdRole = await GuildCommands.createRole(guild.id, copyName, {
|
||||
color: sourceRole.color,
|
||||
hoist: sourceRole.hoist,
|
||||
mentionable: sourceRole.mentionable,
|
||||
permissions: grantablePermissions.toString(),
|
||||
permissions: grantablePermissions,
|
||||
});
|
||||
try {
|
||||
const orderedRoleIds = roles.map((role: GuildRole) => role.id);
|
||||
const orderedRoleIds = roles.map((role: GuildRole) => role.id).filter((id) => id !== createdRole.id);
|
||||
const sourceIndex = orderedRoleIds.indexOf(sourceRoleId);
|
||||
const insertIndex = sourceIndex === -1 ? orderedRoleIds.length : sourceIndex + 1;
|
||||
orderedRoleIds.splice(insertIndex, 0, createdRole.id);
|
||||
setOptimisticRoleOrder(orderedRoleIds);
|
||||
await GuildCommands.updateRole(guild.id, createdRole.id, {
|
||||
hoist: sourceRole.hoist,
|
||||
mentionable: sourceRole.mentionable,
|
||||
});
|
||||
try {
|
||||
const submittableRoleOrder = createSubmittableRoleOrderIds({
|
||||
guildId: guild.id,
|
||||
orderedRoleIds,
|
||||
@@ -384,10 +397,12 @@ const GuildRolesTab: React.FC<{guildId: string}> = observer(({guildId}) => {
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to position duplicated role in guild ${guild.id}:`, error);
|
||||
setOptimisticRoleOrder(null);
|
||||
}
|
||||
ToastCommands.createToast({type: 'success', children: <Trans>Role created successfully</Trans>});
|
||||
} catch (_error) {
|
||||
pendingRoleCreationRef.current = false;
|
||||
setOptimisticRoleOrder(null);
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<RoleCreateFailedModal data-flx="guild.guild-tabs.guild-roles-tab.handle-duplicate-role.role-create-failed-modal" />
|
||||
|
||||
Reference in new issue
Block a user