mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
feat(app): redesign discovery and align skeletons with rendered UI
This commit is contained in:
1 parent
e054aa96be
commit
98c40c6979
380 files changed
+50869
-32207
No files matched your search
+1
-1
@@ -54,10 +54,10 @@
|
||||
.stat {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--count-indicator-gap);
|
||||
}
|
||||
|
||||
.statDot {
|
||||
margin-right: 0.3rem;
|
||||
height: 0.5rem;
|
||||
width: 0.5rem;
|
||||
border-radius: 624.9375rem;
|
||||
|
||||
+8
-2
@@ -139,7 +139,10 @@ export const RoleSidebar: React.FC<RoleSidebarProps> = observer(
|
||||
backend={HTML5Backend}
|
||||
data-flx="guild.guild-tabs.guild-roles-tab.sidebar-content.dnd-provider"
|
||||
>
|
||||
<RoleDragAutoScroll listRef={listRef} />
|
||||
<RoleDragAutoScroll
|
||||
listRef={listRef}
|
||||
data-flx="guild.guild-tabs.guild-roles-tab.role-sidebar.role-drag-auto-scroll"
|
||||
/>
|
||||
{hoistedRoles.map((role, index) => {
|
||||
const roleWithUpdates = applyRoleUpdate(role, roleUpdates.get(role.id));
|
||||
return (
|
||||
@@ -232,7 +235,10 @@ export const RoleSidebar: React.FC<RoleSidebarProps> = observer(
|
||||
backend={HTML5Backend}
|
||||
data-flx="guild.guild-tabs.guild-roles-tab.sidebar-content.dnd-provider--2"
|
||||
>
|
||||
<RoleDragAutoScroll listRef={listRef} />
|
||||
<RoleDragAutoScroll
|
||||
listRef={listRef}
|
||||
data-flx="guild.guild-tabs.guild-roles-tab.role-sidebar.role-drag-auto-scroll--2"
|
||||
/>
|
||||
{roles.map((role: GuildRole, index) => {
|
||||
const roleWithUpdates = applyRoleUpdate(role, roleUpdates.get(role.id));
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import GatewayConnection from '@app/features/gateway/transport/GatewayConnection';
|
||||
import {makeAutoObservable} from 'mobx';
|
||||
import {makeAutoObservable, observable} from 'mobx';
|
||||
|
||||
export interface GuildCounts {
|
||||
memberCount: number;
|
||||
@@ -21,10 +21,9 @@ const FRESH_TTL_MS = 60 * 1000;
|
||||
const REQUEST_DEBOUNCE_MS = 100;
|
||||
|
||||
class GuildCount {
|
||||
private cache: Map<string, GuildCounts> = new Map();
|
||||
private readonly cache = observable.map<string, GuildCounts>(undefined, {deep: false});
|
||||
private pending: Set<string> = new Set();
|
||||
private flushTimer: NodeJS.Timeout | null = null;
|
||||
private cacheVersion = 0;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable<GuildCount, 'cache' | 'pending' | 'flushTimer'>(
|
||||
@@ -35,7 +34,6 @@ class GuildCount {
|
||||
}
|
||||
|
||||
getCounts(guildId: string): GuildCounts | null {
|
||||
void this.cacheVersion;
|
||||
return this.cache.get(guildId) ?? null;
|
||||
}
|
||||
|
||||
@@ -86,13 +84,10 @@ class GuildCount {
|
||||
});
|
||||
this.pending.delete(entry.guild_id);
|
||||
}
|
||||
this.cacheVersion += 1;
|
||||
}
|
||||
|
||||
handleGuildDelete(guildId: string): void {
|
||||
if (this.cache.delete(guildId)) {
|
||||
this.cacheVersion += 1;
|
||||
}
|
||||
this.cache.delete(guildId);
|
||||
this.pending.delete(guildId);
|
||||
}
|
||||
|
||||
@@ -103,12 +98,10 @@ class GuildCount {
|
||||
clearTimeout(this.flushTimer);
|
||||
this.flushTimer = null;
|
||||
}
|
||||
this.cacheVersion += 1;
|
||||
}
|
||||
|
||||
private hydrate(guilds: ReadonlyArray<HydratableGuild>): void {
|
||||
const now = Date.now();
|
||||
let updated = false;
|
||||
for (const guild of guilds) {
|
||||
if (!guild || typeof guild.id !== 'string') continue;
|
||||
if (guild.unavailable) continue;
|
||||
@@ -118,10 +111,6 @@ class GuildCount {
|
||||
onlineCount: guild.online_count,
|
||||
fetchedAt: now,
|
||||
});
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
this.cacheVersion += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,16 +105,23 @@ class GuildList {
|
||||
const guildMap = new Map(this.guilds.map((guild) => [guild.id, guild]));
|
||||
const result: Array<OrganizedItem> = [];
|
||||
const placedGuildIds = new Set<string>();
|
||||
const emittedFolderIds = new Set<number | null>();
|
||||
for (const folder of guildFolders) {
|
||||
const folderGuilds = folder.guildIds
|
||||
.map((guildId) => guildMap.get(guildId))
|
||||
.filter((guild): guild is Guild => guild !== undefined);
|
||||
for (const guild of folderGuilds) {
|
||||
placedGuildIds.add(guild.id);
|
||||
if (folder.id !== UNCATEGORIZED_FOLDER_ID && emittedFolderIds.has(folder.id)) {
|
||||
continue;
|
||||
}
|
||||
const folderGuilds: Array<Guild> = [];
|
||||
for (const guildId of folder.guildIds) {
|
||||
if (placedGuildIds.has(guildId)) continue;
|
||||
const guild = guildMap.get(guildId);
|
||||
if (guild === undefined) continue;
|
||||
placedGuildIds.add(guildId);
|
||||
folderGuilds.push(guild);
|
||||
}
|
||||
if (folderGuilds.length === 0) {
|
||||
continue;
|
||||
}
|
||||
emittedFolderIds.add(folder.id);
|
||||
if (folder.id === UNCATEGORIZED_FOLDER_ID) {
|
||||
for (const guild of folderGuilds) {
|
||||
result.push({type: 'guild', guild});
|
||||
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
const GUILD_ICON_INITIALS_MAX_LENGTH = 4;
|
||||
|
||||
export const GuildInitialsLength = Object.freeze({
|
||||
SHORT: 'short',
|
||||
MEDIUM: 'medium',
|
||||
LONG: 'long',
|
||||
} as const);
|
||||
|
||||
export type GuildInitialsLength = (typeof GuildInitialsLength)[keyof typeof GuildInitialsLength];
|
||||
|
||||
export function getInitialsFromName(name: string): string {
|
||||
const words = name.split(/\s+/u).filter(Boolean);
|
||||
return words
|
||||
.map((word) => Array.from(word)[0])
|
||||
.filter(Boolean)
|
||||
.join('');
|
||||
}
|
||||
|
||||
export function truncateInitials(initials: string, maxLength: number): string {
|
||||
if (maxLength <= 0) return '';
|
||||
return Array.from(initials).slice(0, maxLength).join('');
|
||||
@@ -11,9 +27,9 @@ export function getGuildIconDisplayInitials(initials: string): string {
|
||||
return truncateInitials(initials, GUILD_ICON_INITIALS_MAX_LENGTH);
|
||||
}
|
||||
|
||||
export function getInitialsLength(initials: string): 'short' | 'medium' | 'long' {
|
||||
export function getInitialsLength(initials: string): GuildInitialsLength {
|
||||
const length = Array.from(initials).length;
|
||||
if (length <= 2) return 'short';
|
||||
if (length <= 4) return 'medium';
|
||||
return 'long';
|
||||
if (length <= 2) return GuildInitialsLength.SHORT;
|
||||
if (length <= 4) return GuildInitialsLength.MEDIUM;
|
||||
return GuildInitialsLength.LONG;
|
||||
}
|
||||
Reference in new issue
Block a user