mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(media): stream large files and honour size settings (#3387)
This commit is contained in:
1 parent
6acd7f3d22
commit
45b78a13c2
97 files changed
+2547
-409
No files matched your search
@@ -35,8 +35,13 @@
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.contentScroller > .contentFrame {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: min(33rem, calc(100svh - 12.5rem));
|
||||
|
||||
@@ -1004,7 +1004,11 @@ export const SelfHostedSetupWizardGate = observer(() => {
|
||||
hideCloseButton
|
||||
data-flx="app.self-hosted-setup-wizard-gate.header"
|
||||
/>
|
||||
<Modal.Content className={styles.contentScroller} data-flx="app.self-hosted-setup-wizard-gate.content">
|
||||
<Modal.Content
|
||||
className={styles.contentScroller}
|
||||
contentClassName={styles.contentFrame}
|
||||
data-flx="app.self-hosted-setup-wizard-gate.content"
|
||||
>
|
||||
<div className={styles.content} data-flx="app.self-hosted-setup-wizard-gate.content-inner">
|
||||
{loadError ? (
|
||||
<div className={styles.centeredStep} data-flx="app.self-hosted-setup-wizard-gate.load-error-wrap">
|
||||
|
||||
@@ -67,7 +67,6 @@ export const STATIC_IMAGE_WITH_AVIF_FORMATS = formatAssetUploadExtensions('splas
|
||||
export const ANIMATED_IMAGE_FORMATS = formatAssetUploadExtensions('avatar');
|
||||
export const ANIMATED_AVATAR_FORMATS = formatKnownAnimatedAssetExtensions('avatar');
|
||||
export const AVIF_FORMAT_LABEL = 'AVIF';
|
||||
export const IMAGE_MAX_SIZE_BYTES = 10 * 1024 * 1024;
|
||||
export const BACKGROUND_MEDIA_MAX_SIZE_BYTES = 10 * 1024 * 1024;
|
||||
export const CUSTOM_SOUND_MAX_SIZE_BYTES = 2 * 1024 * 1024;
|
||||
export const AVATAR_RECOMMENDED_SIZE_LABEL = '512×512px';
|
||||
|
||||
@@ -1,25 +1,14 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {LimitResolver} from '@app/features/app/utils/LimitResolverAdapter';
|
||||
|
||||
const FALLBACKS = {
|
||||
emoji_max_size: 384 * 1024,
|
||||
sticker_max_size: 512 * 1024,
|
||||
avatar_max_size: 10 * 1024 * 1024,
|
||||
} as const;
|
||||
import {AVATAR_MAX_SIZE} from '@fluxer/constants/src/LimitConstants';
|
||||
|
||||
class GlobalLimitsClass {
|
||||
getEmojiMaxSize(): number {
|
||||
getAvatarMaxSize(): number {
|
||||
return LimitResolver.resolve({
|
||||
key: 'emoji_max_size',
|
||||
fallback: FALLBACKS.emoji_max_size,
|
||||
});
|
||||
}
|
||||
|
||||
getStickerMaxSize(): number {
|
||||
return LimitResolver.resolve({
|
||||
key: 'sticker_max_size',
|
||||
fallback: FALLBACKS.sticker_max_size,
|
||||
key: 'avatar_max_size',
|
||||
fallback: AVATAR_MAX_SIZE,
|
||||
context: {traits: [], guildFeatures: []},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {AVATAR_MAX_SIZE, EMOJI_MAX_SIZE, STICKER_MAX_SIZE} from '@fluxer/constants/src/LimitConstants';
|
||||
import type {LimitConfigSnapshot} from '@fluxer/limits/src/LimitTypes';
|
||||
import type {Guild as WireGuild} from '@fluxer/schema/src/domains/guild/GuildResponseSchemas';
|
||||
import {beforeEach, describe, expect, it, vi} from 'vitest';
|
||||
|
||||
const RAISED = 5 * 1024 * 1024;
|
||||
const state: {limits: LimitConfigSnapshot} = {limits: {traitDefinitions: [], rules: []}};
|
||||
|
||||
vi.mock('@app/features/app/state/RuntimeConfig', () => ({
|
||||
default: {
|
||||
localInstanceDomain: 'fluxer.test',
|
||||
get limits() {
|
||||
return state.limits;
|
||||
},
|
||||
getSnapshotOrNull: () => ({limits: state.limits}),
|
||||
},
|
||||
}));
|
||||
vi.mock('@app/features/app/state/InstanceSnapshotStore', () => ({default: {getLimitsForInstance: () => null}}));
|
||||
vi.mock('@app/features/user/state/Users', () => ({default: {getCurrentUser: () => ({traits: ['premium']})}}));
|
||||
vi.mock('@app/features/channel/state/Channels', () => ({default: {getChannel: () => null}}));
|
||||
vi.mock('@app/features/guild/state/Guilds', () => ({default: {getGuild: () => null}}));
|
||||
vi.mock('@app/features/navigation/state/SelectedChannel', () => ({default: {currentChannelId: null}}));
|
||||
vi.mock('@app/features/navigation/state/SelectedGuild', () => ({default: {selectedGuildId: null}}));
|
||||
vi.mock('@app/features/theme/fonts/ScriptFontLoader', () => ({noteText: () => {}}));
|
||||
|
||||
const {Guild} = await import('@app/features/guild/models/Guild');
|
||||
const {GlobalLimits} = await import('@app/features/app/utils/GlobalLimits');
|
||||
|
||||
function guild(features: Array<string> = []) {
|
||||
return new Guild({id: '1', name: 'guild', owner_id: '2', features, roles: []} as unknown as WireGuild);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
state.limits = {traitDefinitions: ['premium'], rules: [{id: 'default', limits: {}}]};
|
||||
});
|
||||
|
||||
describe('configured image size limits', () => {
|
||||
it('falls back to the stock sizes when nothing is configured', () => {
|
||||
expect(guild().maxEmojiSize).toBe(EMOJI_MAX_SIZE);
|
||||
expect(guild().maxStickerSize).toBe(STICKER_MAX_SIZE);
|
||||
expect(GlobalLimits.getAvatarMaxSize()).toBe(AVATAR_MAX_SIZE);
|
||||
});
|
||||
|
||||
it('follows a raised default rule', () => {
|
||||
state.limits.rules[0].limits = {emoji_max_size: RAISED, sticker_max_size: RAISED, avatar_max_size: RAISED * 6};
|
||||
expect(guild().maxEmojiSize).toBe(RAISED);
|
||||
expect(guild().maxStickerSize).toBe(RAISED);
|
||||
expect(GlobalLimits.getAvatarMaxSize()).toBe(RAISED * 6);
|
||||
});
|
||||
|
||||
it('applies guild feature rules to emoji and sticker sizes', () => {
|
||||
state.limits.rules.push({
|
||||
id: 'boosted',
|
||||
filters: {guildFeatures: ['MORE_EMOJI']},
|
||||
limits: {emoji_max_size: RAISED, sticker_max_size: RAISED},
|
||||
});
|
||||
expect(guild().maxEmojiSize).toBe(EMOJI_MAX_SIZE);
|
||||
expect(guild(['MORE_EMOJI']).maxEmojiSize).toBe(RAISED);
|
||||
expect(guild(['MORE_EMOJI']).maxStickerSize).toBe(RAISED);
|
||||
});
|
||||
|
||||
it('ignores trait rules the server does not apply', () => {
|
||||
state.limits.rules.push({
|
||||
id: 'premium',
|
||||
filters: {traits: ['premium']},
|
||||
limits: {emoji_max_size: RAISED, sticker_max_size: RAISED, avatar_max_size: RAISED * 6},
|
||||
});
|
||||
expect(guild().maxEmojiSize).toBe(EMOJI_MAX_SIZE);
|
||||
expect(guild().maxStickerSize).toBe(STICKER_MAX_SIZE);
|
||||
expect(GlobalLimits.getAvatarMaxSize()).toBe(AVATAR_MAX_SIZE);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user