2026-02-13 14:30:46 +02:00
|
|
|
const browserLocale = (navigator.language || 'en').split('-')[0]
|
2025-01-30 21:56:07 +02:00
|
|
|
|
2025-10-14 18:15:46 -04:00
|
|
|
/// Instance config entries provided by static config or pleroma api
|
|
|
|
|
/// Put settings here only if it does not make sense for a normal user
|
|
|
|
|
/// to override it.
|
2026-03-24 15:13:24 +02:00
|
|
|
export const instanceIdentityDefaultDefinition = {
|
|
|
|
|
style: {
|
|
|
|
|
description: 'Instance default style name',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
|
|
|
|
palette: {
|
|
|
|
|
description: 'Instance default palette name',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
|
|
|
|
theme: {
|
|
|
|
|
description: 'Instance default theme name',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
|
|
|
|
defaultAvatar: {
|
|
|
|
|
description: "Default avatar image to use when user doesn't have one set",
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/images/avi.png',
|
|
|
|
|
},
|
|
|
|
|
defaultBanner: {
|
|
|
|
|
description: "Default banner image to use when user doesn't have one set",
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/images/banner.png',
|
|
|
|
|
},
|
|
|
|
|
background: {
|
|
|
|
|
description: 'Instance background/wallpaper',
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/static/aurora_borealis.jpg',
|
|
|
|
|
},
|
|
|
|
|
embeddedToS: {
|
|
|
|
|
description: 'Whether to show Terms of Service title bar',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: true,
|
|
|
|
|
},
|
|
|
|
|
logo: {
|
|
|
|
|
description: 'Instance logo',
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/static/logo.svg',
|
|
|
|
|
},
|
|
|
|
|
logoMargin: {
|
|
|
|
|
description: 'Margin for logo (spacing above/below)',
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '.2em',
|
|
|
|
|
},
|
|
|
|
|
logoMask: {
|
|
|
|
|
description:
|
|
|
|
|
'Use logo as a mask (works well for monochrome/transparent logos)',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: true,
|
|
|
|
|
},
|
|
|
|
|
logoLeft: {
|
|
|
|
|
description: 'Show logo on the left side of navbar',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
|
|
|
|
redirectRootLogin: {
|
|
|
|
|
description: 'Where to redirect user after login',
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/main/friends',
|
|
|
|
|
},
|
|
|
|
|
redirectRootNoLogin: {
|
|
|
|
|
description: 'Where to redirect anonymous visitors',
|
|
|
|
|
type: 'string',
|
|
|
|
|
default: '/main/all',
|
|
|
|
|
},
|
|
|
|
|
hideSitename: {
|
|
|
|
|
description: 'Hide the instance name in navbar',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
|
|
|
|
nsfwCensorImage: {
|
|
|
|
|
description: 'Default NSFW censor image',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
|
|
|
|
showFeaturesPanel: {
|
|
|
|
|
description: 'Show features panel to anonymous visitors',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: true,
|
|
|
|
|
},
|
|
|
|
|
showInstanceSpecificPanel: {
|
|
|
|
|
description: 'Show instance-specific panel',
|
|
|
|
|
type: 'boolean',
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
2026-01-29 15:11:47 +02:00
|
|
|
|
|
|
|
|
// Html stuff
|
2026-03-24 15:13:24 +02:00
|
|
|
instanceSpecificPanelContent: {
|
|
|
|
|
description: 'HTML of Instance-specific panel',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
|
|
|
|
tos: {
|
|
|
|
|
description: 'HTML of Terms of Service panel',
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: false,
|
|
|
|
|
},
|
2025-10-14 18:15:46 -04:00
|
|
|
}
|
2026-03-24 15:13:24 +02:00
|
|
|
export const instanceIdentityDefault = Object.fromEntries(
|
|
|
|
|
Object.entries(instanceIdentityDefaultDefinition).map(([k, v]) => [
|
|
|
|
|
k,
|
|
|
|
|
v.default == null ? null : v.default,
|
|
|
|
|
]),
|
|
|
|
|
)
|
2025-01-30 21:56:07 +02:00
|
|
|
|
2025-10-14 18:15:46 -04:00
|
|
|
/// This object contains setting entries that makes sense
|
|
|
|
|
/// at the user level. The defaults can also be overriden by
|
|
|
|
|
/// instance admins in the frontend_configuration endpoint or static config.
|
|
|
|
|
export const instanceDefaultConfig = {
|
|
|
|
|
expertLevel: 0, // used to track which settings to show and hide
|
2025-01-30 21:56:07 +02:00
|
|
|
hideISP: false,
|
|
|
|
|
hideInstanceWallpaper: false,
|
|
|
|
|
hideShoutbox: false,
|
|
|
|
|
// bad name: actually hides posts of muted USERS
|
2025-10-14 18:15:46 -04:00
|
|
|
hideMutedPosts: false,
|
|
|
|
|
hideMutedThreads: true,
|
|
|
|
|
hideWordFilteredPosts: false,
|
|
|
|
|
muteBotStatuses: false,
|
|
|
|
|
muteSensitiveStatuses: false,
|
|
|
|
|
collapseMessageWithSubject: false,
|
2025-01-30 21:56:07 +02:00
|
|
|
padEmoji: true,
|
|
|
|
|
hideAttachmentsInConv: false,
|
|
|
|
|
hideScrobbles: false,
|
|
|
|
|
hideScrobblesAfter: '2d',
|
|
|
|
|
maxThumbnails: 16,
|
|
|
|
|
loopVideo: true,
|
|
|
|
|
loopVideoSilentOnly: true,
|
2025-10-14 18:15:46 -04:00
|
|
|
/// This is not the streaming API configuration, but rather an option
|
|
|
|
|
/// for automatically loading new posts into the timeline without
|
|
|
|
|
/// the user clicking the Show New button.
|
2025-01-30 21:56:07 +02:00
|
|
|
streaming: false,
|
|
|
|
|
emojiReactionsOnTimeline: true,
|
|
|
|
|
alwaysShowNewPostButton: false,
|
|
|
|
|
autohideFloatingPostButton: false,
|
|
|
|
|
pauseOnUnfocused: true,
|
|
|
|
|
stopGifs: true,
|
|
|
|
|
replyVisibility: 'all',
|
|
|
|
|
thirdColumnMode: 'notifications',
|
|
|
|
|
notificationVisibility: {
|
|
|
|
|
follows: true,
|
|
|
|
|
mentions: true,
|
|
|
|
|
statuses: true,
|
|
|
|
|
likes: true,
|
|
|
|
|
repeats: true,
|
|
|
|
|
moves: true,
|
|
|
|
|
emojiReactions: true,
|
|
|
|
|
followRequest: true,
|
|
|
|
|
reports: true,
|
|
|
|
|
chatMention: true,
|
2026-01-06 16:22:52 +02:00
|
|
|
polls: true,
|
2025-01-30 21:56:07 +02:00
|
|
|
},
|
|
|
|
|
notificationNative: {
|
|
|
|
|
follows: true,
|
|
|
|
|
mentions: true,
|
|
|
|
|
statuses: true,
|
|
|
|
|
likes: false,
|
|
|
|
|
repeats: false,
|
|
|
|
|
moves: false,
|
|
|
|
|
emojiReactions: false,
|
|
|
|
|
followRequest: true,
|
|
|
|
|
reports: true,
|
|
|
|
|
chatMention: true,
|
2026-01-06 16:22:52 +02:00
|
|
|
polls: true,
|
2025-01-30 21:56:07 +02:00
|
|
|
},
|
|
|
|
|
webPushNotifications: false,
|
|
|
|
|
webPushAlwaysShowNotifications: false,
|
|
|
|
|
interfaceLanguage: browserLocale,
|
|
|
|
|
hideScopeNotice: false,
|
2025-10-14 18:15:46 -04:00
|
|
|
scopeCopy: true,
|
|
|
|
|
subjectLineBehavior: 'email',
|
|
|
|
|
alwaysShowSubjectInput: true,
|
|
|
|
|
minimalScopesMode: false,
|
2025-06-12 20:04:39 +03:00
|
|
|
|
2025-01-30 21:56:07 +02:00
|
|
|
// This hides statuses filtered via a word filter
|
2025-10-14 18:15:46 -04:00
|
|
|
hideFilteredStatuses: false,
|
2025-06-12 20:04:39 +03:00
|
|
|
|
|
|
|
|
// Confirmations
|
2025-10-14 18:15:46 -04:00
|
|
|
modalOnRepeat: false,
|
|
|
|
|
modalOnUnfollow: false,
|
|
|
|
|
modalOnBlock: true,
|
|
|
|
|
modalOnMute: false,
|
|
|
|
|
modalOnMuteConversation: false,
|
|
|
|
|
modalOnMuteDomain: true,
|
|
|
|
|
modalOnDelete: true,
|
|
|
|
|
modalOnLogout: true,
|
|
|
|
|
modalOnApproveFollow: false,
|
|
|
|
|
modalOnDenyFollow: false,
|
|
|
|
|
modalOnRemoveUserFromFollowers: false,
|
2025-06-12 20:04:39 +03:00
|
|
|
|
|
|
|
|
// Expiry confirmations/default actions
|
|
|
|
|
onMuteDefaultAction: 'ask',
|
|
|
|
|
onBlockDefaultAction: 'ask',
|
|
|
|
|
|
2025-10-14 18:15:46 -04:00
|
|
|
modalMobileCenter: false,
|
2025-01-30 21:56:07 +02:00
|
|
|
playVideosInModal: false,
|
|
|
|
|
useContainFit: true,
|
|
|
|
|
disableStickyHeaders: false,
|
|
|
|
|
showScrollbars: false,
|
|
|
|
|
userPopoverAvatarAction: 'open',
|
|
|
|
|
userPopoverOverlay: false,
|
2025-07-30 01:13:24 +03:00
|
|
|
userCardLeftJustify: false,
|
|
|
|
|
userCardHidePersonalMarks: false,
|
2025-10-14 18:15:46 -04:00
|
|
|
forcedRoundness: -1,
|
|
|
|
|
greentext: false,
|
|
|
|
|
mentionLinkShowTooltip: true,
|
|
|
|
|
mentionLinkShowAvatar: false,
|
|
|
|
|
mentionLinkFadeDomain: true,
|
|
|
|
|
mentionLinkShowYous: false,
|
|
|
|
|
mentionLinkBoldenYou: true,
|
|
|
|
|
hidePostStats: false,
|
|
|
|
|
hideBotIndication: false,
|
|
|
|
|
hideUserStats: false,
|
|
|
|
|
virtualScrolling: true,
|
|
|
|
|
sensitiveByDefault: false,
|
|
|
|
|
conversationDisplay: 'linear',
|
|
|
|
|
conversationTreeAdvanced: false,
|
|
|
|
|
conversationOtherRepliesButton: 'below',
|
|
|
|
|
conversationTreeFadeAncestors: false,
|
|
|
|
|
showExtraNotifications: true,
|
|
|
|
|
showExtraNotificationsTip: true,
|
|
|
|
|
showChatsInExtraNotifications: true,
|
|
|
|
|
showAnnouncementsInExtraNotifications: true,
|
|
|
|
|
showFollowRequestsInExtraNotifications: true,
|
|
|
|
|
maxDepthInThread: 6,
|
|
|
|
|
autocompleteSelect: false,
|
|
|
|
|
closingDrawerMarksAsSeen: true,
|
|
|
|
|
unseenAtTop: false,
|
|
|
|
|
ignoreInactionableSeen: false,
|
|
|
|
|
unsavedPostAction: 'confirm',
|
|
|
|
|
autoSaveDraft: false,
|
|
|
|
|
useAbsoluteTimeFormat: false,
|
|
|
|
|
absoluteTimeFormatMinAge: '0d',
|
|
|
|
|
absoluteTime12h: '24h',
|
2026-03-15 17:59:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const defaultConfigLocal = {
|
|
|
|
|
hideAttachments: false,
|
|
|
|
|
hideAttachmentsInConv: false,
|
2026-03-16 14:42:08 +02:00
|
|
|
hideNsfw: true,
|
|
|
|
|
useOneClickNsfw: false,
|
|
|
|
|
preloadImage: true,
|
2026-03-15 18:57:57 +02:00
|
|
|
postContentType: 'text/plain',
|
2026-03-15 19:08:02 +02:00
|
|
|
sidebarRight: false,
|
2026-03-15 17:59:13 +02:00
|
|
|
sidebarColumnWidth: '25rem',
|
|
|
|
|
contentColumnWidth: '45rem',
|
|
|
|
|
notifsColumnWidth: '25rem',
|
|
|
|
|
themeEditorMinWidth: '0rem',
|
|
|
|
|
emojiReactionsScale: 0.5,
|
|
|
|
|
textSize: '1rem',
|
|
|
|
|
emojiSize: '2.2rem',
|
|
|
|
|
navbarSize: '3.5rem',
|
|
|
|
|
panelHeaderSize: '3.2rem',
|
|
|
|
|
navbarColumnStretch: false,
|
|
|
|
|
mentionLinkDisplay: 'short',
|
2026-01-06 16:22:52 +02:00
|
|
|
alwaysUseJpeg: false,
|
2026-03-15 17:59:13 +02:00
|
|
|
imageCompression: true,
|
2026-03-15 19:08:02 +02:00
|
|
|
useStreamingApi: false,
|
2026-03-18 16:46:39 +02:00
|
|
|
underlay: 'none',
|
|
|
|
|
fontInterface: undefined,
|
|
|
|
|
fontInput: undefined,
|
|
|
|
|
fontPosts: undefined,
|
|
|
|
|
fontMonospace: undefined,
|
|
|
|
|
themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions
|
|
|
|
|
forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists
|
2025-01-30 21:56:07 +02:00
|
|
|
}
|
2026-03-24 13:59:47 +02:00
|
|
|
|
2026-03-16 20:15:39 +02:00
|
|
|
export const LOCAL_ONLY_KEYS = new Set(Object.keys(defaultConfigLocal))
|
2025-10-14 18:15:46 -04:00
|
|
|
|
2026-01-06 16:22:52 +02:00
|
|
|
export const makeUndefined = (c) =>
|
|
|
|
|
Object.fromEntries(Object.keys(c).map((key) => [key, undefined]))
|
2025-10-14 18:15:46 -04:00
|
|
|
|
|
|
|
|
/// For properties with special processing or properties that does not
|
|
|
|
|
/// make sense to be overriden on a instance-wide level.
|
|
|
|
|
export const defaultState = {
|
|
|
|
|
// Set these to undefined so it does not interfere with default settings check
|
|
|
|
|
...makeUndefined(instanceDefaultConfig),
|
2026-03-16 15:13:48 +02:00
|
|
|
...makeUndefined(defaultConfigLocal),
|
|
|
|
|
// If there are any configurations that does not make sense to
|
|
|
|
|
// have instance-wide default, put it here and explain why.
|
2025-10-14 18:15:46 -04:00
|
|
|
|
2026-03-16 15:13:48 +02:00
|
|
|
// # Special processing
|
|
|
|
|
// ## Theme stuff
|
2025-10-14 18:15:46 -04:00
|
|
|
theme: undefined, // Very old theme store, stores preset name, still in use
|
|
|
|
|
|
|
|
|
|
// V1
|
|
|
|
|
colors: {}, // VERY old theme store, just colors of V1, probably not even used anymore
|
|
|
|
|
|
|
|
|
|
// V2
|
|
|
|
|
customTheme: undefined, // "snapshot", previously was used as actual theme store for V2 so it's still used in case of PleromaFE downgrade event.
|
|
|
|
|
customThemeSource: undefined, // "source", stores original theme data
|
|
|
|
|
|
|
|
|
|
// V3
|
|
|
|
|
style: null,
|
|
|
|
|
styleCustomData: null,
|
|
|
|
|
palette: null,
|
|
|
|
|
paletteCustomData: null,
|
|
|
|
|
}
|