const browserLocale = (navigator.language || 'en').split('-')[0] /// 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. 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, }, // Html stuff instanceSpecificPanelContent: { description: 'HTML of Instance-specific panel', type: 'string', required: false, }, tos: { description: 'HTML of Terms of Service panel', type: 'string', required: false, }, } export const instanceIdentityDefault = Object.fromEntries( Object.entries(instanceIdentityDefaultDefinition).map(([k, v]) => [ k, v.default == null ? null : v.default, ]), ) /// 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 hideISP: false, hideInstanceWallpaper: false, hideShoutbox: false, // bad name: actually hides posts of muted USERS hideMutedPosts: false, hideMutedThreads: true, hideWordFilteredPosts: false, muteBotStatuses: false, muteSensitiveStatuses: false, collapseMessageWithSubject: false, padEmoji: true, hideAttachmentsInConv: false, hideScrobbles: false, hideScrobblesAfter: '2d', maxThumbnails: 16, loopVideo: true, loopVideoSilentOnly: true, /// 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. 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, polls: true, }, notificationNative: { follows: true, mentions: true, statuses: true, likes: false, repeats: false, moves: false, emojiReactions: false, followRequest: true, reports: true, chatMention: true, polls: true, }, webPushNotifications: false, webPushAlwaysShowNotifications: false, interfaceLanguage: browserLocale, hideScopeNotice: false, scopeCopy: true, subjectLineBehavior: 'email', alwaysShowSubjectInput: true, minimalScopesMode: false, // This hides statuses filtered via a word filter hideFilteredStatuses: false, // Confirmations modalOnRepeat: false, modalOnUnfollow: false, modalOnBlock: true, modalOnMute: false, modalOnMuteConversation: false, modalOnMuteDomain: true, modalOnDelete: true, modalOnLogout: true, modalOnApproveFollow: false, modalOnDenyFollow: false, modalOnRemoveUserFromFollowers: false, // Expiry confirmations/default actions onMuteDefaultAction: 'ask', onBlockDefaultAction: 'ask', modalMobileCenter: false, playVideosInModal: false, useContainFit: true, disableStickyHeaders: false, showScrollbars: false, userPopoverAvatarAction: 'open', userPopoverOverlay: false, userCardLeftJustify: false, userCardHidePersonalMarks: false, 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', } export const defaultConfigLocal = { hideAttachments: false, hideAttachmentsInConv: false, hideNsfw: true, useOneClickNsfw: false, preloadImage: true, postContentType: 'text/plain', sidebarRight: false, 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', alwaysUseJpeg: false, imageCompression: true, useStreamingApi: false, 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 } export const LOCAL_ONLY_KEYS = new Set(Object.keys(defaultConfigLocal)) export const makeUndefined = (c) => Object.fromEntries(Object.keys(c).map((key) => [key, undefined])) /// 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), ...makeUndefined(defaultConfigLocal), // If there are any configurations that does not make sense to // have instance-wide default, put it here and explain why. // # Special processing // ## Theme stuff 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, }