Copy disabled (too large)
Download .txt
Showing preview only (67,489K chars total). Download the full file to get everything.
Repository: fluxerapp/fluxer
Branch: refactor
Commit: 5da26d4ed5ef
Files: 5720
Total size: 79.8 MB
Directory structure:
gitextract_5eknctna/
├── .devcontainer/
│ ├── Caddyfile.dev
│ ├── Dockerfile
│ ├── devcontainer.json
│ ├── docker-compose.yml
│ ├── livekit.yaml
│ ├── on-create.sh
│ └── process-compose.yml
├── .dockerignore
├── .editorconfig
├── .envrc
├── .gitattributes
├── .github/
│ ├── DISCUSSION_TEMPLATE/
│ │ └── ideas.yaml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── docs.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── build-desktop.yaml
│ ├── channel-vars.yaml
│ ├── ci.yaml
│ ├── deploy-admin.yaml
│ ├── deploy-api.yaml
│ ├── deploy-app.yaml
│ ├── deploy-gateway.yaml
│ ├── deploy-marketing.yaml
│ ├── deploy-media-proxy.yaml
│ ├── deploy-relay-directory.yaml
│ ├── deploy-relay.yaml
│ ├── deploy-static-proxy.yaml
│ ├── migrate-cassandra.yaml
│ ├── promote-canary-to-main.yaml
│ ├── release-livekitctl.yaml
│ ├── release-relay-directory.yaml
│ ├── release-relay.yaml
│ ├── release-server.yaml
│ ├── restart-gateway.yaml
│ ├── sync-desktop.yaml
│ ├── sync-static.yaml
│ ├── test-cassandra-backup.yaml
│ └── update-word-lists.yaml
├── .gitignore
├── .gitmodules
├── .ignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .tool-versions
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ └── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── LICENSING.md
├── README.md
├── SECURITY.md
├── biome.json
├── compose.yaml
├── config/
│ ├── config.dev.template.json
│ ├── config.production.template.json
│ ├── config.schema.json
│ ├── config.test.json
│ └── livekit.example.yaml
├── dev/
│ ├── Caddyfile.dev
│ └── livekit.template.yaml
├── devenv.nix
├── devenv.yaml
├── fluxer_admin/
│ ├── Dockerfile
│ ├── package.json
│ ├── public/
│ │ └── static/
│ │ └── .gitkeep
│ ├── src/
│ │ ├── Config.tsx
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ └── index.tsx
│ └── tsconfig.json
├── fluxer_api/
│ ├── Dockerfile
│ ├── package.json
│ ├── scripts/
│ │ ├── CassandraMigrate.tsx
│ │ ├── Dockerfile.cassandra-migrate
│ │ └── LicenseEnforcer.tsx
│ ├── src/
│ │ ├── App.tsx
│ │ ├── AppEntrypoint.tsx
│ │ ├── Config.tsx
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ └── WorkerEntrypoint.tsx
│ ├── tsconfig.json
│ └── tsconfig.worker.json
├── fluxer_app/
│ ├── crates/
│ │ └── libfluxcore/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── animation.rs
│ │ ├── apng.rs
│ │ ├── gateway.rs
│ │ ├── gif.rs
│ │ ├── lib.rs
│ │ └── static_image.rs
│ ├── index.html
│ ├── lingui.config.js
│ ├── package.json
│ ├── postcss.config.js
│ ├── rspack.config.mjs
│ ├── rust-toolchain.toml
│ ├── scripts/
│ │ ├── DevServer.tsx
│ │ ├── GenerateAvatarMasks.tsx
│ │ ├── GenerateColorSystem.tsx
│ │ ├── GenerateEmojiSprites.tsx
│ │ ├── auto-i18n.mjs
│ │ ├── build/
│ │ │ ├── Config.tsx
│ │ │ ├── rspack/
│ │ │ │ ├── externals.mjs
│ │ │ │ ├── lingui.mjs
│ │ │ │ ├── po-loader.mjs
│ │ │ │ ├── static-files.mjs
│ │ │ │ └── wasm.mjs
│ │ │ ├── tsconfig.json
│ │ │ ├── types.d.ts
│ │ │ └── utils/
│ │ │ ├── Assets.tsx
│ │ │ ├── CssDts.tsx
│ │ │ ├── Html.tsx
│ │ │ ├── Resolve.tsx
│ │ │ ├── ServiceWorker.tsx
│ │ │ └── Sourcemaps.tsx
│ │ ├── build-sw.mjs
│ │ └── translate-i18n.mjs
│ ├── src/
│ │ ├── App.module.css
│ │ ├── App.tsx
│ │ ├── AppConstants.tsx
│ │ ├── Config.tsx
│ │ ├── Endpoints.tsx
│ │ ├── I18n.tsx
│ │ ├── Router.tsx
│ │ ├── Routes.tsx
│ │ ├── actions/
│ │ │ ├── AccessibilityActionCreators.tsx
│ │ │ ├── AuthSessionActionCreators.tsx
│ │ │ ├── AuthenticationActionCreators.tsx
│ │ │ ├── CallActionCreators.tsx
│ │ │ ├── ChannelActionCreators.tsx
│ │ │ ├── ChannelPinsActionCreators.tsx
│ │ │ ├── ChannelStickerActionCreators.tsx
│ │ │ ├── ConnectionActionCreators.tsx
│ │ │ ├── ContextMenuActionCreators.tsx
│ │ │ ├── DeveloperOptionsActionCreators.tsx
│ │ │ ├── DimensionActionCreators.tsx
│ │ │ ├── DiscoveryActionCreators.tsx
│ │ │ ├── DraftActionCreators.tsx
│ │ │ ├── EmojiActionCreators.tsx
│ │ │ ├── EmojiPickerActionCreators.tsx
│ │ │ ├── ExpressionPickerActionCreators.tsx
│ │ │ ├── FavoriteMemeActionCreators.tsx
│ │ │ ├── FavoritesActionCreators.tsx
│ │ │ ├── GifActionCreators.tsx
│ │ │ ├── GiftActionCreators.tsx
│ │ │ ├── GuildActionCreators.tsx
│ │ │ ├── GuildEmojiActionCreators.tsx
│ │ │ ├── GuildMemberActionCreators.tsx
│ │ │ ├── GuildNSFWActionCreators.tsx
│ │ │ ├── GuildStickerActionCreators.tsx
│ │ │ ├── HighlightActionCreators.tsx
│ │ │ ├── IARActionCreators.tsx
│ │ │ ├── InboxActionCreators.tsx
│ │ │ ├── InviteActionCreators.tsx
│ │ │ ├── KlipyActionCreators.tsx
│ │ │ ├── LayoutActionCreators.tsx
│ │ │ ├── MediaViewerActionCreators.tsx
│ │ │ ├── MessageActionCreators.tsx
│ │ │ ├── MfaActionCreators.tsx
│ │ │ ├── ModalActionCreators.tsx
│ │ │ ├── ModalRender.tsx
│ │ │ ├── NagbarActionCreators.tsx
│ │ │ ├── NavigationActionCreators.tsx
│ │ │ ├── NotificationActionCreators.tsx
│ │ │ ├── OAuth2AuthorizationActionCreators.tsx
│ │ │ ├── PackActionCreators.tsx
│ │ │ ├── PackInviteActionCreators.tsx
│ │ │ ├── PiPActionCreators.tsx
│ │ │ ├── PopoutActionCreators.tsx
│ │ │ ├── PremiumActionCreators.tsx
│ │ │ ├── PremiumModalActionCreators.tsx
│ │ │ ├── PrivateChannelActionCreators.tsx
│ │ │ ├── QuickSwitcherActionCreators.tsx
│ │ │ ├── ReactionActionCreators.tsx
│ │ │ ├── ReadStateActionCreators.tsx
│ │ │ ├── RecentMentionActionCreators.tsx
│ │ │ ├── RelationshipActionCreators.tsx
│ │ │ ├── SavedMessageActionCreators.tsx
│ │ │ ├── ScheduledMessageActionCreators.tsx
│ │ │ ├── SlowmodeActionCreators.tsx
│ │ │ ├── SoundActionCreators.tsx
│ │ │ ├── StickerPickerActionCreators.tsx
│ │ │ ├── TextCopyActionCreators.tsx
│ │ │ ├── ThemeActionCreators.tsx
│ │ │ ├── ThemePreferenceActionCreators.tsx
│ │ │ ├── ToastActionCreators.tsx
│ │ │ ├── TrustedDomainActionCreators.tsx
│ │ │ ├── TypingActionCreators.tsx
│ │ │ ├── UnsavedChangesActionCreators.tsx
│ │ │ ├── UserActionCreators.tsx
│ │ │ ├── UserGuildSettingsActionCreators.tsx
│ │ │ ├── UserNoteActionCreators.tsx
│ │ │ ├── UserProfileActionCreators.tsx
│ │ │ ├── UserSettingsActionCreators.tsx
│ │ │ ├── VoiceCallLayoutActionCreators.tsx
│ │ │ ├── VoiceSettingsActionCreators.tsx
│ │ │ ├── VoiceStateActionCreators.tsx
│ │ │ ├── WebhookActionCreators.tsx
│ │ │ └── WindowActionCreators.tsx
│ │ ├── bootstrap/
│ │ │ └── SetupHttpClient.tsx
│ │ ├── components/
│ │ │ ├── AppBadge.tsx
│ │ │ ├── BootstrapErrorScreen.tsx
│ │ │ ├── ErrorFallback.module.css
│ │ │ ├── ErrorFallback.tsx
│ │ │ ├── LongPressable.tsx
│ │ │ ├── NetworkErrorScreen.tsx
│ │ │ ├── accounts/
│ │ │ │ ├── AccountListItem.module.css
│ │ │ │ ├── AccountListItem.tsx
│ │ │ │ ├── AccountRow.module.css
│ │ │ │ ├── AccountRow.tsx
│ │ │ │ ├── AccountSelector.module.css
│ │ │ │ ├── AccountSelector.tsx
│ │ │ │ ├── AccountSwitcherModal.module.css
│ │ │ │ └── AccountSwitcherModal.tsx
│ │ │ ├── alerts/
│ │ │ │ ├── CallNotRingableModal.tsx
│ │ │ │ ├── CameraPermissionDeniedModal.tsx
│ │ │ │ ├── ChannelPermissionsUpdateFailedModal.tsx
│ │ │ │ ├── DMCloseFailedModal.tsx
│ │ │ │ ├── FeatureTemporarilyDisabledModal.tsx
│ │ │ │ ├── FileSizeTooLargeModal.tsx
│ │ │ │ ├── GenericErrorModal.tsx
│ │ │ │ ├── GroupLeaveFailedModal.tsx
│ │ │ │ ├── GroupOwnershipTransferFailedModal.tsx
│ │ │ │ ├── GroupRemoveUserFailedModal.tsx
│ │ │ │ ├── GuildAtCapacityModal.tsx
│ │ │ │ ├── InviteAcceptFailedModal.tsx
│ │ │ │ ├── InviteRevokeFailedModal.tsx
│ │ │ │ ├── InvitesDisabledModal.tsx
│ │ │ │ ├── InvitesLoadFailedModal.tsx
│ │ │ │ ├── MaxBookmarksModal.tsx
│ │ │ │ ├── MaxFavoriteMemesModal.tsx
│ │ │ │ ├── MaxGuildsModal.tsx
│ │ │ │ ├── MessageDeleteFailedModal.tsx
│ │ │ │ ├── MessageDeleteTooQuickModal.tsx
│ │ │ │ ├── MessageEditFailedModal.tsx
│ │ │ │ ├── MessageEditTooQuickModal.tsx
│ │ │ │ ├── MessageForwardFailedModal.tsx
│ │ │ │ ├── MessageSendFailedModal.tsx
│ │ │ │ ├── MessageSendTooQuickModal.tsx
│ │ │ │ ├── MicrophonePermissionDeniedModal.tsx
│ │ │ │ ├── NSFWContentRejectedModal.tsx
│ │ │ │ ├── PinFailedModal.tsx
│ │ │ │ ├── RateLimitedConfirmModal.tsx
│ │ │ │ ├── ReactionInteractionDisabledModal.tsx
│ │ │ │ ├── RoleCreateFailedModal.tsx
│ │ │ │ ├── RoleDeleteFailedModal.tsx
│ │ │ │ ├── RoleNameBlankModal.tsx
│ │ │ │ ├── RoleUpdateFailedModal.tsx
│ │ │ │ ├── ScreenRecordingPermissionDeniedModal.tsx
│ │ │ │ ├── ScreenShareUnsupportedModal.tsx
│ │ │ │ ├── SlowmodeRateLimitedModal.tsx
│ │ │ │ ├── TemporaryInviteRequiresPresenceModal.tsx
│ │ │ │ ├── TooManyAttachmentsModal.tsx
│ │ │ │ ├── TooManyReactionsModal.tsx
│ │ │ │ ├── TtsUnsupportedModal.tsx
│ │ │ │ ├── UserBannedFromGuildModal.tsx
│ │ │ │ ├── UserIpBannedFromGuildModal.tsx
│ │ │ │ ├── VoiceChannelFullModal.tsx
│ │ │ │ ├── VoiceConnectionConfirmModal.module.css
│ │ │ │ └── VoiceConnectionConfirmModal.tsx
│ │ │ ├── auth/
│ │ │ │ ├── AuthBackground.tsx
│ │ │ │ ├── AuthBottomLink.tsx
│ │ │ │ ├── AuthCardContainer.module.css
│ │ │ │ ├── AuthCardContainer.tsx
│ │ │ │ ├── AuthErrorState.tsx
│ │ │ │ ├── AuthLoadingState.tsx
│ │ │ │ ├── AuthLoginLayout.tsx
│ │ │ │ ├── AuthMinimalRegisterFormCore.tsx
│ │ │ │ ├── AuthPageHeader.tsx
│ │ │ │ ├── AuthPageStyles.module.css
│ │ │ │ ├── AuthRegisterFormCore.tsx
│ │ │ │ ├── AuthRouterLink.tsx
│ │ │ │ ├── BrowserLoginHandoffModal.module.css
│ │ │ │ ├── BrowserLoginHandoffModal.tsx
│ │ │ │ ├── DateOfBirthField.module.css
│ │ │ │ ├── DateOfBirthField.tsx
│ │ │ │ ├── DesktopDeepLinkPrompt.module.css
│ │ │ │ ├── DesktopDeepLinkPrompt.tsx
│ │ │ │ ├── DesktopHandoffAccountSelector.tsx
│ │ │ │ ├── FormField.tsx
│ │ │ │ ├── GiftHeader.tsx
│ │ │ │ ├── HandoffCodeDisplay.module.css
│ │ │ │ ├── HandoffCodeDisplay.tsx
│ │ │ │ ├── InstanceSelector.module.css
│ │ │ │ ├── InstanceSelector.tsx
│ │ │ │ ├── InviteHeader.tsx
│ │ │ │ ├── IpAuthorizationScreen.module.css
│ │ │ │ ├── IpAuthorizationScreen.tsx
│ │ │ │ ├── MfaScreen.module.css
│ │ │ │ ├── MfaScreen.tsx
│ │ │ │ ├── MockMinimalRegisterForm.tsx
│ │ │ │ ├── SubmitTooltip.module.css
│ │ │ │ ├── SubmitTooltip.tsx
│ │ │ │ └── auth_login_core/
│ │ │ │ ├── AuthLoginEmailPasswordForm.tsx
│ │ │ │ ├── AuthLoginPasskeyActions.tsx
│ │ │ │ └── useDesktopHandoffFlow.tsx
│ │ │ ├── bottomsheets/
│ │ │ │ ├── CategoryBottomSheet.tsx
│ │ │ │ ├── ChannelBottomSheet.tsx
│ │ │ │ ├── ChannelDetailsBottomSheet.module.css
│ │ │ │ ├── ChannelDetailsBottomSheet.tsx
│ │ │ │ ├── ChannelPinsBottomSheet.tsx
│ │ │ │ ├── ChannelSearchBottomSheet.tsx
│ │ │ │ ├── CreateDMBottomSheet.module.css
│ │ │ │ ├── CreateDMBottomSheet.tsx
│ │ │ │ ├── DMBottomSheet.tsx
│ │ │ │ ├── DirectCallLobbyBottomSheet.module.css
│ │ │ │ ├── DirectCallLobbyBottomSheet.tsx
│ │ │ │ ├── EmojiInfoBottomSheet.module.css
│ │ │ │ ├── EmojiInfoBottomSheet.tsx
│ │ │ │ ├── FavoritesGuildHeaderBottomSheet.tsx
│ │ │ │ ├── GuildHeaderBottomSheet.module.css
│ │ │ │ ├── GuildHeaderBottomSheet.tsx
│ │ │ │ ├── MuteDurationSheet.tsx
│ │ │ │ ├── QuickSwitcherBottomSheet.module.css
│ │ │ │ ├── QuickSwitcherBottomSheet.tsx
│ │ │ │ ├── VoiceLobbyBottomSheet.module.css
│ │ │ │ ├── VoiceLobbyBottomSheet.tsx
│ │ │ │ ├── VoiceParticipantBottomSheet.tsx
│ │ │ │ ├── VoiceSettingsBottomSheets.tsx
│ │ │ │ └── shared.module.css
│ │ │ ├── captcha/
│ │ │ │ └── TurnstileWidget.tsx
│ │ │ ├── channel/
│ │ │ │ ├── Autocomplete.module.css
│ │ │ │ ├── Autocomplete.tsx
│ │ │ │ ├── AutocompleteChannel.module.css
│ │ │ │ ├── AutocompleteChannel.tsx
│ │ │ │ ├── AutocompleteCommand.tsx
│ │ │ │ ├── AutocompleteEmoji.module.css
│ │ │ │ ├── AutocompleteEmoji.tsx
│ │ │ │ ├── AutocompleteGif.module.css
│ │ │ │ ├── AutocompleteGif.tsx
│ │ │ │ ├── AutocompleteItem.module.css
│ │ │ │ ├── AutocompleteItem.tsx
│ │ │ │ ├── AutocompleteMeme.tsx
│ │ │ │ ├── AutocompleteMention.module.css
│ │ │ │ ├── AutocompleteMention.tsx
│ │ │ │ ├── AutocompleteSticker.tsx
│ │ │ │ ├── BlockedMessageGroups.module.css
│ │ │ │ ├── BlockedMessageGroups.tsx
│ │ │ │ ├── CallMessage.module.css
│ │ │ │ ├── CallMessage.tsx
│ │ │ │ ├── ChannelAttachmentArea.module.css
│ │ │ │ ├── ChannelAttachmentArea.tsx
│ │ │ │ ├── ChannelChatLayout.module.css
│ │ │ │ ├── ChannelChatLayout.tsx
│ │ │ │ ├── ChannelHeader.module.css
│ │ │ │ ├── ChannelHeader.tsx
│ │ │ │ ├── ChannelIconChangeMessage.tsx
│ │ │ │ ├── ChannelIndexPage.module.css
│ │ │ │ ├── ChannelIndexPage.tsx
│ │ │ │ ├── ChannelLayout.module.css
│ │ │ │ ├── ChannelLayout.tsx
│ │ │ │ ├── ChannelMembers.module.css
│ │ │ │ ├── ChannelMembers.tsx
│ │ │ │ ├── ChannelMessageStream.tsx
│ │ │ │ ├── ChannelNameChangeMessage.tsx
│ │ │ │ ├── ChannelSearchHighlight.css
│ │ │ │ ├── ChannelSearchResults.module.css
│ │ │ │ ├── ChannelSearchResults.tsx
│ │ │ │ ├── ChannelSourcePreview.module.css
│ │ │ │ ├── ChannelSourcePreview.tsx
│ │ │ │ ├── ChannelStickersArea.module.css
│ │ │ │ ├── ChannelStickersArea.tsx
│ │ │ │ ├── ChannelTextarea.tsx
│ │ │ │ ├── ChannelWelcomeSection.module.css
│ │ │ │ ├── ChannelWelcomeSection.tsx
│ │ │ │ ├── Divider.module.css
│ │ │ │ ├── Divider.tsx
│ │ │ │ ├── EditBar.module.css
│ │ │ │ ├── EditBar.tsx
│ │ │ │ ├── EditingMessageInput.module.css
│ │ │ │ ├── EditingMessageInput.tsx
│ │ │ │ ├── EmojiPicker.module.css
│ │ │ │ ├── EmojiPicker.tsx
│ │ │ │ ├── ExpressionPickerShared.module.css
│ │ │ │ ├── GifPicker.module.css
│ │ │ │ ├── GifVideoPool.tsx
│ │ │ │ ├── GiftEmbed.module.css
│ │ │ │ ├── GiftEmbed.tsx
│ │ │ │ ├── GuildJoinMessage.module.css
│ │ │ │ ├── GuildJoinMessage.tsx
│ │ │ │ ├── GuildMembersPage.module.css
│ │ │ │ ├── GuildMembersPage.tsx
│ │ │ │ ├── InviteEmbed.module.css
│ │ │ │ ├── InviteEmbed.tsx
│ │ │ │ ├── MasonryListComputer.tsx
│ │ │ │ ├── MediaActionBottomSheet.tsx
│ │ │ │ ├── MemberListContainer.module.css
│ │ │ │ ├── MemberListContainer.tsx
│ │ │ │ ├── MemberListItem.module.css
│ │ │ │ ├── MemberListItem.tsx
│ │ │ │ ├── MemesPicker.module.css
│ │ │ │ ├── MentionEveryonePopout.module.css
│ │ │ │ ├── MentionEveryonePopout.tsx
│ │ │ │ ├── Message.tsx
│ │ │ │ ├── MessageActionBar.module.css
│ │ │ │ ├── MessageActionBar.tsx
│ │ │ │ ├── MessageActionBottomSheet.module.css
│ │ │ │ ├── MessageActionBottomSheet.tsx
│ │ │ │ ├── MessageActionMenu.tsx
│ │ │ │ ├── MessageActionUtils.tsx
│ │ │ │ ├── MessageAttachmentStateUtils.tsx
│ │ │ │ ├── MessageAttachmentUtils.tsx
│ │ │ │ ├── MessageAttachments.module.css
│ │ │ │ ├── MessageAttachments.tsx
│ │ │ │ ├── MessageAuthorInfo.tsx
│ │ │ │ ├── MessageAvatar.tsx
│ │ │ │ ├── MessageCharacterCounter.module.css
│ │ │ │ ├── MessageCharacterCounter.tsx
│ │ │ │ ├── MessageGroup.tsx
│ │ │ │ ├── MessageReactions.module.css
│ │ │ │ ├── MessageReactions.tsx
│ │ │ │ ├── MessageReactionsSheet.module.css
│ │ │ │ ├── MessageReactionsSheet.tsx
│ │ │ │ ├── MessageUploadProgress.module.css
│ │ │ │ ├── MessageUploadProgress.tsx
│ │ │ │ ├── MessageUsername.tsx
│ │ │ │ ├── MessageViewContext.tsx
│ │ │ │ ├── Messages.module.css
│ │ │ │ ├── Messages.tsx
│ │ │ │ ├── MobileEmojiPicker.module.css
│ │ │ │ ├── MobileEmojiPicker.tsx
│ │ │ │ ├── MobileMemesPicker.tsx
│ │ │ │ ├── MobileStickersPicker.tsx
│ │ │ │ ├── MuteOptions.tsx
│ │ │ │ ├── NSFWChannelGate.module.css
│ │ │ │ ├── NSFWChannelGate.tsx
│ │ │ │ ├── NewMessagesBar.tsx
│ │ │ │ ├── PinSystemMessage.tsx
│ │ │ │ ├── PreloadableUserPopout.tsx
│ │ │ │ ├── PremiumUpsellBanner.module.css
│ │ │ │ ├── PremiumUpsellBanner.tsx
│ │ │ │ ├── QuickReactionsRow.module.css
│ │ │ │ ├── QuickReactionsRow.tsx
│ │ │ │ ├── RecipientAddMessage.module.css
│ │ │ │ ├── RecipientAddMessage.tsx
│ │ │ │ ├── RecipientRemoveMessage.module.css
│ │ │ │ ├── RecipientRemoveMessage.tsx
│ │ │ │ ├── ReplyBar.module.css
│ │ │ │ ├── ReplyBar.tsx
│ │ │ │ ├── ReplyPreview.tsx
│ │ │ │ ├── ScheduledMessageEditBar.module.css
│ │ │ │ ├── ScheduledMessageEditBar.tsx
│ │ │ │ ├── ScrollFillerSkeleton.module.css
│ │ │ │ ├── ScrollFillerSkeleton.tsx
│ │ │ │ ├── SearchResultsUtils.tsx
│ │ │ │ ├── SearchScopeOptions.tsx
│ │ │ │ ├── SlowmodeIndicator.module.css
│ │ │ │ ├── SlowmodeIndicator.tsx
│ │ │ │ ├── StickersPicker.module.css
│ │ │ │ ├── StickersPicker.tsx
│ │ │ │ ├── SystemMessage.tsx
│ │ │ │ ├── SystemMessageUsername.tsx
│ │ │ │ ├── ThemeEmbed.module.css
│ │ │ │ ├── ThemeEmbed.tsx
│ │ │ │ ├── TimestampWithTooltip.module.css
│ │ │ │ ├── TimestampWithTooltip.tsx
│ │ │ │ ├── Typing.tsx
│ │ │ │ ├── TypingUsers.module.css
│ │ │ │ ├── TypingUsers.tsx
│ │ │ │ ├── UnknownMessage.tsx
│ │ │ │ ├── UnreadDividerSlot.tsx
│ │ │ │ ├── UploadManager.tsx
│ │ │ │ ├── UserMessage.tsx
│ │ │ │ ├── UserTag.module.css
│ │ │ │ ├── UserTag.tsx
│ │ │ │ ├── VerificationBarrier.tsx
│ │ │ │ ├── VoiceMessageRecorder.module.css
│ │ │ │ ├── VoiceMessageRecorder.tsx
│ │ │ │ ├── active_now/
│ │ │ │ │ ├── ActiveNowSidebar.module.css
│ │ │ │ │ ├── ActiveNowSidebar.tsx
│ │ │ │ │ └── useActiveFriendVoiceStates.tsx
│ │ │ │ ├── barriers/
│ │ │ │ │ ├── BarrierComponents.module.css
│ │ │ │ │ └── BarrierComponents.tsx
│ │ │ │ ├── channel_header/
│ │ │ │ │ └── useChannelHeaderData.tsx
│ │ │ │ ├── channel_header_components/
│ │ │ │ │ ├── CallButtons.tsx
│ │ │ │ │ ├── ChannelHeaderIcon.tsx
│ │ │ │ │ ├── ChannelNotificationSettingsButton.tsx
│ │ │ │ │ ├── ChannelNotificationSettingsDropdown.tsx
│ │ │ │ │ ├── ChannelPinsButton.tsx
│ │ │ │ │ ├── UpdaterIcon.tsx
│ │ │ │ │ └── UtilityButtons.tsx
│ │ │ │ ├── channel_view/
│ │ │ │ │ ├── ChannelViewScaffold.tsx
│ │ │ │ │ ├── DMChannelView.tsx
│ │ │ │ │ ├── GuildChannelView.tsx
│ │ │ │ │ ├── useCallHeaderState.tsx
│ │ │ │ │ └── useChannelSearchState.tsx
│ │ │ │ ├── direct_message/
│ │ │ │ │ ├── AddFriendForm.module.css
│ │ │ │ │ ├── AddFriendForm.tsx
│ │ │ │ │ ├── AddFriendView.module.css
│ │ │ │ │ ├── AddFriendView.tsx
│ │ │ │ │ ├── DMChannelView.module.css
│ │ │ │ │ ├── DMFriendsView.module.css
│ │ │ │ │ ├── DMFriendsView.tsx
│ │ │ │ │ ├── DMLayout.module.css
│ │ │ │ │ ├── DMLayout.tsx
│ │ │ │ │ ├── DMList.module.css
│ │ │ │ │ ├── DMList.tsx
│ │ │ │ │ ├── DMWelcomeSection.module.css
│ │ │ │ │ ├── DMWelcomeSection.tsx
│ │ │ │ │ ├── GroupDMWelcomeSection.module.css
│ │ │ │ │ ├── GroupDMWelcomeSection.tsx
│ │ │ │ │ ├── PersonalNotesWelcomeSection.module.css
│ │ │ │ │ └── PersonalNotesWelcomeSection.tsx
│ │ │ │ ├── embeds/
│ │ │ │ │ ├── AltTextBadge.module.css
│ │ │ │ │ ├── AltTextBadge.tsx
│ │ │ │ │ ├── Embed.module.css
│ │ │ │ │ ├── Embed.tsx
│ │ │ │ │ ├── EmbedUtils.tsx
│ │ │ │ │ ├── NSFWBlurOverlay.module.css
│ │ │ │ │ ├── NSFWBlurOverlay.tsx
│ │ │ │ │ ├── attachments/
│ │ │ │ │ │ ├── Attachment.module.css
│ │ │ │ │ │ ├── Attachment.tsx
│ │ │ │ │ │ ├── AttachmentFile.tsx
│ │ │ │ │ │ ├── AttachmentGridItem.tsx
│ │ │ │ │ │ ├── AttachmentLayoutGrid.tsx
│ │ │ │ │ │ ├── AttachmentMosaic.tsx
│ │ │ │ │ │ ├── AttachmentSingleMedia.tsx
│ │ │ │ │ │ ├── TextualAttachmentCodePanel.tsx
│ │ │ │ │ │ ├── TextualAttachmentLanguagePopout.tsx
│ │ │ │ │ │ ├── TextualAttachmentPreview.module.css
│ │ │ │ │ │ ├── TextualAttachmentPreview.tsx
│ │ │ │ │ │ ├── TextualAttachmentPreviewBottomSheet.module.css
│ │ │ │ │ │ ├── TextualAttachmentPreviewBottomSheet.tsx
│ │ │ │ │ │ ├── TextualAttachmentPreviewFooter.tsx
│ │ │ │ │ │ ├── TextualAttachmentPreviewModal.tsx
│ │ │ │ │ │ ├── TextualAttachmentPreviewUtils.tsx
│ │ │ │ │ │ └── TextualPreviewContextMenu.tsx
│ │ │ │ │ └── media/
│ │ │ │ │ ├── EmbedAudio.module.css
│ │ │ │ │ ├── EmbedAudio.tsx
│ │ │ │ │ ├── EmbedGifv.module.css
│ │ │ │ │ ├── EmbedGifv.tsx
│ │ │ │ │ ├── EmbedImage.module.css
│ │ │ │ │ ├── EmbedImage.tsx
│ │ │ │ │ ├── EmbedVideo.module.css
│ │ │ │ │ ├── EmbedVideo.tsx
│ │ │ │ │ ├── EmbedYouTube.module.css
│ │ │ │ │ ├── EmbedYouTube.tsx
│ │ │ │ │ ├── GifIndicator.module.css
│ │ │ │ │ ├── GifIndicator.tsx
│ │ │ │ │ ├── MediaButtonUtils.tsx
│ │ │ │ │ ├── MediaButtons.module.css
│ │ │ │ │ ├── MediaButtons.tsx
│ │ │ │ │ ├── MediaContainer.module.css
│ │ │ │ │ ├── MediaContainer.tsx
│ │ │ │ │ ├── MediaTypes.tsx
│ │ │ │ │ ├── VoiceMessagePlayer.module.css
│ │ │ │ │ └── VoiceMessagePlayer.tsx
│ │ │ │ ├── emoji_picker/
│ │ │ │ │ ├── EmojiPickerCategoryList.tsx
│ │ │ │ │ ├── EmojiPickerConstants.tsx
│ │ │ │ │ ├── EmojiPickerInspector.tsx
│ │ │ │ │ ├── EmojiPickerSearchBar.module.css
│ │ │ │ │ ├── EmojiPickerSearchBar.tsx
│ │ │ │ │ ├── EmojiRenderer.tsx
│ │ │ │ │ ├── SkinToneSelector.tsx
│ │ │ │ │ ├── VirtualRow.tsx
│ │ │ │ │ └── hooks/
│ │ │ │ │ ├── useEmojiCategories.tsx
│ │ │ │ │ └── useVirtualRows.tsx
│ │ │ │ ├── friends/
│ │ │ │ │ ├── ActionButton.module.css
│ │ │ │ │ ├── ActionButton.tsx
│ │ │ │ │ ├── EmptyStateView.module.css
│ │ │ │ │ ├── EmptyStateView.tsx
│ │ │ │ │ ├── FriendListItem.module.css
│ │ │ │ │ ├── FriendListItem.tsx
│ │ │ │ │ ├── FriendsTypes.tsx
│ │ │ │ │ ├── ListSection.module.css
│ │ │ │ │ ├── ListSection.tsx
│ │ │ │ │ ├── MobileFriendRequestItem.module.css
│ │ │ │ │ ├── MobileFriendRequestItem.tsx
│ │ │ │ │ └── views/
│ │ │ │ │ ├── FriendsList.module.css
│ │ │ │ │ ├── FriendsList.tsx
│ │ │ │ │ ├── PendingFriendsView.module.css
│ │ │ │ │ └── PendingFriendsView.tsx
│ │ │ │ ├── invite_embed/
│ │ │ │ │ └── InviteEmbedUtils.tsx
│ │ │ │ ├── message_search_bar/
│ │ │ │ │ ├── AutocompleteOption.tsx
│ │ │ │ │ ├── ChannelsSection.tsx
│ │ │ │ │ ├── DateSection.tsx
│ │ │ │ │ ├── FilterOption.tsx
│ │ │ │ │ ├── HistorySection.tsx
│ │ │ │ │ ├── MessageSearchBar.module.css
│ │ │ │ │ ├── MessageSearchBar.tsx
│ │ │ │ │ ├── UsersSection.tsx
│ │ │ │ │ └── ValuesSection.tsx
│ │ │ │ ├── pickers/
│ │ │ │ │ ├── gif/
│ │ │ │ │ │ ├── GifPicker.tsx
│ │ │ │ │ │ ├── GifPickerGrid.tsx
│ │ │ │ │ │ ├── GifPickerGridItem.tsx
│ │ │ │ │ │ ├── GifPickerHeader.tsx
│ │ │ │ │ │ ├── GifPickerStore.tsx
│ │ │ │ │ │ ├── GifPickerTypes.tsx
│ │ │ │ │ │ └── GifPickerView.tsx
│ │ │ │ │ ├── memes/
│ │ │ │ │ │ ├── MediaFormat.tsx
│ │ │ │ │ │ ├── MemeGridItem.tsx
│ │ │ │ │ │ ├── MemesGrid.tsx
│ │ │ │ │ │ ├── MemesPicker.tsx
│ │ │ │ │ │ ├── MemesPickerHeader.tsx
│ │ │ │ │ │ └── MemesPickerView.tsx
│ │ │ │ │ └── shared/
│ │ │ │ │ ├── ComputeColumns.tsx
│ │ │ │ │ ├── MasonryVirtualGrid.tsx
│ │ │ │ │ ├── PickerConstants.tsx
│ │ │ │ │ ├── usePooledVideo.tsx
│ │ │ │ │ └── useScrollerViewport.tsx
│ │ │ │ ├── shared/
│ │ │ │ │ ├── MemberListUnavailableFallback.module.css
│ │ │ │ │ ├── MemberListUnavailableFallback.tsx
│ │ │ │ │ ├── PickerEmptyState.tsx
│ │ │ │ │ ├── PickerSearchInput.module.css
│ │ │ │ │ └── PickerSearchInput.tsx
│ │ │ │ ├── sticker_picker/
│ │ │ │ │ ├── StickerPickerCategoryList.tsx
│ │ │ │ │ ├── StickerPickerConstants.tsx
│ │ │ │ │ ├── StickerPickerInspector.tsx
│ │ │ │ │ ├── StickerPickerSearchBar.tsx
│ │ │ │ │ ├── VirtualRow.module.css
│ │ │ │ │ ├── VirtualRow.tsx
│ │ │ │ │ └── hooks/
│ │ │ │ │ ├── useStickerCategories.tsx
│ │ │ │ │ └── useVirtualRows.tsx
│ │ │ │ └── textarea/
│ │ │ │ ├── HoldToRecordButton.tsx
│ │ │ │ ├── InputWrapper.module.css
│ │ │ │ ├── MobileTextareaLayout.module.css
│ │ │ │ ├── MobileTextareaLayout.tsx
│ │ │ │ ├── MobileTextareaPlusBottomSheet.tsx
│ │ │ │ ├── TextareaButton.module.css
│ │ │ │ ├── TextareaButton.tsx
│ │ │ │ ├── TextareaButtons.module.css
│ │ │ │ ├── TextareaButtons.tsx
│ │ │ │ ├── TextareaContextMenu.tsx
│ │ │ │ ├── TextareaInput.module.css
│ │ │ │ ├── TextareaInputField.tsx
│ │ │ │ └── TextareaPlusMenu.tsx
│ │ │ ├── common/
│ │ │ │ ├── ExpiryFootnote.module.css
│ │ │ │ ├── ExpiryFootnote.tsx
│ │ │ │ ├── ExpiryFootnoteContextMenu.tsx
│ │ │ │ ├── ExternalLink.module.css
│ │ │ │ ├── ExternalLink.tsx
│ │ │ │ ├── FriendSelector.module.css
│ │ │ │ ├── FriendSelector.tsx
│ │ │ │ ├── GroupDMAvatar.module.css
│ │ │ │ ├── GroupDMAvatar.tsx
│ │ │ │ ├── InstanceBadge.module.css
│ │ │ │ ├── InstanceBadge.tsx
│ │ │ │ ├── SpoilerOverlay.module.css
│ │ │ │ ├── SpoilerOverlay.tsx
│ │ │ │ └── custom_status_display/
│ │ │ │ ├── CustomStatusDisplay.module.css
│ │ │ │ └── CustomStatusDisplay.tsx
│ │ │ ├── debug/
│ │ │ │ ├── ChannelDebugModal.tsx
│ │ │ │ ├── DebugModal.module.css
│ │ │ │ ├── DebugModal.tsx
│ │ │ │ ├── GuildDebugModal.tsx
│ │ │ │ ├── GuildMemberDebugModal.tsx
│ │ │ │ ├── MessageDebugModal.tsx
│ │ │ │ └── UserDebugModal.tsx
│ │ │ ├── embeds/
│ │ │ │ └── embed_card/
│ │ │ │ ├── EmbedCard.module.css
│ │ │ │ ├── EmbedCard.tsx
│ │ │ │ └── useEmbedSkeletonOverride.tsx
│ │ │ ├── emojis/
│ │ │ │ ├── EmojiAttributionSubtext.tsx
│ │ │ │ ├── EmojiInfoContent.module.css
│ │ │ │ ├── EmojiInfoContent.tsx
│ │ │ │ ├── EmojiListItem.module.css
│ │ │ │ └── EmojiListItem.tsx
│ │ │ ├── favorites/
│ │ │ │ ├── FavoritesWelcomeSection.module.css
│ │ │ │ └── FavoritesWelcomeSection.tsx
│ │ │ ├── form/
│ │ │ │ ├── ColorPickerField.module.css
│ │ │ │ ├── ColorPickerField.tsx
│ │ │ │ ├── DateTimePickerField.module.css
│ │ │ │ ├── DateTimePickerField.tsx
│ │ │ │ ├── Form.tsx
│ │ │ │ ├── FormErrorText.module.css
│ │ │ │ ├── FormErrorText.tsx
│ │ │ │ ├── FormSurface.module.css
│ │ │ │ ├── Input.module.css
│ │ │ │ ├── Input.tsx
│ │ │ │ ├── Select.module.css
│ │ │ │ ├── Select.tsx
│ │ │ │ ├── SelectBottomSheet.module.css
│ │ │ │ ├── SelectBottomSheet.tsx
│ │ │ │ ├── Switch.module.css
│ │ │ │ ├── Switch.tsx
│ │ │ │ ├── UsernameValidationRules.module.css
│ │ │ │ └── UsernameValidationRules.tsx
│ │ │ ├── guild/
│ │ │ │ ├── GuildBadge.module.css
│ │ │ │ ├── GuildBadge.tsx
│ │ │ │ ├── RoleManagement.module.css
│ │ │ │ ├── RoleManagement.tsx
│ │ │ │ ├── UploadDropZone.module.css
│ │ │ │ ├── UploadDropZone.tsx
│ │ │ │ ├── UploadSlotInfo.module.css
│ │ │ │ └── UploadSlotInfo.tsx
│ │ │ ├── icons/
│ │ │ │ ├── BlueskyIcon.tsx
│ │ │ │ ├── FluxerIcon.tsx
│ │ │ │ ├── FluxerSymbol.tsx
│ │ │ │ ├── InboxIcon.tsx
│ │ │ │ ├── NSFWIcon.tsx
│ │ │ │ ├── UnverifiedConnectionIcon.tsx
│ │ │ │ └── VerifiedConnectionIcon.tsx
│ │ │ ├── invites/
│ │ │ │ ├── DisableInvitesButton.module.css
│ │ │ │ ├── DisableInvitesButton.tsx
│ │ │ │ ├── InviteDateToggle.module.css
│ │ │ │ ├── InviteDateToggle.tsx
│ │ │ │ ├── InviteListItem.module.css
│ │ │ │ └── InviteListItem.tsx
│ │ │ ├── keybinds/
│ │ │ │ ├── KeybindRecorder.module.css
│ │ │ │ └── KeybindRecorder.tsx
│ │ │ ├── layout/
│ │ │ │ ├── AppLayout.module.css
│ │ │ │ ├── AppLayout.tsx
│ │ │ │ ├── AuthLayout.module.css
│ │ │ │ ├── AuthLayout.tsx
│ │ │ │ ├── ChannelItem.module.css
│ │ │ │ ├── ChannelItem.tsx
│ │ │ │ ├── ChannelItemContent.tsx
│ │ │ │ ├── ChannelItemIcon.module.css
│ │ │ │ ├── ChannelItemIcon.tsx
│ │ │ │ ├── ChannelItemSurface.module.css
│ │ │ │ ├── ChannelListContent.module.css
│ │ │ │ ├── ChannelListContent.tsx
│ │ │ │ ├── ChannelListSkeleton.tsx
│ │ │ │ ├── CollapsedCategoryVoiceParticipants.module.css
│ │ │ │ ├── CollapsedCategoryVoiceParticipants.tsx
│ │ │ │ ├── DndContext.tsx
│ │ │ │ ├── DropIndicator.module.css
│ │ │ │ ├── DropIndicator.tsx
│ │ │ │ ├── FavoritesChannelListContent.module.css
│ │ │ │ ├── FavoritesChannelListContent.tsx
│ │ │ │ ├── FavoritesGuildHeader.module.css
│ │ │ │ ├── FavoritesGuildHeader.tsx
│ │ │ │ ├── FavoritesLayout.tsx
│ │ │ │ ├── FrameContext.tsx
│ │ │ │ ├── GenericChannelItem.tsx
│ │ │ │ ├── GlobalOverlays.tsx
│ │ │ │ ├── GroupedVoiceParticipant.module.css
│ │ │ │ ├── GroupedVoiceParticipant.tsx
│ │ │ │ ├── GuildDetachedBanner.module.css
│ │ │ │ ├── GuildDetachedBanner.tsx
│ │ │ │ ├── GuildHeader.module.css
│ │ │ │ ├── GuildHeader.tsx
│ │ │ │ ├── GuildHeaderShell.tsx
│ │ │ │ ├── GuildLayout.module.css
│ │ │ │ ├── GuildLayout.tsx
│ │ │ │ ├── GuildNavbar.module.css
│ │ │ │ ├── GuildNavbar.tsx
│ │ │ │ ├── GuildNavbarSkeleton.module.css
│ │ │ │ ├── GuildNavbarSkeleton.tsx
│ │ │ │ ├── GuildSidebar.tsx
│ │ │ │ ├── GuildsLayout.module.css
│ │ │ │ ├── GuildsLayout.tsx
│ │ │ │ ├── KeyboardModeListener.tsx
│ │ │ │ ├── MobileBottomNav.module.css
│ │ │ │ ├── MobileBottomNav.tsx
│ │ │ │ ├── Nagbar.module.css
│ │ │ │ ├── Nagbar.tsx
│ │ │ │ ├── NagbarButton.module.css
│ │ │ │ ├── NagbarButton.tsx
│ │ │ │ ├── NagbarContent.module.css
│ │ │ │ ├── NagbarContent.tsx
│ │ │ │ ├── NativeDragRegion.module.css
│ │ │ │ ├── NativeDragRegion.tsx
│ │ │ │ ├── NativeTitlebar.module.css
│ │ │ │ ├── NativeTitlebar.tsx
│ │ │ │ ├── NativeTrafficLightsBackdrop.module.css
│ │ │ │ ├── NativeTrafficLightsBackdrop.tsx
│ │ │ │ ├── NullSpaceDropIndicator.module.css
│ │ │ │ ├── NullSpaceDropIndicator.tsx
│ │ │ │ ├── OutlineFrame.module.css
│ │ │ │ ├── OutlineFrame.tsx
│ │ │ │ ├── ScrollIndicatorOverlay.module.css
│ │ │ │ ├── ScrollIndicatorOverlay.tsx
│ │ │ │ ├── SplashScreen.module.css
│ │ │ │ ├── SplashScreen.tsx
│ │ │ │ ├── UserArea.module.css
│ │ │ │ ├── UserArea.tsx
│ │ │ │ ├── VoiceChannelUserCount.module.css
│ │ │ │ ├── VoiceChannelUserCount.tsx
│ │ │ │ ├── VoiceParticipantItem.module.css
│ │ │ │ ├── VoiceParticipantItem.tsx
│ │ │ │ ├── VoiceParticipantsList.module.css
│ │ │ │ ├── VoiceParticipantsList.tsx
│ │ │ │ ├── VoiceStateIcons.module.css
│ │ │ │ ├── VoiceStateIcons.tsx
│ │ │ │ ├── app_layout/
│ │ │ │ │ ├── AppLayoutHooks.tsx
│ │ │ │ │ ├── AppLayoutTypes.tsx
│ │ │ │ │ ├── NagbarContainer.module.css
│ │ │ │ │ ├── NagbarContainer.tsx
│ │ │ │ │ ├── TopNagbarContext.tsx
│ │ │ │ │ └── nagbars/
│ │ │ │ │ ├── DesktopDownloadNagbar.module.css
│ │ │ │ │ ├── DesktopDownloadNagbar.tsx
│ │ │ │ │ ├── DesktopNotificationNagbar.module.css
│ │ │ │ │ ├── DesktopNotificationNagbar.tsx
│ │ │ │ │ ├── EmailVerificationNagbar.tsx
│ │ │ │ │ ├── GiftInventoryNagbar.tsx
│ │ │ │ │ ├── GuildMembershipCtaNagbar.tsx
│ │ │ │ │ ├── MobileDownloadNagbar.module.css
│ │ │ │ │ ├── MobileDownloadNagbar.tsx
│ │ │ │ │ ├── PendingBulkDeletionNagbar.tsx
│ │ │ │ │ ├── PremiumExpiredNagbar.tsx
│ │ │ │ │ ├── PremiumGracePeriodNagbar.tsx
│ │ │ │ │ ├── PremiumOnboardingNagbar.tsx
│ │ │ │ │ ├── UnclaimedAccountNagbar.tsx
│ │ │ │ │ └── VisionaryMfaNagbar.tsx
│ │ │ │ ├── dnd/
│ │ │ │ │ └── DndDropPosition.tsx
│ │ │ │ ├── guild_list/
│ │ │ │ │ ├── AddGuildButton.module.css
│ │ │ │ │ ├── AddGuildButton.tsx
│ │ │ │ │ ├── DiscoveryButton.module.css
│ │ │ │ │ ├── DiscoveryButton.tsx
│ │ │ │ │ ├── DownloadButton.module.css
│ │ │ │ │ ├── DownloadButton.tsx
│ │ │ │ │ ├── FavoritesButton.tsx
│ │ │ │ │ ├── FluxerButton.tsx
│ │ │ │ │ ├── GuildFolderItem.module.css
│ │ │ │ │ ├── GuildFolderItem.tsx
│ │ │ │ │ ├── GuildListDMItem.module.css
│ │ │ │ │ ├── GuildListDMItem.tsx
│ │ │ │ │ ├── GuildListItem.tsx
│ │ │ │ │ ├── HelpButton.module.css
│ │ │ │ │ ├── HelpButton.tsx
│ │ │ │ │ └── VoiceBadge.tsx
│ │ │ │ ├── types/
│ │ │ │ │ └── DndTypes.tsx
│ │ │ │ └── utils/
│ │ │ │ ├── ChannelMoveOperation.test.tsx
│ │ │ │ ├── ChannelMoveOperation.tsx
│ │ │ │ ├── ChannelOrganization.tsx
│ │ │ │ └── ChannelUnreadState.tsx
│ │ │ ├── media_player/
│ │ │ │ ├── AudioPlayer.module.css
│ │ │ │ ├── InlineAudioPlayer.module.css
│ │ │ │ ├── MediaPlayButton.module.css
│ │ │ │ ├── MediaPlaybackRate.module.css
│ │ │ │ ├── MediaProgressBar.module.css
│ │ │ │ ├── MediaTimeDisplay.module.css
│ │ │ │ ├── MediaVerticalVolumeControl.module.css
│ │ │ │ ├── MediaVolumeControl.module.css
│ │ │ │ ├── VideoPlayer.module.css
│ │ │ │ ├── components/
│ │ │ │ │ ├── AudioPlayer.tsx
│ │ │ │ │ ├── InlineAudioPlayer.tsx
│ │ │ │ │ ├── MediaFullscreenButton.tsx
│ │ │ │ │ ├── MediaPipButton.tsx
│ │ │ │ │ ├── MediaPlayButton.tsx
│ │ │ │ │ ├── MediaPlaybackRate.tsx
│ │ │ │ │ ├── MediaProgressBar.tsx
│ │ │ │ │ ├── MediaTimeDisplay.tsx
│ │ │ │ │ ├── MediaVerticalVolumeControl.tsx
│ │ │ │ │ ├── MediaVolumeControl.tsx
│ │ │ │ │ └── VideoPlayer.tsx
│ │ │ │ ├── hooks/
│ │ │ │ │ ├── useControlsVisibility.tsx
│ │ │ │ │ ├── useMediaFullscreen.tsx
│ │ │ │ │ ├── useMediaKeyboard.tsx
│ │ │ │ │ ├── useMediaPiP.tsx
│ │ │ │ │ ├── useMediaPlayer.tsx
│ │ │ │ │ ├── useMediaProgress.tsx
│ │ │ │ │ └── useMediaVolume.tsx
│ │ │ │ └── utils/
│ │ │ │ └── MediaConstants.tsx
│ │ │ ├── modals/
│ │ │ │ ├── AccountDeleteModal.module.css
│ │ │ │ ├── AccountDeleteModal.tsx
│ │ │ │ ├── AccountDisableModal.module.css
│ │ │ │ ├── AccountDisableModal.tsx
│ │ │ │ ├── AddConnectionModal.module.css
│ │ │ │ ├── AddConnectionModal.tsx
│ │ │ │ ├── AddFavoriteChannelModal.module.css
│ │ │ │ ├── AddFavoriteChannelModal.tsx
│ │ │ │ ├── AddFavoriteMemeModal.tsx
│ │ │ │ ├── AddFriendSheet.module.css
│ │ │ │ ├── AddFriendSheet.tsx
│ │ │ │ ├── AddFriendsToGroupModal.tsx
│ │ │ │ ├── AddGuildModal.module.css
│ │ │ │ ├── AddGuildModal.tsx
│ │ │ │ ├── AddGuildStickerModal.module.css
│ │ │ │ ├── AddGuildStickerModal.tsx
│ │ │ │ ├── AssetCropModal.tsx
│ │ │ │ ├── AttachmentEditModal.module.css
│ │ │ │ ├── AttachmentEditModal.tsx
│ │ │ │ ├── AudioPlaybackPermissionModal.tsx
│ │ │ │ ├── BackgroundImageGalleryModal.module.css
│ │ │ │ ├── BackgroundImageGalleryModal.tsx
│ │ │ │ ├── BackupCodesModal.module.css
│ │ │ │ ├── BackupCodesModal.tsx
│ │ │ │ ├── BackupCodesRegenerateModal.tsx
│ │ │ │ ├── BackupCodesViewModal.tsx
│ │ │ │ ├── BanDetailsModal.module.css
│ │ │ │ ├── BanDetailsModal.tsx
│ │ │ │ ├── BanMemberModal.module.css
│ │ │ │ ├── BanMemberModal.tsx
│ │ │ │ ├── BaseChangeNicknameModal.module.css
│ │ │ │ ├── BaseChangeNicknameModal.tsx
│ │ │ │ ├── BookmarksBottomSheet.module.css
│ │ │ │ ├── BookmarksBottomSheet.tsx
│ │ │ │ ├── CameraPreviewModal.module.css
│ │ │ │ ├── CameraPreviewModal.tsx
│ │ │ │ ├── CaptchaModal.module.css
│ │ │ │ ├── CaptchaModal.tsx
│ │ │ │ ├── CategoryCreateModal.tsx
│ │ │ │ ├── ChangeFriendNicknameModal.tsx
│ │ │ │ ├── ChangeGroupDMNicknameModal.tsx
│ │ │ │ ├── ChangeNicknameModal.tsx
│ │ │ │ ├── ChannelCreateModal.module.css
│ │ │ │ ├── ChannelCreateModal.tsx
│ │ │ │ ├── ChannelDeleteModal.tsx
│ │ │ │ ├── ChannelSettingsModal.tsx
│ │ │ │ ├── ChannelTopicModal.module.css
│ │ │ │ ├── ChannelTopicModal.tsx
│ │ │ │ ├── ClaimAccountModal.module.css
│ │ │ │ ├── ClaimAccountModal.tsx
│ │ │ │ ├── ConfirmModal.module.css
│ │ │ │ ├── ConfirmModal.tsx
│ │ │ │ ├── CreateDMModal.tsx
│ │ │ │ ├── CreateFavoriteCategoryModal.tsx
│ │ │ │ ├── CreatePackModal.module.css
│ │ │ │ ├── CreatePackModal.tsx
│ │ │ │ ├── CustomStatusBottomSheet.module.css
│ │ │ │ ├── CustomStatusBottomSheet.tsx
│ │ │ │ ├── CustomStatusModal.module.css
│ │ │ │ ├── CustomStatusModal.tsx
│ │ │ │ ├── DeviceRevokeModal.tsx
│ │ │ │ ├── DisablePiPConfirmModal.module.css
│ │ │ │ ├── DisablePiPConfirmModal.tsx
│ │ │ │ ├── DiscoveryModal.module.css
│ │ │ │ ├── DiscoveryModal.tsx
│ │ │ │ ├── DuplicateGroupConfirmModal.module.css
│ │ │ │ ├── DuplicateGroupConfirmModal.tsx
│ │ │ │ ├── EditAltTextModal.tsx
│ │ │ │ ├── EditConnectionModal.tsx
│ │ │ │ ├── EditFavoriteMemeModal.module.css
│ │ │ │ ├── EditFavoriteMemeModal.tsx
│ │ │ │ ├── EditGroupBottomSheet.module.css
│ │ │ │ ├── EditGroupBottomSheet.tsx
│ │ │ │ ├── EditGroupModal.module.css
│ │ │ │ ├── EditGroupModal.tsx
│ │ │ │ ├── EditGuildStickerModal.module.css
│ │ │ │ ├── EditGuildStickerModal.tsx
│ │ │ │ ├── EditPackModal.tsx
│ │ │ │ ├── EmailChangeModal.module.css
│ │ │ │ ├── EmailChangeModal.tsx
│ │ │ │ ├── EmojiUploadModal.module.css
│ │ │ │ ├── EmojiUploadModal.tsx
│ │ │ │ ├── ExpressionPickerSheet.module.css
│ │ │ │ ├── ExpressionPickerSheet.tsx
│ │ │ │ ├── ExternalLinkWarningModal.module.css
│ │ │ │ ├── ExternalLinkWarningModal.tsx
│ │ │ │ ├── FluxerTagChangeModal.module.css
│ │ │ │ ├── FluxerTagChangeModal.tsx
│ │ │ │ ├── ForwardModal.module.css
│ │ │ │ ├── ForwardModal.tsx
│ │ │ │ ├── GiftAcceptModal.module.css
│ │ │ │ ├── GiftAcceptModal.tsx
│ │ │ │ ├── GroupInvitesBottomSheet.module.css
│ │ │ │ ├── GroupInvitesBottomSheet.tsx
│ │ │ │ ├── GroupInvitesModal.module.css
│ │ │ │ ├── GroupInvitesModal.tsx
│ │ │ │ ├── GuildDeleteModal.tsx
│ │ │ │ ├── GuildFolderSettingsModal.tsx
│ │ │ │ ├── GuildNotificationSettingsModal.module.css
│ │ │ │ ├── GuildNotificationSettingsModal.tsx
│ │ │ │ ├── GuildOwnershipWarningModal.module.css
│ │ │ │ ├── GuildOwnershipWarningModal.tsx
│ │ │ │ ├── GuildPrivacySettingsModal.module.css
│ │ │ │ ├── GuildPrivacySettingsModal.tsx
│ │ │ │ ├── GuildSettingsModal.module.css
│ │ │ │ ├── GuildSettingsModal.tsx
│ │ │ │ ├── HideOwnCameraConfirmModal.module.css
│ │ │ │ ├── HideOwnCameraConfirmModal.tsx
│ │ │ │ ├── HideOwnScreenShareConfirmModal.tsx
│ │ │ │ ├── IARModal.module.css
│ │ │ │ ├── IARModal.tsx
│ │ │ │ ├── ImageCropModal.module.css
│ │ │ │ ├── ImageCropModal.tsx
│ │ │ │ ├── InputMonitoringCTAModal.tsx
│ │ │ │ ├── InviteAcceptModal.module.css
│ │ │ │ ├── InviteAcceptModal.tsx
│ │ │ │ ├── InviteAcceptModalPreview.tsx
│ │ │ │ ├── InviteModal.module.css
│ │ │ │ ├── InviteModal.tsx
│ │ │ │ ├── InvitePagePreviewModal.module.css
│ │ │ │ ├── InvitePagePreviewModal.tsx
│ │ │ │ ├── KeyboardModeIntroModal.module.css
│ │ │ │ ├── KeyboardModeIntroModal.tsx
│ │ │ │ ├── KickMemberModal.tsx
│ │ │ │ ├── MediaModal.module.css
│ │ │ │ ├── MediaModal.tsx
│ │ │ │ ├── MediaViewerModal.module.css
│ │ │ │ ├── MediaViewerModal.tsx
│ │ │ │ ├── MessageHistoryThresholdModal.tsx
│ │ │ │ ├── MessageReactionsModal.module.css
│ │ │ │ ├── MessageReactionsModal.tsx
│ │ │ │ ├── MfaTotpDisableModal.tsx
│ │ │ │ ├── MfaTotpEnableModal.module.css
│ │ │ │ ├── MfaTotpEnableModal.tsx
│ │ │ │ ├── MobileVideoViewer.module.css
│ │ │ │ ├── MobileVideoViewer.tsx
│ │ │ │ ├── Modal.module.css
│ │ │ │ ├── Modal.tsx
│ │ │ │ ├── Modals.module.css
│ │ │ │ ├── Modals.tsx
│ │ │ │ ├── NoteEditSheet.module.css
│ │ │ │ ├── NoteEditSheet.tsx
│ │ │ │ ├── PackInviteModal.module.css
│ │ │ │ ├── PackInviteModal.tsx
│ │ │ │ ├── PasskeyNameModal.tsx
│ │ │ │ ├── PasswordChangeModal.module.css
│ │ │ │ ├── PasswordChangeModal.tsx
│ │ │ │ ├── PhoneAddModal.module.css
│ │ │ │ ├── PhoneAddModal.tsx
│ │ │ │ ├── PremiumModal.module.css
│ │ │ │ ├── PremiumModal.tsx
│ │ │ │ ├── RemoveTimeoutModal.module.css
│ │ │ │ ├── RemoveTimeoutModal.tsx
│ │ │ │ ├── RenameChannelModal.tsx
│ │ │ │ ├── RequiredActionModal.module.css
│ │ │ │ ├── RequiredActionModal.tsx
│ │ │ │ ├── ScheduleMessageModal.tsx
│ │ │ │ ├── ScreenShareSettingsModal.module.css
│ │ │ │ ├── ScreenShareSettingsModal.tsx
│ │ │ │ ├── ScreenShareSourceModal.module.css
│ │ │ │ ├── ScreenShareSourceModal.tsx
│ │ │ │ ├── ShareThemeModal.module.css
│ │ │ │ ├── ShareThemeModal.tsx
│ │ │ │ ├── StatusChangeBottomSheet.module.css
│ │ │ │ ├── StatusChangeBottomSheet.tsx
│ │ │ │ ├── SudoVerificationModal.module.css
│ │ │ │ ├── SudoVerificationModal.tsx
│ │ │ │ ├── ThemeAcceptModal.module.css
│ │ │ │ ├── ThemeAcceptModal.tsx
│ │ │ │ ├── TimeoutMemberModal.module.css
│ │ │ │ ├── TimeoutMemberModal.tsx
│ │ │ │ ├── TimeoutMemberOptions.tsx
│ │ │ │ ├── TimeoutMemberSheet.module.css
│ │ │ │ ├── TimeoutMemberSheet.tsx
│ │ │ │ ├── TransferOwnershipModal.module.css
│ │ │ │ ├── TransferOwnershipModal.tsx
│ │ │ │ ├── UploadDropModal.module.css
│ │ │ │ ├── UploadDropModal.tsx
│ │ │ │ ├── UserProfileActionsSheet.module.css
│ │ │ │ ├── UserProfileActionsSheet.tsx
│ │ │ │ ├── UserProfileMobileSheet.module.css
│ │ │ │ ├── UserProfileMobileSheet.tsx
│ │ │ │ ├── UserProfileModal.module.css
│ │ │ │ ├── UserProfileModal.tsx
│ │ │ │ ├── UserProfileUtils.tsx
│ │ │ │ ├── UserSettingsModal.module.css
│ │ │ │ ├── UserSettingsModal.tsx
│ │ │ │ ├── channel_tabs/
│ │ │ │ │ ├── ChannelInvitesTab.module.css
│ │ │ │ │ ├── ChannelInvitesTab.tsx
│ │ │ │ │ ├── ChannelOverviewTab.module.css
│ │ │ │ │ ├── ChannelOverviewTab.tsx
│ │ │ │ │ ├── ChannelPermissionsTab.module.css
│ │ │ │ │ ├── ChannelPermissionsTab.tsx
│ │ │ │ │ ├── ChannelWebhooksTab.module.css
│ │ │ │ │ └── ChannelWebhooksTab.tsx
│ │ │ │ ├── components/
│ │ │ │ │ ├── AllSettingsRenderer.module.css
│ │ │ │ │ ├── AllSettingsRenderer.tsx
│ │ │ │ │ ├── ClientInfo.module.css
│ │ │ │ │ ├── ClientInfo.tsx
│ │ │ │ │ ├── ComparisonCheckRow.module.css
│ │ │ │ │ ├── ComparisonCheckRow.tsx
│ │ │ │ │ ├── ComparisonRow.module.css
│ │ │ │ │ ├── ComparisonRow.tsx
│ │ │ │ │ ├── DesktopChannelSettingsView.tsx
│ │ │ │ │ ├── DesktopGuildSettingsView.tsx
│ │ │ │ │ ├── DesktopSettingsView.module.css
│ │ │ │ │ ├── DesktopSettingsView.tsx
│ │ │ │ │ ├── EmailVerificationAlert.tsx
│ │ │ │ │ ├── FeatureComparisonTable.module.css
│ │ │ │ │ ├── FeatureComparisonTable.tsx
│ │ │ │ │ ├── LogoutModal.tsx
│ │ │ │ │ ├── MobileChannelSettingsView.tsx
│ │ │ │ │ ├── MobileGuildSettingsView.module.css
│ │ │ │ │ ├── MobileGuildSettingsView.tsx
│ │ │ │ │ ├── MobileSettingsView.module.css
│ │ │ │ │ ├── MobileSettingsView.tsx
│ │ │ │ │ ├── PerksButton.module.css
│ │ │ │ │ ├── PerksButton.tsx
│ │ │ │ │ ├── PlutoniumContent.module.css
│ │ │ │ │ ├── PlutoniumContent.tsx
│ │ │ │ │ ├── PricingCard.module.css
│ │ │ │ │ ├── PricingCard.tsx
│ │ │ │ │ ├── PricingGrid.module.css
│ │ │ │ │ ├── PurchaseDisclaimer.module.css
│ │ │ │ │ ├── PurchaseDisclaimer.tsx
│ │ │ │ │ ├── SettingsModalHeader.module.css
│ │ │ │ │ ├── SettingsModalHeader.tsx
│ │ │ │ │ ├── SettingsSearch.module.css
│ │ │ │ │ ├── SettingsSearch.tsx
│ │ │ │ │ ├── SettingsSearchHighlight.css
│ │ │ │ │ ├── Slate.module.css
│ │ │ │ │ ├── Slate.tsx
│ │ │ │ │ ├── ToggleButton.module.css
│ │ │ │ │ ├── ToggleButton.tsx
│ │ │ │ │ ├── UnclaimedAccountAlert.tsx
│ │ │ │ │ └── plutonium/
│ │ │ │ │ ├── BottomCTASection.module.css
│ │ │ │ │ ├── BottomCTASection.tsx
│ │ │ │ │ ├── GiftInventoryBanner.module.css
│ │ │ │ │ ├── GiftInventoryBanner.tsx
│ │ │ │ │ ├── GiftSection.module.css
│ │ │ │ │ ├── GiftSection.tsx
│ │ │ │ │ ├── PlutoniumUpsellBanner.tsx
│ │ │ │ │ ├── PricingSection.module.css
│ │ │ │ │ ├── PricingSection.tsx
│ │ │ │ │ ├── PurchaseDisabledWrapper.tsx
│ │ │ │ │ ├── PurchaseHistorySection.module.css
│ │ │ │ │ ├── PurchaseHistorySection.tsx
│ │ │ │ │ ├── SectionHeader.module.css
│ │ │ │ │ ├── SectionHeader.tsx
│ │ │ │ │ ├── SubscriptionCard.module.css
│ │ │ │ │ ├── SubscriptionCard.tsx
│ │ │ │ │ └── hooks/
│ │ │ │ │ ├── useCheckoutActions.tsx
│ │ │ │ │ ├── useCommunityActions.tsx
│ │ │ │ │ ├── usePremiumData.tsx
│ │ │ │ │ ├── useSubscriptionActions.tsx
│ │ │ │ │ └── useSubscriptionStatus.tsx
│ │ │ │ ├── discovery/
│ │ │ │ │ ├── DiscoveryGuildCard.module.css
│ │ │ │ │ └── DiscoveryGuildCard.tsx
│ │ │ │ ├── guild_tabs/
│ │ │ │ │ ├── BannedUserActionsSheet.tsx
│ │ │ │ │ ├── GuildAuditLogTab.Components.tsx
│ │ │ │ │ ├── GuildAuditLogTab.Constants.tsx
│ │ │ │ │ ├── GuildAuditLogTab.Renderers.tsx
│ │ │ │ │ ├── GuildAuditLogTab.Utils.tsx
│ │ │ │ │ ├── GuildAuditLogTab.module.css
│ │ │ │ │ ├── GuildAuditLogTab.tsx
│ │ │ │ │ ├── GuildBansTab.tsx
│ │ │ │ │ ├── GuildDiscoveryTab.module.css
│ │ │ │ │ ├── GuildDiscoveryTab.tsx
│ │ │ │ │ ├── GuildEmojiTab.module.css
│ │ │ │ │ ├── GuildEmojiTab.tsx
│ │ │ │ │ ├── GuildInvitesTab.module.css
│ │ │ │ │ ├── GuildInvitesTab.tsx
│ │ │ │ │ ├── GuildMemberActionsSheet.module.css
│ │ │ │ │ ├── GuildMemberActionsSheet.tsx
│ │ │ │ │ ├── GuildMembersDateRangeModal.tsx
│ │ │ │ │ ├── GuildModerationTab.module.css
│ │ │ │ │ ├── GuildModerationTab.tsx
│ │ │ │ │ ├── GuildRolesTab.module.css
│ │ │ │ │ ├── GuildRolesTab.tsx
│ │ │ │ │ ├── GuildStickersTab.module.css
│ │ │ │ │ ├── GuildStickersTab.tsx
│ │ │ │ │ ├── GuildVanityURLTab.module.css
│ │ │ │ │ ├── GuildVanityURLTab.tsx
│ │ │ │ │ ├── GuildWebhooksTab.module.css
│ │ │ │ │ ├── GuildWebhooksTab.tsx
│ │ │ │ │ ├── MemberListStyles.module.css
│ │ │ │ │ ├── RoleMoveOperation.tsx
│ │ │ │ │ ├── UserListItem.tsx
│ │ │ │ │ └── guild_overview_tab/
│ │ │ │ │ ├── GuildOverviewTab.module.css
│ │ │ │ │ ├── GuildOverviewTypes.tsx
│ │ │ │ │ ├── components/
│ │ │ │ │ │ └── SettingsSection.tsx
│ │ │ │ │ ├── fields/
│ │ │ │ │ │ ├── GuildBannerUploadField.tsx
│ │ │ │ │ │ ├── GuildEmbedSplashUploadField.tsx
│ │ │ │ │ │ ├── GuildIconUploadField.tsx
│ │ │ │ │ │ ├── GuildInviteSplashSettingsField.tsx
│ │ │ │ │ │ └── GuildInviteSplashUploadField.tsx
│ │ │ │ │ ├── hooks/
│ │ │ │ │ │ └── useGuildImageAssetField.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ ├── sections/
│ │ │ │ │ │ ├── BrandingSection.tsx
│ │ │ │ │ │ ├── DefaultNotificationsSection.tsx
│ │ │ │ │ │ ├── IdleSettingsSection.tsx
│ │ │ │ │ │ ├── MessageHistoryCutoffSection.tsx
│ │ │ │ │ │ ├── MessageHistoryThresholdContent.tsx
│ │ │ │ │ │ ├── SystemWelcomeSection.tsx
│ │ │ │ │ │ └── TextChannelNamesSection.tsx
│ │ │ │ │ └── utils/
│ │ │ │ │ └── ImageAsset.tsx
│ │ │ │ ├── hooks/
│ │ │ │ │ ├── ScrollSpyContext.tsx
│ │ │ │ │ ├── useMobileNavigation.tsx
│ │ │ │ │ ├── useScrollSpy.tsx
│ │ │ │ │ ├── useSettingsContentKey.tsx
│ │ │ │ │ └── useUnsavedChangesFlash.tsx
│ │ │ │ ├── meme_form/
│ │ │ │ │ ├── MemeFormFields.module.css
│ │ │ │ │ └── MemeFormFields.tsx
│ │ │ │ ├── shared/
│ │ │ │ │ ├── AddOverridePopout.module.css
│ │ │ │ │ ├── AddOverridePopout.tsx
│ │ │ │ │ ├── CopyLinkSection.module.css
│ │ │ │ │ ├── CopyLinkSection.tsx
│ │ │ │ │ ├── EmptySlate.module.css
│ │ │ │ │ ├── EmptySlate.tsx
│ │ │ │ │ ├── ForwardChannelSelection.tsx
│ │ │ │ │ ├── GuildSelectComponents.tsx
│ │ │ │ │ ├── MobileSettingsComponents.module.css
│ │ │ │ │ ├── MobileSettingsComponents.tsx
│ │ │ │ │ ├── PermissionComponents.module.css
│ │ │ │ │ ├── PermissionComponents.tsx
│ │ │ │ │ ├── RecipientList.module.css
│ │ │ │ │ ├── RecipientList.tsx
│ │ │ │ │ ├── SelectorModalStyles.module.css
│ │ │ │ │ ├── SettingsModalLayout.module.css
│ │ │ │ │ ├── SettingsModalLayout.tsx
│ │ │ │ │ ├── SettingsSection.module.css
│ │ │ │ │ ├── SettingsSection.tsx
│ │ │ │ │ ├── SettingsTabLayout.module.css
│ │ │ │ │ ├── SettingsTabLayout.tsx
│ │ │ │ │ ├── StatusSlate.module.css
│ │ │ │ │ └── StatusSlate.tsx
│ │ │ │ ├── sticker_form/
│ │ │ │ │ ├── StickerFormFields.module.css
│ │ │ │ │ ├── StickerFormFields.tsx
│ │ │ │ │ ├── StickerPreview.module.css
│ │ │ │ │ └── StickerPreview.tsx
│ │ │ │ ├── tabs/
│ │ │ │ │ ├── AccessibilityTab.module.css
│ │ │ │ │ ├── AccessibilityTab.tsx
│ │ │ │ │ ├── AccountSecurityTab.module.css
│ │ │ │ │ ├── AccountSecurityTab.tsx
│ │ │ │ │ ├── AdvancedTab.tsx
│ │ │ │ │ ├── AppearanceTab.module.css
│ │ │ │ │ ├── AppearanceTab.tsx
│ │ │ │ │ ├── AuthorizedAppsTab.module.css
│ │ │ │ │ ├── AuthorizedAppsTab.tsx
│ │ │ │ │ ├── BlockedUsersTab.module.css
│ │ │ │ │ ├── BlockedUsersTab.tsx
│ │ │ │ │ ├── ChatSettingsTab.module.css
│ │ │ │ │ ├── ChatSettingsTab.tsx
│ │ │ │ │ ├── DevicesTab.module.css
│ │ │ │ │ ├── DevicesTab.tsx
│ │ │ │ │ ├── ExpressionPacksTab.module.css
│ │ │ │ │ ├── ExpressionPacksTab.tsx
│ │ │ │ │ ├── GiftInventoryTab.module.css
│ │ │ │ │ ├── GiftInventoryTab.tsx
│ │ │ │ │ ├── KeybindsTab.module.css
│ │ │ │ │ ├── KeybindsTab.tsx
│ │ │ │ │ ├── LanguageTab.module.css
│ │ │ │ │ ├── LanguageTab.tsx
│ │ │ │ │ ├── LimitsConfigTab.module.css
│ │ │ │ │ ├── LimitsConfigTab.tsx
│ │ │ │ │ ├── LinkedAccountsTab.module.css
│ │ │ │ │ ├── LinkedAccountsTab.tsx
│ │ │ │ │ ├── MyProfileTab.module.css
│ │ │ │ │ ├── MyProfileTab.tsx
│ │ │ │ │ ├── NotificationsTab.tsx
│ │ │ │ │ ├── PlutoniumTab.tsx
│ │ │ │ │ ├── PrivacySafetyTab.module.css
│ │ │ │ │ ├── PrivacySafetyTab.tsx
│ │ │ │ │ ├── VideoTab.module.css
│ │ │ │ │ ├── VideoTab.tsx
│ │ │ │ │ ├── VoiceTab.module.css
│ │ │ │ │ ├── VoiceTab.tsx
│ │ │ │ │ ├── VoiceVideoTab.module.css
│ │ │ │ │ ├── VoiceVideoTab.tsx
│ │ │ │ │ ├── accessibility_tab/
│ │ │ │ │ │ ├── AnimationTab.module.css
│ │ │ │ │ │ ├── AnimationTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── KeyboardTab.tsx
│ │ │ │ │ │ ├── MotionTab.tsx
│ │ │ │ │ │ ├── VisualTab.module.css
│ │ │ │ │ │ └── VisualTab.tsx
│ │ │ │ │ ├── account_security_tab/
│ │ │ │ │ │ ├── AccountTab.module.css
│ │ │ │ │ │ ├── AccountTab.tsx
│ │ │ │ │ │ ├── DangerZoneTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── SecurityTab.module.css
│ │ │ │ │ │ └── SecurityTab.tsx
│ │ │ │ │ ├── appearance_tab/
│ │ │ │ │ │ ├── ActiveNowTab.tsx
│ │ │ │ │ │ ├── ChannelListTab.tsx
│ │ │ │ │ │ ├── FavoritesTab.tsx
│ │ │ │ │ │ ├── HdrTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── InterfaceTab.module.css
│ │ │ │ │ │ ├── InterfaceTab.tsx
│ │ │ │ │ │ ├── MessagesTab.module.css
│ │ │ │ │ │ ├── MessagesTab.tsx
│ │ │ │ │ │ ├── ScalingTab.tsx
│ │ │ │ │ │ ├── ThemeTab.module.css
│ │ │ │ │ │ └── ThemeTab.tsx
│ │ │ │ │ ├── applications_tab/
│ │ │ │ │ │ ├── ApplicationCreateModal.tsx
│ │ │ │ │ │ ├── ApplicationDetail.tsx
│ │ │ │ │ │ ├── ApplicationsList.tsx
│ │ │ │ │ │ ├── ApplicationsTab.module.css
│ │ │ │ │ │ ├── ApplicationsTabStore.tsx
│ │ │ │ │ │ ├── application_detail/
│ │ │ │ │ │ │ ├── ApplicationDetail.module.css
│ │ │ │ │ │ │ ├── ApplicationDetailTypes.tsx
│ │ │ │ │ │ │ ├── ApplicationHeader.tsx
│ │ │ │ │ │ │ ├── ApplicationInfoSection.tsx
│ │ │ │ │ │ │ ├── BotProfileSection.tsx
│ │ │ │ │ │ │ ├── OAuthBuilderSection.tsx
│ │ │ │ │ │ │ ├── SecretsSection.tsx
│ │ │ │ │ │ │ └── SectionCard.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── chat_settings_tab/
│ │ │ │ │ │ ├── DisplayTab.module.css
│ │ │ │ │ │ ├── DisplayTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── InputTab.module.css
│ │ │ │ │ │ ├── InputTab.tsx
│ │ │ │ │ │ ├── InteractionTab.module.css
│ │ │ │ │ │ ├── InteractionTab.tsx
│ │ │ │ │ │ ├── LinksTab.tsx
│ │ │ │ │ │ ├── MediaTab.module.css
│ │ │ │ │ │ ├── MediaTab.tsx
│ │ │ │ │ │ └── SidebarTab.tsx
│ │ │ │ │ ├── component_gallery_tab/
│ │ │ │ │ │ ├── ButtonsTab.module.css
│ │ │ │ │ │ ├── ButtonsTab.tsx
│ │ │ │ │ │ ├── ComponentGalleryTabSubsectionTitle.tsx
│ │ │ │ │ │ ├── IndicatorsTab.module.css
│ │ │ │ │ │ ├── IndicatorsTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── InputsTab.module.css
│ │ │ │ │ │ ├── InputsTab.tsx
│ │ │ │ │ │ ├── MarkdownTab.module.css
│ │ │ │ │ │ ├── MarkdownTab.tsx
│ │ │ │ │ │ ├── MessagesTab.module.css
│ │ │ │ │ │ ├── MessagesTab.tsx
│ │ │ │ │ │ ├── OverlaysTab.module.css
│ │ │ │ │ │ ├── OverlaysTab.tsx
│ │ │ │ │ │ ├── SelectionsTab.module.css
│ │ │ │ │ │ ├── SelectionsTab.tsx
│ │ │ │ │ │ ├── index.tsx
│ │ │ │ │ │ └── shared.module.css
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── EntranceSoundSection.module.css
│ │ │ │ │ │ ├── EntranceSoundSection.tsx
│ │ │ │ │ │ ├── InputMonitoringSection.tsx
│ │ │ │ │ │ ├── MicTestSection.module.css
│ │ │ │ │ │ └── MicTestSection.tsx
│ │ │ │ │ ├── developer_options_tab/
│ │ │ │ │ │ ├── AccountPremiumTab.module.css
│ │ │ │ │ │ ├── AccountPremiumTab.tsx
│ │ │ │ │ │ ├── DeveloperOptionsToggleGroups.tsx
│ │ │ │ │ │ ├── GeneralTab.module.css
│ │ │ │ │ │ ├── GeneralTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── MockingTab.module.css
│ │ │ │ │ │ ├── MockingTab.tsx
│ │ │ │ │ │ ├── NagbarControls.tsx
│ │ │ │ │ │ ├── NagbarsTab.module.css
│ │ │ │ │ │ ├── NagbarsTab.tsx
│ │ │ │ │ │ ├── PremiumScenarioOptions.tsx
│ │ │ │ │ │ ├── ToolsTab.module.css
│ │ │ │ │ │ ├── ToolsTab.tsx
│ │ │ │ │ │ ├── TypographyTab.module.css
│ │ │ │ │ │ ├── TypographyTab.tsx
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ ├── hooks/
│ │ │ │ │ │ ├── useEntranceSound.tsx
│ │ │ │ │ │ ├── useMediaPermission.tsx
│ │ │ │ │ │ └── useMicTest.tsx
│ │ │ │ │ ├── my_profile_tab/
│ │ │ │ │ │ ├── AccentColorPicker.module.css
│ │ │ │ │ │ ├── AccentColorPicker.tsx
│ │ │ │ │ │ ├── AvatarUploader.module.css
│ │ │ │ │ │ ├── AvatarUploader.tsx
│ │ │ │ │ │ ├── BannerUploader.module.css
│ │ │ │ │ │ ├── BannerUploader.tsx
│ │ │ │ │ │ ├── BioEditor.module.css
│ │ │ │ │ │ ├── BioEditor.tsx
│ │ │ │ │ │ ├── PerGuildPremiumUpsell.tsx
│ │ │ │ │ │ ├── PremiumBadgeSettings.module.css
│ │ │ │ │ │ ├── PremiumBadgeSettings.tsx
│ │ │ │ │ │ ├── ProfileTypeSelector.module.css
│ │ │ │ │ │ ├── ProfileTypeSelector.tsx
│ │ │ │ │ │ ├── UsernameSection.module.css
│ │ │ │ │ │ └── UsernameSection.tsx
│ │ │ │ │ ├── notifications_tab/
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ ├── Inline.tsx
│ │ │ │ │ │ ├── Notifications.module.css
│ │ │ │ │ │ ├── Notifications.tsx
│ │ │ │ │ │ ├── PushSettings.module.css
│ │ │ │ │ │ ├── PushSettings.tsx
│ │ │ │ │ │ ├── Sounds.module.css
│ │ │ │ │ │ ├── Sounds.tsx
│ │ │ │ │ │ ├── TextToSpeech.module.css
│ │ │ │ │ │ ├── TextToSpeech.tsx
│ │ │ │ │ │ └── useSoundSettings.tsx
│ │ │ │ │ ├── privacy_safety_tab/
│ │ │ │ │ │ ├── CommunicationTab.module.css
│ │ │ │ │ │ ├── CommunicationTab.tsx
│ │ │ │ │ │ ├── ConnectionsTab.module.css
│ │ │ │ │ │ ├── ConnectionsTab.tsx
│ │ │ │ │ │ ├── DataDeletionTab.module.css
│ │ │ │ │ │ ├── DataDeletionTab.tsx
│ │ │ │ │ │ ├── DataExportTab.tsx
│ │ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ │ └── Inline.tsx
│ │ │ │ │ └── voice_video_tab/
│ │ │ │ │ ├── Inline.module.css
│ │ │ │ │ └── Inline.tsx
│ │ │ │ └── utils/
│ │ │ │ ├── AppZoomLevelUtils.tsx
│ │ │ │ ├── ChannelSettingsConstants.tsx
│ │ │ │ ├── DesktopSettingsTabs.tsx
│ │ │ │ ├── GuildSettingsConstants.tsx
│ │ │ │ ├── SettingsConstants.tsx
│ │ │ │ ├── SettingsSearchIndex.tsx
│ │ │ │ ├── SettingsSectionRegistry.tsx
│ │ │ │ └── SettingsTabFilters.tsx
│ │ │ ├── pages/
│ │ │ │ ├── AuthorizeIPPage.module.css
│ │ │ │ ├── AuthorizeIPPage.tsx
│ │ │ │ ├── ConnectionCallbackPage.module.css
│ │ │ │ ├── ConnectionCallbackPage.tsx
│ │ │ │ ├── EmailRevertPage.tsx
│ │ │ │ ├── ForgotPasswordPage.module.css
│ │ │ │ ├── ForgotPasswordPage.tsx
│ │ │ │ ├── GiftLoginPage.tsx
│ │ │ │ ├── GiftRegisterPage.tsx
│ │ │ │ ├── InviteLoginPage.tsx
│ │ │ │ ├── InviteRegisterPage.tsx
│ │ │ │ ├── LoginPage.module.css
│ │ │ │ ├── LoginPage.tsx
│ │ │ │ ├── MessageListPage.module.css
│ │ │ │ ├── MessageListPage.tsx
│ │ │ │ ├── NotFoundPage.module.css
│ │ │ │ ├── NotFoundPage.tsx
│ │ │ │ ├── NotificationsPage.module.css
│ │ │ │ ├── NotificationsPage.tsx
│ │ │ │ ├── OAuthAuthorizePage.module.css
│ │ │ │ ├── OAuthAuthorizePage.tsx
│ │ │ │ ├── PremiumCallbackPage.module.css
│ │ │ │ ├── PremiumCallbackPage.tsx
│ │ │ │ ├── RecentMentionsPage.module.css
│ │ │ │ ├── RecentMentionsPage.tsx
│ │ │ │ ├── RegisterPage.tsx
│ │ │ │ ├── ReportPage.module.css
│ │ │ │ ├── ReportPage.tsx
│ │ │ │ ├── ResetPasswordPage.module.css
│ │ │ │ ├── ResetPasswordPage.tsx
│ │ │ │ ├── SavedMessagesPage.module.css
│ │ │ │ ├── SavedMessagesPage.tsx
│ │ │ │ ├── SsoCallbackPage.tsx
│ │ │ │ ├── ThemeLoginPage.tsx
│ │ │ │ ├── ThemeRegisterPage.tsx
│ │ │ │ ├── VerifyEmailPage.module.css
│ │ │ │ ├── VerifyEmailPage.tsx
│ │ │ │ ├── YouPage.module.css
│ │ │ │ ├── YouPage.tsx
│ │ │ │ └── report/
│ │ │ │ ├── OptionDescriptors.tsx
│ │ │ │ ├── ReportBreadcrumbs.tsx
│ │ │ │ ├── ReportStepComplete.tsx
│ │ │ │ ├── ReportStepDetails.tsx
│ │ │ │ ├── ReportStepEmail.tsx
│ │ │ │ ├── ReportStepSelection.tsx
│ │ │ │ ├── ReportStepVerification.tsx
│ │ │ │ ├── ReportTypes.tsx
│ │ │ │ ├── State.tsx
│ │ │ │ └── Validators.tsx
│ │ │ ├── panels/
│ │ │ │ ├── ExpressionPickerPanel.tsx
│ │ │ │ └── panels/
│ │ │ │ └── GuildExpressionPickerPanel.tsx
│ │ │ ├── popouts/
│ │ │ │ ├── ChannelPinsPopout.module.css
│ │ │ │ ├── ChannelPinsPopout.tsx
│ │ │ │ ├── ColorPickerPopout.module.css
│ │ │ │ ├── ColorPickerPopout.tsx
│ │ │ │ ├── EmojiPickerPopout.tsx
│ │ │ │ ├── ExpressionPickerPopout.module.css
│ │ │ │ ├── ExpressionPickerPopout.tsx
│ │ │ │ ├── FavoritesGuildHeaderPopout.tsx
│ │ │ │ ├── GuildHeaderPopout.module.css
│ │ │ │ ├── GuildHeaderPopout.tsx
│ │ │ │ ├── GuildIcon.module.css
│ │ │ │ ├── GuildIcon.tsx
│ │ │ │ ├── InboxMessageHeader.module.css
│ │ │ │ ├── InboxMessageHeader.tsx
│ │ │ │ ├── InboxPopout.module.css
│ │ │ │ ├── InboxPopout.tsx
│ │ │ │ ├── ReactionTooltip.module.css
│ │ │ │ ├── ReactionTooltip.tsx
│ │ │ │ ├── RecentMentionsContent.module.css
│ │ │ │ ├── RecentMentionsContent.tsx
│ │ │ │ ├── SavedMessagesContent.module.css
│ │ │ │ ├── SavedMessagesContent.tsx
│ │ │ │ ├── ScheduledMessagesContent.module.css
│ │ │ │ ├── ScheduledMessagesContent.tsx
│ │ │ │ ├── UnreadChannelsContent.module.css
│ │ │ │ ├── UnreadChannelsContent.tsx
│ │ │ │ ├── UserAreaPopout.module.css
│ │ │ │ ├── UserAreaPopout.tsx
│ │ │ │ ├── UserProfileBadges.module.css
│ │ │ │ ├── UserProfileBadges.tsx
│ │ │ │ ├── UserProfileDataWarning.tsx
│ │ │ │ ├── UserProfilePopout.module.css
│ │ │ │ ├── UserProfilePopout.tsx
│ │ │ │ ├── UserProfileShared.module.css
│ │ │ │ └── UserProfileShared.tsx
│ │ │ ├── profile/
│ │ │ │ ├── ProfilePreview.module.css
│ │ │ │ ├── ProfilePreview.tsx
│ │ │ │ ├── VoiceActivityCard.module.css
│ │ │ │ ├── VoiceActivityCard.tsx
│ │ │ │ ├── VoiceActivitySection.module.css
│ │ │ │ ├── VoiceActivitySection.tsx
│ │ │ │ ├── profile_card/
│ │ │ │ │ ├── ProfileCardActions.module.css
│ │ │ │ │ ├── ProfileCardActions.tsx
│ │ │ │ │ ├── ProfileCardBanner.module.css
│ │ │ │ │ ├── ProfileCardBanner.tsx
│ │ │ │ │ ├── ProfileCardContent.module.css
│ │ │ │ │ ├── ProfileCardContent.tsx
│ │ │ │ │ ├── ProfileCardFooter.module.css
│ │ │ │ │ ├── ProfileCardFooter.tsx
│ │ │ │ │ ├── ProfileCardLayout.module.css
│ │ │ │ │ ├── ProfileCardLayout.tsx
│ │ │ │ │ ├── ProfileCardUserInfo.module.css
│ │ │ │ │ └── ProfileCardUserInfo.tsx
│ │ │ │ └── useProfileCardDisplayState.tsx
│ │ │ ├── quick_switcher/
│ │ │ │ ├── QuickSwitcherConstants.tsx
│ │ │ │ ├── QuickSwitcherModal.module.css
│ │ │ │ └── QuickSwitcherModal.tsx
│ │ │ ├── search/
│ │ │ │ ├── HasFilterSheet.module.css
│ │ │ │ ├── HasFilterSheet.tsx
│ │ │ │ ├── ScopeSheet.module.css
│ │ │ │ ├── ScopeSheet.tsx
│ │ │ │ ├── SearchFilterChip.module.css
│ │ │ │ ├── SearchFilterChip.tsx
│ │ │ │ ├── SortModeSheet.module.css
│ │ │ │ ├── SortModeSheet.tsx
│ │ │ │ ├── UserFilterSheet.module.css
│ │ │ │ └── UserFilterSheet.tsx
│ │ │ ├── shared/
│ │ │ │ ├── ChannelPinsContent.tsx
│ │ │ │ ├── ImagePreviewField.module.css
│ │ │ │ ├── ImagePreviewField.tsx
│ │ │ │ ├── MessagePreview.module.css
│ │ │ │ ├── MessageReactionsContent.module.css
│ │ │ │ ├── MessageReactionsContent.tsx
│ │ │ │ ├── SavedMessageMissingCard.tsx
│ │ │ │ └── message_context_prefix/
│ │ │ │ ├── MessageContextPrefix.module.css
│ │ │ │ └── MessageContextPrefix.tsx
│ │ │ ├── stickers/
│ │ │ │ ├── StickerGridItem.module.css
│ │ │ │ └── StickerGridItem.tsx
│ │ │ ├── uikit/
│ │ │ │ ├── Avatar.tsx
│ │ │ │ ├── AvatarStatusGeometry.tsx
│ │ │ │ ├── AvatarStatusLayout.tsx
│ │ │ │ ├── BaseAvatar.module.css
│ │ │ │ ├── BaseAvatar.tsx
│ │ │ │ ├── FocusRingWrapper.tsx
│ │ │ │ ├── InlineEdit.module.css
│ │ │ │ ├── InlineEdit.tsx
│ │ │ │ ├── KeyboardKey.module.css
│ │ │ │ ├── KeyboardKey.tsx
│ │ │ │ ├── LiveBadge.module.css
│ │ │ │ ├── LiveBadge.tsx
│ │ │ │ ├── MentionBadge.module.css
│ │ │ │ ├── MentionBadge.tsx
│ │ │ │ ├── MockAvatar.tsx
│ │ │ │ ├── QRCodeCanvas.tsx
│ │ │ │ ├── Scroller.module.css
│ │ │ │ ├── Scroller.tsx
│ │ │ │ ├── Slider.module.css
│ │ │ │ ├── Slider.tsx
│ │ │ │ ├── SliderTooltip.module.css
│ │ │ │ ├── Spinner.module.css
│ │ │ │ ├── Spinner.tsx
│ │ │ │ ├── StatusAwareAvatar.tsx
│ │ │ │ ├── StatusIndicator.module.css
│ │ │ │ ├── StatusIndicator.tsx
│ │ │ │ ├── SwitchGroup.module.css
│ │ │ │ ├── SwitchGroup.tsx
│ │ │ │ ├── TypingConstants.tsx
│ │ │ │ ├── accordion/
│ │ │ │ │ ├── Accordion.module.css
│ │ │ │ │ └── Accordion.tsx
│ │ │ │ ├── alt_text_tooltip/
│ │ │ │ │ ├── AltTextTooltip.module.css
│ │ │ │ │ └── AltTextTooltip.tsx
│ │ │ │ ├── avatars/
│ │ │ │ │ ├── AvatarStack.module.css
│ │ │ │ │ ├── AvatarStack.tsx
│ │ │ │ │ ├── AvatarWithPresence.module.css
│ │ │ │ │ ├── AvatarWithPresence.tsx
│ │ │ │ │ ├── StackUserAvatar.module.css
│ │ │ │ │ └── StackUserAvatar.tsx
│ │ │ │ ├── bottom_sheet/
│ │ │ │ │ └── BottomSheet.tsx
│ │ │ │ ├── button/
│ │ │ │ │ ├── Button.module.css
│ │ │ │ │ └── Button.tsx
│ │ │ │ ├── card_alignment_controls/
│ │ │ │ │ ├── CardAlignmentControls.module.css
│ │ │ │ │ └── CardAlignmentControls.tsx
│ │ │ │ ├── character_counter/
│ │ │ │ │ ├── CharacterCounter.module.css
│ │ │ │ │ └── CharacterCounter.tsx
│ │ │ │ ├── checkbox/
│ │ │ │ │ ├── Checkbox.module.css
│ │ │ │ │ └── Checkbox.tsx
│ │ │ │ ├── context_menu/
│ │ │ │ │ ├── BannedUserContextMenu.tsx
│ │ │ │ │ ├── CategoryContextMenu.tsx
│ │ │ │ │ ├── ChannelContextMenu.tsx
│ │ │ │ │ ├── ChannelListContextMenu.tsx
│ │ │ │ │ ├── ContextMenu.module.css
│ │ │ │ │ ├── ContextMenu.tsx
│ │ │ │ │ ├── ContextMenuIcons.tsx
│ │ │ │ │ ├── DMContextMenu.tsx
│ │ │ │ │ ├── DataMenuRenderer.tsx
│ │ │ │ │ ├── FavoritesCategoryContextMenu.tsx
│ │ │ │ │ ├── FavoritesChannelContextMenu.tsx
│ │ │ │ │ ├── FavoritesChannelListContextMenu.tsx
│ │ │ │ │ ├── FavoritesGuildContextMenu.tsx
│ │ │ │ │ ├── GroupDMContextMenu.tsx
│ │ │ │ │ ├── GuildContextMenu.tsx
│ │ │ │ │ ├── GuildFolderContextMenu.tsx
│ │ │ │ │ ├── GuildMemberContextMenu.tsx
│ │ │ │ │ ├── MediaContextMenu.tsx
│ │ │ │ │ ├── MenuGroup.tsx
│ │ │ │ │ ├── MenuGroups.tsx
│ │ │ │ │ ├── MenuItem.module.css
│ │ │ │ │ ├── MenuItem.tsx
│ │ │ │ │ ├── MenuItemRadio.module.css
│ │ │ │ │ ├── MenuItemRadio.tsx
│ │ │ │ │ ├── MenuItemSlider.tsx
│ │ │ │ │ ├── MenuItemSubmenu.tsx
│ │ │ │ │ ├── MessageContextMenu.tsx
│ │ │ │ │ ├── SettingsContextMenu.tsx
│ │ │ │ │ ├── UserContextMenu.tsx
│ │ │ │ │ ├── VoiceParticipantContextMenu.tsx
│ │ │ │ │ ├── WebhookContextMenu.tsx
│ │ │ │ │ └── items/
│ │ │ │ │ ├── ActionsSubmenu.tsx
│ │ │ │ │ ├── CallMenuItems.tsx
│ │ │ │ │ ├── CategoryMenuData.tsx
│ │ │ │ │ ├── CategoryMenuItems.tsx
│ │ │ │ │ ├── ChannelMenuData.tsx
│ │ │ │ │ ├── ChannelMenuItems.tsx
│ │ │ │ │ ├── CopyMenuItems.tsx
│ │ │ │ │ ├── DMMenuData.tsx
│ │ │ │ │ ├── DMMenuItems.tsx
│ │ │ │ │ ├── DebugMenuItems.tsx
│ │ │ │ │ ├── GuildMemberMenuItems.tsx
│ │ │ │ │ ├── GuildMenuData.tsx
│ │ │ │ │ ├── GuildMenuItems.tsx
│ │ │ │ │ ├── InviteMenuItems.tsx
│ │ │ │ │ ├── MediaMenuData.tsx
│ │ │ │ │ ├── MentionUserMenuItem.tsx
│ │ │ │ │ ├── MenuItems.module.css
│ │ │ │ │ ├── MessageMenuItems.tsx
│ │ │ │ │ ├── MessageUserMenuItem.tsx
│ │ │ │ │ ├── ModerationSubmenu.tsx
│ │ │ │ │ ├── MoveToChannelSubmenu.tsx
│ │ │ │ │ ├── RelationshipMenuItems.tsx
│ │ │ │ │ ├── ReportGuildMenuItem.tsx
│ │ │ │ │ ├── ReportMessageMenuItem.tsx
│ │ │ │ │ ├── UserNoteMenuItems.tsx
│ │ │ │ │ ├── UserProfileMenuItem.tsx
│ │ │ │ │ ├── VoiceParticipantMenuData.tsx
│ │ │ │ │ └── VoiceParticipantMenuItems.tsx
│ │ │ │ ├── emoji_tooltip_content/
│ │ │ │ │ ├── EmojiTooltipContent.module.css
│ │ │ │ │ └── EmojiTooltipContent.tsx
│ │ │ │ ├── focus_ring/
│ │ │ │ │ ├── FocusRing.module.css
│ │ │ │ │ ├── FocusRing.tsx
│ │ │ │ │ ├── FocusRingContext.tsx
│ │ │ │ │ ├── FocusRingManager.tsx
│ │ │ │ │ ├── FocusRingScope.tsx
│ │ │ │ │ └── FocusRingTypes.tsx
│ │ │ │ ├── keybind_hint/
│ │ │ │ │ ├── KeybindHint.module.css
│ │ │ │ │ └── KeybindHint.tsx
│ │ │ │ ├── menu_bottom_sheet/
│ │ │ │ │ ├── MenuBottomSheet.module.css
│ │ │ │ │ └── MenuBottomSheet.tsx
│ │ │ │ ├── plutonium_link/
│ │ │ │ │ ├── PlutoniumLink.module.css
│ │ │ │ │ └── PlutoniumLink.tsx
│ │ │ │ ├── plutonium_upsell/
│ │ │ │ │ ├── PlutoniumUpsell.module.css
│ │ │ │ │ └── PlutoniumUpsell.tsx
│ │ │ │ ├── popout/
│ │ │ │ │ ├── Popout.module.css
│ │ │ │ │ ├── Popout.tsx
│ │ │ │ │ ├── Popouts.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── searchable_list_popout/
│ │ │ │ │ ├── SearchableListPopout.module.css
│ │ │ │ │ └── SearchableListPopout.tsx
│ │ │ │ ├── radio_group/
│ │ │ │ │ ├── RadioGroup.module.css
│ │ │ │ │ └── RadioGroup.tsx
│ │ │ │ ├── scroller/
│ │ │ │ │ ├── ScrollerMath.tsx
│ │ │ │ │ ├── ScrollerTrack.module.css
│ │ │ │ │ ├── ScrollerTrack.tsx
│ │ │ │ │ └── useScrollerThumb.tsx
│ │ │ │ ├── segmented_tabs/
│ │ │ │ │ ├── SegmentedTabs.module.css
│ │ │ │ │ └── SegmentedTabs.tsx
│ │ │ │ ├── sheet/
│ │ │ │ │ ├── Sheet.module.css
│ │ │ │ │ └── Sheet.tsx
│ │ │ │ ├── tabs/
│ │ │ │ │ ├── Tabs.module.css
│ │ │ │ │ └── Tabs.tsx
│ │ │ │ ├── toast/
│ │ │ │ │ ├── Toast.module.css
│ │ │ │ │ ├── Toast.tsx
│ │ │ │ │ ├── Toasts.module.css
│ │ │ │ │ ├── Toasts.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── tooltip/
│ │ │ │ │ ├── Tooltip.module.css
│ │ │ │ │ └── Tooltip.tsx
│ │ │ │ └── warning_alert/
│ │ │ │ ├── WarningAlert.module.css
│ │ │ │ └── WarningAlert.tsx
│ │ │ ├── voice/
│ │ │ │ ├── CompactVoiceCallView.module.css
│ │ │ │ ├── CompactVoiceCallView.tsx
│ │ │ │ ├── FeedHiddenOverlay.module.css
│ │ │ │ ├── FeedHiddenOverlay.tsx
│ │ │ │ ├── GetPlaceholderAvatarColor.tsx
│ │ │ │ ├── HiddenStreamPlaceholder.module.css
│ │ │ │ ├── HiddenStreamPlaceholder.tsx
│ │ │ │ ├── IncomingCallManager.module.css
│ │ │ │ ├── IncomingCallManager.tsx
│ │ │ │ ├── IncomingCallOverlayConstants.tsx
│ │ │ │ ├── IncomingCallPortal.tsx
│ │ │ │ ├── IncomingCallUI.module.css
│ │ │ │ ├── IncomingCallUI.tsx
│ │ │ │ ├── NewDeviceMonitoringManager.tsx
│ │ │ │ ├── OwnStreamPreviewState.tsx
│ │ │ │ ├── PiPOverlay.module.css
│ │ │ │ ├── PiPOverlay.tsx
│ │ │ │ ├── SignalStrengthIcon.module.css
│ │ │ │ ├── SignalStrengthIcon.tsx
│ │ │ │ ├── StreamFocusHeaderInfo.tsx
│ │ │ │ ├── StreamInfoPill.module.css
│ │ │ │ ├── StreamInfoPill.tsx
│ │ │ │ ├── StreamKeys.tsx
│ │ │ │ ├── StreamSpectatorsPopout.module.css
│ │ │ │ ├── StreamSpectatorsPopout.tsx
│ │ │ │ ├── StreamWatchHoverCard.module.css
│ │ │ │ ├── StreamWatchHoverCard.tsx
│ │ │ │ ├── StreamWatchHoverPopout.tsx
│ │ │ │ ├── VoiceCallFullscreenFeatureFlag.tsx
│ │ │ │ ├── VoiceCallLayoutContent.tsx
│ │ │ │ ├── VoiceCallView.module.css
│ │ │ │ ├── VoiceCallView.tsx
│ │ │ │ ├── VoiceConnectionStatus.module.css
│ │ │ │ ├── VoiceConnectionStatus.tsx
│ │ │ │ ├── VoiceControlBar.module.css
│ │ │ │ ├── VoiceControlBar.tsx
│ │ │ │ ├── VoiceGridLayout.module.css
│ │ │ │ ├── VoiceGridLayout.tsx
│ │ │ │ ├── VoiceParticipantAvatarList.module.css
│ │ │ │ ├── VoiceParticipantAvatarList.tsx
│ │ │ │ ├── VoiceParticipantSortUtils.tsx
│ │ │ │ ├── VoiceParticipantSpeakingUtils.tsx
│ │ │ │ ├── VoiceParticipantTile.module.css
│ │ │ │ ├── VoiceParticipantTile.tsx
│ │ │ │ ├── VoiceReconnectionManager.tsx
│ │ │ │ ├── VoiceRegionSelector.module.css
│ │ │ │ ├── VoiceRegionSelector.tsx
│ │ │ │ ├── VoiceSettingsMenus.module.css
│ │ │ │ ├── VoiceSettingsMenus.tsx
│ │ │ │ ├── VoiceStatsOverlay.module.css
│ │ │ │ ├── VoiceStatsOverlay.tsx
│ │ │ │ ├── usePinnedTrackRef.tsx
│ │ │ │ ├── useStreamPreview.tsx
│ │ │ │ ├── useStreamSpectators.tsx
│ │ │ │ ├── useStreamTrackInfo.tsx
│ │ │ │ ├── useStreamWatchState.tsx
│ │ │ │ ├── useVoiceCallAppFullscreen.tsx
│ │ │ │ └── useVoiceCallTracksAndLayout.tsx
│ │ │ └── webhooks/
│ │ │ ├── WebhookListItem.module.css
│ │ │ └── WebhookListItem.tsx
│ │ ├── constants/
│ │ │ ├── AuditLogConstants.tsx
│ │ │ ├── HelpCenterConstants.tsx
│ │ │ ├── IARConstants.tsx
│ │ │ └── TimeWindowPresets.tsx
│ │ ├── contexts/
│ │ │ ├── AuthLayoutContext.tsx
│ │ │ ├── AuthRegisterDraftContext.tsx
│ │ │ └── LayoutVariantContext.tsx
│ │ ├── data/
│ │ │ ├── CountryCodes.tsx
│ │ │ ├── emoji-shortcuts.json
│ │ │ └── emojis.json
│ │ ├── devtools/
│ │ │ └── ShowMyselfTypingHelper.tsx
│ │ ├── env.d.ts
│ │ ├── global.css
│ │ ├── hooks/
│ │ │ ├── useActivityRecorder.tsx
│ │ │ ├── useAntiShiftFloating.tsx
│ │ │ ├── useAudioSettingsMenu.tsx
│ │ │ ├── useAuthBackground.tsx
│ │ │ ├── useAuthForm.tsx
│ │ │ ├── useAutoplayExpandedProfileAnimations.tsx
│ │ │ ├── useBottomSheetBackHandler.tsx
│ │ │ ├── useCaptcha.tsx
│ │ │ ├── useChannelMemberListVisibility.tsx
│ │ │ ├── useChannelSearch.tsx
│ │ │ ├── useChannelSearchVisibility.tsx
│ │ │ ├── useCloudUpload.tsx
│ │ │ ├── useCommands.tsx
│ │ │ ├── useConnectedVoiceSession.tsx
│ │ │ ├── useContextMenuHoverState.tsx
│ │ │ ├── useCursorAtEnd.tsx
│ │ │ ├── useDeleteAttachment.tsx
│ │ │ ├── useElectronScreenSharePicker.tsx
│ │ │ ├── useFluxerDocumentTitle.tsx
│ │ │ ├── useForceUpdate.tsx
│ │ │ ├── useForm.tsx
│ │ │ ├── useFormSubmit.tsx
│ │ │ ├── useHashParam.tsx
│ │ │ ├── useHover.tsx
│ │ │ ├── useInputFocusManagement.tsx
│ │ │ ├── useInviteCountdown.tsx
│ │ │ ├── useInviteRevoke.tsx
│ │ │ ├── useLeaveGroup.tsx
│ │ │ ├── useLeaveGuild.tsx
│ │ │ ├── useListNavigation.tsx
│ │ │ ├── useLoginFlow.tsx
│ │ │ ├── useMarkdownKeybinds.tsx
│ │ │ ├── useMasonryGridNavigation.tsx
│ │ │ ├── useMediaDevices.tsx
│ │ │ ├── useMediaFavorite.tsx
│ │ │ ├── useMediaLoading.tsx
│ │ │ ├── useMemberListCustomStatus.tsx
│ │ │ ├── useMemberListPresence.tsx
│ │ │ ├── useMemberListSubscription.tsx
│ │ │ ├── useMemberListVisible.tsx
│ │ │ ├── useMergeRefs.tsx
│ │ │ ├── useMessageListKeyboardNavigation.tsx
│ │ │ ├── useMessageReactionsState.tsx
│ │ │ ├── useMessageSubmission.tsx
│ │ │ ├── useMuteSheet.tsx
│ │ │ ├── useNSFWMedia.tsx
│ │ │ ├── useNativePlatform.tsx
│ │ │ ├── usePendingVoiceConnection.tsx
│ │ │ ├── usePopout.tsx
│ │ │ ├── usePremiumUpsellData.tsx
│ │ │ ├── usePresenceCustomStatus.tsx
│ │ │ ├── usePressable.tsx
│ │ │ ├── usePushSubscriptions.tsx
│ │ │ ├── useReactionTooltip.tsx
│ │ │ ├── useRoleHierarchy.tsx
│ │ │ ├── useRovingFocusList.tsx
│ │ │ ├── useSearchInputAutofocus.tsx
│ │ │ ├── useSlowmode.tsx
│ │ │ ├── useStickerAnimation.tsx
│ │ │ ├── useStreamWatchDoubleClick.tsx
│ │ │ ├── useSudo.tsx
│ │ │ ├── useSystemMessageData.tsx
│ │ │ ├── useTextInputContextMenu.tsx
│ │ │ ├── useTextOverflow.tsx
│ │ │ ├── useTextareaAutocomplete.tsx
│ │ │ ├── useTextareaAutocompleteKeyboard.tsx
│ │ │ ├── useTextareaAutofocus.tsx
│ │ │ ├── useTextareaDraftAndTyping.tsx
│ │ │ ├── useTextareaEditing.tsx
│ │ │ ├── useTextareaEmojiPicker.tsx
│ │ │ ├── useTextareaExpressionHandlers.tsx
│ │ │ ├── useTextareaExpressionPicker.tsx
│ │ │ ├── useTextareaKeyboard.tsx
│ │ │ ├── useTextareaPaste.tsx
│ │ │ ├── useTextareaSegments.tsx
│ │ │ ├── useTextareaSubmit.tsx
│ │ │ ├── useThemeExists.tsx
│ │ │ ├── useUserVoiceActivities.tsx
│ │ │ ├── useUsernameSuggestions.tsx
│ │ │ ├── useVoiceJoinEligibility.tsx
│ │ │ ├── useWebhookUpdates.tsx
│ │ │ └── useWindowFocusVideoControl.tsx
│ │ ├── images/
│ │ │ └── i-like-food.d.svg.ts
│ │ ├── index.tsx
│ │ ├── lib/
│ │ │ ├── AccountStorage.tsx
│ │ │ ├── AppStorage.tsx
│ │ │ ├── AutofocusUtils.tsx
│ │ │ ├── CaptchaInterceptor.tsx
│ │ │ ├── ChannelMessages.test.tsx
│ │ │ ├── ChannelMessages.tsx
│ │ │ ├── CloudUpload.tsx
│ │ │ ├── ComponentDispatch.tsx
│ │ │ ├── CustomStatus.tsx
│ │ │ ├── CustomStatusEmitter.tsx
│ │ │ ├── E2EEncryption.tsx
│ │ │ ├── Env.tsx
│ │ │ ├── ExponentialBackoff.tsx
│ │ │ ├── ExpressionPickerUtils.tsx
│ │ │ ├── FocusManager.tsx
│ │ │ ├── GatewayCompression.tsx
│ │ │ ├── GatewaySocket.tsx
│ │ │ ├── HttpClient.tsx
│ │ │ ├── HttpError.tsx
│ │ │ ├── HttpTypes.tsx
│ │ │ ├── InputFocusManager.tsx
│ │ │ ├── IsTextInputKeyEvent.tsx
│ │ │ ├── KeybindManager.tsx
│ │ │ ├── LibFluxcore.Worker.tsx
│ │ │ ├── LibFluxcore.tsx
│ │ │ ├── Logger.tsx
│ │ │ ├── MediaDeviceCache.tsx
│ │ │ ├── MessageQueue.tsx
│ │ │ ├── MobXPersistence.tsx
│ │ │ ├── MultiAccountGatewaySocket.tsx
│ │ │ ├── PasswordManagerAutocomplete.tsx
│ │ │ ├── PlaceholderSpecs.tsx
│ │ │ ├── Platform.tsx
│ │ │ ├── Queue.tsx
│ │ │ ├── ReadStateCleanup.tsx
│ │ │ ├── RelayClient.tsx
│ │ │ ├── RemoteInstanceAuth.tsx
│ │ │ ├── ScrollManager.tsx
│ │ │ ├── SessionManager.tsx
│ │ │ ├── StickerSendUtils.tsx
│ │ │ ├── TextareaAutosize.tsx
│ │ │ ├── UnicodeEmojis.tsx
│ │ │ ├── Versioning.tsx
│ │ │ ├── VoiceStatsDB.tsx
│ │ │ ├── markdown/
│ │ │ │ ├── EmojiProviderSetup.tsx
│ │ │ │ ├── MarkdownTableParsingConfig.tsx
│ │ │ │ ├── Plaintext.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── renderers/
│ │ │ │ │ ├── EmojiRenderer.tsx
│ │ │ │ │ ├── LinkRenderer.tsx
│ │ │ │ │ ├── MentionRenderer.tsx
│ │ │ │ │ ├── MessageJumpLink.module.css
│ │ │ │ │ ├── RendererTypes.tsx
│ │ │ │ │ ├── TextRenderer.tsx
│ │ │ │ │ ├── TimestampRenderer.test.tsx
│ │ │ │ │ ├── TimestampRenderer.tsx
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── BlockElements.tsx
│ │ │ │ │ │ ├── CodeElements.tsx
│ │ │ │ │ │ └── FormattingElements.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── utils/
│ │ │ │ ├── DateFormatter.test.tsx
│ │ │ │ ├── DateFormatter.tsx
│ │ │ │ ├── EmojiDetector.tsx
│ │ │ │ ├── JumboDetector.tsx
│ │ │ │ ├── TimestampValidation.test.tsx
│ │ │ │ └── TimestampValidation.tsx
│ │ │ ├── router/
│ │ │ │ ├── Builder.tsx
│ │ │ │ ├── Core.tsx
│ │ │ │ ├── History.tsx
│ │ │ │ ├── React.tsx
│ │ │ │ ├── RouterErrors.tsx
│ │ │ │ └── RouterTypes.tsx
│ │ │ └── scroll/
│ │ │ └── ScrollPosition.tsx
│ │ ├── locales/
│ │ │ ├── ar/
│ │ │ │ └── messages.po
│ │ │ ├── bg/
│ │ │ │ └── messages.po
│ │ │ ├── cs/
│ │ │ │ └── messages.po
│ │ │ ├── da/
│ │ │ │ └── messages.po
│ │ │ ├── de/
│ │ │ │ └── messages.po
│ │ │ ├── el/
│ │ │ │ └── messages.po
│ │ │ ├── en-GB/
│ │ │ │ └── messages.po
│ │ │ ├── en-US/
│ │ │ │ └── messages.po
│ │ │ ├── es-419/
│ │ │ │ └── messages.po
│ │ │ ├── es-ES/
│ │ │ │ └── messages.po
│ │ │ ├── fi/
│ │ │ │ └── messages.po
│ │ │ ├── fr/
│ │ │ │ └── messages.po
│ │ │ ├── he/
│ │ │ │ └── messages.po
│ │ │ ├── hi/
│ │ │ │ └── messages.po
│ │ │ ├── hr/
│ │ │ │ └── messages.po
│ │ │ ├── hu/
│ │ │ │ └── messages.po
│ │ │ ├── id/
│ │ │ │ └── messages.po
│ │ │ ├── it/
│ │ │ │ └── messages.po
│ │ │ ├── ja/
│ │ │ │ └── messages.po
│ │ │ ├── ko/
│ │ │ │ └── messages.po
│ │ │ ├── lt/
│ │ │ │ └── messages.po
│ │ │ ├── nl/
│ │ │ │ └── messages.po
│ │ │ ├── no/
│ │ │ │ └── messages.po
│ │ │ ├── pl/
│ │ │ │ └── messages.po
│ │ │ ├── pt-BR/
│ │ │ │ └── messages.po
│ │ │ ├── ro/
│ │ │ │ └── messages.po
│ │ │ ├── ru/
│ │ │ │ └── messages.po
│ │ │ ├── sv-SE/
│ │ │ │ └── messages.po
│ │ │ ├── th/
│ │ │ │ └── messages.po
│ │ │ ├── tr/
│ │ │ │ └── messages.po
│ │ │ ├── uk/
│ │ │ │ └── messages.po
│ │ │ ├── vi/
│ │ │ │ └── messages.po
│ │ │ ├── zh-CN/
│ │ │ │ └── messages.po
│ │ │ └── zh-TW/
│ │ │ └── messages.po
│ │ ├── records/
│ │ │ ├── AuthSessionRecord.tsx
│ │ │ ├── ChannelRecord.tsx
│ │ │ ├── ConnectionRecord.tsx
│ │ │ ├── DeveloperApplicationRecord.tsx
│ │ │ ├── FavoriteMemeRecord.tsx
│ │ │ ├── GuildEmojiRecord.tsx
│ │ │ ├── GuildMemberRecord.tsx
│ │ │ ├── GuildRecord.tsx
│ │ │ ├── GuildRoleRecord.tsx
│ │ │ ├── GuildStickerRecord.tsx
│ │ │ ├── MessageRecord.tsx
│ │ │ ├── ProfileRecord.tsx
│ │ │ ├── RelationshipRecord.tsx
│ │ │ ├── SavedMessageEntryRecord.tsx
│ │ │ ├── ScheduledMessageRecord.tsx
│ │ │ ├── UserGuildSettingsRecord.tsx
│ │ │ ├── UserRecord.tsx
│ │ │ └── WebhookRecord.tsx
│ │ ├── router/
│ │ │ ├── RouterConstants.tsx
│ │ │ ├── components/
│ │ │ │ ├── GuildChannelRouter.tsx
│ │ │ │ └── RootComponent.tsx
│ │ │ └── routes/
│ │ │ ├── AppRoutes.tsx
│ │ │ ├── AuthRoutes.tsx
│ │ │ ├── RootRoutes.tsx
│ │ │ └── Routes.tsx
│ │ ├── service_worker/
│ │ │ ├── Register.tsx
│ │ │ └── Worker.tsx
│ │ ├── services/
│ │ │ └── push/
│ │ │ └── PushSubscriptionService.tsx
│ │ ├── stores/
│ │ │ ├── AccessibilityOverrideStore.tsx
│ │ │ ├── AccessibilityStore.tsx
│ │ │ ├── AccountManager.tsx
│ │ │ ├── AudioVolumeStore.tsx
│ │ │ ├── AuthSessionStore.tsx
│ │ │ ├── AuthenticationStore.tsx
│ │ │ ├── AutoAckStore.tsx
│ │ │ ├── AutocompleteStore.tsx
│ │ │ ├── CallAvailabilityStore.tsx
│ │ │ ├── CallInitiatorStore.tsx
│ │ │ ├── CallMediaPrefsStore.tsx
│ │ │ ├── CallStateStore.tsx
│ │ │ ├── ChannelDisplayNameStore.tsx
│ │ │ ├── ChannelPinsStore.tsx
│ │ │ ├── ChannelSearchStore.tsx
│ │ │ ├── ChannelStickerStore.tsx
│ │ │ ├── ChannelStore.tsx
│ │ │ ├── CompactVoiceCallHeightStore.tsx
│ │ │ ├── CompactVoiceCallPiPPositionStore.tsx
│ │ │ ├── ContextMenuStore.tsx
│ │ │ ├── CountryCodeStore.tsx
│ │ │ ├── DeveloperModeStore.tsx
│ │ │ ├── DeveloperOptionsStore.tsx
│ │ │ ├── DimensionStore.tsx
│ │ │ ├── DiscoveryStore.tsx
│ │ │ ├── DismissedUpsellStore.tsx
│ │ │ ├── DraftStore.tsx
│ │ │ ├── EmojiPickerStore.tsx
│ │ │ ├── EmojiStickerLayoutStore.tsx
│ │ │ ├── EmojiStore.test.tsx
│ │ │ ├── EmojiStore.tsx
│ │ │ ├── ExpressionPickerStore.tsx
│ │ │ ├── FavoriteMemeStore.tsx
│ │ │ ├── FavoritesStore.tsx
│ │ │ ├── FriendsTabStore.tsx
│ │ │ ├── GeoIPStore.tsx
│ │ │ ├── GiftStore.tsx
│ │ │ ├── GuildAvailabilityStore.tsx
│ │ │ ├── GuildExpressionTabCache.tsx
│ │ │ ├── GuildFolderExpandedStore.tsx
│ │ │ ├── GuildListStore.tsx
│ │ │ ├── GuildMemberLayoutStore.tsx
│ │ │ ├── GuildMemberStore.tsx
│ │ │ ├── GuildNSFWAgreeStore.tsx
│ │ │ ├── GuildReadStateStore.tsx
│ │ │ ├── GuildSettingsModalStore.tsx
│ │ │ ├── GuildStore.tsx
│ │ │ ├── GuildVerificationStore.tsx
│ │ │ ├── IdleStore.tsx
│ │ │ ├── InboxStore.tsx
│ │ │ ├── InitializationStore.tsx
│ │ │ ├── InputMonitoringPromptsStore.tsx
│ │ │ ├── InstanceConfigStore.tsx
│ │ │ ├── InviteStore.tsx
│ │ │ ├── KeybindStore.tsx
│ │ │ ├── KeyboardModeStore.tsx
│ │ │ ├── LayerManager.tsx
│ │ │ ├── LimitOverrideStore.tsx
│ │ │ ├── LocalPresenceStore.tsx
│ │ │ ├── LocalVoiceStateStore.tsx
│ │ │ ├── LocationStore.tsx
│ │ │ ├── MediaPermissionStore.tsx
│ │ │ ├── MediaViewerStore.tsx
│ │ │ ├── MemberListStore.tsx
│ │ │ ├── MemberPresenceSubscriptionStore.tsx
│ │ │ ├── MemberSearchStore.tsx
│ │ │ ├── MemberSidebarStore.test.tsx
│ │ │ ├── MemberSidebarStore.tsx
│ │ │ ├── MemesPickerStore.tsx
│ │ │ ├── MessageEditMobileStore.tsx
│ │ │ ├── MessageEditStore.tsx
│ │ │ ├── MessageFocusStore.tsx
│ │ │ ├── MessageReactionsStore.tsx
│ │ │ ├── MessageReferenceStore.tsx
│ │ │ ├── MessageReplyStore.tsx
│ │ │ ├── MessageStore.tsx
│ │ │ ├── MobileLayoutStore.tsx
│ │ │ ├── MockIncomingCallStore.tsx
│ │ │ ├── ModalStore.tsx
│ │ │ ├── NagbarStore.tsx
│ │ │ ├── NativePermissionStore.tsx
│ │ │ ├── NativeWindowStateStore.tsx
│ │ │ ├── NavigationSideEffectsStore.tsx
│ │ │ ├── NavigationStore.tsx
│ │ │ ├── NewDeviceMonitoringStore.tsx
│ │ │ ├── NotificationStore.tsx
│ │ │ ├── OverlayStackStore.tsx
│ │ │ ├── PackStore.tsx
│ │ │ ├── ParticipantVolumeStore.tsx
│ │ │ ├── PermissionLayoutStore.tsx
│ │ │ ├── PermissionStore.tsx
│ │ │ ├── PiPStore.tsx
│ │ │ ├── PopoutStore.tsx
│ │ │ ├── PresenceStore.tsx
│ │ │ ├── PrivacyPreferencesStore.tsx
│ │ │ ├── QuickSwitcherStore.tsx
│ │ │ ├── ReadStateStore.test.tsx
│ │ │ ├── ReadStateStore.tsx
│ │ │ ├── RecentMentionsStore.tsx
│ │ │ ├── RelationshipStore.tsx
│ │ │ ├── RtcRegionsStore.tsx
│ │ │ ├── RuntimeConfigStore.tsx
│ │ │ ├── RuntimeCrashStore.tsx
│ │ │ ├── SavedMessagesStore.tsx
│ │ │ ├── ScheduledMessageEditorStore.tsx
│ │ │ ├── ScheduledMessagesStore.tsx
│ │ │ ├── SearchHistoryStore.tsx
│ │ │ ├── SelectedChannelStore.tsx
│ │ │ ├── SelectedGuildStore.tsx
│ │ │ ├── SettingsSidebarStore.tsx
│ │ │ ├── SlowmodeStore.tsx
│ │ │ ├── SoundStore.tsx
│ │ │ ├── SpellcheckStore.tsx
│ │ │ ├── StatusExpiryStore.tsx
│ │ │ ├── StickerPickerStore.tsx
│ │ │ ├── StickerStore.tsx
│ │ │ ├── StreamAudioPrefsStore.tsx
│ │ │ ├── SudoPromptStore.tsx
│ │ │ ├── SudoStore.tsx
│ │ │ ├── TextualPreviewStore.tsx
│ │ │ ├── ThemeStore.tsx
│ │ │ ├── ToastStore.tsx
│ │ │ ├── TransientPresenceStore.tsx
│ │ │ ├── TrustedDomainStore.tsx
│ │ │ ├── TypingStore.tsx
│ │ │ ├── UnreadChannelsStore.tsx
│ │ │ ├── UnsavedChangesStore.tsx
│ │ │ ├── UpdaterStore.tsx
│ │ │ ├── UserConnectionStore.tsx
│ │ │ ├── UserGuildSettingsStore.tsx
│ │ │ ├── UserNoteStore.tsx
│ │ │ ├── UserPinnedDMStore.tsx
│ │ │ ├── UserProfileMobileStore.tsx
│ │ │ ├── UserProfileStore.tsx
│ │ │ ├── UserSettingsStore.tsx
│ │ │ ├── UserStore.tsx
│ │ │ ├── VideoVolumeStore.tsx
│ │ │ ├── VoiceCallLayoutStore.tsx
│ │ │ ├── VoicePromptsStore.tsx
│ │ │ ├── VoiceSettingsStore.tsx
│ │ │ ├── WebhookStore.tsx
│ │ │ ├── WindowStore.tsx
│ │ │ ├── gateway/
│ │ │ │ ├── GatewayConnectionStore.tsx
│ │ │ │ └── handlers/
│ │ │ │ ├── Ready.tsx
│ │ │ │ ├── Resumed.tsx
│ │ │ │ ├── call/
│ │ │ │ │ ├── CallCreate.tsx
│ │ │ │ │ ├── CallDelete.tsx
│ │ │ │ │ └── CallUpdate.tsx
│ │ │ │ ├── channel/
│ │ │ │ │ ├── ChannelCreate.tsx
│ │ │ │ │ ├── ChannelDelete.tsx
│ │ │ │ │ ├── ChannelPinsAck.tsx
│ │ │ │ │ ├── ChannelPinsUpdate.tsx
│ │ │ │ │ ├── ChannelRecipientAdd.tsx
│ │ │ │ │ ├── ChannelRecipientRemove.tsx
│ │ │ │ │ ├── ChannelUpdate.tsx
│ │ │ │ │ └── ChannelUpdateBulk.tsx
│ │ │ │ ├── guild/
│ │ │ │ │ ├── GuildBan.tsx
│ │ │ │ │ ├── GuildCreate.tsx
│ │ │ │ │ ├── GuildDelete.tsx
│ │ │ │ │ ├── GuildEmojisUpdate.tsx
│ │ │ │ │ ├── GuildMemberAdd.tsx
│ │ │ │ │ ├── GuildMemberListUpdate.tsx
│ │ │ │ │ ├── GuildMemberRemove.tsx
│ │ │ │ │ ├── GuildMemberUpdate.tsx
│ │ │ │ │ ├── GuildMembersChunk.tsx
│ │ │ │ │ ├── GuildRoleCreate.tsx
│ │ │ │ │ ├── GuildRoleDelete.tsx
│ │ │ │ │ ├── GuildRoleUpdate.tsx
│ │ │ │ │ ├── GuildRoleUpdateBulk.tsx
│ │ │ │ │ ├── GuildStickersUpdate.tsx
│ │ │ │ │ ├── GuildSync.tsx
│ │ │ │ │ ├── GuildUpdate.tsx
│ │ │ │ │ └── PassiveUpdates.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── invite/
│ │ │ │ │ ├── InviteCreate.tsx
│ │ │ │ │ └── InviteDelete.tsx
│ │ │ │ ├── message/
│ │ │ │ │ ├── MessageAck.tsx
│ │ │ │ │ ├── MessageCreate.tsx
│ │ │ │ │ ├── MessageDelete.tsx
│ │ │ │ │ ├── MessageDeleteBulk.tsx
│ │ │ │ │ ├── MessageReactionAdd.tsx
│ │ │ │ │ ├── MessageReactionAddMany.tsx
│ │ │ │ │ ├── MessageReactionRemove.tsx
│ │ │ │ │ ├── MessageReactionRemoveAll.tsx
│ │ │ │ │ ├── MessageReactionRemoveEmoji.tsx
│ │ │ │ │ ├── MessageUpdate.tsx
│ │ │ │ │ ├── RecentMentionDelete.tsx
│ │ │ │ │ ├── SavedMessageCreate.tsx
│ │ │ │ │ ├── SavedMessageDelete.tsx
│ │ │ │ │ └── TypingStart.tsx
│ │ │ │ ├── misc/
│ │ │ │ │ ├── FavoriteMemeCreate.tsx
│ │ │ │ │ ├── FavoriteMemeDelete.tsx
│ │ │ │ │ ├── FavoriteMemeUpdate.tsx
│ │ │ │ │ └── WebhooksUpdate.tsx
│ │ │ │ ├── presence/
│ │ │ │ │ ├── PresenceUpdate.tsx
│ │ │ │ │ └── PresenceUpdateBulk.tsx
│ │ │ │ ├── relationship/
│ │ │ │ │ ├── RelationshipAdd.tsx
│ │ │ │ │ ├── RelationshipRemove.tsx
│ │ │ │ │ └── RelationshipUpdate.tsx
│ │ │ │ ├── user/
│ │ │ │ │ ├── AuthSessionChange.tsx
│ │ │ │ │ ├── UserConnectionsUpdate.tsx
│ │ │ │ │ ├── UserGuildSettingsUpdate.tsx
│ │ │ │ │ ├── UserNoteUpdate.tsx
│ │ │ │ │ ├── UserPinnedDmsUpdate.tsx
│ │ │ │ │ ├── UserSettingsUpdate.tsx
│ │ │ │ │ └── UserUpdate.tsx
│ │ │ │ └── voice/
│ │ │ │ ├── VoiceServerUpdate.tsx
│ │ │ │ └── VoiceStateUpdate.tsx
│ │ │ └── voice/
│ │ │ ├── MediaEngineFacade.tsx
│ │ │ ├── ScreenShareSubscriptionManager.tsx
│ │ │ ├── VideoSubscriptionManager.tsx
│ │ │ ├── VoiceAudioManager.tsx
│ │ │ ├── VoiceChannelConnector.tsx
│ │ │ ├── VoiceConnectionManager.tsx
│ │ │ ├── VoiceConnectionThrottle.tsx
│ │ │ ├── VoiceDevicePermissionStore.tsx
│ │ │ ├── VoiceEntranceSoundManager.tsx
│ │ │ ├── VoiceMediaEngineBridge.tsx
│ │ │ ├── VoiceMediaManager.tsx
│ │ │ ├── VoiceMediaStateCoordinator.tsx
│ │ │ ├── VoiceParticipantManager.tsx
│ │ │ ├── VoicePermissionManager.tsx
│ │ │ ├── VoiceReconnectManager.tsx
│ │ │ ├── VoiceRoomEventBinder.tsx
│ │ │ ├── VoiceScreenShareManager.tsx
│ │ │ ├── VoiceStateGatewayHandler.tsx
│ │ │ ├── VoiceStateManager.tsx
│ │ │ ├── VoiceStateSyncManager.tsx
│ │ │ ├── VoiceStatsManager.tsx
│ │ │ └── VoiceSubscriptionManager.tsx
│ │ ├── styles/
│ │ │ ├── AttachmentFile.module.css
│ │ │ ├── AttachmentGridItem.module.css
│ │ │ ├── AttachmentLayoutGrid.module.css
│ │ │ ├── AttachmentMosaic.module.css
│ │ │ ├── AttachmentSingleMedia.module.css
│ │ │ ├── ChannelSearchBottomSheet.module.css
│ │ │ ├── CodeElements.module.css
│ │ │ ├── Markup.module.css
│ │ │ ├── MentionRenderer.module.css
│ │ │ ├── Message.module.css
│ │ │ ├── Scroller.module.css
│ │ │ ├── TimestampRenderer.module.css
│ │ │ ├── Typing.module.css
│ │ │ └── preflight.css
│ │ ├── test/
│ │ │ ├── LibfluxcoreMock.tsx
│ │ │ ├── LibfluxcoreMock.wasm
│ │ │ ├── Setup.tsx
│ │ │ └── StyleMock.ts
│ │ ├── types/
│ │ │ ├── BrandedTypes.tsx
│ │ │ ├── Browser.tsx
│ │ │ ├── Combokeys.d.ts
│ │ │ ├── ElectronTypes.tsx
│ │ │ ├── EmojiTypes.tsx
│ │ │ ├── InviteTypes.tsx
│ │ │ ├── Media.d.ts
│ │ │ ├── Sudo.tsx
│ │ │ ├── VerificationError.tsx
│ │ │ ├── assets.d.ts
│ │ │ ├── browser.d.ts
│ │ │ ├── dom-augmentations.d.ts
│ │ │ ├── electron.d.ts
│ │ │ ├── favico.d.ts
│ │ │ ├── gateway/
│ │ │ │ ├── GatewayGuildTypes.tsx
│ │ │ │ ├── GatewayPresenceTypes.tsx
│ │ │ │ └── GatewayVoiceTypes.tsx
│ │ │ ├── lingui-react-macro.d.ts
│ │ │ └── phosphor-icons-augmentations.d.ts
│ │ ├── utils/
│ │ │ ├── AccentColorUtils.tsx
│ │ │ ├── AnimatedImageUtils.tsx
│ │ │ ├── ApiErrorUtils.tsx
│ │ │ ├── AppProtocol.tsx
│ │ │ ├── AttachmentExpiryUtils.tsx
│ │ │ ├── AttachmentPreviewUtils.tsx
│ │ │ ├── AttachmentUtils.tsx
│ │ │ ├── AutostartUtils.tsx
│ │ │ ├── AvatarUtils.tsx
│ │ │ ├── BackgroundImageDB.tsx
│ │ │ ├── CSSHighlightSearch.tsx
│ │ │ ├── CallUtils.tsx
│ │ │ ├── ChannelSearchHighlight.tsx
│ │ │ ├── ChannelShared.tsx
│ │ │ ├── ChannelUtils.tsx
│ │ │ ├── ClientInfoUtils.tsx
│ │ │ ├── CodeLinkUtils.tsx
│ │ │ ├── ColorUtils.test.tsx
│ │ │ ├── ColorUtils.tsx
│ │ │ ├── CommandUtils.test.tsx
│ │ │ ├── CommandUtils.tsx
│ │ │ ├── ContextMenuUtils.tsx
│ │ │ ├── CopyLinkHandlers.tsx
│ │ │ ├── CustomSoundDB.tsx
│ │ │ ├── DateUtils.tsx
│ │ │ ├── DeepLinkUtils.test.tsx
│ │ │ ├── DeepLinkUtils.tsx
│ │ │ ├── DesktopRpcClient.tsx
│ │ │ ├── DimensionUtils.test.tsx
│ │ │ ├── DimensionUtils.tsx
│ │ │ ├── DmChannelUtils.tsx
│ │ │ ├── EmbeddableImageTypes.tsx
│ │ │ ├── EmojiCodepointUtils.tsx
│ │ │ ├── EmojiUtils.test.tsx
│ │ │ ├── EmojiUtils.tsx
│ │ │ ├── ExpressionPermissionUtils.tsx
│ │ │ ├── ExpressionPremiumSummary.tsx
│ │ │ ├── FavoriteMemeUtils.tsx
│ │ │ ├── FileDownloadUtils.tsx
│ │ │ ├── FilePickerUtils.tsx
│ │ │ ├── FileUploadUtils.tsx
│ │ │ ├── FileUtils.test.tsx
│ │ │ ├── FileUtils.tsx
│ │ │ ├── FormUtils.tsx
│ │ │ ├── ForwardedMessageUtils.tsx
│ │ │ ├── GeoUtils.tsx
│ │ │ ├── GiftCodeUtils.tsx
│ │ │ ├── GiftUtils.tsx
│ │ │ ├── GroupDMColorUtils.test.tsx
│ │ │ ├── GroupDMColorUtils.tsx
│ │ │ ├── GroupDmUtils.tsx
│ │ │ ├── GuildInitialsUtils.test.tsx
│ │ │ ├── GuildInitialsUtils.tsx
│ │ │ ├── HelpCenterUtils.tsx
│ │ │ ├── ImageCacheUtils.tsx
│ │ │ ├── ImageCropUtils.tsx
│ │ │ ├── InviteUtils.tsx
│ │ │ ├── KeybindUtils.tsx
│ │ │ ├── KeyboardUtils.tsx
│ │ │ ├── KlipyUtils.tsx
│ │ │ ├── LinkSuppressionUtils.test.tsx
│ │ │ ├── LinkSuppressionUtils.tsx
│ │ │ ├── LocaleUtils.tsx
│ │ │ ├── MarkdownToSegmentUtils.tsx
│ │ │ ├── MediaDeviceRefresh.tsx
│ │ │ ├── MediaDimensionConfig.tsx
│ │ │ ├── MediaProxyUtils.tsx
│ │ │ ├── MediaViewerItemUtils.tsx
│ │ │ ├── MemberListLayout.test.tsx
│ │ │ ├── MemberListLayout.tsx
│ │ │ ├── MemberListUtils.tsx
│ │ │ ├── MessageAttachmentUtils.tsx
│ │ │ ├── MessageComponentUtils.tsx
│ │ │ ├── MessageGroupingUtils.test.tsx
│ │ │ ├── MessageGroupingUtils.tsx
│ │ │ ├── MessageLinkUtils.tsx
│ │ │ ├── MessageNavigator.tsx
│ │ │ ├── MessageRequestUtils.test.tsx
│ │ │ ├── MessageRequestUtils.tsx
│ │ │ ├── MessageSelectionCopyUtils.test.tsx
│ │ │ ├── MessageSelectionCopyUtils.tsx
│ │ │ ├── MessageSubmitUtils.tsx
│ │ │ ├── MessageUtils.tsx
│ │ │ ├── MfaUtils.tsx
│ │ │ ├── MobileExperience.tsx
│ │ │ ├── MobileNavigation.tsx
│ │ │ ├── NativePermissions.tsx
│ │ │ ├── NativeUtils.tsx
│ │ │ ├── NicknameUtils.tsx
│ │ │ ├── NotificationUtils.tsx
│ │ │ ├── PasteSegmentUtils.tsx
│ │ │ ├── PermissionUtils.tsx
│ │ │ ├── PlaceholderUtils.test.tsx
│ │ │ ├── PlaceholderUtils.tsx
│ │ │ ├── Positioning.tsx
│ │ │ ├── PremiumUtils.tsx
│ │ │ ├── PricingUtils.tsx
│ │ │ ├── ProfileDisplayUtils.tsx
│ │ │ ├── ProfileUtils.tsx
│ │ │ ├── PwaUtils.tsx
│ │ │ ├── React.tsx
│ │ │ ├── ReactionUtils.tsx
│ │ │ ├── ReducedMotionAnimation.tsx
│ │ │ ├── RegexUtils.test.tsx
│ │ │ ├── RegexUtils.tsx
│ │ │ ├── RelationshipActionUtils.tsx
│ │ │ ├── ReplaceCommandUtils.tsx
│ │ │ ├── RouterUtils.tsx
│ │ │ ├── ScreenShareUtils.tsx
│ │ │ ├── ScrollbarDragState.tsx
│ │ │ ├── SearchQueryParser.tsx
│ │ │ ├── SearchQueryTokenizer.tsx
│ │ │ ├── SearchSegmentManager.tsx
│ │ │ ├── SearchUtils.tsx
│ │ │ ├── SelectUtils.tsx
│ │ │ ├── SkinToneUtils.tsx
│ │ │ ├── SlashCommandUtils.test.tsx
│ │ │ ├── SlashCommandUtils.tsx
│ │ │ ├── SnowflakeUtils.test.tsx
│ │ │ ├── SoundLabels.tsx
│ │ │ ├── SoundUtils.tsx
│ │ │ ├── SpoilerUtils.tsx
│ │ │ ├── StreamPreviewPermissionUtils.test.tsx
│ │ │ ├── StreamPreviewPermissionUtils.tsx
│ │ │ ├── StringUtils.test.tsx
│ │ │ ├── StringUtils.tsx
│ │ │ ├── SystemMessageUtils.tsx
│ │ │ ├── TenorUtils.tsx
│ │ │ ├── TextareaAutocompleteFlow.test.tsx
│ │ │ ├── TextareaInsertMentionFlow.test.tsx
│ │ │ ├── TextareaSegmentManager.test.tsx
│ │ │ ├── TextareaSegmentManager.tsx
│ │ │ ├── TextareaStateManager.test.tsx
│ │ │ ├── TextareaStateManager.tsx
│ │ │ ├── ThemeUtils.tsx
│ │ │ ├── TtsSpeechUtils.tsx
│ │ │ ├── TtsTextFormatter.tsx
│ │ │ ├── TtsUtils.tsx
│ │ │ ├── TypingUtils.tsx
│ │ │ ├── UiohookKeycodes.tsx
│ │ │ ├── UrlUtils.tsx
│ │ │ ├── VideoBackgroundProcessor.tsx
│ │ │ ├── VoiceDeviceManager.tsx
│ │ │ ├── VoiceMessageRecordingUtils.tsx
│ │ │ ├── VoiceMessageSendUtils.tsx
│ │ │ ├── VoiceVolumeUtils.test.tsx
│ │ │ ├── VoiceVolumeUtils.tsx
│ │ │ ├── WebAuthnUtils.tsx
│ │ │ ├── WebhookUtils.tsx
│ │ │ ├── WindowStateUtils.tsx
│ │ │ ├── __tests__/
│ │ │ │ └── SearchQueryParser.test.tsx
│ │ │ ├── accounts/
│ │ │ │ └── AccountSwitcherModalUtils.tsx
│ │ │ ├── alerts/
│ │ │ │ └── VoiceConnectionConfirmModalUtils.tsx
│ │ │ ├── errors/
│ │ │ │ └── ScreenRecordingPermissionDeniedError.tsx
│ │ │ ├── friends/
│ │ │ │ ├── FriendsListUtils.module.css
│ │ │ │ └── FriendsListUtils.tsx
│ │ │ ├── invite/
│ │ │ │ ├── GroupDmInviteCounts.tsx
│ │ │ │ └── GuildInviteActionState.tsx
│ │ │ ├── limits/
│ │ │ │ ├── GlobalLimits.tsx
│ │ │ │ ├── LimitContext.tsx
│ │ │ │ ├── LimitResolverAdapter.tsx
│ │ │ │ ├── LimitUtils.tsx
│ │ │ │ └── UserLimits.tsx
│ │ │ ├── modals/
│ │ │ │ ├── AddFriendsToGroupModalUtils.tsx
│ │ │ │ ├── AnimatedAvifModalUtils.tsx
│ │ │ │ ├── ChannelCreateModalUtils.tsx
│ │ │ │ ├── ChannelDeleteModalUtils.tsx
│ │ │ │ ├── ChannelSettingsModalUtils.tsx
│ │ │ │ ├── ChannelTopicModalUtils.tsx
│ │ │ │ ├── CreateDMModalUtils.tsx
│ │ │ │ ├── ModalUtils.tsx
│ │ │ │ ├── PremiumModalUtils.tsx
│ │ │ │ ├── ScreenShareSettingsModalUtils.tsx
│ │ │ │ ├── SettingsModalLayoutUtils.tsx
│ │ │ │ └── guild_tabs/
│ │ │ │ ├── GuildAuditLogTabUtils.tsx
│ │ │ │ └── GuildOverviewTabUtils.tsx
│ │ │ └── quick_switcher/
│ │ │ └── QuickSwitcherModalUtils.tsx
│ │ ├── videos/
│ │ │ └── banned.webm
│ │ ├── viewmodels/
│ │ │ └── auth/
│ │ │ ├── AuthFlow.test.tsx
│ │ │ └── AuthFlow.tsx
│ │ ├── vite-env.d.ts
│ │ └── workers/
│ │ ├── AnimatedImageCrop.Worker.tsx
│ │ ├── AnimatedImageCropWorkerManager.tsx
│ │ ├── AnimatedImageCropWorkerPool.tsx
│ │ └── MemberSearch.Worker.tsx
│ ├── tsconfig.json
│ └── vitest.config.ts
├── fluxer_app_proxy/
│ ├── Dockerfile
│ ├── package.json
│ ├── src/
│ │ ├── Config.tsx
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ └── index.tsx
│ └── tsconfig.json
├── fluxer_desktop/
│ ├── .gitignore
│ ├── .npmrc
│ ├── README.md
│ ├── build_resources/
│ │ ├── entitlements.mac.canary.plist
│ │ ├── entitlements.mac.inherit.plist
│ │ ├── entitlements.mac.stable.plist
│ │ ├── icons-canary/
│ │ │ ├── AppIcon.icon/
│ │ │ │ └── icon.json
│ │ │ └── _compiled/
│ │ │ ├── AppIcon.icns
│ │ │ ├── Assets.car
│ │ │ ├── assetcatalog_generated_info.plist
│ │ │ └── icon.part.plist
│ │ ├── icons-stable/
│ │ │ ├── AppIcon.icon/
│ │ │ │ └── icon.json
│ │ │ └── _compiled/
│ │ │ ├── AppIcon.icns
│ │ │ ├── Assets.car
│ │ │ ├── assetcatalog_generated_info.plist
│ │ │ └── icon.part.plist
│ │ ├── notarize.js
│ │ └── profiles/
│ │ ├── Fluxer.provisionprofile
│ │ └── Fluxer_Canary.provisionprofile
│ ├── electron-builder.config.cjs
│ ├── package.json
│ ├── packaging/
│ │ ├── aur/
│ │ │ ├── PKGBUILD
│ │ │ └── README.md
│ │ ├── homebrew/
│ │ │ ├── README.md
│ │ │ └── fluxer.rb
│ │ ├── linux/
│ │ │ ├── README.md
│ │ │ ├── app.fluxer.Fluxer.desktop
│ │ │ └── app.fluxer.Fluxer.metainfo.xml
│ │ └── winget/
│ │ ├── Fluxer.Fluxer.installer.yaml
│ │ ├── Fluxer.Fluxer.locale.en-US.yaml
│ │ ├── Fluxer.Fluxer.yaml
│ │ └── README.md
│ ├── pnpm-workspace.yaml
│ ├── scripts/
│ │ ├── build.mjs
│ │ └── set-build-channel.mjs
│ ├── src/
│ │ ├── common/
│ │ │ ├── BrandedTypes.tsx
│ │ │ ├── BuildChannel.tsx
│ │ │ ├── Constants.tsx
│ │ │ ├── DesktopConfig.tsx
│ │ │ ├── Logger.tsx
│ │ │ ├── Types.tsx
│ │ │ └── UserDataPath.tsx
│ │ ├── main/
│ │ │ ├── Autostart.tsx
│ │ │ ├── DeepLinks.tsx
│ │ │ ├── GlobalKeyHook.tsx
│ │ │ ├── IpcHandlers.tsx
│ │ │ ├── Menu.tsx
│ │ │ ├── RpcServer.tsx
│ │ │ ├── Spellcheck.tsx
│ │ │ ├── Updater.tsx
│ │ │ ├── Window.tsx
│ │ │ ├── WindowsBadge.tsx
│ │ │ └── index.tsx
│ │ └── preload/
│ │ └── index.tsx
│ └── tsconfig.json
├── fluxer_devops/
│ ├── caddy/
│ │ ├── Caddyfile.global
│ │ └── compose.yaml
│ ├── caddy-gateway/
│ │ ├── Caddyfile.global
│ │ └── compose.yaml
│ ├── cassandra/
│ │ ├── Dockerfile.backup
│ │ ├── RESTORE.md
│ │ ├── backup.sh
│ │ ├── compose.yaml
│ │ ├── conf/
│ │ │ ├── cassandra.yaml
│ │ │ └── jvm-server.options
│ │ └── migrations/
│ │ ├── 20251019182829_init.cql
│ │ ├── 20251020105255_visionary_gifts.cql
│ │ ├── 20251020111123_beta_code_allowance.cql
│ │ ├── 20251020162124_premium_cancel.cql
│ │ ├── 20251020162528_premium_cycle.cql
│ │ ├── 20251021024919_payments_v2.cql
│ │ ├── 20251021141627_gift_inventory_ack.cql
│ │ ├── 20251021172928_visionary_slots_v2.cql
│ │ ├── 20251022154916_favorite_meme_gifv.cql
│ │ ├── 20251023131948_pinned_dms.cql
│ │ ├── 20251027204850_voice_regions_v2.cql
│ │ ├── 20251030154245_incoming_call_flags.cql
│ │ ├── 20251030181703_group_dm_add_permission_flags.cql
│ │ ├── 20251103134142_favorite_meme_tenor_id.cql
│ │ ├── 20251106171446_global_names.cql
│ │ ├── 20251106222624_premium_onboarding_dismiss.cql
│ │ ├── 20251111164136_oauth.cql
│ │ ├── 20251112093000_favorite_meme_tenor_id_str.cql
│ │ ├── 20251112134500_oidc_keys_refactor.cql
│ │ ├── 20251125170255_guild_member_profile_flags.cql
│ │ ├── 20251202000000_push_devices.cql
│ │ ├── 20251203135719_push_devices_by_fcm_token.cql
│ │ ├── 20251203141656_add_ttls_devices_subscriptions.cql
│ │ ├── 20251203144440_applications_and_bots.cql
│ │ ├── 20251203145112_oauth_bot_tokens_by_client.cql
│ │ ├── 20251204115402_oauth2_v2.cql
│ │ ├── 20251205000000_fix_authorized_ips_schema.cql
│ │ ├── 20251205231839_add_guild_banner_height.cql
│ │ ├── 20251205233545_add_guild_banner_width.cql
│ │ ├── 20251206120000_add_bot_is_public_to_applications.cql
│ │ ├── 20251206163442_add_admin_archives.cql
│ │ ├── 20251206164609_adjust_oauth2_access_token_ttl_7d.cql
│ │ ├── 20251206180000_attachment_decay.cql
│ │ ├── 20251207120000_email_change.cql
│ │ ├── 20251208120000_email_change_original_proof.cql
│ │ ├── 20251212120000_user_contact_change_logs.cql
│ │ ├── 20251213100000_user_avatar_banner_color.cql
│ │ ├── 20251214191436_guild_audit_logs_v2.cql
│ │ ├── 20251215120000_pending_bulk_message_deletion.cql
│ │ ├── 20251215130000_add_guild_splash_dimensions.cql
│ │ ├── 20251215140000_add_guild_embed_splash.cql
│ │ ├── 20251216233434_channel_state_and_bucket_index.cql
│ │ ├── 20251217020455_empty_buckets.cql
│ │ ├── 20251217173221_payments_version.cql
│ │ ├── 20251217180000_add_version_columns.cql
│ │ ├── 20251219003157_guild_splash_card_alignment.cql
│ │ ├── 20251223200236_messages_has_reaction.cql
│ │ ├── 20251224122758_instance_configuration.cql
│ │ ├── 20251225000000_expression_packs.cql
│ │ ├── 20251225012439_add_pending_verification_metadata.cql
│ │ ├── 20251225120000_add_auth_session_location.cql
│ │ ├── 20251225170000_add_scheduled_messages.cql
│ │ ├── 20251225183000_reports_dsa.cql
│ │ ├── 20251225194859_expression_packs_by_creator.cql
│ │ ├── 20251226120000_status_expiry.cql
│ │ ├── 20251229143845_add_role_hoist_position.cql
│ │ ├── 20251229154931_swish_payments.cql
│ │ ├── 20260105174407_add_auth_session_user_agent_cols.cql
│ │ ├── 20260106001944_user_dm_history.cql
│ │ ├── 20260107131535_add_edited_timestamp_to_message_snapshot.cql
│ │ ├── 20260108222247_user_traits.cql
│ │ ├── 20260109000910_bot_restricted_guild_settings.cql
│ │ ├── 20260109002750_system_dm_jobs.cql
│ │ ├── 20260109193656_admin_api_keys.cql
│ │ ├── 20260109200406_add_admin_api_key_acls.cql
│ │ ├── 20260109233843_relationships_by_target.cql
│ │ ├── 20260110232608_fix_messages_by_author_clustering_key.cql
│ │ ├── 20260113011925_csam_evidence_hold.cql
│ │ ├── 20260113020449_csam_scan_jobs.cql
│ │ ├── 20260114000000_csam_evidence_expirations.cql
│ │ ├── 20260114120000_sticker_animated.cql
│ │ ├── 20260114150000_message_sticker_item_animated.cql
│ │ ├── 20260116171533_ncmec_submissions.cql
│ │ ├── 20260122123000_voice_messages.cql
│ │ ├── 20260129195639_add_klipy_slug_to_favorite_memes.cql
│ │ ├── 20260130142437_trusted_domains.cql
│ │ ├── 20260130160000_default_hide_muted_channels.cql
│ │ ├── 20260205224843_guild_folder_flags_and_icon.cql
│ │ ├── 20260206172322_message_embed_children.cql
│ │ ├── 20260207140000_guild_message_history_cutoff.cql
│ │ ├── 20260207160000_guild_members_indexed_at.cql
│ │ ├── 20260207160233_user_connections.cql
│ │ ├── 20260208165214_donation_system_unified.cql
│ │ ├── 20260214120000_password_change_tickets.cql
│ │ ├── 20260214123000_bot_require_code_grant.cql
│ │ └── 20260217140000_guild_discovery.cql
│ ├── clamav/
│ │ ├── compose.yaml
│ │ └── conf/
│ │ └── clamd.conf
│ ├── ghost_blog/
│ │ └── compose.yaml
│ ├── livekitctl/
│ │ ├── README.md
│ │ ├── cmd/
│ │ │ ├── bootstrap.go
│ │ │ ├── logs.go
│ │ │ ├── restart.go
│ │ │ ├── root.go
│ │ │ ├── status.go
│ │ │ └── webhook.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── internal/
│ │ │ ├── configgen/
│ │ │ │ └── configgen.go
│ │ │ ├── constants/
│ │ │ │ └── constants.go
│ │ │ ├── dnswait/
│ │ │ │ └── dnswait.go
│ │ │ ├── download/
│ │ │ │ └── download.go
│ │ │ ├── errors/
│ │ │ │ └── errors.go
│ │ │ ├── firewall/
│ │ │ │ └── firewall.go
│ │ │ ├── install/
│ │ │ │ └── install.go
│ │ │ ├── netutil/
│ │ │ │ └── netutil.go
│ │ │ ├── ops/
│ │ │ │ └── ops.go
│ │ │ ├── platform/
│ │ │ │ └── platform.go
│ │ │ ├── secrets/
│ │ │ │ └── secrets.go
│ │ │ ├── state/
│ │ │ │ └── state.go
│ │ │ ├── util/
│ │ │ │ └── util.go
│ │ │ └── validate/
│ │ │ └── validate.go
│ │ ├── main.go
│ │ └── scripts/
│ │ └── install.sh
│ ├── nats_core/
│ │ ├── compose.yaml
│ │ └── nats.conf
│ ├── nats_jetstream/
│ │ ├── compose.yaml
│ │ └── nats.conf
│ ├── nginx/
│ │ └── nginx.conf
│ ├── signoz/
│ │ ├── compose.yaml
│ │ ├── conf/
│ │ │ ├── clickhouse/
│ │ │ │ ├── cluster.xml
│ │ │ │ ├── config.d/
│ │ │ │ │ └── keeper.xml
│ │ │ │ ├── config.xml
│ │ │ │ ├── custom-function.xml
│ │ │ │ ├── user_scripts/
│ │ │ │ │ └── .gitkeep
│ │ │ │ └── users.xml
│ │ │ └── signoz/
│ │ │ ├── otel-collector-config.yaml
│ │ │ ├── otel-collector-opamp-config.yaml
│ │ │ └── prometheus.yml
│ │ ├── dashboards/
│ │ │ └── .gitkeep
│ │ └── deploy.sh
│ ├── turborepo_cache/
│ │ └── compose.yaml
│ ├── valkey/
│ │ ├── compose.yaml
│ │ ├── conf/
│ │ │ └── valkey.conf.template
│ │ └── entrypoint.sh
│ └── weblate/
│ └── compose.yaml
├── fluxer_docs/
│ ├── .gitignore
│ ├── .npmrc
│ ├── LICENSE
│ ├── api-reference/
│ │ ├── introduction.mdx
│ │ └── openapi.json
│ ├── docs.json
│ ├── gateway/
│ │ ├── close_codes.mdx
│ │ ├── connection_lifecycle.mdx
│ │ ├── events.mdx
│ │ ├── opcodes.mdx
│ │ └── overview.mdx
│ ├── index.mdx
│ ├── introduction/
│ │ └── authentication.mdx
│ ├── media-proxy-api/
│ │ └── openapi.json
│ ├── quickstart.mdx
│ ├── relay-api/
│ │ └── openapi.json
│ ├── resources/
│ │ ├── admin.mdx
│ │ ├── auth.mdx
│ │ ├── billing.mdx
│ │ ├── channels.mdx
│ │ ├── common.mdx
│ │ ├── gateway.mdx
│ │ ├── gifts.mdx
│ │ ├── guilds.mdx
│ │ ├── instance.mdx
│ │ ├── invites.mdx
│ │ ├── klipy.mdx
│ │ ├── media_proxy.mdx
│ │ ├── oauth2.mdx
│ │ ├── overview.mdx
│ │ ├── packs.mdx
│ │ ├── premium.mdx
│ │ ├── read_states.mdx
│ │ ├── reports.mdx
│ │ ├── saved_media.mdx
│ │ ├── search.mdx
│ │ ├── themes.mdx
│ │ ├── users.mdx
│ │ └── webhooks.mdx
│ ├── schemas/
│ │ └── events/
│ │ ├── AUTH_SESSION_CHANGE.json
│ │ ├── CALL_CREATE.json
│ │ ├── CALL_DELETE.json
│ │ ├── CALL_UPDATE.json
│ │ ├── CHANNEL_CREATE.json
│ │ ├── CHANNEL_DELETE.json
│ │ ├── CHANNEL_PINS_ACK.json
│ │ ├── CHANNEL_PINS_UPDATE.json
│ │ ├── CHANNEL_RECIPIENT_ADD.json
│ │ ├── CHANNEL_RECIPIENT_REMOVE.json
│ │ ├── CHANNEL_UPDATE.json
│ │ ├── CHANNEL_UPDATE_BULK.json
│ │ ├── FAVORITE_MEME_CREATE.json
│ │ ├── FAVORITE_MEME_DELETE.json
│ │ ├── FAVORITE_MEME_UPDATE.json
│ │ ├── GUILD_BAN_ADD.json
│ │ ├── GUILD_BAN_REMOVE.json
│ │ ├── GUILD_CREATE.json
│ │ ├── GUILD_DELETE.json
│ │ ├── GUILD_EMOJIS_UPDATE.json
│ │ ├── GUILD_MEMBER_ADD.json
│ │ ├── GUILD_MEMBER_REMOVE.json
│ │ ├── GUILD_MEMBER_UPDATE.json
│ │ ├── GUILD_ROLE_CREATE.json
│ │ ├── GUILD_ROLE_DELETE.json
│ │ ├── GUILD_ROLE_UPDATE.json
│ │ ├── GUILD_ROLE_UPDATE_BULK.json
│ │ ├── GUILD_STICKERS_UPDATE.json
│ │ ├── GUILD_UPDATE.json
│ │ ├── INVITE_CREATE.json
│ │ ├── INVITE_DELETE.json
│ │ ├── MESSAGE_ACK.json
│ │ ├── MESSAGE_CREATE.json
│ │ ├── MESSAGE_DELETE.json
│ │ ├── MESSAGE_DELETE_BULK.json
│ │ ├── MESSAGE_REACTION_ADD.json
│ │ ├── MESSAGE_REACTION_ADD_MANY.json
│ │ ├── MESSAGE_REACTION_REMOVE.json
│ │ ├── MESSAGE_REACTION_REMOVE_ALL.json
│ │ ├── MESSAGE_REACTION_REMOVE_EMOJI.json
│ │ ├── MESSAGE_UPDATE.json
│ │ ├── PRESENCE_UPDATE.json
│ │ ├── READY.json
│ │ ├── RECENT_MENTION_DELETE.json
│ │ ├── RELATIONSHIP_ADD.json
│ │ ├── RELATIONSHIP_REMOVE.json
│ │ ├── RELATIONSHIP_UPDATE.json
│ │ ├── RESUMED.json
│ │ ├── SAVED_MESSAGE_CREATE.json
│ │ ├── SAVED_MESSAGE_DELETE.json
│ │ ├── SESSIONS_REPLACE.json
│ │ ├── TYPING_START.json
│ │ ├── USER_GUILD_SETTINGS_UPDATE.json
│ │ ├── USER_NOTE_UPDATE.json
│ │ ├── USER_PINNED_DMS_UPDATE.json
│ │ ├── USER_SETTINGS_UPDATE.json
│ │ ├── USER_UPDATE.json
│ │ ├── VOICE_SERVER_UPDATE.json
│ │ ├── VOICE_STATE_UPDATE.json
│ │ └── WEBHOOKS_UPDATE.json
│ ├── scripts/
│ │ ├── check_broken_links.mjs
│ │ ├── generate_config.mjs
│ │ ├── generate_error_codes.mjs
│ │ ├── generate_gateway.mjs
│ │ ├── generate_media_proxy.mjs
│ │ ├── generate_permissions.mjs
│ │ ├── generate_resources.mjs
│ │ ├── generate_scopes.mjs
│ │ └── shared.mjs
│ ├── self-hosting/
│ │ ├── architecture.mdx
│ │ ├── configuration.mdx
│ │ ├── index.mdx
│ │ ├── quickstart.mdx
│ │ ├── upgrading.mdx
│ │ └── voice.mdx
│ ├── style.css
│ └── topics/
│ ├── audit_log.mdx
│ ├── error_codes.mdx
│ ├── media_proxy.mdx
│ ├── oauth2.mdx
│ ├── permissions.mdx
│ ├── rate_limits.mdx
│ ├── snowflakes.mdx
│ └── voice.mdx
├── fluxer_gateway/
│ ├── Dockerfile
│ ├── config/
│ │ ├── sys.config.template
│ │ ├── vm.args.src
│ │ └── vm.args.template
│ ├── dialyzer.ignore-warnings
│ ├── include/
│ │ ├── timeout_config.hrl
│ │ └── voice_state.hrl
│ ├── rebar.config
│ ├── scripts/
│ │ ├── docker_entrypoint.sh
│ │ ├── rebar3_wrapper.sh
│ │ ├── run_compile.sh
│ │ ├── run_dialyzer.sh
│ │ ├── run_eunit.sh
│ │ ├── run_fmt.sh
│ │ └── run_prod_compile.sh
│ └── src/
│ ├── call/
│ │ ├── call.erl
│ │ └── call_manager.erl
│ ├── fluxer_gateway.app.src
│ ├── gateway/
│ │ ├── fluxer_gateway_app.erl
│ │ ├── fluxer_gateway_config.erl
│ │ ├── fluxer_gateway_crypto.erl
│ │ ├── fluxer_gateway_env.erl
│ │ ├── fluxer_gateway_sup.erl
│ │ ├── gateway_codec.erl
│ │ ├── gateway_compress.erl
│ │ ├── gateway_errors.erl
│ │ ├── gateway_handler.erl
│ │ ├── gateway_http_client.erl
│ │ ├── gateway_nats_rpc.erl
│ │ ├── gateway_rpc_call.erl
│ │ ├── gateway_rpc_guild.erl
│ │ ├── gateway_rpc_misc.erl
│ │ ├── gateway_rpc_presence.erl
│ │ ├── gateway_rpc_push.erl
│ │ ├── gateway_rpc_router.erl
│ │ ├── gateway_rpc_voice.erl
│ │ ├── health_handler.erl
│ │ ├── hot_reload.erl
│ │ ├── hot_reload_handler.erl
│ │ ├── rendezvous_router.erl
│ │ └── rpc_client.erl
│ ├── guild/
│ │ ├── guild.erl
│ │ ├── guild_availability.erl
│ │ ├── guild_client.erl
│ │ ├── guild_common.erl
│ │ ├── guild_counts_cache.erl
│ │ ├── guild_data.erl
│ │ ├── guild_data_index.erl
│ │ ├── guild_dispatch.erl
│ │ ├── guild_ets_utils.erl
│ │ ├── guild_manager.erl
│ │ ├── guild_manager_shard.erl
│ │ ├── guild_member_list.erl
│ │ ├── guild_member_list_common.erl
│ │ ├── guild_member_storage.erl
│ │ ├── guild_members.erl
│ │ ├── guild_passive_sync.erl
│ │ ├── guild_permission_cache.erl
│ │ ├── guild_permissions.erl
│ │ ├── guild_presence.erl
│ │ ├── guild_query_handler.erl
│ │ ├── guild_request_members.erl
│ │ ├── guild_sessions.erl
│ │ ├── guild_state.erl
│ │ ├── guild_subscription_handler.erl
│ │ ├── guild_subscriptions.erl
│ │ ├── guild_unified_subscriptions.erl
│ │ ├── guild_user_data.erl
│ │ ├── guild_virtual_channel_access.erl
│ │ ├── guild_visibility.erl
│ │ ├── guild_voice_handler.erl
│ │ ├── passive_sync_registry.erl
│ │ ├── very_large_guild.erl
│ │ ├── very_large_guild_member_list.erl
│ │ └── voice/
│ │ ├── dm_voice.erl
│ │ ├── guild_voice.erl
│ │ ├── guild_voice_broadcast.erl
│ │ ├── guild_voice_connection.erl
│ │ ├── guild_voice_disconnect.erl
│ │ ├── guild_voice_member.erl
│ │ ├── guild_voice_move.erl
│ │ ├── guild_voice_permission_sync.erl
│ │ ├── guild_voice_permissions.erl
│ │ ├── guild_voice_region.erl
│ │ ├── guild_voice_server.erl
│ │ ├── guild_voice_state.erl
│ │ ├── guild_voice_unclaimed_account_utils.erl
│ │ ├── voice_disconnect_common.erl
│ │ ├── voice_pending_common.erl
│ │ ├── voice_state_utils.erl
│ │ └── voice_utils.erl
│ ├── presence/
│ │ ├── presence.erl
│ │ ├── presence_bus.erl
│ │ ├── presence_bus_shard.erl
│ │ ├── presence_cache.erl
│ │ ├── presence_cache_shard.erl
│ │ ├── presence_manager.erl
│ │ ├── presence_manager_shard.erl
│ │ ├── presence_payload.erl
│ │ ├── presence_session.erl
│ │ ├── presence_status.erl
│ │ ├── presence_targets.erl
│ │ └── presence_utils.erl
│ ├── push/
│ │ ├── push.erl
│ │ ├── push_cache.erl
│ │ ├── push_core.erl
│ │ ├── push_dispatcher.erl
│ │ ├── push_eligibility.erl
│ │ ├── push_notification.erl
│ │ ├── push_sender.erl
│ │ ├── push_subscriptions.erl
│ │ └── push_utils.erl
│ ├── session/
│ │ ├── session.erl
│ │ ├── session_connection.erl
│ │ ├── session_dispatch.erl
│ │ ├── session_manager.erl
│ │ ├── session_manager_shard.erl
│ │ ├── session_monitor.erl
│ │ ├── session_passive.erl
│ │ ├── session_ready.erl
│ │ └── session_voice.erl
│ ├── telemetry/
│ │ ├── gateway_metrics_collector.erl
│ │ ├── gateway_tracing.erl
│ │ ├── guild_crash_logger.erl
│ │ ├── otel_metrics.erl
│ │ ├── process_memory_stats.erl
│ │ └── process_registry.erl
│ └── utils/
│ ├── backoff_utils.erl
│ ├── constants.erl
│ ├── custom_status_validation.erl
│ ├── event_atoms.erl
│ ├── list_ops.erl
│ ├── map_utils.erl
│ ├── snowflake_util.erl
│ ├── type_conv.erl
│ ├── user_utils.erl
│ ├── utils.erl
│ └── validation.erl
├── fluxer_integration/
│ ├── docker/
│ │ ├── compose.yaml
│ │ ├── config.json
│ │ └── livekit.yaml
│ ├── package.json
│ ├── scripts/
│ │ ├── run_integration.sh
│ │ ├── server_logs.sh
│ │ ├── server_start.sh
│ │ └── server_stop.sh
│ ├── src/
│ │ ├── Config.tsx
│ │ ├── Setup.tsx
│ │ ├── gateway/
│ │ │ ├── GatewayClient.tsx
│ │ │ ├── GatewayConnection.test.tsx
│ │ │ ├── GatewayGuildEvents.test.tsx
│ │ │ ├── GatewayTypes.tsx
│ │ │ └── GatewayVoiceState.test.tsx
│ │ ├── globalSetup.tsx
│ │ ├── globalTeardown.tsx
│ │ └── helpers/
│ │ ├── AccountHelper.tsx
│ │ ├── ApiClient.tsx
│ │ ├── GuildHelper.tsx
│ │ └── VoiceHelper.tsx
│ ├── tsconfig.json
│ └── vitest.config.ts
├── fluxer_marketing/
│ ├── Dockerfile
│ ├── package.json
│ ├── src/
│ │ ├── App.tsx
│ │ ├── Config.tsx
│ │ ├── HonoJsx.d.ts
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ └── index.tsx
│ └── tsconfig.json
├── fluxer_media_proxy/
│ ├── Dockerfile
│ ├── data/
│ │ └── model.onnx
│ ├── package.json
│ ├── src/
│ │ ├── App.tsx
│ │ ├── AppMain.tsx
│ │ ├── Config.tsx
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ ├── Metrics.tsx
│ │ └── Tracing.tsx
│ └── tsconfig.json
├── fluxer_relay/
│ ├── Dockerfile
│ ├── config/
│ │ ├── relay.json
│ │ ├── sys.config.src
│ │ └── vm.args.src
│ ├── rebar.config
│ └── src/
│ ├── fluxer_relay.app.src
│ └── relay/
│ ├── fluxer_relay_app.erl
│ ├── fluxer_relay_config.erl
│ ├── fluxer_relay_connection_manager.erl
│ ├── fluxer_relay_env.erl
│ ├── fluxer_relay_health_handler.erl
│ ├── fluxer_relay_http_handler.erl
│ ├── fluxer_relay_instance_discovery.erl
│ ├── fluxer_relay_sup.erl
│ └── fluxer_relay_ws_handler.erl
├── fluxer_relay_directory/
│ ├── Dockerfile
│ ├── config/
│ │ └── directory.json
│ ├── package.json
│ ├── scripts/
│ │ └── GenerateOpenAPI.tsx
│ ├── src/
│ │ ├── App.tsx
│ │ ├── Config.tsx
│ │ ├── Logger.tsx
│ │ ├── controllers/
│ │ │ └── RelayController.tsx
│ │ ├── database/
│ │ │ └── Database.tsx
│ │ ├── index.tsx
│ │ ├── middleware/
│ │ │ ├── ServiceMiddleware.tsx
│ │ │ └── Validator.tsx
│ │ ├── repositories/
│ │ │ └── RelayRepository.tsx
│ │ └── services/
│ │ ├── GeoSelectionService.tsx
│ │ ├── HealthCheckService.tsx
│ │ └── RelayRegistryService.tsx
│ └── tsconfig.json
├── fluxer_server/
│ ├── .dockerignore
│ ├── Dockerfile
│ ├── Dockerfile.dev
│ ├── package.json
│ ├── src/
│ │ ├── Config.tsx
│ │ ├── HealthCheck.tsx
│ │ ├── Instrument.tsx
│ │ ├── Logger.tsx
│ │ ├── Routes.tsx
│ │ ├── ServiceInitializer.tsx
│ │ ├── index.tsx
│ │ ├── startServer.tsx
│ │ └── utils/
│ │ ├── ConfigUtils.tsx
│ │ ├── GatewayProcessManager.tsx
│ │ └── GatewayProxy.tsx
│ └── tsconfig.json
├── knip.json
├── package.json
├── packages/
│ ├── admin/
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── AccessControlList.tsx
│ │ │ ├── AdminPackageConstants.tsx
│ │ │ ├── App.tsx
│ │ │ ├── HonoJsx.d.ts
│ │ │ ├── Navigation.tsx
│ │ │ ├── Oauth2.tsx
│ │ │ ├── PublicDir.tsx
│ │ │ ├── SelfHostedOverride.tsx
│ │ │ ├── Session.tsx
│ │ │ ├── api/
│ │ │ │ ├── AdminApiKeys.tsx
│ │ │ │ ├── Archives.tsx
│ │ │ │ ├── Assets.tsx
│ │ │ │ ├── Audit.tsx
│ │ │ │ ├── Bans.tsx
│ │ │ │ ├── Bulk.tsx
│ │ │ │ ├── Client.tsx
│ │ │ │ ├── Codes.tsx
│ │ │ │ ├── Discovery.tsx
│ │ │ │ ├── Errors.tsx
│ │ │ │ ├── GuildAssets.tsx
│ │ │ │ ├── Guilds.tsx
│ │ │ │ ├── InstanceConfig.tsx
│ │ │ │ ├── JsonTypes.tsx
│ │ │ │ ├── LimitConfig.tsx
│ │ │ │ ├── Messages.tsx
│ │ │ │ ├── Reports.tsx
│ │ │ │ ├── Search.tsx
│ │ │ │ ├── System.tsx
│ │ │ │ ├── SystemDm.tsx
│ │ │ │ ├── Users.tsx
│ │ │ │ ├── VisionarySlots.tsx
│ │ │ │ └── Voice.tsx
│ │ │ ├── components/
│ │ │ │ ├── ErrorDisplay.tsx
│ │ │ │ ├── Icons.tsx
│ │ │ │ ├── Layout.tsx
│ │ │ │ ├── MessageList.tsx
│ │ │ │ ├── UserProfileBadges.tsx
│ │ │ │ ├── VoiceComponents.tsx
│ │ │ │ └── ui/
│ │ │ │ ├── Alert.tsx
│ │ │ │ ├── Badge.tsx
│ │ │ │ ├── Card.tsx
│ │ │ │ ├── CardBody.tsx
│ │ │ │ ├── CardFooter.tsx
│ │ │ │ ├── CardHeader.tsx
│ │ │ │ ├── Chip.tsx
│ │ │ │ ├── CodeBlock.tsx
│ │ │ │ ├── Container.tsx
│ │ │ │ ├── EmptyState.tsx
│ │ │ │ ├── Form/
│ │ │ │ │ ├── FormActions.tsx
│ │ │ │ │ ├── FormCard.tsx
│ │ │ │ │ ├── FormFieldGroup.tsx
│ │ │ │ │ ├── FormRow.tsx
│ │ │ │ │ └── FormSection.tsx
│ │ │ │ ├── Grid.tsx
│ │ │ │ ├── InlineStack.tsx
│ │ │ │ ├── Input.tsx
│ │ │ │ ├── Layout/
│ │ │ │ │ ├── Box.tsx
│ │ │ │ │ ├── DetailPageLayout.tsx
│ │ │ │ │ ├── Flex.tsx
│ │ │ │ │ ├── FormGrid.tsx
│ │ │ │ │ ├── HStack.tsx
│ │ │ │ │ ├── PageContainer.tsx
│ │ │ │ │ ├── PageHeader.tsx
│ │ │ │ │ ├── PageLayout.tsx
│ │ │ │ │ ├── SearchListPageLayout.tsx
│ │ │ │ │ ├── TwoColumnGrid.tsx
│ │ │ │ │ └── VStack.tsx
│ │ │ │ ├── MetadataRow.tsx
│ │ │ │ ├── NavLink.tsx
│ │ │ │ ├── Pill.tsx
│ │ │ │ ├── ResourceLink.tsx
│ │ │ │ ├── Select.tsx
│ │ │ │ ├── Stack.tsx
│ │ │ │ ├── StatusBadge.tsx
│ │ │ │ ├── Table.tsx
│ │ │ │ ├── TableBody.tsx
│ │ │ │ ├── TableCell.tsx
│ │ │ │ ├── TableContainer.tsx
│ │ │ │ ├── TableHeader.tsx
│ │ │ │ ├── TableHeaderCell.tsx
│ │ │ │ ├── TableRow.tsx
│ │ │ │ ├── TextLink.tsx
│ │ │ │ ├── Textarea.tsx
│ │ │ │ └── Typography.tsx
│ │ │ ├── hooks/
│ │ │ │ └── usePaginationUrl.ts
│ │ │ ├── middleware/
│ │ │ │ ├── Auth.tsx
│ │ │ │ ├── Csrf.tsx
│ │ │ │ └── ErrorHandler.tsx
│ │ │ ├── navigation/
│ │ │ │ └── NavigationTypes.tsx
│ │ │ ├── pages/
│ │ │ │ ├── AdminApiKeysPage.tsx
│ │ │ │ ├── ArchivesPage.tsx
│ │ │ │ ├── AssetPurgePage.tsx
│ │ │ │ ├── AuditLogsPage.tsx
│ │ │ │ ├── BanManagementPage.tsx
│ │ │ │ ├── BulkActionsPage.tsx
│ │ │ │ ├── DiscoveryPage.tsx
│ │ │ │ ├── GatewayPage.tsx
│ │ │ │ ├── GiftCodesPage.tsx
│ │ │ │ ├── GuildDetailPage.tsx
│ │ │ │ ├── GuildsPage.tsx
│ │ │ │ ├── InstanceConfigPage.tsx
│ │ │ │ ├── LimitConfigPage.tsx
│ │ │ │ ├── LoginPage.tsx
│ │ │ │ ├── MessagesPage.tsx
│ │ │ │ ├── ReportDetailPage.tsx
│ │ │ │ ├── ReportsPage.tsx
│ │ │ │ ├── SearchIndexPage.tsx
│ │ │ │ ├── StrangePlacePage.tsx
│ │ │ │ ├── SystemDmPage.tsx
│ │ │ │ ├── UserDetailPage.tsx
│ │ │ │ ├── UsersPage.tsx
│ │ │ │ ├── VisionarySlotsPage.tsx
│ │ │ │ ├── VoiceRegionsPage.tsx
│ │ │ │ ├── VoiceServersPage.tsx
│ │ │ │ ├── guild_detail/
│ │ │ │ │ ├── Forms.tsx
│ │ │ │ │ └── tabs/
│ │ │ │ │ ├── EmojisTab.tsx
│ │ │ │ │ ├── FeaturesTab.tsx
│ │ │ │ │ ├── MembersTab.tsx
│ │ │ │ │ ├── ModerationTab.tsx
│ │ │ │ │ ├── OverviewTab.tsx
│ │ │ │ │ ├── SettingsTab.tsx
│ │ │ │ │ └── StickersTab.tsx
│ │ │ │ └── user_detail/
│ │ │ │ ├── Forms.tsx
│ │ │ │ └── tabs/
│ │ │ │ ├── AccountTab.tsx
│ │ │ │ ├── DmHistoryTab.tsx
│ │ │ │ ├── GuildsTab.tsx
│ │ │ │ ├── ModerationTab.tsx
│ │ │ │ └── OverviewTab.tsx
│ │ │ ├── routes/
│ │ │ │ ├── Admin.tsx
│ │ │ │ ├── Auth.tsx
│ │ │ │ ├── Bans.tsx
│ │ │ │ ├── Codes.tsx
│ │ │ │ ├── Discovery.tsx
│ │ │ │ ├── Guilds.tsx
│ │ │ │ ├── Messages.tsx
│ │ │ │ ├── Reports.tsx
│ │ │ │ ├── RouteContext.tsx
│ │ │ │ ├── RouteTypes.tsx
│ │ │ │ ├── System.tsx
│ │ │ │ ├── Users.tsx
│ │ │ │ ├── VisionarySlots.tsx
│ │ │ │ └── Voice.tsx
│ │ │ ├── styles/
│ │ │ │ └── app.css
│ │ │ ├── types/
│ │ │ │ ├── App.tsx
│ │ │ │ └── Config.tsx
│ │ │ └── utils/
│ │ │ ├── Bigint.tsx
│ │ │ ├── ClassNames.tsx
│ │ │ ├── Forms.tsx
│ │ │ └── User.tsx
│ │ └── tsconfig.json
│ ├── api/
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── App.tsx
│ │ │ ├── BrandedTypes.tsx
│ │ │ ├── Config.tsx
│ │ │ ├── ILogger.tsx
│ │ │ ├── Logger.tsx
│ │ │ ├── RateLimitConfig.tsx
│ │ │ ├── SearchFactory.tsx
│ │ │ ├── Tables.tsx
│ │ │ ├── Telemetry.tsx
│ │ │ ├── Validator.tsx
│ │ │ ├── ZodErrorMap.tsx
│ │ │ ├── admin/
│ │ │ │ ├── AdminRepository.tsx
│ │ │ │ ├── AdminService.tsx
│ │ │ │ ├── IAdminRepository.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── AdminApiKeyAdminController.tsx
│ │ │ │ │ ├── ArchiveAdminController.tsx
│ │ │ │ │ ├── AssetAdminController.tsx
│ │ │ │ │ ├── AuditLogAdminController.tsx
│ │ │ │ │ ├── BanAdminController.tsx
│ │ │ │ │ ├── BulkAdminController.tsx
│ │ │ │ │ ├── ChildSafetyAdminController.tsx
│ │ │ │ │ ├── CodesAdminController.tsx
│ │ │ │ │ ├── DiscoveryAdminController.tsx
│ │ │ │ │ ├── GatewayAdminController.tsx
│ │ │ │ │ ├── GuildAdminController.tsx
│ │ │ │ │ ├── InstanceConfigAdminController.tsx
│ │ │ │ │ ├── LimitConfigAdminController.tsx
│ │ │ │ │ ├── MessageAdminController.tsx
│ │ │ │ │ ├── ReportAdminController.tsx
│ │ │ │ │ ├── SearchAdminController.tsx
│ │ │ │ │ ├── SnowflakeReservationAdminController.tsx
│ │ │ │ │ ├── SystemDmAdminController.tsx
│ │ │ │ │ ├── UserAdminController.tsx
│ │ │ │ │ ├── VisionarySlotAdminController.tsx
│ │ │ │ │ ├── VoiceAdminController.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── models/
│ │ │ │ │ ├── AdminArchiveModel.tsx
│ │ │ │ │ ├── GuildTypes.tsx
│ │ │ │ │ └── UserTypes.tsx
│ │ │ │ ├── repositories/
│ │ │ │ │ ├── AdminApiKeyRepository.tsx
│ │ │ │ │ ├── AdminArchiveRepository.tsx
│ │ │ │ │ ├── IAdminApiKeyRepository.tsx
│ │ │ │ │ └── SystemDmJobRepository.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── AdminApiKeyService.tsx
│ │ │ │ │ ├── AdminArchiveService.tsx
│ │ │ │ │ ├── AdminAssetPurgeService.tsx
│ │ │ │ │ ├── AdminAuditService.tsx
│ │ │ │ │ ├── AdminBanManagementService.tsx
│ │ │ │ │ ├── AdminCodeGenerationService.tsx
│ │ │ │ │ ├── AdminGuildService.tsx
│ │ │ │ │ ├── AdminMessageDeletionService.tsx
│ │ │ │ │ ├── AdminMessageService.tsx
│ │ │ │ │ ├── AdminMessageShredService.tsx
│ │ │ │ │ ├── AdminReportService.tsx
│ │ │ │ │ ├── AdminSearchService.tsx
│ │ │ │ │ ├── AdminSnowflakeReservationService.tsx
│ │ │ │ │ ├── AdminUserBanService.tsx
│ │ │ │ │ ├── AdminUserDeletionService.tsx
│ │ │ │ │ ├── AdminUserLookupService.tsx
│ │ │ │ │ ├── AdminUserProfileService.tsx
│ │ │ │ │ ├── AdminUserSecurityService.tsx
│ │ │ │ │ ├── AdminUserService.tsx
│ │ │ │ │ ├── AdminUserUpdatePropagator.tsx
│ │ │ │ │ ├── AdminVisionarySlotService.tsx
│ │ │ │ │ ├── AdminVoiceService.tsx
│ │ │ │ │ ├── SystemDmService.tsx
│ │ │ │ │ └── guild/
│ │ │ │ │ ├── AdminGuildBulkService.tsx
│ │ │ │ │ ├── AdminGuildLookupService.tsx
│ │ │ │ │ ├── AdminGuildManagementService.tsx
│ │ │ │ │ ├── AdminGuildMembershipService.tsx
│ │ │ │ │ ├── AdminGuildUpdatePropagator.tsx
│ │ │ │ │ ├── AdminGuildUpdateService.tsx
│ │ │ │ │ └── AdminGuildVanityService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── AdminApiKeyACLValidation.test.tsx
│ │ │ │ ├── AdminApiKeyAuthentication.test.tsx
│ │ │ │ ├── AdminApiKeyAuthorization.test.tsx
│ │ │ │ ├── AdminApiKeyLifecycle.test.tsx
│ │ │ │ ├── AdminApiKeyManagement.test.tsx
│ │ │ │ ├── AdminApiKeyRevocation.test.tsx
│ │ │ │ ├── AdminArchivesList.test.tsx
│ │ │ │ ├── AdminEndpointsAuthorization.test.tsx
│ │ │ │ ├── AdminOAuth2ScopeRequirement.test.tsx
│ │ │ │ ├── AdminSearchEndpoints.test.tsx
│ │ │ │ ├── AdminSearchFieldCoverage.test.tsx
│ │ │ │ ├── AdminTestUtils.tsx
│ │ │ │ ├── DiscoveryAdminOperations.test.tsx
│ │ │ │ ├── SecurityAccessControl.test.tsx
│ │ │ │ └── VisionarySlotManagement.test.tsx
│ │ │ ├── alert/
│ │ │ │ └── AlertService.tsx
│ │ │ ├── app/
│ │ │ │ ├── APILifecycle.tsx
│ │ │ │ ├── ControllerRegistry.tsx
│ │ │ │ └── MiddlewarePipeline.tsx
│ │ │ ├── attachment/
│ │ │ │ ├── AttachmentDecayRepository.tsx
│ │ │ │ └── AttachmentDecayService.tsx
│ │ │ ├── auth/
│ │ │ │ ├── AuthController.tsx
│ │ │ │ ├── AuthModel.tsx
│ │ │ │ ├── AuthRequestService.tsx
│ │ │ │ ├── AuthService.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── AuthEmailRevertService.tsx
│ │ │ │ │ ├── AuthEmailService.tsx
│ │ │ │ │ ├── AuthLoginService.tsx
│ │ │ │ │ ├── AuthMfaService.tsx
│ │ │ │ │ ├── AuthPasswordService.tsx
│ │ │ │ │ ├── AuthPhoneService.tsx
│ │ │ │ │ ├── AuthRegistrationService.tsx
│ │ │ │ │ ├── AuthSessionService.tsx
│ │ │ │ │ ├── AuthUtilityService.tsx
│ │ │ │ │ ├── DesktopHandoffService.tsx
│ │ │ │ │ ├── SsoService.tsx
│ │ │ │ │ ├── SsoUtils.tsx
│ │ │ │ │ ├── SudoModeService.tsx
│ │ │ │ │ └── SudoVerificationService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── AppStoreReviewerBypass.test.tsx
│ │ │ │ ├── AppStoreReviewerMultiFlag.test.tsx
│ │ │ │ ├── AuthSudoMFAMethods.test.tsx
│ │ │ │ ├── AuthSudoPasswordVerification.test.tsx
│ │ │ │ ├── AuthSudoRequiredOperations.test.tsx
│ │ │ │ ├── AuthSudoTOTPVerification.test.tsx
│ │ │ │ ├── AuthTestUtils.tsx
│ │ │ │ ├── BouncedEmailRecoveryFlow.test.tsx
│ │ │ │ ├── CaseInsensitiveEmail.test.tsx
│ │ │ │ ├── ConcurrentSessions.test.tsx
│ │ │ │ ├── DesktopHandoffCodeNormalization.test.tsx
│ │ │ │ ├── DesktopHandoffFlow.test.tsx
│ │ │ │ ├── DesktopHandoffNegative.test.tsx
│ │ │ │ ├── DesktopHandoffUsage.test.tsx
│ │ │ │ ├── EmailChangeFlow.test.tsx
│ │ │ │ ├── EmailChangeResendCooldown.test.tsx
│ │ │ │ ├── EmailRevertFlow.test.tsx
│ │ │ │ ├── EmailVerificationFlow.test.tsx
│ │ │ │ ├── EmailVerificationSuspiciousFlags.test.tsx
│ │ │ │ ├── IPAuthBypassFlags.test.tsx
│ │ │ │ ├── IPAuthFlow.test.tsx
│ │ │ │ ├── IPAuthMultipleIPs.test.tsx
│ │ │ │ ├── IPAuthPoll.test.tsx
│ │ │ │ ├── IPAuthResend.test.tsx
│ │ │ │ ├── IPAuthStream.test.tsx
│ │ │ │ ├── IPAuthTicket.test.tsx
│ │ │ │ ├── IPAuthTokenValidation.test.tsx
│ │ │ │ ├── LoginAndSessions.test.tsx
│ │ │ │ ├── LoginDisabledFlagRecovery.test.tsx
│ │ │ │ ├── LoginInvalidCredentials.test.tsx
│ │ │ │ ├── LoginInviteAutoJoin.test.tsx
│ │ │ │ ├── LoginInviteInvalidCode.test.tsx
│ │ │ │ ├── LoginSelfDeletedRecovery.test.tsx
│ │ │ │ ├── MfaConsistency.test.tsx
│ │ │ │ ├── MfaEndpoints.test.tsx
│ │ │ │ ├── MfaSmsEnableDisable.test.tsx
│ │ │ │ ├── MfaSmsLoginFlow.test.tsx
│ │ │ │ ├── MfaTicketExpiryAndReuse.test.tsx
│ │ │ │ ├── MfaTotpFlag.test.tsx
│ │ │ │ ├── MfaTotpWithoutSecret.test.tsx
│ │ │ │ ├── PasswordChange.test.tsx
│ │ │ │ ├── PasswordReset.test.tsx
│ │ │ │ ├── PhoneVerificationFlow.test.tsx
│ │ │ │ ├── Registration.test.tsx
│ │ │ │ ├── RegistrationValidation.test.tsx
│ │ │ │ ├── ResetPasswordRequiresMfa.test.tsx
│ │ │ │ ├── SecurityFlagsSuspiciousActivity.test.tsx
│ │ │ │ ├── SettingsDefaults.test.tsx
│ │ │ │ ├── SsoFlow.test.tsx
│ │ │ │ ├── SudoModeNegativeCases.test.tsx
│ │ │ │ ├── TokenValidation.test.tsx
│ │ │ │ ├── UnclaimedAccountRestrictions.test.tsx
│ │ │ │ ├── UnclaimedClaimFlow.test.tsx
│ │ │ │ ├── WebAuthnAuthenticationReplay.test.tsx
│ │ │ │ ├── WebAuthnAuthenticationWrongChallenge.test.tsx
│ │ │ │ ├── WebAuthnCredentialDelete.test.tsx
│ │ │ │ ├── WebAuthnCredentialList.test.tsx
│ │ │ │ ├── WebAuthnCredentialRegister.test.tsx
│ │ │ │ ├── WebAuthnCredentialRename.test.tsx
│ │ │ │ ├── WebAuthnErrorLocalization.test.tsx
│ │ │ │ ├── WebAuthnMfaConsistency.test.tsx
│ │ │ │ ├── WebAuthnMfaLogin.test.tsx
│ │ │ │ ├── WebAuthnPasswordlessLogin.test.tsx
│ │ │ │ ├── WebAuthnRegistrationUserHandle.test.tsx
│ │ │ │ ├── WebAuthnTestUtils.tsx
│ │ │ │ └── WebAuthnUserVerificationRequired.test.tsx
│ │ │ ├── bluesky/
│ │ │ │ ├── BlueskyOAuthController.tsx
│ │ │ │ ├── BlueskyOAuthService.tsx
│ │ │ │ ├── BlueskyOAuthStores.tsx
│ │ │ │ ├── IBlueskyOAuthService.tsx
│ │ │ │ └── tests/
│ │ │ │ └── BlueskyOAuth.test.tsx
│ │ │ ├── bot/
│ │ │ │ └── tests/
│ │ │ │ ├── BotAuthorizeAllowsNoRedirect.test.tsx
│ │ │ │ ├── BotAuthorizeWithGuildSelectionRedirects.test.tsx
│ │ │ │ ├── BotTestUtils.tsx
│ │ │ │ ├── BotTokenReset.test.tsx
│ │ │ │ └── BotTokenResetWithMfaSudoMode.test.tsx
│ │ │ ├── channel/
│ │ │ │ ├── AttachmentDTOs.tsx
│ │ │ │ ├── ChannelController.tsx
│ │ │ │ ├── ChannelMappers.tsx
│ │ │ │ ├── ChannelRepository.tsx
│ │ │ │ ├── EmbedTypes.tsx
│ │ │ │ ├── IChannelRepository.tsx
│ │ │ │ ├── MessageMappers.tsx
│ │ │ │ ├── MessageTypes.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── CallController.tsx
│ │ │ │ │ ├── ChannelController.tsx
│ │ │ │ │ ├── MessageController.tsx
│ │ │ │ │ ├── MessageInteractionController.tsx
│ │ │ │ │ ├── ScheduledMessageController.tsx
│ │ │ │ │ ├── ScheduledMessageParsing.tsx
│ │ │ │ │ ├── StreamController.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── repositories/
│ │ │ │ │ ├── ChannelDataRepository.tsx
│ │ │ │ │ ├── ChannelRepository.tsx
│ │ │ │ │ ├── IChannelDataRepository.tsx
│ │ │ │ │ ├── IChannelRepositoryAggregate.tsx
│ │ │ │ │ ├── IMessageInteractionRepository.tsx
│ │ │ │ │ ├── IMessageRepository.tsx
│ │ │ │ │ ├── MessageInteractionRepository.tsx
│ │ │ │ │ ├── MessageRepository.tsx
│ │ │ │ │ └── message/
│ │ │ │ │ ├── BucketScanEngine.tsx
│ │ │ │ │ ├── MessageAttachmentRepository.tsx
│ │ │ │ │ ├── MessageAuthorRepository.tsx
│ │ │ │ │ ├── MessageDataRepository.tsx
│ │ │ │ │ └── MessageDeletionRepository.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── AttachmentUploadService.tsx
│ │ │ │ │ ├── AuthenticatedChannel.tsx
│ │ │ │ │ ├── BaseChannelAuthService.tsx
│ │ │ │ │ ├── CallService.tsx
│ │ │ │ │ ├── ChannelDataService.tsx
│ │ │ │ │ ├── ChannelRequestService.tsx
│ │ │ │ │ ├── ChannelService.tsx
│ │ │ │ │ ├── DMPermissionValidator.tsx
│ │ │ │ │ ├── GroupDmService.tsx
│ │ │ │ │ ├── MessageInteractionService.tsx
│ │ │ │ │ ├── MessageService.tsx
│ │ │ │ │ ├── ScheduledMessageService.tsx
│ │ │ │ │ ├── StreamPreviewService.tsx
│ │ │ │ │ ├── StreamService.tsx
│ │ │ │ │ ├── channel_data/
│ │ │ │ │ │ ├── ChannelAuthService.tsx
│ │ │ │ │ │ ├── ChannelOperationsService.tsx
│ │ │ │ │ │ ├── ChannelUtilsService.tsx
│ │ │ │ │ │ └── GroupDmUpdateService.tsx
│ │ │ │ │ ├── group_dm/
│ │ │ │ │ │ ├── GroupDmHelpers.tsx
│ │ │ │ │ │ └── GroupDmOperationsService.tsx
│ │ │ │ │ ├── interaction/
│ │ │ │ │ │ ├── MessageInteractionAuthService.tsx
│ │ │ │ │ │ ├── MessageInteractionBase.tsx
│ │ │ │ │ │ ├── MessagePinService.tsx
│ │ │ │ │ │ ├── MessageReactionService.tsx
│ │ │ │ │ │ └── MessageReadStateService.tsx
│ │ │ │ │ └── message/
│ │ │ │ │ ├── AttachmentProcessingService.tsx
│ │ │ │ │ ├── DmScopeUtils.tsx
│ │ │ │ │ ├── MessageAnonymizationService.tsx
│ │ │ │ │ ├── MessageChannelAuthService.tsx
│ │ │ │ │ ├── MessageContentService.tsx
│ │ │ │ │ ├── MessageDeleteService.tsx
│ │ │ │ │ ├── MessageDispatchService.tsx
│ │ │ │ │ ├── MessageEditService.tsx
│ │ │ │ │ ├── MessageEmbedAttachmentResolver.tsx
│ │ │ │ │ ├── MessageHelpers.tsx
│ │ │ │ │ ├── MessageMentionService.tsx
│ │ │ │ │ ├── MessageOperationsHelpers.tsx
│ │ │ │ │ ├── MessageOperationsService.tsx
│ │ │ │ │ ├── MessagePersistenceService.tsx
│ │ │ │ │ ├── MessageProcessingService.tsx
│ │ │ │ │ ├── MessageRequestParser.tsx
│ │ │ │ │ ├── MessageRequestService.tsx
│ │ │ │ │ ├── MessageRetrievalService.tsx
│ │ │ │ │ ├── MessageSearchService.tsx
│ │ │ │ │ ├── MessageSendService.tsx
│ │ │ │ │ ├── MessageStickerService.tsx
│ │ │ │ │ ├── MessageSystemService.tsx
│ │ │ │ │ ├── MessageValidationService.tsx
│ │ │ │ │ └── ReadStateHelpers.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── AttachmentDecay.test.tsx
│ │ │ │ ├── AttachmentTestUtils.tsx
│ │ │ │ ├── AttachmentUploadValidation.test.tsx
│ │ │ │ ├── BulkDeleteMessages.test.tsx
│ │ │ │ ├── CallEndpoints.test.tsx
│ │ │ │ ├── ChannelOperationPermissions.test.tsx
│ │ │ │ ├── ChannelOperationValidation.test.tsx
│ │ │ │ ├── ChannelPermissionOverwrites.test.tsx
│ │ │ │ ├── ChannelTestUtils.tsx
│ │ │ │ ├── DMBlockingBehaviors.test.tsx
│ │ │ │ ├── DMChannelManagement.test.tsx
│ │ │ │ ├── DMCreationAllowedWithFriendship.test.tsx
│ │ │ │ ├── DMCreationAllowedWithMutualGuild.test.tsx
│ │ │ │ ├── DMCreationRequiresFriendshipOrMutualGuild.test.tsx
│ │ │ │ ├── EmbedAttachmentUrlResolution.test.tsx
│ │ │ │ ├── GroupDMNameUpdate.test.tsx
│ │ │ │ ├── GroupDMNicknameUpdate.test.tsx
│ │ │ │ ├── GroupDMSecurityBoundaries.test.tsx
│ │ │ │ ├── GroupDmAddRecipientPermissions.test.tsx
│ │ │ │ ├── GroupDmLimit.test.tsx
│ │ │ │ ├── GroupDmManagement.test.tsx
│ │ │ │ ├── GroupDmRecipientLimit.test.tsx
│ │ │ │ ├── MessageCustomEmojiSanitization.test.tsx
│ │ │ │ ├── ScheduledMessageTestUtils.tsx
│ │ │ │ ├── ScheduledMessageTraitGated.test.tsx
│ │ │ │ ├── ScheduledMessageValidation.test.tsx
│ │ │ │ ├── ScheduledMessageWorkerLifecycle.test.tsx
│ │ │ │ ├── ScheduledMessagesListInvalidEntry.test.tsx
│ │ │ │ ├── ScheduledMessagesListLifecycle.test.tsx
│ │ │ │ ├── StreamPreviewAuth.test.tsx
│ │ │ │ └── TypingIndicators.test.tsx
│ │ │ ├── config/
│ │ │ │ └── APIConfig.tsx
│ │ │ ├── connection/
│ │ │ │ ├── ConnectionController.tsx
│ │ │ │ ├── ConnectionInitiationToken.tsx
│ │ │ │ ├── ConnectionMappers.tsx
│ │ │ │ ├── ConnectionRepository.tsx
│ │ │ │ ├── ConnectionRequestService.tsx
│ │ │ │ ├── ConnectionService.tsx
│ │ │ │ ├── IConnectionRepository.tsx
│ │ │ │ ├── IConnectionService.tsx
│ │ │ │ ├── errors/
│ │ │ │ │ ├── BlueskyOAuthAuthorizationFailedError.tsx
│ │ │ │ │ ├── BlueskyOAuthCallbackFailedError.tsx
│ │ │ │ │ ├── BlueskyOAuthNotEnabledError.tsx
│ │ │ │ │ ├── BlueskyOAuthSessionExpiredError.tsx
│ │ │ │ │ ├── BlueskyOAuthStateInvalidError.tsx
│ │ │ │ │ ├── ConnectionAlreadyExistsError.tsx
│ │ │ │ │ ├── ConnectionInitiationTokenInvalidError.tsx
│ │ │ │ │ ├── ConnectionInvalidTypeError.tsx
│ │ │ │ │ ├── ConnectionLimitReachedError.tsx
│ │ │ │ │ ├── ConnectionNotFoundError.tsx
│ │ │ │ │ └── ConnectionVerificationFailedError.tsx
│ │ │ │ ├── tests/
│ │ │ │ │ ├── ConnectionCrud.test.tsx
│ │ │ │ │ ├── ConnectionTestUtils.tsx
│ │ │ │ │ └── ConnectionVerification.test.tsx
│ │ │ │ └── verification/
│ │ │ │ ├── BlueskyOAuthVerifier.tsx
│ │ │ │ ├── DomainConnectionVerifier.tsx
│ │ │ │ └── IConnectionVerifier.tsx
│ │ │ ├── constants/
│ │ │ │ ├── Channel.tsx
│ │ │ │ ├── Core.tsx
│ │ │ │ ├── Gateway.tsx
│ │ │ │ ├── InstanceConfig.tsx
│ │ │ │ ├── IpBan.tsx
│ │ │ │ └── LimitConfig.tsx
│ │ │ ├── csam/
│ │ │ │ ├── CsamEvidenceRetentionService.tsx
│ │ │ │ ├── CsamEvidenceService.tsx
│ │ │ │ ├── CsamLegalHoldService.tsx
│ │ │ │ ├── CsamReportSnapshotService.tsx
│ │ │ │ ├── CsamResponseService.tsx
│ │ │ │ ├── CsamScanJobService.tsx
│ │ │ │ ├── CsamScanQueueService.tsx
│ │ │ │ ├── CsamTypes.tsx
│ │ │ │ ├── ICsamEvidenceService.tsx
│ │ │ │ ├── ICsamReportSnapshotService.tsx
│ │ │ │ ├── ISynchronousCsamScanner.tsx
│ │ │ │ ├── NcmecReporter.tsx
│ │ │ │ ├── NcmecSubmissionService.tsx
│ │ │ │ ├── PhotoDnaHashClient.tsx
│ │ │ │ ├── PhotoDnaMatchService.tsx
│ │ │ │ ├── SynchronousCsamScanner.tsx
│ │ │ │ ├── providers/
│ │ │ │ │ ├── ArachnidShieldProvider.tsx
│ │ │ │ │ ├── CsamProviderFactory.tsx
│ │ │ │ │ ├── ICsamScanProvider.tsx
│ │ │ │ │ ├── PhotoDnaProvider.tsx
│ │ │ │ │ └── tests/
│ │ │ │ │ ├── ArachnidShieldProvider.test.tsx
│ │ │ │ │ └── PhotoDnaProvider.test.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── CsamBlockingBehavior.test.tsx
│ │ │ │ ├── CsamEvidenceRetentionService.test.tsx
│ │ │ │ ├── CsamLegalHoldExpiry.test.tsx
│ │ │ │ ├── CsamLegalHoldService.test.tsx
│ │ │ │ ├── CsamReportSnapshotService.test.tsx
│ │ │ │ ├── CsamScanQueueService.test.tsx
│ │ │ │ ├── CsamTestUtils.tsx
│ │ │ │ ├── NcmecReporter.test.tsx
│ │ │ │ ├── NcmecSubmissionService.test.tsx
│ │ │ │ └── SynchronousCsamScanner.test.tsx
│ │ │ ├── database/
│ │ │ │ ├── Cassandra.tsx
│ │ │ │ ├── SqliteKV.tsx
│ │ │ │ └── types/
│ │ │ │ ├── AdminArchiveTypes.tsx
│ │ │ │ ├── AdminAuthTypes.tsx
│ │ │ │ ├── AuthTypes.tsx
│ │ │ │ ├── ChannelTypes.tsx
│ │ │ │ ├── ConnectionTypes.tsx
│ │ │ │ ├── CsamTypes.tsx
│ │ │ │ ├── DatabaseRowTypes.tsx
│ │ │ │ ├── DonationTypes.tsx
│ │ │ │ ├── GuildDiscoveryTypes.tsx
│ │ │ │ ├── GuildTypes.tsx
│ │ │ │ ├── InstanceConfigTypes.tsx
│ │ │ │ ├── MessageTypes.tsx
│ │ │ │ ├── OAuth2Types.tsx
│ │ │ │ ├── PaymentTypes.tsx
│ │ │ │ ├── ReportTypes.tsx
│ │ │ │ ├── SystemDmJobTypes.tsx
│ │ │ │ ├── UserTypes.tsx
│ │ │ │ └── VoiceTypes.tsx
│ │ │ ├── donation/
│ │ │ │ ├── DonationController.tsx
│ │ │ │ ├── DonationRepository.tsx
│ │ │ │ ├── DonationService.tsx
│ │ │ │ ├── DonationTables.tsx
│ │ │ │ ├── IDonationRepository.tsx
│ │ │ │ ├── IDonationService.tsx
│ │ │ │ ├── models/
│ │ │ │ │ ├── Donor.tsx
│ │ │ │ │ └── DonorMagicLinkToken.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── DonationCheckoutService.tsx
│ │ │ │ │ └── DonationMagicLinkService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── DonationCheckout.test.tsx
│ │ │ │ ├── DonationManage.test.tsx
│ │ │ │ ├── DonationRequestLink.test.tsx
│ │ │ │ └── DonationTestUtils.tsx
│ │ │ ├── download/
│ │ │ │ ├── DownloadController.tsx
│ │ │ │ ├── DownloadService.tsx
│ │ │ │ └── tests/
│ │ │ │ └── DownloadService.test.tsx
│ │ │ ├── email/
│ │ │ │ └── EmailProviderFactory.tsx
│ │ │ ├── emoji/
│ │ │ │ └── tests/
│ │ │ │ ├── EmojiBulkCreate.test.tsx
│ │ │ │ ├── EmojiNameValidation.test.tsx
│ │ │ │ ├── EmojiPermissions.test.tsx
│ │ │ │ ├── EmojiReactions.test.tsx
│ │ │ │ ├── EmojiTestUtils.tsx
│ │ │ │ ├── EmojiUploadValidPng.test.tsx
│ │ │ │ ├── EmojiUploadValidation.test.tsx
│ │ │ │ ├── StickerPermissions.test.tsx
│ │ │ │ ├── StickerUploadValidation.test.tsx
│ │ │ │ └── TypingIndicatorsPermissions.test.tsx
│ │ │ ├── favorite_meme/
│ │ │ │ ├── FavoriteMemeController.tsx
│ │ │ │ ├── FavoriteMemeModel.tsx
│ │ │ │ ├── FavoriteMemeRepository.tsx
│ │ │ │ ├── FavoriteMemeRequestService.tsx
│ │ │ │ ├── FavoriteMemeService.tsx
│ │ │ │ ├── IFavoriteMemeRepository.tsx
│ │ │ │ └── tests/
│ │ │ │ └── FavoriteMemeExtended.test.tsx
│ │ │ ├── federation/
│ │ │ │ ├── EncryptionMiddleware.tsx
│ │ │ │ ├── KeyManager.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── EncryptionMiddleware.test.tsx
│ │ │ │ └── KeyManager.test.tsx
│ │ │ ├── gateway/
│ │ │ │ ├── GatewayController.tsx
│ │ │ │ ├── GatewayRequestService.tsx
│ │ │ │ └── tests/
│ │ │ │ └── GatewayRpcService.test.tsx
│ │ │ ├── guild/
│ │ │ │ ├── GuildAuditLogService.tsx
│ │ │ │ ├── GuildAuditLogTypes.tsx
│ │ │ │ ├── GuildController.tsx
│ │ │ │ ├── GuildFeatureUtils.tsx
│ │ │ │ ├── GuildMemberLimitUtils.tsx
│ │ │ │ ├── GuildModel.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── GuildAuditLogController.tsx
│ │ │ │ │ ├── GuildBaseController.tsx
│ │ │ │ │ ├── GuildChannelController.tsx
│ │ │ │ │ ├── GuildDiscoveryController.tsx
│ │ │ │ │ ├── GuildEmojiController.tsx
│ │ │ │ │ ├── GuildMemberController.tsx
│ │ │ │ │ ├── GuildMemberSearchController.tsx
│ │ │ │ │ ├── GuildRoleController.tsx
│ │ │ │ │ ├── GuildStickerController.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── repositories/
│ │ │ │ │ ├── GuildContentRepository.tsx
│ │ │ │ │ ├── GuildDataRepository.tsx
│ │ │ │ │ ├── GuildDiscoveryRepository.tsx
│ │ │ │ │ ├── GuildMemberRepository.tsx
│ │ │ │ │ ├── GuildModerationRepository.tsx
│ │ │ │ │ ├── GuildRepository.tsx
│ │ │ │ │ ├── GuildRoleRepository.tsx
│ │ │ │ │ ├── IGuildContentRepository.tsx
│ │ │ │ │ ├── IGuildDataRepository.tsx
│ │ │ │ │ ├── IGuildMemberRepository.tsx
│ │ │ │ │ ├── IGuildModerationRepository.tsx
│ │ │ │ │ ├── IGuildRepositoryAggregate.tsx
│ │ │ │ │ └── IGuildRoleRepository.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── GuildChannelService.tsx
│ │ │ │ │ ├── GuildContentService.tsx
│ │ │ │ │ ├── GuildDataService.tsx
│ │ │ │ │ ├── GuildDiscoveryService.tsx
│ │ │ │ │ ├── GuildMemberService.tsx
│ │ │ │ │ ├── GuildModerationService.tsx
│ │ │ │ │ ├── GuildRoleService.tsx
│ │ │ │ │ ├── GuildSearchService.tsx
│ │ │ │ │ ├── GuildService.tsx
│ │ │ │ │ ├── channel/
│ │ │ │ │ │ ├── ChannelHelpers.tsx
│ │ │ │ │ │ └── ChannelOperationsService.tsx
│ │ │ │ │ ├── content/
│ │ │ │ │ │ ├── ContentHelpers.tsx
│ │ │ │ │ │ ├── EmojiService.tsx
│ │ │ │ │ │ ├── ExpressionAssetPurger.tsx
│ │ │ │ │ │ └── StickerService.tsx
│ │ │ │ │ ├── data/
│ │ │ │ │ │ ├── GuildDataHelpers.tsx
│ │ │ │ │ │ ├── GuildOperationsService.tsx
│ │ │ │ │ │ ├── GuildOwnershipService.tsx
│ │ │ │ │ │ └── GuildVanityService.tsx
│ │ │ │ │ └── member/
│ │ │ │ │ ├── GuildMemberAuditService.tsx
│ │ │ │ │ ├── GuildMemberAuthService.tsx
│ │ │ │ │ ├── GuildMemberEventService.tsx
│ │ │ │ │ ├── GuildMemberOperationsService.tsx
│ │ │ │ │ ├── GuildMemberRoleService.tsx
│ │ │ │ │ ├── GuildMemberSearchIndexService.tsx
│ │ │ │ │ └── GuildMemberValidationService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── DiscoveryApplicationLifecycle.test.tsx
│ │ │ │ ├── DiscoveryApplicationValidation.test.tsx
│ │ │ │ ├── DiscoverySearchAndJoin.test.tsx
│ │ │ │ ├── GuildAssetUpload.test.tsx
│ │ │ │ ├── GuildAuditLogs.test.tsx
│ │ │ │ ├── GuildChannelManagement.test.tsx
│ │ │ │ ├── GuildChannelPositions.test.tsx
│ │ │ │ ├── GuildFeatures.test.tsx
│ │ │ │ ├── GuildFolderOperations.test.tsx
│ │ │ │ ├── GuildMemberManagement.test.tsx
│ │ │ │ ├── GuildMfaLevel.test.tsx
│ │ │ │ ├── GuildOperationPermissions.test.tsx
│ │ │ │ ├── GuildOperationValidation.test.tsx
│ │ │ │ ├── GuildOwnershipTransfer.test.tsx
│ │ │ │ ├── GuildRoleManagement.test.tsx
│ │ │ │ ├── GuildRoleOperations.test.tsx
│ │ │ │ ├── GuildRoleReorder.test.tsx
│ │ │ │ ├── GuildTestUtils.tsx
│ │ │ │ ├── GuildUnavailableFeatureAccess.test.tsx
│ │ │ │ ├── InvitePermissions.test.tsx
│ │ │ │ ├── InviteSecurity.test.tsx
│ │ │ │ ├── InviteValidation.test.tsx
│ │ │ │ ├── RoleHierarchyEnforcement.test.tsx
│ │ │ │ └── RolePermissionAssignmentHierarchy.test.tsx
│ │ │ ├── infrastructure/
│ │ │ │ ├── AssetDeletionQueue.tsx
│ │ │ │ ├── AvatarService.tsx
│ │ │ │ ├── ClamAV.tsx
│ │ │ │ ├── CloudflarePurgeQueue.tsx
│ │ │ │ ├── DirectMediaService.tsx
│ │ │ │ ├── DirectS3ExpirationManager.tsx
│ │ │ │ ├── DirectS3ExpirationStore.tsx
│ │ │ │ ├── DirectS3StorageService.tsx
│ │ │ │ ├── DisabledLiveKitService.tsx
│ │ │ │ ├── DisabledVirusScanService.tsx
│ │ │ │ ├── DiscriminatorService.tsx
│ │ │ │ ├── ElasticsearchSearchProvider.tsx
│ │ │ │ ├── EmailDnsValidationService.tsx
│ │ │ │ ├── EmbedService.tsx
│ │ │ │ ├── EntityAssetService.tsx
│ │ │ │ ├── ErrorI18nService.tsx
│ │ │ │ ├── GatewayRpcClient.tsx
│ │ │ │ ├── GatewayRpcError.tsx
│ │ │ │ ├── GatewayService.tsx
│ │ │ │ ├── IAssetDeletionQueue.tsx
│ │ │ │ ├── IEmailDnsValidationService.tsx
│ │ │ │ ├── IGatewayRpcTransport.tsx
│ │ │ │ ├── IGatewayService.tsx
│ │ │ │ ├── IKlipyService.tsx
│ │ │ │ ├── ILiveKitService.tsx
│ │ │ │ ├── IMediaService.tsx
│ │ │ │ ├── IMetricsService.tsx
│ │ │ │ ├── ISnowflakeService.tsx
│ │ │ │ ├── IStorageService.tsx
│ │ │ │ ├── ITenorService.tsx
│ │ │ │ ├── IUnfurlerService.tsx
│ │ │ │ ├── IVoiceRoomStore.tsx
│ │ │ │ ├── InMemoryVoiceRoomStore.tsx
│ │ │ │ ├── KVAccountDeletionQueueService.tsx
│ │ │ │ ├── KVActivityTracker.tsx
│ │ │ │ ├── KVBulkMessageDeletionQueueService.tsx
│ │ │ │ ├── LiveKitService.tsx
│ │ │ │ ├── LiveKitWebhookService.tsx
│ │ │ │ ├── MediaService.tsx
│ │ │ │ ├── MeilisearchSearchProvider.tsx
│ │ │ │ ├── MetricsService.tsx
│ │ │ │ ├── NatsGatewayRpcTransport.tsx
│ │ │ │ ├── NullSearchProvider.tsx
│ │ │ │ ├── SnowflakeService.tsx
│ │ │ │ ├── StorageObjectHelpers.tsx
│ │ │ │ ├── StorageService.tsx
│ │ │ │ ├── StorageServiceFactory.tsx
│ │ │ │ ├── UnfurlerService.tsx
│ │ │ │ ├── UserCacheService.tsx
│ │ │ │ ├── VirusScanService.tsx
│ │ │ │ ├── VoiceRoomContext.tsx
│ │ │ │ ├── VoiceRoomStore.tsx
│ │ │ │ ├── error_i18n/
│ │ │ │ │ └── index.tsx
│ │ │ │ └── tests/
│ │ │ │ └── EmailDnsValidationService.test.tsx
│ │ │ ├── instance/
│ │ │ │ ├── InstanceConfigRepository.tsx
│ │ │ │ ├── InstanceController.tsx
│ │ │ │ ├── SnowflakeReservationRepository.tsx
│ │ │ │ └── SnowflakeReservationService.tsx
│ │ │ ├── invite/
│ │ │ │ ├── IInviteRepository.tsx
│ │ │ │ ├── InviteController.tsx
│ │ │ │ ├── InviteModel.tsx
│ │ │ │ ├── InviteRepository.tsx
│ │ │ │ ├── InviteRequestService.tsx
│ │ │ │ ├── InviteService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── GroupDMInviteRecipientsSerialization.test.tsx
│ │ │ │ ├── InviteGuildMemberLimit.test.tsx
│ │ │ │ ├── InvitePermissions.test.tsx
│ │ │ │ ├── InviteSecurityChecks.test.tsx
│ │ │ │ ├── InviteTestUtils.tsx
│ │ │ │ └── InviteValidation.test.tsx
│ │ │ ├── klipy/
│ │ │ │ ├── KlipyController.tsx
│ │ │ │ └── KlipyService.tsx
│ │ │ ├── limits/
│ │ │ │ ├── LimitConfigService.tsx
│ │ │ │ ├── LimitConfigUtils.tsx
│ │ │ │ ├── LimitMatchContextBuilder.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── LimitConfigDefaults.test.tsx
│ │ │ │ └── LimitWireFormat.test.tsx
│ │ │ ├── message/
│ │ │ │ └── tests/
│ │ │ │ ├── AllowedMentions.test.tsx
│ │ │ │ ├── MessageAck.test.tsx
│ │ │ │ ├── MessageAttachmentDeleteLastAttachmentEmptyMessage.test.tsx
│ │ │ │ ├── MessageAttachmentUploadAuthorTypes.test.tsx
│ │ │ │ ├── MessageEditAddNewAttachmentWithEmbed.test.tsx
│ │ │ │ ├── MessageEditAttachmentDescription.test.tsx
│ │ │ │ ├── MessageEditAttachmentsReplaced.test.tsx
│ │ │ │ ├── MessageEditEmbedReferenceMissingAttachment.test.tsx
│ │ │ │ ├── MessageEditValidation.test.tsx
│ │ │ │ ├── MessageEditWithEmbedAttachmentUrl.test.tsx
│ │ │ │ ├── MessageFetch.test.tsx
│ │ │ │ ├── MessageFetchBeforeSingleBucket.test.tsx
│ │ │ │ ├── MessageFetchEmptyChannel.test.tsx
│ │ │ │ ├── MessageFetchPaginationNoDuplicates.test.tsx
│ │ │ │ ├── MessageForwardingAccessControl.test.tsx
│ │ │ │ ├── MessageForwardingBetweenChannels.test.tsx
│ │ │ │ ├── MessageForwardingInGuildChannels.test.tsx
│ │ │ │ ├── MessageForwardingPermissions.test.tsx
│ │ │ │ ├── MessageForwardingSuppressedEmbeds.test.tsx
│ │ │ │ ├── MessageForwardingValidationErrorsContent.test.tsx
│ │ │ │ ├── MessageForwardingValidationErrorsGuildMismatch.test.tsx
│ │ │ │ ├── MessageHistoryCutoff.test.tsx
│ │ │ │ ├── MessageOperationValidation.test.tsx
│ │ │ │ ├── MessagePermissions.test.tsx
│ │ │ │ ├── MessagePins.test.tsx
│ │ │ │ ├── MessageReactionOperations.test.tsx
│ │ │ │ ├── MessageReactionPermissions.test.tsx
│ │ │ │ ├── MessageReactionValidation.test.tsx
│ │ │ │ ├── MessageShred.test.tsx
│ │ │ │ ├── MessageState.test.tsx
│ │ │ │ ├── MessageStickerDMPremium.test.tsx
│ │ │ │ ├── MessageSuppressNotificationsFlag.test.tsx
│ │ │ │ ├── MessageTestUtils.tsx
│ │ │ │ └── VoiceMessageValidation.test.tsx
│ │ │ ├── middleware/
│ │ │ │ ├── AdminMiddleware.tsx
│ │ │ │ ├── AuditLogMiddleware.tsx
│ │ │ │ ├── AuthMiddleware.tsx
│ │ │ │ ├── BlockAppOriginMiddleware.tsx
│ │ │ │ ├── CaptchaMiddleware.tsx
│ │ │ │ ├── ConcurrencyLimitMiddleware.tsx
│ │ │ │ ├── GuildAvailabilityMiddleware.tsx
│ │ │ │ ├── IpBanMiddleware.tsx
│ │ │ │ ├── LocalAuthMiddleware.tsx
│ │ │ │ ├── LocaleMiddleware.tsx
│ │ │ │ ├── MetricsMiddleware.tsx
│ │ │ │ ├── OAuth2ScopeMiddleware.tsx
│ │ │ │ ├── RateLimitMiddleware.tsx
│ │ │ │ ├── RequestCacheMiddleware.tsx
│ │ │ │ ├── RequireXForwardedForMiddleware.tsx
│ │ │ │ ├── ResponseTypeMiddleware.tsx
│ │ │ │ ├── ServiceMiddleware.tsx
│ │ │ │ ├── ServiceRegistry.tsx
│ │ │ │ ├── SudoModeMiddleware.tsx
│ │ │ │ ├── UserMiddleware.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── GlobalRateLimitRevokesSession.test.tsx
│ │ │ │ └── IpBanMiddleware.test.tsx
│ │ │ ├── models/
│ │ │ │ ├── AdminApiKey.tsx
│ │ │ │ ├── Application.tsx
│ │ │ │ ├── Attachment.tsx
│ │ │ │ ├── AuthSession.tsx
│ │ │ │ ├── CallInfo.tsx
│ │ │ │ ├── Channel.tsx
│ │ │ │ ├── ChannelPermissionOverwrite.tsx
│ │ │ │ ├── EmailRevertToken.tsx
│ │ │ │ ├── EmailVerificationToken.tsx
│ │ │ │ ├── Embed.tsx
│ │ │ │ ├── EmbedAuthor.tsx
│ │ │ │ ├── EmbedField.tsx
│ │ │ │ ├── EmbedFooter.tsx
│ │ │ │ ├── EmbedMedia.tsx
│ │ │ │ ├── EmbedProvider.tsx
│ │ │ │ ├── ExpressionPack.tsx
│ │ │ │ ├── FavoriteMeme.tsx
│ │ │ │ ├── GiftCode.tsx
│ │ │ │ ├── Guild.tsx
│ │ │ │ ├── GuildAuditLog.tsx
│ │ │ │ ├── GuildBan.tsx
│ │ │ │ ├── GuildChannelOverride.tsx
│ │ │ │ ├── GuildEmoji.tsx
│ │ │ │ ├── GuildMember.tsx
│ │ │ │ ├── GuildRole.tsx
│ │ │ │ ├── GuildSticker.tsx
│ │ │ │ ├── Invite.tsx
│ │ │ │ ├── Message.tsx
│ │ │ │ ├── MessageReaction.tsx
│ │ │ │ ├── MessageRef.tsx
│ │ │ │ ├── MessageSnapshot.tsx
│ │ │ │ ├── MfaBackupCode.tsx
│ │ │ │ ├── MuteConfiguration.tsx
│ │ │ │ ├── OAuth2AccessToken.tsx
│ │ │ │ ├── OAuth2AuthorizationCode.tsx
│ │ │ │ ├── OAuth2RefreshToken.tsx
│ │ │ │ ├── PasswordResetToken.tsx
│ │ │ │ ├── Payment.tsx
│ │ │ │ ├── PushSubscription.tsx
│ │ │ │ ├── ReadState.tsx
│ │ │ │ ├── RecentMention.tsx
│ │ │ │ ├── Relationship.tsx
│ │ │ │ ├── SavedMessage.tsx
│ │ │ │ ├── ScheduledMessage.tsx
│ │ │ │ ├── StickerItem.tsx
│ │ │ │ ├── User.tsx
│ │ │ │ ├── UserCustomStatus.tsx
│ │ │ │ ├── UserGuildFolder.tsx
│ │ │ │ ├── UserGuildSettings.tsx
│ │ │ │ ├── UserNote.tsx
│ │ │ │ ├── UserSettings.tsx
│ │ │ │ ├── VisionarySlot.tsx
│ │ │ │ ├── WebAuthnCredential.tsx
│ │ │ │ ├── Webhook.tsx
│ │ │ │ └── tests/
│ │ │ │ └── EmbedIconUrlSanitization.test.tsx
│ │ │ ├── moderation/
│ │ │ │ └── tests/
│ │ │ │ ├── BannedUserRestrictions.test.tsx
│ │ │ │ ├── BlockedUserCannotInteract.test.tsx
│ │ │ │ ├── ModerationTestUtils.tsx
│ │ │ │ └── TimeoutModerationGuards.test.tsx
│ │ │ ├── oauth/
│ │ │ │ ├── ApplicationMessageAuthorAnonymization.tsx
│ │ │ │ ├── ApplicationService.tsx
│ │ │ │ ├── BotAuthService.tsx
│ │ │ │ ├── BotMfaMirrorService.tsx
│ │ │ │ ├── OAuth2ApplicationsController.tsx
│ │ │ │ ├── OAuth2ApplicationsRequestService.tsx
│ │ │ │ ├── OAuth2Controller.tsx
│ │ │ │ ├── OAuth2Mappers.tsx
│ │ │ │ ├── OAuth2RedirectURI.tsx
│ │ │ │ ├── OAuth2RequestService.tsx
│ │ │ │ ├── OAuth2Service.tsx
│ │ │ │ ├── OAuth2Types.tsx
│ │ │ │ ├── repositories/
│ │ │ │ │ ├── ApplicationRepository.tsx
│ │ │ │ │ ├── IApplicationRepository.tsx
│ │ │ │ │ ├── IOAuth2TokenRepository.tsx
│ │ │ │ │ └── OAuth2TokenRepository.tsx
│ │ │ │ ├── tests/
│ │ │ │ │ ├── OAuth2ApplicationCreate.test.tsx
│ │ │ │ │ ├── OAuth2ApplicationDelete.test.tsx
│ │ │ │ │ ├── OAuth2ApplicationGet.test.tsx
│ │ │ │ │ ├── OAuth2ApplicationList.test.tsx
│ │ │ │ │ ├── OAuth2ApplicationUpdate.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizationsDeauthorize.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizationsList.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizationsRequiresAuth.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizeCodeFlow.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizeRedirectURI.test.tsx
│ │ │ │ │ ├── OAuth2AuthorizeStateParameter.test.tsx
│ │ │ │ │ ├── OAuth2BotGuildAdd.test.tsx
│ │ │ │ │ ├── OAuth2BotToken.test.tsx
│ │ │ │ │ ├── OAuth2ClientSecret.test.tsx
│ │ │ │ │ ├── OAuth2CodeReplay.test.tsx
│ │ │ │ │ ├── OAuth2ScopeEnforcement.test.tsx
│ │ │ │ │ ├── OAuth2ScopeMiddleware.test.tsx
│ │ │ │ │ ├── OAuth2ScopeValidation.test.tsx
│ │ │ │ │ ├── OAuth2Scopes.test.tsx
│ │ │ │ │ ├── OAuth2TestUtils.tsx
│ │ │ │ │ ├── OAuth2TokenExchange.test.tsx
│ │ │ │ │ ├── OAuth2TokenExpiration.test.tsx
│ │ │ │ │ ├── OAuth2TokenIntrospection.test.tsx
│ │ │ │ │ ├── OAuth2TokenRefresh.test.tsx
│ │ │ │ │ ├── OAuth2TokenRevocation.test.tsx
│ │ │ │ │ └── OAuthTestUtils.tsx
│ │ │ │ └── utils/
│ │ │ │ └── ParseClientCredentials.tsx
│ │ │ ├── oauth2/
│ │ │ │ └── tests/
│ │ │ │ ├── OAuth2ApplicationOperations.test.tsx
│ │ │ │ ├── OAuth2AuthorizationFlow.test.tsx
│ │ │ │ ├── OAuth2BotOperations.test.tsx
│ │ │ │ ├── OAuth2Me.test.tsx
│ │ │ │ └── OAuth2TokenRevoke.test.tsx
│ │ │ ├── pack/
│ │ │ │ ├── PackExpressionAccessResolver.tsx
│ │ │ │ ├── PackModel.tsx
│ │ │ │ ├── PackRepository.tsx
│ │ │ │ ├── PackRequestService.tsx
│ │ │ │ ├── PackService.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── PackController.tsx
│ │ │ │ │ ├── PackEmojiController.tsx
│ │ │ │ │ ├── PackStickerController.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── PackInviteFlow.test.tsx
│ │ │ │ ├── PackPremiumRequirements.test.tsx
│ │ │ │ └── PackTestUtils.tsx
│ │ │ ├── rate_limit_configs/
│ │ │ │ ├── AdminRateLimitConfig.tsx
│ │ │ │ ├── AuthRateLimitConfig.tsx
│ │ │ │ ├── ChannelRateLimitConfig.tsx
│ │ │ │ ├── ConnectionRateLimitConfig.tsx
│ │ │ │ ├── DiscoveryRateLimitConfig.tsx
│ │ │ │ ├── DonationRateLimitConfig.tsx
│ │ │ │ ├── GuildRateLimitConfig.tsx
│ │ │ │ ├── IntegrationRateLimitConfig.tsx
│ │ │ │ ├── InviteRateLimitConfig.tsx
│ │ │ │ ├── MiscRateLimitConfig.tsx
│ │ │ │ ├── OAuthRateLimitConfig.tsx
│ │ │ │ ├── PackRateLimitConfig.tsx
│ │ │ │ ├── RateLimitHelpers.tsx
│ │ │ │ ├── UserRateLimitConfig.tsx
│ │ │ │ └── WebhookRateLimitConfig.tsx
│ │ │ ├── read_state/
│ │ │ │ ├── IReadStateRepository.tsx
│ │ │ │ ├── ReadStateController.tsx
│ │ │ │ ├── ReadStateRepository.tsx
│ │ │ │ ├── ReadStateRequestService.tsx
│ │ │ │ └── ReadStateService.tsx
│ │ │ ├── report/
│ │ │ │ ├── IReportRepository.tsx
│ │ │ │ ├── ReportController.tsx
│ │ │ │ ├── ReportRepository.tsx
│ │ │ │ ├── ReportRequestService.tsx
│ │ │ │ ├── ReportService.tsx
│ │ │ │ └── tests/
│ │ │ │ └── ContentReporting.test.tsx
│ │ │ ├── rpc/
│ │ │ │ ├── NatsApiRpcListener.tsx
│ │ │ │ ├── RpcService.tsx
│ │ │ │ └── tests/
│ │ │ │ └── RpcGuildMemberCountRepair.test.tsx
│ │ │ ├── search/
│ │ │ │ ├── BuildMessageSearchFilters.tsx
│ │ │ │ ├── ChannelIndexingUtils.tsx
│ │ │ │ ├── GlobalSearchService.tsx
│ │ │ │ ├── IAuditLogSearchService.tsx
│ │ │ │ ├── IGuildMemberSearchService.tsx
│ │ │ │ ├── IGuildSearchService.tsx
│ │ │ │ ├── IMessageSearchService.tsx
│ │ │ │ ├── IReportSearchService.tsx
│ │ │ │ ├── ISearchProvider.tsx
│ │ │ │ ├── IUserSearchService.tsx
│ │ │ │ ├── MessageSearchResponseMapper.tsx
│ │ │ │ ├── SearchConstants.tsx
│ │ │ │ ├── SearchService.tsx
│ │ │ │ ├── SearchTaskTracker.tsx
│ │ │ │ ├── SearchWarmup.tsx
│ │ │ │ ├── auditlog/
│ │ │ │ │ └── AuditLogSearchSerializer.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ └── SearchController.tsx
│ │ │ │ ├── elasticsearch/
│ │ │ │ │ ├── ElasticsearchAuditLogSearchService.tsx
│ │ │ │ │ ├── ElasticsearchGuildMemberSearchService.tsx
│ │ │ │ │ ├── ElasticsearchGuildSearchService.tsx
│ │ │ │ │ ├── ElasticsearchMessageSearchService.tsx
│ │ │ │ │ ├── ElasticsearchReportSearchService.tsx
│ │ │ │ │ ├── ElasticsearchSearchServiceBase.tsx
│ │ │ │ │ └── ElasticsearchUserSearchService.tsx
│ │ │ │ ├── guild/
│ │ │ │ │ └── GuildSearchSerializer.tsx
│ │ │ │ ├── guild_member/
│ │ │ │ │ └── GuildMemberSearchSerializer.tsx
│ │ │ │ ├── meilisearch/
│ │ │ │ │ ├── MeilisearchAuditLogSearchService.tsx
│ │ │ │ │ ├── MeilisearchGuildMemberSearchService.tsx
│ │ │ │ │ ├── MeilisearchGuildSearchService.tsx
│ │ │ │ │ ├── MeilisearchMessageSearchService.tsx
│ │ │ │ │ ├── MeilisearchReportSearchService.tsx
│ │ │ │ │ ├── MeilisearchSearchServiceBase.tsx
│ │ │ │ │ └── MeilisearchUserSearchService.tsx
│ │ │ │ ├── message/
│ │ │ │ │ ├── MessageSearchSerializer.tsx
│ │ │ │ │ └── tests/
│ │ │ │ │ └── MessageSearchSerializer.test.tsx
│ │ │ │ ├── report/
│ │ │ │ │ └── ReportSearchSerializer.tsx
│ │ │ │ ├── tests/
│ │ │ │ │ ├── GuildMemberSearchEndpoint.test.tsx
│ │ │ │ │ ├── MessageSearchEndpoint.test.tsx
│ │ │ │ │ ├── MessageSearchExactPhrase.test.tsx
│ │ │ │ │ ├── MessageSearchFilters.test.tsx
│ │ │ │ │ ├── MessageSearchPermissions.test.tsx
│ │ │ │ │ └── MessageSearchSorting.test.tsx
│ │ │ │ └── user/
│ │ │ │ └── UserSearchSerializer.tsx
│ │ │ ├── sticker/
│ │ │ │ └── tests/
│ │ │ │ └── StickerUploadValidation.test.tsx
│ │ │ ├── stripe/
│ │ │ │ ├── ProductRegistry.tsx
│ │ │ │ ├── StripeController.tsx
│ │ │ │ ├── StripeModel.tsx
│ │ │ │ ├── StripeService.tsx
│ │ │ │ ├── StripeSubscriptionPeriod.tsx
│ │ │ │ ├── StripeUtils.tsx
│ │ │ │ ├── VisionarySlotInitializer.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── StripeCheckoutService.tsx
│ │ │ │ │ ├── StripeGiftService.tsx
│ │ │ │ │ ├── StripePremiumService.tsx
│ │ │ │ │ ├── StripeSubscriptionService.tsx
│ │ │ │ │ └── StripeWebhookService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── StripeCheckoutService.test.tsx
│ │ │ │ ├── StripeGiftService.test.tsx
│ │ │ │ ├── StripePremiumService.test.tsx
│ │ │ │ ├── StripeSubscriptionService.test.tsx
│ │ │ │ ├── StripeUtils.test.tsx
│ │ │ │ ├── StripeWebhookCheckout.test.tsx
│ │ │ │ ├── StripeWebhookCore.test.tsx
│ │ │ │ ├── StripeWebhookDispute.test.tsx
│ │ │ │ ├── StripeWebhookEdgeCases.test.tsx
│ │ │ │ ├── StripeWebhookIdempotency.test.tsx
│ │ │ │ ├── StripeWebhookInvoice.test.tsx
│ │ │ │ ├── StripeWebhookRefund.test.tsx
│ │ │ │ ├── StripeWebhookSubscription.test.tsx
│ │ │ │ └── StripeWebhookTestUtils.tsx
│ │ │ ├── system_dm/
│ │ │ │ └── TargetFinder.tsx
│ │ │ ├── telemetry/
│ │ │ │ ├── BusinessSpans.tsx
│ │ │ │ ├── CsamTelemetry.tsx
│ │ │ │ ├── MessageTelemetry.tsx
│ │ │ │ └── Tracing.tsx
│ │ │ ├── tenor/
│ │ │ │ ├── TenorController.tsx
│ │ │ │ └── TenorService.tsx
│ │ │ ├── test/
│ │ │ │ ├── ApiTestHarness.tsx
│ │ │ │ ├── NoopGatewayService.tsx
│ │ │ │ ├── NoopWorkerService.tsx
│ │ │ │ ├── Setup.tsx
│ │ │ │ ├── TestConstants.tsx
│ │ │ │ ├── TestHarnessController.tsx
│ │ │ │ ├── TestHarnessReset.tsx
│ │ │ │ ├── TestMediaService.tsx
│ │ │ │ ├── TestRequestBuilder.tsx
│ │ │ │ ├── TestS3Service.tsx
│ │ │ │ ├── fixtures/
│ │ │ │ │ └── ncmec/
│ │ │ │ │ └── NcmecXmlFixtures.tsx
│ │ │ │ ├── meilisearch/
│ │ │ │ │ └── MeilisearchTestServer.tsx
│ │ │ │ ├── mocks/
│ │ │ │ │ ├── MockAssetDeletionQueue.tsx
│ │ │ │ │ ├── MockBlueskyOAuthService.tsx
│ │ │ │ │ ├── MockCsamEvidenceService.tsx
│ │ │ │ │ ├── MockCsamReportSnapshotService.tsx
│ │ │ │ │ ├── MockCsamScanQueueService.tsx
│ │ │ │ │ ├── MockGatewayRpcTransport.tsx
│ │ │ │ │ ├── MockGatewayService.tsx
│ │ │ │ │ ├── MockKVProvider.tsx
│ │ │ │ │ ├── MockLiveKitService.tsx
│ │ │ │ │ ├── MockMediaService.tsx
│ │ │ │ │ ├── MockNcmecReporter.tsx
│ │ │ │ │ ├── MockPhotoDnaHashClient.tsx
│ │ │ │ │ ├── MockSnowflakeService.tsx
│ │ │ │ │ ├── MockStorageService.tsx
│ │ │ │ │ ├── MockSynchronousCsamScanner.tsx
│ │ │ │ │ ├── MockVirusScanService.tsx
│ │ │ │ │ └── NoopLogger.tsx
│ │ │ │ └── msw/
│ │ │ │ ├── handlers/
│ │ │ │ │ ├── ArachnidShieldHandlers.tsx
│ │ │ │ │ ├── BlueskyApiHandlers.tsx
│ │ │ │ │ ├── DockerEngineHandlers.tsx
│ │ │ │ │ ├── MeilisearchHandlers.tsx
│ │ │ │ │ ├── NcmecHandlers.tsx
│ │ │ │ │ ├── PhotoDnaHandlers.tsx
│ │ │ │ │ ├── PwnedPasswordsHandlers.tsx
│ │ │ │ │ ├── StripeApiHandlers.tsx
│ │ │ │ │ └── WikipediaApiHandlers.tsx
│ │ │ │ └── server.tsx
│ │ │ ├── tests/
│ │ │ │ └── Smoke.test.tsx
│ │ │ ├── theme/
│ │ │ │ ├── ThemeController.tsx
│ │ │ │ ├── ThemeService.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── ThemeAuthRequired.test.tsx
│ │ │ │ ├── ThemeBotUserDenied.test.tsx
│ │ │ │ ├── ThemeCreation.test.tsx
│ │ │ │ ├── ThemeCssSizeLimit.test.tsx
│ │ │ │ └── ThemeValidation.test.tsx
│ │ │ ├── types/
│ │ │ │ ├── AttachmentDecayTypes.tsx
│ │ │ │ └── HonoEnv.tsx
│ │ │ ├── typing/
│ │ │ │ └── tests/
│ │ │ │ ├── TypingInDMChannel.test.tsx
│ │ │ │ ├── TypingInGuildChannel.test.tsx
│ │ │ │ ├── TypingPermissions.test.tsx
│ │ │ │ └── TypingTestUtils.tsx
│ │ │ ├── unfurler/
│ │ │ │ ├── resolvers/
│ │ │ │ │ ├── AudioResolver.tsx
│ │ │ │ │ ├── BaseResolver.tsx
│ │ │ │ │ ├── BlueskyResolver.tsx
│ │ │ │ │ ├── DefaultResolver.tsx
│ │ │ │ │ ├── HackerNewsResolver.tsx
│ │ │ │ │ ├── ImageResolver.tsx
│ │ │ │ │ ├── KlipyResolver.tsx
│ │ │ │ │ ├── TenorResolver.tsx
│ │ │ │ │ ├── VideoResolver.tsx
│ │ │ │ │ ├── WikipediaResolver.tsx
│ │ │ │ │ ├── XkcdResolver.tsx
│ │ │ │ │ ├── YouTubeResolver.tsx
│ │ │ │ │ ├── bluesky/
│ │ │ │ │ │ ├── BlueskyApiClient.tsx
│ │ │ │ │ │ ├── BlueskyEmbedProcessor.tsx
│ │ │ │ │ │ ├── BlueskyTextFormatter.tsx
│ │ │ │ │ │ └── BlueskyTypes.tsx
│ │ │ │ │ ├── media/
│ │ │ │ │ │ └── MediaMetadataHelpers.tsx
│ │ │ │ │ └── subresolvers/
│ │ │ │ │ ├── ActivityPubFetcher.tsx
│ │ │ │ │ ├── ActivityPubFormatter.tsx
│ │ │ │ │ ├── ActivityPubResolver.tsx
│ │ │ │ │ ├── ActivityPubTypes.tsx
│ │ │ │ │ └── ActivityPubUtils.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── ActivityPubFetcher.test.tsx
│ │ │ │ ├── ActivityPubFormatter.test.tsx
│ │ │ │ ├── ActivityPubResolver.test.tsx
│ │ │ │ ├── AudioResolver.test.tsx
│ │ │ │ ├── BaseResolver.test.tsx
│ │ │ │ ├── BlueskyEmbedProcessor.test.tsx
│ │ │ │ ├── BlueskyResolver.test.tsx
│ │ │ │ ├── DefaultResolver.test.tsx
│ │ │ │ ├── HackerNewsResolver.test.tsx
│ │ │ │ ├── ImageResolver.test.tsx
│ │ │ │ ├── KlipyResolver.test.tsx
│ │ │ │ ├── ResolverTestUtils.tsx
│ │ │ │ ├── TenorResolver.test.tsx
│ │ │ │ ├── VideoResolver.test.tsx
│ │ │ │ ├── WikipediaResolver.test.tsx
│ │ │ │ ├── XkcdResolver.test.tsx
│ │ │ │ └── YouTubeResolver.test.tsx
│ │ │ ├── user/
│ │ │ │ ├── IUserRepository.tsx
│ │ │ │ ├── UserCacheHelpers.tsx
│ │ │ │ ├── UserHarvestModel.tsx
│ │ │ │ ├── UserHarvestRepository.tsx
│ │ │ │ ├── UserHelpers.tsx
│ │ │ │ ├── UserMappers.tsx
│ │ │ │ ├── UserModel.tsx
│ │ │ │ ├── controllers/
│ │ │ │ │ ├── UserAccountController.tsx
│ │ │ │ │ ├── UserAuthController.tsx
│ │ │ │ │ ├── UserChannelController.tsx
│ │ │ │ │ ├── UserContentController.tsx
│ │ │ │ │ ├── UserController.tsx
│ │ │ │ │ ├── UserRelationshipController.tsx
│ │ │ │ │ └── UserScheduledMessageController.tsx
│ │ │ │ ├── repositories/
│ │ │ │ │ ├── GiftCodeRepository.tsx
│ │ │ │ │ ├── IUserAccountRepository.tsx
│ │ │ │ │ ├── IUserAuthRepository.tsx
│ │ │ │ │ ├── IUserChannelRepository.tsx
│ │ │ │ │ ├── IUserContentRepository.tsx
│ │ │ │ │ ├── IUserRelationshipRepository.tsx
│ │ │ │ │ ├── IUserRepositoryAggregate.tsx
│ │ │ │ │ ├── IUserSettingsRepository.tsx
│ │ │ │ │ ├── PaymentRepository.tsx
│ │ │ │ │ ├── PushSubscriptionRepository.tsx
│ │ │ │ │ ├── RecentMentionRepository.tsx
│ │ │ │ │ ├── SavedMessageRepository.tsx
│ │ │ │ │ ├── ScheduledMessageRepository.tsx
│ │ │ │ │ ├── UserAccountRepository.tsx
│ │ │ │ │ ├── UserAuthRepository.tsx
│ │ │ │ │ ├── UserChannelRepository.tsx
│ │ │ │ │ ├── UserContactChangeLogRepository.tsx
│ │ │ │ │ ├── UserContentRepository.tsx
│ │ │ │ │ ├── UserRelationshipRepository.tsx
│ │ │ │ │ ├── UserRepository.tsx
│ │ │ │ │ ├── UserSettingsRepository.tsx
│ │ │ │ │ ├── VisionarySlotRepository.tsx
│ │ │ │ │ ├── account/
│ │ │ │ │ │ ├── UserAccountRepository.tsx
│ │ │ │ │ │ ├── UserDeletionRepository.tsx
│ │ │ │ │ │ ├── UserGuildRepository.tsx
│ │ │ │ │ │ ├── UserLookupRepository.tsx
│ │ │ │ │ │ └── crud/
│ │ │ │ │ │ ├── UserDataRepository.tsx
│ │ │ │ │ │ ├── UserIndexRepository.tsx
│ │ │ │ │ │ └── UserSearchRepository.tsx
│ │ │ │ │ └── auth/
│ │ │ │ │ ├── AuthSessionRepository.tsx
│ │ │ │ │ ├── EmailChangeRepository.tsx
│ │ │ │ │ ├── IpAuthorizationRepository.tsx
│ │ │ │ │ ├── MfaBackupCodeRepository.tsx
│ │ │ │ │ ├── PasswordChangeRepository.tsx
│ │ │ │ │ ├── TokenRepository.tsx
│ │ │ │ │ └── WebAuthnRepository.tsx
│ │ │ │ ├── services/
│ │ │ │ │ ├── BaseUserUpdatePropagator.tsx
│ │ │ │ │ ├── CustomStatusValidator.tsx
│ │ │ │ │ ├── EmailChangeService.tsx
│ │ │ │ │ ├── PasswordChangeService.tsx
│ │ │ │ │ ├── UserAccountLifecycleService.tsx
│ │ │ │ │ ├── UserAccountLookupService.tsx
│ │ │ │ │ ├── UserAccountNotesService.tsx
│ │ │ │ │ ├── UserAccountProfileService.tsx
│ │ │ │ │ ├── UserAccountRequestService.tsx
│ │ │ │ │ ├── UserAccountSecurityService.tsx
│ │ │ │ │ ├── UserAccountService.tsx
│ │ │ │ │ ├── UserAccountSettingsService.tsx
│ │ │ │ │ ├── UserAccountUpdatePropagator.tsx
│ │ │ │ │ ├── UserAuthRequestService.tsx
│ │ │ │ │ ├── UserAuthService.tsx
│ │ │ │ │ ├── UserChannelRequestService.tsx
│ │ │ │ │ ├── UserChannelService.tsx
│ │ │ │ │ ├── UserContactChangeLogService.tsx
│ │ │ │ │ ├── UserContentRequestService.tsx
│ │ │ │ │ ├── UserContentService.tsx
│ │ │ │ │ ├── UserDeletionEligibilityService.tsx
│ │ │ │ │ ├── UserDeletionService.tsx
│ │ │ │ │ ├── UserRelationshipRequestService.tsx
│ │ │ │ │ ├── UserRelationshipService.tsx
│ │ │ │ │ └── UserService.tsx
│ │ │ │ ├── tests/
│ │ │ │ │ ├── AccountDeleteAutoCancelOnLogin.test.tsx
│ │ │ │ │ ├── AccountDeleteGracePeriod.test.tsx
│ │ │ │ │ ├── AccountDeleteMentionResolution.test.tsx
│ │ │ │ │ ├── AccountDeleteMessagePagination.test.tsx
│ │ │ │ │ ├── AccountDeletePermanent.test.tsx
│ │ │ │ │ ├── AccountDisable.test.tsx
│ │ │ │ │ ├── FavoriteMemeLimits.test.tsx
│ │ │ │ │ ├── FavoriteMemeOperations.test.tsx
│ │ │ │ │ ├── FavoriteMemeTestUtils.tsx
│ │ │ │ │ ├── HarvestDownloadExpirationBoundary.test.tsx
│ │ │ │ │ ├── HarvestDownloadExpired.test.tsx
│ │ │ │ │ ├── HarvestDownloadNotExpired.test.tsx
│ │ │ │ │ ├── HarvestTestUtils.tsx
│ │ │ │ │ ├── InactivityDeletion.test.tsx
│ │ │ │ │ ├── PasswordChangeFlow.test.tsx
│ │ │ │ │ ├── ProfileImageUpload.test.tsx
│ │ │ │ │ ├── PushSubscriptionLifecycle.test.tsx
│ │ │ │ │ ├── RelationshipAcceptAfterPrivacyChangeAllowsExistingRequest.test.tsx
│ │ │ │ │ ├── RelationshipBlocking.test.tsx
│ │ │ │ │ ├── RelationshipBlockingBehaviors.test.tsx
│ │ │ │ │ ├── RelationshipNicknameUpdate.test.tsx
│ │ │ │ │ ├── RelationshipTestUtils.tsx
│ │ │ │ │ ├── UnclaimedAccountRestrictions.test.tsx
│ │ │ │ │ ├── UserAccountAndSettings.test.tsx
│ │ │ │ │ ├── UserAuthorizedIps.test.tsx
│ │ │ │ │ ├── UserChannelService.test.tsx
│ │ │ │ │ ├── UserContactChangeLogService.test.tsx
│ │ │ │ │ ├── UserCustomStatusEmojiPremium.test.tsx
│ │ │ │ │ ├── UserDeletionEligibilityService.test.tsx
│ │ │ │ │ ├── UserDisableAndDeleteEndpoints.test.tsx
│ │ │ │ │ ├── UserFlagsResponse.test.tsx
│ │ │ │ │ ├── UserNoteLifecycle.test.tsx
│ │ │ │ │ ├── UserPremiumReset.test.tsx
│ │ │ │ │ ├── UserProfileConnectionVisibility.test.tsx
│ │ │ │ │ ├── UserProfileImageValidation.test.tsx
│ │ │ │ │ ├── UserProfileTextValidation.test.tsx
│ │ │ │ │ ├── UserRelationshipEndpoints.test.tsx
│ │ │ │ │ ├── UserRelationshipStateTransitions.test.tsx
│ │ │ │ │ ├── UserReservedDiscriminatorRoll.test.tsx
│ │ │ │ │ ├── UserSettingsGuildFolders.test.tsx
│ │ │ │ │ ├── UserSettingsValidation.test.tsx
│ │ │ │ │ ├── UserTestUtils.tsx
│ │ │ │ │ └── UserUsernameCaseUpdate.test.tsx
│ │ │ │ └── utils/
│ │ │ │ └── GuildFolderUtils.tsx
│ │ │ ├── utils/
│ │ │ │ ├── AgeUtils.tsx
│ │ │ │ ├── AttachmentDecay.tsx
│ │ │ │ ├── AuditSerializationUtils.tsx
│ │ │ │ ├── AvatarColorUtils.tsx
│ │ │ │ ├── CurrencyUtils.tsx
│ │ │ │ ├── DOMUtils.tsx
│ │ │ │ ├── EmojiUtils.tsx
│ │ │ │ ├── FetchUtils.tsx
│ │ │ │ ├── GeoUtils.tsx
│ │ │ │ ├── GuildVerificationUtils.tsx
│ │ │ │ ├── IdUtils.tsx
│ │ │ │ ├── InviteUtils.tsx
│ │ │ │ ├── IpRangeUtils.tsx
│ │ │ │ ├── IpUtils.tsx
│ │ │ │ ├── LosslessJsonParser.tsx
│ │ │ │ ├── PasswordUtils.tsx
│ │ │ │ ├── PermissionUtils.tsx
│ │ │ │ ├── RandomUtils.tsx
│ │ │ │ ├── RegexUtils.tsx
│ │ │ │ ├── RequestPathUtils.tsx
│ │ │ │ ├── StringUtils.tsx
│ │ │ │ ├── SudoCookieUtils.tsx
│ │ │ │ ├── TotpGenerator.tsx
│ │ │ │ ├── UnfurlerUtils.tsx
│ │ │ │ ├── UrlSanitizer.tsx
│ │ │ │ ├── UserAgentUtils.tsx
│ │ │ │ ├── UserPermissionUtils.tsx
│ │ │ │ ├── UsernameGenerator.tsx
│ │ │ │ ├── UsernameSuggestionUtils.tsx
│ │ │ │ ├── featureUtils.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── AgeUtils.test.tsx
│ │ │ │ ├── BucketUtils.test.tsx
│ │ │ │ ├── CurrencyUtils.test.tsx
│ │ │ │ ├── DOMUtils.test.tsx
│ │ │ │ ├── GeoUtils.test.tsx
│ │ │ │ ├── IdUtils.test.tsx
│ │ │ │ ├── IpRangeUtils.test.tsx
│ │ │ │ ├── LosslessJsonParser.test.tsx
│ │ │ │ ├── RegexUtils.test.tsx
│ │ │ │ ├── StringUtils.test.tsx
│ │ │ │ └── UrlSanitizer.test.tsx
│ │ │ ├── validation/
│ │ │ │ └── tests/
│ │ │ │ └── ValidationErrorInterpolation.test.tsx
│ │ │ ├── voice/
│ │ │ │ ├── IVoiceRepository.tsx
│ │ │ │ ├── VoiceAvailabilityService.tsx
│ │ │ │ ├── VoiceConstants.tsx
│ │ │ │ ├── VoiceDataInitializer.tsx
│ │ │ │ ├── VoiceModel.tsx
│ │ │ │ ├── VoiceReconciliationWorker.tsx
│ │ │ │ ├── VoiceRegionSelection.tsx
│ │ │ │ ├── VoiceRepository.tsx
│ │ │ │ ├── VoiceService.tsx
│ │ │ │ ├── VoiceTopology.tsx
│ │ │ │ └── tests/
│ │ │ │ ├── VoiceAvailabilityService.test.tsx
│ │ │ │ ├── VoiceCallEligibility.test.tsx
│ │ │ │ ├── VoiceCallRinging.test.tsx
│ │ │ │ ├── VoiceCallUpdate.test.tsx
│ │ │ │ ├── VoiceChannelPermissions.test.tsx
│ │ │ │ ├── VoiceChannelRtcRegion.test.tsx
│ │ │ │ ├── VoiceRegionSelection.test.tsx
│ │ │ │ ├── VoiceTestUtils.tsx
│ │ │ │ ├── VoiceTopology.test.tsx
│ │ │ │ └── VoiceUnclaimedAccountRestrictions.test.tsx
│ │ │ ├── webhook/
│ │ │ │ ├── IWebhookRepository.tsx
│ │ │ │ ├── SweegoWebhookService.tsx
│ │ │ │ ├── WebhookController.tsx
│ │ │ │ ├── WebhookModel.tsx
│ │ │ │ ├── WebhookRepository.tsx
│ │ │ │ ├── WebhookRequestService.tsx
│ │ │ │ ├── WebhookService.tsx
│ │ │ │ ├── tests/
│ │ │ │ │ ├── GitHubCheckTransformer.test.tsx
│ │ │ │ │ ├── GitHubCommitTransformer.test.tsx
│ │ │ │ │ ├── GitHubIssueTransformer.test.tsx
│ │ │ │ │ ├── GitHubPullRequestTransformer.test.tsx
│ │ │ │ │ ├── GitHubPushTransformer.test.tsx
│ │ │ │ │ ├── GitHubRepositoryTransformer.test.tsx
│ │ │ │ │ ├── GitHubTransformer.test.tsx
│ │ │ │ │ ├── SentryTransformer.test.tsx
│ │ │ │ │ ├── SlackTransformer.test.tsx
│ │ │ │ │ ├── SweegoWebhookService.test.tsx
│ │ │ │ │ ├── WebhookChannelValidation.test.tsx
│ │ │ │ │ ├── WebhookCompareUser.test.tsx
│ │ │ │ │ ├── WebhookEmojiBypass.test.tsx
│ │ │ │ │ ├── WebhookExecution.test.tsx
│ │ │ │ │ ├── WebhookExecutionAdvanced.test.tsx
│ │ │ │ │ ├── WebhookGitHub.test.tsx
│ │ │ │ │ ├── WebhookLimits.test.tsx
│ │ │ │ │ ├── WebhookMultipartAttachmentUploads.test.tsx
│ │ │ │ │ ├── WebhookOperations.test.tsx
│ │ │ │ │ ├── WebhookPermissions.test.tsx
│ │ │ │ │ ├── WebhookSentry.test.tsx
│ │ │
================================================
FILE CONTENTS
================================================
================================================
FILE: .devcontainer/Caddyfile.dev
================================================
# Like dev/Caddyfile.dev, but LiveKit and Mailpit are referenced by their
# Docker Compose hostnames instead of 127.0.0.1.
{
auto_https off
admin off
}
:48763 {
handle /_caddy_health {
respond "OK" 200
}
@gateway path /gateway /gateway/*
handle @gateway {
uri strip_prefix /gateway
reverse_proxy 127.0.0.1:49107
}
@marketing path /marketing /marketing/*
handle @marketing {
uri strip_prefix /marketing
reverse_proxy 127.0.0.1:49531
}
@server path /admin /admin/* /api /api/* /s3 /s3/* /queue /queue/* /media /media/* /_health /_ready /_live /.well-known/fluxer
handle @server {
reverse_proxy 127.0.0.1:49319
}
@livekit path /livekit /livekit/*
handle @livekit {
uri strip_prefix /livekit
reverse_proxy livekit:7880
}
redir /mailpit /mailpit/
handle_path /mailpit/* {
rewrite * /mailpit{path}
reverse_proxy mailpit:8025
}
handle {
reverse_proxy 127.0.0.1:49427 {
header_up Connection {http.request.header.Connection}
header_up Upgrade {http.request.header.Upgrade}
}
}
log {
output stdout
format console
}
}
================================================
FILE: .devcontainer/Dockerfile
================================================
# Language runtimes (Node.js, Go, Rust, Python) are installed via devcontainer
# features. This Dockerfile handles Erlang/OTP (no feature available) and
# tools like Caddy, process-compose, rebar3, uv, ffmpeg, and exiftool.
FROM erlang:28-slim AS erlang
FROM mcr.microsoft.com/devcontainers/base:debian-13
ARG DEBIAN_FRONTEND=noninteractive
ARG REBAR3_VERSION=3.24.0
ARG PROCESS_COMPOSE_VERSION=1.90.0
# Both erlang:28-slim and debian-13 are Trixie-based, so OpenSSL versions match.
COPY --from=erlang /usr/local/lib/erlang /usr/local/lib/erlang
RUN ln -sf /usr/local/lib/erlang/bin/* /usr/local/bin/
RUN apt-get update && apt-get install -y --no-install-recommends \
libncurses6 libsctp1 \
build-essential pkg-config \
ffmpeg libimage-exiftool-perl \
sqlite3 libsqlite3-dev \
libssl-dev openssl \
gettext-base lsof iproute2 \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL "https://github.com/erlang/rebar3/releases/download/${REBAR3_VERSION}/rebar3" \
-o /usr/local/bin/rebar3 \
&& chmod +x /usr/local/bin/rebar3
RUN curl -fsSL "https://caddyserver.com/api/download?os=linux&arch=amd64" \
-o /usr/local/bin/caddy \
&& chmod +x /usr/local/bin/caddy
RUN curl -fsSL "https://github.com/F1bonacc1/process-compose/releases/download/v${PROCESS_COMPOSE_VERSION}/process-compose_linux_amd64.tar.gz" \
| tar xz -C /usr/local/bin process-compose \
&& chmod +x /usr/local/bin/process-compose
RUN curl -fsSL "https://github.com/astral-sh/uv/releases/latest/download/uv-x86_64-unknown-linux-gnu.tar.gz" \
| tar xz --strip-components=1 -C /usr/local/bin \
&& chmod +x /usr/local/bin/uv /usr/local/bin/uvx
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"name": "Fluxer",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "24",
"pnpmVersion": "10.29.3"
},
"ghcr.io/devcontainers/features/go:1": {
"version": "1.24"
},
"ghcr.io/devcontainers/features/rust:1": {
"version": "1.93.0",
"targets": "wasm32-unknown-unknown"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "os-provided",
"installTools": false
}
},
"onCreateCommand": ".devcontainer/on-create.sh",
"remoteEnv": {
"FLUXER_CONFIG": "${containerWorkspaceFolder}/config/config.json",
"FLUXER_DATABASE": "sqlite"
},
"forwardPorts": [48763, 6379, 7700, 7880],
"portsAttributes": {
"48763": {
"label": "Fluxer (Caddy)",
"onAutoForward": "openBrowser",
"protocol": "http"
},
"6379": {
"label": "Valkey",
"onAutoForward": "silent"
},
"7700": {
"label": "Meilisearch",
"onAutoForward": "silent"
},
"7880": {
"label": "LiveKit",
"onAutoForward": "silent"
},
"9229": {
"label": "Node.js Debugger",
"onAutoForward": "silent"
}
},
"customizations": {
"vscode": {
"extensions": [
"TypeScriptTeam.native-preview",
"biomejs.biome",
"clinyong.vscode-css-modules",
"pgourlain.erlang",
"golang.go",
"rust-lang.rust-analyzer"
],
"settings": {
"typescript.preferences.includePackageJsonAutoImports": "auto",
"typescript.suggest.autoImports": true,
"typescript.experimental.useTsgo": true
}
}
}
}
================================================
FILE: .devcontainer/docker-compose.yml
================================================
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
valkey:
image: valkey/valkey:8-alpine
restart: unless-stopped
command: ['valkey-server', '--appendonly', 'yes', '--save', '60', '1', '--loglevel', 'warning']
volumes:
- valkey-data:/data
healthcheck:
test: ['CMD', 'valkey-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
meilisearch:
image: getmeili/meilisearch:v1.14
restart: unless-stopped
environment:
MEILI_NO_ANALYTICS: 'true'
MEILI_ENV: development
MEILI_MASTER_KEY: fluxer-devcontainer-meili-master-key
volumes:
- meilisearch-data:/meili_data
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:7700/health']
interval: 10s
timeout: 5s
retries: 5
livekit:
image: livekit/livekit-server:v1.9
restart: unless-stopped
command: --config /etc/livekit.yaml
volumes:
- ./livekit.yaml:/etc/livekit.yaml:ro
mailpit:
image: axllent/mailpit:latest
restart: unless-stopped
command: ['--webroot', '/mailpit/']
nats-core:
image: nats:2-alpine
restart: unless-stopped
command: ['--port', '4222']
nats-jetstream:
image: nats:2-alpine
restart: unless-stopped
command: ['--port', '4223', '--jetstream', '--store_dir', '/data']
volumes:
- nats-jetstream-data:/data
volumes:
valkey-data:
meilisearch-data:
nats-jetstream-data:
================================================
FILE: .devcontainer/livekit.yaml
================================================
# Credentials here must match the values on-create.sh writes to config.json.
port: 7880
keys:
fluxer-devcontainer-key: fluxer-devcontainer-secret-key-00000000
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 50100
use_external_ip: false
node_ip: 127.0.0.1
turn:
enabled: true
domain: localhost
udp_port: 3478
webhook:
api_key: fluxer-devcontainer-key
urls:
- http://app:49319/api/webhooks/livekit
room:
auto_create: true
max_participants: 100
empty_timeout: 300
development: true
================================================
FILE: .devcontainer/on-create.sh
================================================
#!/usr/bin/env bash
# Runs once when the container is first created.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export FLUXER_CONFIG="${FLUXER_CONFIG:-$REPO_ROOT/config/config.json}"
GREEN='\033[0;32m'
NC='\033[0m'
info() { printf "%b\n" "${GREEN}[devcontainer]${NC} $1"; }
info "Installing pnpm dependencies..."
pnpm install
# Codegen outputs (e.g. MasterZodSchema.generated.tsx) are gitignored.
info "Generating config schema..."
pnpm --filter @fluxer/config generate
if [ ! -f "$FLUXER_CONFIG" ]; then
info "Creating config from development template..."
cp "$REPO_ROOT/config/config.dev.template.json" "$FLUXER_CONFIG"
fi
# Point services at Docker Compose hostnames and adjust settings that differ
# from the default dev template.
info "Patching config for Docker Compose networking..."
jq '
# rspack defaults public_scheme to "https" when unset
.domain.public_scheme = "http" |
# Relative path so the app works on any hostname (localhost, 127.0.0.1, etc.)
.app_public.bootstrap_api_endpoint = "/api" |
.internal.kv = "redis://valkey:6379/0" |
.integrations.search.url = "http://meilisearch:7700" |
.integrations.search.api_key = "fluxer-devcontainer-meili-master-key" |
# Credentials must match .devcontainer/livekit.yaml
.integrations.voice.url = "ws://livekit:7880" |
.integrations.voice.webhook_url = "http://app:49319/api/webhooks/livekit" |
.integrations.voice.api_key = "fluxer-devcontainer-key" |
.integrations.voice.api_secret = "fluxer-devcontainer-secret-key-00000000" |
.integrations.email.smtp.host = "mailpit" |
.integrations.email.smtp.port = 1025 |
.services.nats.core_url = "nats://nats-core:4222" |
.services.nats.jetstream_url = "nats://nats-jetstream:4223" |
# Bluesky OAuth requires HTTPS + loopback IPs (RFC 8252), incompatible with
# the HTTP-only devcontainer setup.
.auth.bluesky.enabled = false
' "$FLUXER_CONFIG" > "$FLUXER_CONFIG.tmp" && mv "$FLUXER_CONFIG.tmp" "$FLUXER_CONFIG"
info "Running bootstrap..."
"$REPO_ROOT/scripts/dev_bootstrap.sh"
info "Pre-compiling Erlang gateway dependencies..."
(cd "$REPO_ROOT/fluxer_gateway" && rebar3 compile) || {
info "Gateway pre-compilation failed (non-fatal, will compile on first start)"
}
info "Devcontainer setup complete."
info ""
info " Start all dev processes: process-compose -f .devcontainer/process-compose.yml up"
info " Open the app: http://127.0.0.1:48763"
info " Dev email inbox: http://127.0.0.1:48763/mailpit/"
info ""
================================================
FILE: .devcontainer/process-compose.yml
================================================
# Application processes only — backing services (Valkey, Meilisearch, LiveKit,
# Mailpit, NATS) run via Docker Compose.
# process-compose -f .devcontainer/process-compose.yml up
is_tui_disabled: false
log_level: info
log_configuration:
flush_each_line: true
processes:
caddy:
command: caddy run --config .devcontainer/Caddyfile.dev --adapter caddyfile
log_location: dev/logs/caddy.log
readiness_probe:
http_get:
host: 127.0.0.1
port: 48763
path: /_caddy_health
availability:
restart: always
fluxer_server:
command: pnpm --filter fluxer_server dev
log_location: dev/logs/fluxer_server.log
availability:
restart: always
fluxer_app:
command: ./scripts/dev_fluxer_app.sh
environment:
- FORCE_COLOR=1
- FLUXER_APP_DEV_PORT=49427
log_location: dev/logs/fluxer_app.log
availability:
restart: always
fluxer_gateway:
command: ./scripts/dev_gateway.sh
environment:
- FLUXER_GATEWAY_NO_SHELL=1
log_location: dev/logs/fluxer_gateway.log
availability:
restart: always
marketing_dev:
command: pnpm --filter fluxer_marketing dev
environment:
- FORCE_COLOR=1
log_location: dev/logs/marketing_dev.log
availability:
restart: always
css_watch:
command: ./scripts/dev_css_watch.sh
log_location: dev/logs/css_watch.log
availability:
restart: always
================================================
FILE: .dockerignore
================================================
**/*.dump
**/*.lock
**/*.log
**/*.swo
**/*.swp
**/*.tmp
**/*~
**/.cache
**/.dev.vars
**/.DS_Store
**/.env
**/.env.*.local
**/.env.local
**/.git
**/.idea
**/.pnpm-store
**/.rebar
**/.rebar3
**/.turbo
**/.vscode
**/_build
**/_checkouts
**/_vendor
**/build
**/certificates
**/coverage
**/dist
**/erl_crash.dump
**/generated
**/log
**/logs
**/node_modules
**/npm-debug.log*
**/pnpm-debug.log*
**/rebar3.crashdump
**/target
**/Thumbs.db
**/yarn-debug.log*
**/yarn-error.log*
/fluxer_app/src/data/emojis.json
/fluxer_app/src/locales/*/messages.js
dev
!fluxer_app/dist
!fluxer_app/dist/**
!fluxer_devops/cassandra/migrations
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 120
indent_style = tab
indent_size = 2
[*.{yml,yaml,Dockerfile}]
indent_style = space
indent_size = 2
[justfile]
indent_style = space
indent_size = 4
================================================
FILE: .envrc
================================================
#!/usr/bin/env bash
eval "$(devenv direnvrc)"
use devenv
================================================
FILE: .gitattributes
================================================
* text=auto
================================================
FILE: .github/DISCUSSION_TEMPLATE/ideas.yaml
================================================
body:
- type: markdown
attributes:
value: |
Thanks for the suggestion.
For larger changes, please align with maintainers before investing time.
Security issues should go to https://fluxer.app/security.
- type: textarea
id: problem
attributes:
label: Problem
description: What problem are you trying to solve, and for whom?
placeholder: "Right now, users can't ..., which causes ..."
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed solution
description: What would you like to see happen?
placeholder: "Add ..., so that ..."
validations:
required: true
- type: textarea
id: notes
attributes:
label: Notes (optional)
description: Constraints, rough plan, or links to relevant code.
placeholder: "Notes: ...\nPotential files/areas: ..."
validations:
required: false
- type: checkboxes
id: checks
attributes:
label: Checks
options:
- label: I searched for existing discussions and didn't find a duplicate.
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug report
description: Report a reproducible problem in Fluxer
labels: ['bug']
body:
- type: markdown
attributes:
value: |
Thanks for the report.
Please check our status page at https://fluxerstatus.com and search for existing issues before filing.
Security issues should go to https://fluxer.app/security.
- type: textarea
id: summary
attributes:
label: Summary
description: What happened, and what did you expect instead?
placeholder: "When I ..., the app ..., but I expected ..."
validations:
required: true
- type: textarea
id: repro
attributes:
label: Steps to reproduce
description: Provide clear, numbered steps.
placeholder: |
1. Go to ...
2. Click ...
3. See ...
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment (optional)
description: Include versions that matter (commit/tag, OS, runtime, browser/device).
placeholder: |
- Commit/Tag:
- OS:
- Runtime:
- Browser (if applicable):
validations:
required: false
- type: textarea
id: logs
attributes:
label: Logs or screenshots (optional)
description: Paste logs (redact secrets) or attach screenshots/recordings.
placeholder: "Paste stack traces, console output, network errors, etc."
validations:
required: false
- type: checkboxes
id: checks
attributes:
label: Checks
options:
- label: I searched for existing issues and didn't find a duplicate.
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Feature requests
url: https://github.com/orgs/fluxerapp/discussions
about: Suggest an improvement or new capability.
- name: Security vulnerability report
url: https://fluxer.app/security
about: Please report security issues privately using our security policy.
================================================
FILE: .github/ISSUE_TEMPLATE/docs.yml
================================================
name: Documentation
description: Report a docs issue or suggest an improvement
labels: ['docs']
body:
- type: markdown
attributes:
value: |
Thanks.
Please check our status page at https://fluxerstatus.com and search for existing issues before filing.
Security issues should go to https://fluxer.app/security.
- type: textarea
id: issue
attributes:
label: What needs fixing?
description: Describe the gap, error, or outdated content.
placeholder: "The README says ..., but actually ..."
validations:
required: true
- type: textarea
id: location
attributes:
label: Where is it? (optional)
description: Link the file/section if possible.
placeholder: "File: ...\nSection/heading: ...\nLink: ..."
validations:
required: false
- type: textarea
id: suggestion
attributes:
label: Suggested wording (optional)
description: If you already know how it should read, propose text.
placeholder: "Proposed text: ..."
validations:
required: false
- type: checkboxes
id: checks
attributes:
label: Checks
options:
- label: I searched for existing issues and didn't find a duplicate.
required: true
================================================
FILE: .github/pull_request_template.md
================================================
## Summary
<!-- A few bullets is perfect: what changed, why it changed, and anything reviewers should pay attention to. -->
- **What:**
- **Why:**
- **Notes for reviewers:**
## How to verify
<!-- Concrete steps to validate the change. Include screenshots/recordings for UI changes when helpful. -->
1.
2.
3.
## Tests
<!-- List what you ran, or explain why tests weren't added/changed. -->
- [ ] Added/updated unit tests (where it makes sense)
- [ ] Manual verification:
## Checklist
- [ ] PR targets `canary`
- [ ] PR title follows Conventional Commits (mostly lowercase)
- [ ] CI is green (or I'm actively addressing failures)
## Screenshots / recordings (UI changes)
<!-- Drag and drop images/videos here. -->
================================================
FILE: .github/workflows/build-desktop.yaml
================================================
name: build desktop
on:
workflow_dispatch:
inputs:
channel:
description: Channel to build (stable or canary)
required: false
type: choice
options:
- stable
- canary
default: stable
ref:
description: Git ref to build (branch, tag, or commit SHA)
required: false
default: ''
type: string
skip_windows:
description: Skip Windows builds
required: false
default: false
type: boolean
skip_macos:
description: Skip macOS builds
required: false
default: false
type: boolean
skip_linux:
description: Skip Linux builds
required: false
default: false
type: boolean
skip_windows_x64:
description: Skip Windows x64 builds
required: false
default: false
type: boolean
skip_windows_arm64:
description: Skip Windows ARM64 builds
required: false
default: false
type: boolean
skip_macos_x64:
description: Skip macOS x64 builds
required: false
default: false
type: boolean
skip_macos_arm64:
description: Skip macOS ARM64 builds
required: false
default: false
type: boolean
skip_linux_x64:
description: Skip Linux x64 builds
required: false
default: false
type: boolean
skip_linux_arm64:
description: Skip Linux ARM64 builds
required: false
default: false
type: boolean
permissions:
contents: write
concurrency:
group: desktop-${{ inputs.channel }}
cancel-in-progress: true
env:
CHANNEL: ${{ inputs.channel }}
BUILD_CHANNEL: ${{ inputs.channel == 'canary' && 'canary' || 'stable' }}
jobs:
meta:
name: Resolve build metadata
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
version: ${{ steps.meta.outputs.version }}
pub_date: ${{ steps.meta.outputs.pub_date }}
channel: ${{ steps.meta.outputs.channel }}
build_channel: ${{ steps.meta.outputs.build_channel }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: Set metadata
id: meta
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step set_metadata
--channel "${{ inputs.channel }}"
--ref "${{ inputs.ref }}"
matrix:
name: Resolve build matrix
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: Build platform matrix
id: set-matrix
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step set_matrix
--skip-windows "${{ inputs.skip_windows }}"
--skip-windows-x64 "${{ inputs.skip_windows_x64 }}"
--skip-windows-arm64 "${{ inputs.skip_windows_arm64 }}"
--skip-macos "${{ inputs.skip_macos }}"
--skip-macos-x64 "${{ inputs.skip_macos_x64 }}"
--skip-macos-arm64 "${{ inputs.skip_macos_arm64 }}"
--skip-linux "${{ inputs.skip_linux }}"
--skip-linux-x64 "${{ inputs.skip_linux_x64 }}"
--skip-linux-arm64 "${{ inputs.skip_linux_arm64 }}"
build:
name: Build ${{ matrix.platform }} (${{ matrix.arch }})
needs:
- meta
- matrix
runs-on: ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
env:
CHANNEL: ${{ needs.meta.outputs.channel }}
BUILD_CHANNEL: ${{ needs.meta.outputs.build_channel }}
VERSION: ${{ needs.meta.outputs.version }}
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
PLATFORM: ${{ matrix.platform }}
ARCH: ${{ matrix.arch }}
ELECTRON_ARCH: ${{ matrix.electron_arch }}
steps:
- name: Checkout source
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
- name: Shorten Windows paths (workspace + temp for Squirrel) and pin pnpm store
if: runner.os == 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step windows_paths
- name: Set workdir (Unix)
if: runner.os != 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step set_workdir_unix
- name: Set up pnpm
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: Resolve pnpm store path (Windows)
if: runner.os == 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step resolve_pnpm_store_windows
- name: Resolve pnpm store path (Unix)
if: runner.os != 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step resolve_pnpm_store_unix
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ${{ env.PNPM_STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install Python setuptools (Windows ARM64)
if: matrix.platform == 'windows' && matrix.arch == 'arm64'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step install_setuptools_windows_arm64
- name: Install Python setuptools (macOS)
if: matrix.platform == 'macos'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step install_setuptools_macos
- name: Install Linux dependencies
if: matrix.platform == 'linux'
env:
DEBIAN_FRONTEND: noninteractive
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step install_linux_deps
- name: Install dependencies
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step install_dependencies
- name: Update version
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step update_version
- name: Set build channel
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step set_build_channel
- name: Build Electron main process
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step build_electron_main
- name: Build Electron app (macOS)
if: matrix.platform == 'macos'
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step build_app_macos
- name: Verify macOS bundle ID (fail fast if wrong channel)
if: matrix.platform == 'macos'
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step verify_bundle_id
- name: Build Electron app (Windows)
if: matrix.platform == 'windows'
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
TEMP: C:\t
TMP: C:\t
SQUIRREL_TEMP: C:\sq
ELECTRON_BUILDER_CACHE: C:\ebcache
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step build_app_windows
- name: Analyze Squirrel nupkg for long paths
if: matrix.platform == 'windows'
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_VERSION: ${{ env.VERSION }}
MAX_WINDOWS_PATH_LEN: 260
PATH_HEADROOM: 10
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step analyse_squirrel_paths
- name: Build Electron app (Linux)
if: matrix.platform == 'linux'
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
env:
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
USE_SYSTEM_FPM: true
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step build_app_linux
- name: Prepare artifacts (Windows)
if: runner.os == 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step prepare_artifacts_windows
- name: Prepare artifacts (Unix)
if: runner.os != 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step prepare_artifacts_unix
- name: Normalize updater YAML (arm64)
if: matrix.arch == 'arm64'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step normalise_updater_yaml
- name: Generate SHA256 checksums (Unix)
if: runner.os != 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step generate_checksums_unix
- name: Generate SHA256 checksums (Windows)
if: runner.os == 'Windows'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
--step generate_checksums_windows
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: fluxer-desktop-${{ env.BUILD_CHANNEL }}-${{ matrix.platform }}-${{ matrix.arch }}
path: |
upload_staging/*.exe
upload_staging/*.exe.blockmap
upload_staging/*.exe.sha256
upload_staging/*.dmg
upload_staging/*.dmg.sha256
upload_staging/*.zip
upload_staging/*.zip.blockmap
upload_staging/*.zip.sha256
upload_staging/*.AppImage
upload_staging/*.AppImage.sha256
upload_staging/*.deb
upload_staging/*.deb.sha256
upload_staging/*.rpm
upload_staging/*.rpm.sha256
upload_staging/*.tar.gz
upload_staging/*.tar.gz.sha256
upload_staging/*.yml
upload_staging/*.nupkg
upload_staging/*.nupkg.blockmap
upload_staging/*.nupkg.sha256
upload_staging/RELEASES*
retention-days: 30
upload:
name: Upload to S3 (rclone)
needs:
- meta
- build
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
CHANNEL: ${{ needs.meta.outputs.build_channel }}
DISPLAY_CHANNEL: ${{ needs.meta.outputs.channel }}
VERSION: ${{ needs.meta.outputs.version }}
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
S3_ENDPOINT: https://s3.us-east-va.io.cloud.ovh.us
S3_BUCKET: fluxer-downloads
PUBLIC_DL_BASE: https://api.fluxer.app/dl
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: fluxer-desktop-${{ needs.meta.outputs.build_channel }}-*
- name: Install rclone
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step install_rclone
- name: Configure rclone (OVH S3)
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step configure_rclone
- name: Build S3 payload layout (+ manifest.json)
env:
VERSION: ${{ needs.meta.outputs.version }}
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step build_payload
- name: Upload payload to S3
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step upload_payload
- name: Build summary
run: >-
python3 scripts/ci/workflows/build_desktop.py
--step build_summary
================================================
FILE: .github/workflows/channel-vars.yaml
================================================
name: channel vars
on:
workflow_call:
inputs:
github_event_name:
type: string
github_ref_name:
type: string
required: false
workflow_dispatch_channel:
type: string
required: false
outputs:
channel:
description: 'Computed release channel (stable|canary)'
value: ${{ jobs.emit.outputs.channel }}
is_canary:
description: 'Whether this is a canary deploy (true|false)'
value: ${{ jobs.emit.outputs.is_canary }}
stack_suffix:
description: "Suffix for stack/image names ('' or '-canary')"
value: ${{ jobs.emit.outputs.stack_suffix }}
jobs:
emit:
runs-on: ubuntu-latest
timeout-minutes: 25
outputs:
channel: ${{ steps.compute.outputs.channel }}
is_canary: ${{ steps.compute.outputs.is_canary }}
stack_suffix: ${{ steps.compute.outputs.stack_suffix }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: Determine channel
id: compute
shell: bash
run: >-
python3 scripts/ci/workflows/channel_vars.py
--event-name "${{ inputs.github_event_name }}"
--ref-name "${{ inputs.github_ref_name || '' }}"
--dispatch-channel "${{ inputs.workflow_dispatch_channel || '' }}"
================================================
FILE: .github/workflows/ci.yaml
================================================
name: CI
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
typecheck:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: Install dependencies
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
- name: Run typecheck
run: python3 scripts/ci/workflows/ci.py --step typecheck
env:
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
test:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: Install dependencies
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
- name: Run tests
run: python3 scripts/ci/workflows/ci.py --step test
env:
FLUXER_CONFIG: config/config.test.json
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
gateway:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Erlang
uses: erlef/setup-beam@v1
with:
otp-version: '28'
rebar3-version: '3.24.0'
- name: Cache rebar3 dependencies
uses: actions/cache@v4
with:
path: |
fluxer_gateway/_build
~/.cache/rebar3
key: rebar3-${{ runner.os }}-${{ hashFiles('fluxer_gateway/rebar.lock') }}
restore-keys: |
rebar3-${{ runner.os }}-
- name: Compile
run: python3 scripts/ci/workflows/ci.py --step gateway_compile
- name: Run dialyzer
run: python3 scripts/ci/workflows/ci.py --step gateway_dialyzer
- name: Run eunit tests
run: python3 scripts/ci/workflows/ci.py --step gateway_eunit
env:
FLUXER_CONFIG: ../config/config.test.json
knip:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: Install dependencies
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
- name: Run knip
run: python3 scripts/ci/workflows/ci.py --step knip
env:
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
ci-scripts:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Sync ci python dependencies
run: python3 scripts/ci/workflows/ci_scripts.py --step sync
- name: Run ci python tests
run: python3 scripts/ci/workflows/ci_scripts.py --step test
================================================
FILE: .github/workflows/deploy-admin.yaml
================================================
name: deploy admin
on:
push:
branches:
- main
- canary
paths:
- fluxer_admin/**
- .github/workflows/deploy-admin.yaml
workflow_dispatch:
inputs:
channel:
type: choice
options:
- stable
- canary
default: stable
description: Release channel to deploy
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-admin-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
cancel-in-progress: true
permissions:
contents: read
jobs:
channel-vars:
uses: ./.github/workflows/channel-vars.yaml
with:
github_event_name: ${{ github.event_name }}
github_ref_name: ${{ github.ref_name }}
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
deploy:
name: Deploy admin
needs: channel-vars
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
STACK: ${{ format('fluxer-admin{0}', needs.channel-vars.outputs.stack_suffix) }}
CACHE_SCOPE: ${{ format('deploy-fluxer-admin{0}', needs.channel-vars.outputs.stack_suffix) }}
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'admin.canary.fluxer.app' || 'admin.fluxer.app' }}
REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
fetch-depth: 0
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_admin.py --step record_deploy_commit
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_admin.py --step set_build_timestamp
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_admin/Dockerfile
tags: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_admin.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_admin.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
STACK: ${{ env.STACK }}
CADDY_DOMAIN: ${{ env.CADDY_DOMAIN }}
REPLICAS: ${{ env.REPLICAS }}
run: python3 scripts/ci/workflows/deploy_admin.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-api.yaml
================================================
name: deploy api
on:
push:
branches:
- main
- canary
paths:
- fluxer_api/**
- .github/workflows/deploy-api.yaml
workflow_dispatch:
inputs:
channel:
type: choice
options:
- stable
- canary
default: stable
description: Release channel to deploy
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-api-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
cancel-in-progress: true
permissions:
contents: read
jobs:
channel-vars:
uses: ./.github/workflows/channel-vars.yaml
with:
github_event_name: ${{ github.event_name }}
github_ref_name: ${{ github.ref_name }}
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
deploy:
name: Deploy api
needs: channel-vars
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
STACK: ${{ format('fluxer-api{0}', needs.channel-vars.outputs.stack_suffix) }}
WORKER_STACK: fluxer-api-worker
CANARY_WORKER_REPLICAS: 3
CACHE_SCOPE: ${{ format('deploy-fluxer-api{0}', needs.channel-vars.outputs.stack_suffix) }}
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'api.canary.fluxer.app' || 'api.fluxer.app' }}
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
fetch-depth: 0
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_api.py --step record_deploy_commit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build image(s)
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_api/Dockerfile
tags: |
${{ env.STACK }}:${{ env.DEPLOY_SHA }}
${{ env.WORKER_STACK }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
build-args: |
BUILD_SHA=${{ env.SENTRY_BUILD_SHA }}
BUILD_NUMBER=${{ env.SENTRY_BUILD_NUMBER }}
BUILD_TIMESTAMP=${{ env.SENTRY_BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_api.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_api.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image(s) and deploy
env:
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
IMAGE_TAG_APP: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
IMAGE_TAG_WORKER: ${{ env.WORKER_STACK }}:${{ env.DEPLOY_SHA }}
CANARY_WORKER_REPLICAS: ${{ env.CANARY_WORKER_REPLICAS }}
SENTRY_BUILD_SHA: ${{ env.SENTRY_BUILD_SHA }}
SENTRY_BUILD_NUMBER: ${{ env.SENTRY_BUILD_NUMBER }}
SENTRY_BUILD_TIMESTAMP: ${{ env.SENTRY_BUILD_TIMESTAMP }}
RELEASE_CHANNEL: ${{ env.CHANNEL }}
SENTRY_RELEASE: ${{ format('fluxer-api@{0}', env.SENTRY_BUILD_SHA) }}
run: python3 scripts/ci/workflows/deploy_api.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-app.yaml
================================================
name: deploy app
on:
push:
branches:
- main
- canary
paths:
- fluxer_app/**
- fluxer_app_proxy/**
- .github/workflows/deploy-app.yaml
workflow_dispatch:
inputs:
channel:
type: choice
options:
- stable
- canary
default: stable
description: Release channel to deploy
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-app-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
cancel-in-progress: true
permissions:
contents: write
jobs:
channel-vars:
uses: ./.github/workflows/channel-vars.yaml
with:
github_event_name: ${{ github.event_name }}
github_ref_name: ${{ github.ref_name }}
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
deploy:
name: Deploy app
needs: channel-vars
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
SERVICE_NAME: ${{ format('fluxer-app{0}', needs.channel-vars.outputs.stack_suffix) }}
DOCKERFILE: fluxer_app_proxy/Dockerfile
CACHE_SCOPE: ${{ format('fluxer-app{0}', needs.channel-vars.outputs.stack_suffix) }}
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
APP_REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
fetch-depth: 0
- name: Set up pnpm
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
cache-dependency-path: fluxer_app/pnpm-lock.yaml
- name: Install dependencies
run: python3 scripts/ci/workflows/deploy_app.py --step install_dependencies
- name: Run Lingui i18n tasks
run: python3 scripts/ci/workflows/deploy_app.py --step run_lingui
env:
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_app.py --step record_deploy_commit
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: Cache Rust dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
fluxer_app/crates/gif_wasm/target/
key: ${{ runner.os }}-cargo-${{ hashFiles('fluxer_app/crates/gif_wasm/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Install wasm-pack
run: python3 scripts/ci/workflows/deploy_app.py --step install_wasm_pack
- name: Generate wasm artifacts
run: python3 scripts/ci/workflows/deploy_app.py --step generate_wasm
env:
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_app.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Fetch deployment config
env:
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
run: python3 scripts/ci/workflows/deploy_app.py --step fetch_deployment_config
- name: Build application
env:
FLUXER_CONFIG: ${{ github.workspace }}/fluxer_app/config.json
TURBO_API: https://turborepo.fluxer.dev
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: team_fluxer
run: python3 scripts/ci/workflows/deploy_app.py --step build_application
- name: Install rclone
run: python3 scripts/ci/workflows/deploy_app.py --step install_rclone
- name: Upload assets to S3 static bucket
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: python3 scripts/ci/workflows/deploy_app.py --step upload_assets
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_app.py --step set_build_timestamp
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: ${{ env.DOCKERFILE }}
tags: ${{ env.SERVICE_NAME }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_app.py --step install_docker_pussh
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.SERVICE_NAME }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
SERVICE_NAME: ${{ env.SERVICE_NAME }}
COMPOSE_STACK: ${{ env.SERVICE_NAME }}
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
APP_REPLICAS: ${{ env.APP_REPLICAS }}
run: python3 scripts/ci/workflows/deploy_app.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-gateway.yaml
================================================
name: deploy gateway
on:
workflow_dispatch:
inputs:
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
push:
branches:
- canary
paths:
- 'fluxer_gateway/**'
concurrency:
group: deploy-gateway
cancel-in-progress: true
permissions:
contents: read
jobs:
deploy:
name: Deploy (hot patch)
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
sparse-checkout: |
fluxer_gateway
scripts/ci
- name: Set up Erlang
uses: erlef/setup-beam@v1
with:
otp-version: '28'
rebar3-version: '3.24.0'
- name: Compile
run: python3 scripts/ci/workflows/deploy_gateway.py --step compile
- name: Set up SSH
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_gateway.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_gateway.py --step record_deploy_commit
- name: Deploy
env:
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
GATEWAY_ADMIN_SECRET: ${{ secrets.GATEWAY_ADMIN_SECRET }}
run: python3 scripts/ci/workflows/deploy_gateway.py --step deploy
================================================
FILE: .github/workflows/deploy-marketing.yaml
================================================
name: deploy marketing
on:
push:
branches:
- main
- canary
paths:
- fluxer_marketing/**
- .github/workflows/deploy-marketing.yaml
workflow_dispatch:
inputs:
channel:
type: choice
options:
- stable
- canary
default: stable
description: Release channel to deploy
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-marketing-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
cancel-in-progress: true
permissions:
contents: read
jobs:
channel-vars:
uses: ./.github/workflows/channel-vars.yaml
with:
github_event_name: ${{ github.event_name }}
github_ref_name: ${{ github.ref_name }}
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
deploy:
name: Deploy marketing
needs: channel-vars
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
STACK: ${{ format('fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
IMAGE_NAME: ${{ format('fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
CACHE_SCOPE: ${{ format('deploy-fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
APP_REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'canary.fluxer.app' || 'fluxer.app' }}
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
fetch-depth: 0
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_marketing.py --step record_deploy_commit
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_marketing.py --step set_build_timestamp
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_marketing/Dockerfile
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_marketing.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_marketing.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
STACK: ${{ env.STACK }}
IS_CANARY: ${{ env.IS_CANARY }}
CADDY_DOMAIN: ${{ env.CADDY_DOMAIN }}
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
APP_REPLICAS: ${{ env.APP_REPLICAS }}
run: python3 scripts/ci/workflows/deploy_marketing.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-media-proxy.yaml
================================================
name: deploy media-proxy
on:
push:
branches:
- main
paths:
- fluxer_media_proxy/**
- .github/workflows/deploy-media-proxy.yaml
workflow_dispatch:
inputs:
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-media-proxy
cancel-in-progress: true
permissions:
contents: read
env:
SERVICE_NAME: fluxer-media-proxy
IMAGE_NAME: fluxer-media-proxy
CONTEXT_DIR: fluxer_media_proxy
COMPOSE_STACK: fluxer-media-proxy
jobs:
deploy:
name: Deploy media proxy
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
RELEASE_CHANNEL: stable
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step record_deploy_commit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step set_build_timestamp
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: ${{ env.CONTEXT_DIR }}/Dockerfile
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-relay-directory.yaml
================================================
name: deploy relay directory
on:
push:
branches:
- canary
paths:
- fluxer_relay_directory/**
- .github/workflows/deploy-relay-directory.yaml
workflow_dispatch:
inputs:
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-relay-directory
cancel-in-progress: true
permissions:
contents: read
jobs:
deploy:
name: Deploy relay directory
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
STACK: fluxer-relay-directory
CACHE_SCOPE: deploy-fluxer-relay-directory
IS_CANARY: true
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
fetch-depth: 0
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step record_deploy_commit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step set_build_timestamp
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_relay_directory/Dockerfile
tags: |
${{ env.STACK }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=canary
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
IMAGE_TAG: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step push_and_deploy
================================================
FILE: .github/workflows/deploy-relay.yaml
================================================
name: deploy relay
on:
workflow_dispatch:
inputs:
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
push:
branches:
- canary
paths:
- 'fluxer_relay/**'
concurrency:
group: deploy-relay
cancel-in-progress: true
permissions:
contents: read
jobs:
deploy:
name: Deploy (hot patch)
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
sparse-checkout: |
fluxer_relay
scripts/ci
- name: Set up Erlang
uses: erlef/setup-beam@v1
with:
otp-version: '28'
rebar3-version: '3.24.0'
- name: Compile
run: python3 scripts/ci/workflows/deploy_relay.py --step compile
- name: Set up SSH
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_relay.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_relay.py --step record_deploy_commit
- name: Deploy
env:
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
RELAY_ADMIN_SECRET: ${{ secrets.RELAY_ADMIN_SECRET }}
run: python3 scripts/ci/workflows/deploy_relay.py --step deploy
================================================
FILE: .github/workflows/deploy-static-proxy.yaml
================================================
name: deploy static-proxy
on:
push:
branches:
- main
paths:
- fluxer_media_proxy/**
- .github/workflows/deploy-static-proxy.yaml
workflow_dispatch:
inputs:
ref:
type: string
required: false
default: ''
description: Optional git ref (defaults to the triggering branch)
concurrency:
group: deploy-fluxer-static-proxy
cancel-in-progress: true
permissions:
contents: read
env:
SERVICE_NAME: fluxer-static-proxy
IMAGE_NAME: fluxer-static-proxy
CONTEXT_DIR: fluxer_media_proxy
COMPOSE_STACK: fluxer-static-proxy
jobs:
deploy:
name: Deploy static proxy
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
env:
RELEASE_CHANNEL: stable
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
- name: Record deploy commit
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step record_deploy_commit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set build timestamp
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step set_build_timestamp
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: ${{ env.CONTEXT_DIR }}/Dockerfile
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
build-args: |
BUILD_SHA=${{ env.DEPLOY_SHA }}
BUILD_NUMBER=${{ github.run_number }}
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step push_and_deploy
================================================
FILE: .github/workflows/migrate-cassandra.yaml
================================================
name: migrate cassandra
on:
push:
branches:
- canary
paths:
- fluxer_devops/cassandra/migrations/**/*.cql
workflow_dispatch:
concurrency:
group: migrate-cassandra-prod
cancel-in-progress: false
permissions:
contents: read
jobs:
migrate:
name: Run database migrations
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- uses: actions/checkout@v6
- name: Set up pnpm
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: python3 scripts/ci/workflows/migrate_cassandra.py --step install_dependencies
- name: Validate migrations
run: python3 scripts/ci/workflows/migrate_cassandra.py --step validate_migrations
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/migrate_cassandra.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Set up SSH tunnel for Cassandra
run: python3 scripts/ci/workflows/migrate_cassandra.py --step setup_tunnel --server-user ${{ secrets.SERVER_USER }} --server-ip ${{ secrets.SERVER_IP }}
- name: Test Cassandra connection
env:
CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }}
CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }}
run: python3 scripts/ci/workflows/migrate_cassandra.py --step test_connection
- name: Run migrations
env:
CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }}
CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }}
run: python3 scripts/ci/workflows/migrate_cassandra.py --step run_migrations
- name: Close SSH tunnel
if: always()
run: python3 scripts/ci/workflows/migrate_cassandra.py --step close_tunnel
================================================
FILE: .github/workflows/promote-canary-to-main.yaml
================================================
name: promote canary -> main
on:
workflow_dispatch:
inputs:
dry_run:
type: boolean
default: false
description: "Show what would change, but don't push"
src:
type: string
default: canary
description: 'Source branch'
dst:
type: string
default: main
description: 'Destination branch'
concurrency:
group: promote-${{ inputs.dst }}
cancel-in-progress: false
permissions:
contents: read
jobs:
promote:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Create GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.PROMOTE_APP_ID }}
private-key: ${{ secrets.PROMOTE_APP_PRIVATE_KEY }}
- name: Checkout source
uses: actions/checkout@v6
with:
ref: ${{ inputs.src }}
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Verify ff-only + summarize
id: verify
run: >-
python3 scripts/ci/workflows/promote_canary_to_main.py
--step verify
--src "${{ inputs.src }}"
--dst "${{ inputs.dst }}"
- name: Push fast-forward
if: ${{ steps.verify.outputs.ahead != '0' && inputs.dry_run != true }}
run: >-
python3 scripts/ci/workflows/promote_canary_to_main.py
--step push
--dst "${{ inputs.dst }}"
- name: Dry run / no-op
if: ${{ steps.verify.outputs.ahead == '0' || inputs.dry_run == true }}
run: >-
python3 scripts/ci/workflows/promote_canary_to_main.py
--step dry_run
--dry-run "${{ inputs.dry_run }}"
--ahead "${{ steps.verify.outputs.ahead }}"
================================================
FILE: .github/workflows/release-livekitctl.yaml
================================================
name: release livekitctl
on:
push:
tags:
- 'livekitctl-v*'
workflow_dispatch:
inputs:
version:
description: Version to release (e.g., 1.0.0)
required: true
type: string
permissions:
contents: write
concurrency:
group: release-livekitctl
cancel-in-progress: false
env:
GO_VERSION: '1.24'
jobs:
build:
name: Build ${{ matrix.goos }}/${{ matrix.goarch }}
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: fluxer_devops/livekitctl/go.sum
- name: Determine version
id: version
run: >-
python3 scripts/ci/workflows/release_livekitctl.py
--step determine_version
--event-name "${{ github.event_name }}"
--input-version "${{ inputs.version }}"
--ref-name "${{ github.ref_name }}"
- name: Build binary
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
--step build_binary
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: livekitctl-${{ matrix.goos }}-${{ matrix.goarch }}
path: fluxer_devops/livekitctl/livekitctl-${{ matrix.goos }}-${{ matrix.goarch }}
retention-days: 1
release:
name: Create release
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
needs: build
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Determine version
id: version
run: >-
python3 scripts/ci/workflows/release_livekitctl.py
--step determine_version
--event-name "${{ github.event_name }}"
--input-version "${{ inputs.version }}"
--ref-name "${{ github.ref_name }}"
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
--step prepare_release_assets
- name: Generate checksums
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
--step generate_checksums
--release-dir release
- name: Create tag (workflow_dispatch only)
if: github.event_name == 'workflow_dispatch'
run: >-
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
--step create_tag
--tag "${{ steps.version.outputs.tag }}"
--version "${{ steps.version.outputs.version }}"
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: livekitctl v${{ steps.version.outputs.version }}
body: |
## livekitctl v${{ steps.version.outputs.version }}
Self-hosted LiveKit bootstrap and operations CLI.
### Installation
```bash
curl -fsSL https://fluxer.app/get/livekitctl | sudo bash
```
### Manual download
Download the appropriate binary for your system:
- `livekitctl-linux-amd64` - Linux x86_64
- `livekitctl-linux-arm64` - Linux ARM64
Then make it executable and move to your PATH:
```bash
chmod +x livekitctl-linux-*
sudo mv livekitctl-linux-* /usr/local/bin/livekitctl
```
### Checksums
See `checksums.txt` for SHA256 checksums.
files: |
release/livekitctl-linux-amd64
release/livekitctl-linux-arm64
release/checksums.txt
draft: false
prerelease: false
================================================
FILE: .github/workflows/release-relay-directory.yaml
================================================
name: release relay directory
on:
push:
branches: [canary]
paths:
- fluxer_relay_directory/**
- .github/workflows/release-relay-directory.yaml
workflow_dispatch:
inputs:
channel:
description: Release channel
type: choice
options: [stable, nightly]
default: nightly
required: false
ref:
description: Git ref (branch, tag, or commit SHA)
type: string
default: ''
required: false
version:
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
type: string
required: false
permissions:
contents: write
packages: write
id-token: write
attestations: write
concurrency:
group: release-relay-directory-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/fluxer-relay-directory
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
SOURCE_REF: >-
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|| 'canary' }}
jobs:
meta:
name: resolve build metadata
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
version: ${{ steps.meta.outputs.version }}
channel: ${{ steps.meta.outputs.channel }}
source_ref: ${{ steps.meta.outputs.source_ref }}
sha_short: ${{ steps.meta.outputs.sha_short }}
timestamp: ${{ steps.meta.outputs.timestamp }}
date: ${{ steps.meta.outputs.date }}
build_number: ${{ steps.meta.outputs.build_number }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ env.SOURCE_REF }}
- name: metadata
id: meta
run: >-
python3 scripts/ci/workflows/release_relay_directory.py
--step metadata
--version-input "${{ github.event.inputs.version }}"
--channel "${{ env.CHANNEL }}"
--source-ref "${{ env.SOURCE_REF }}"
build:
name: build fluxer relay directory
needs: meta
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
image_tags: ${{ steps.docker_meta.outputs.tags }}
image_digest: ${{ steps.build.outputs.digest }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: set up buildx
uses: docker/setup-buildx-action@v3
- name: login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: docker metadata
id: docker_meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
- name: build and push
id: build
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_relay_directory/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.docker_meta.outputs.tags }}
labels: |
${{ steps.docker_meta.outputs.labels }}
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
dev.fluxer.build.sha=${{ github.sha }}
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
build-args: |
BUILD_SHA=${{ github.sha }}
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
cache-from: type=gha,scope=relay-directory-${{ needs.meta.outputs.channel }}
cache-to: type=gha,mode=max,scope=relay-directory-${{ needs.meta.outputs.channel }}
provenance: true
sbom: true
- name: attest
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
create-release:
name: create release
needs: [meta, build]
if: |
always() &&
needs.meta.outputs.version != '' &&
needs.build.result == 'success'
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: stable release
if: needs.meta.outputs.channel == 'stable'
uses: softprops/action-gh-release@v2
with:
tag_name: relay-directory-v${{ needs.meta.outputs.version }}
name: Fluxer Relay Directory v${{ needs.meta.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
body: |
Fluxer Relay Directory
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${{ needs.meta.outputs.version }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: stable
Docs: https://docs.fluxer.app/federation
- name: nightly release
if: needs.meta.outputs.channel == 'nightly'
uses: softprops/action-gh-release@v2
with:
tag_name: relay-directory-nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
name: Relay Directory nightly ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
draft: false
prerelease: true
generate_release_notes: true
body: |
Nightly Fluxer Relay Directory image from canary.
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.meta.outputs.date }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ needs.meta.outputs.sha_short }}
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: nightly
- branch: canary
release-summary:
name: release summary
needs: [meta, build]
if: always()
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: summary
run: >-
python3 scripts/ci/workflows/release_relay_directory.py
--step summary
--build-result "${{ needs.build.result }}"
--channel "${{ needs.meta.outputs.channel }}"
--version "${{ needs.meta.outputs.version }}"
--build-number "${{ needs.meta.outputs.build_number }}"
--sha-short "${{ needs.meta.outputs.sha_short }}"
--timestamp "${{ needs.meta.outputs.timestamp }}"
--date-ymd "${{ needs.meta.outputs.date }}"
--source-ref "${{ needs.meta.outputs.source_ref }}"
--image-tags "${{ needs.build.outputs.image_tags }}"
--image-digest "${{ needs.build.outputs.image_digest }}"
--registry "${{ env.REGISTRY }}"
--image-name "${{ env.IMAGE_NAME }}"
================================================
FILE: .github/workflows/release-relay.yaml
================================================
name: release relay
on:
push:
branches: [canary]
paths:
- fluxer_relay/**
- .github/workflows/release-relay.yaml
workflow_dispatch:
inputs:
channel:
description: Release channel
type: choice
options: [stable, nightly]
default: nightly
required: false
ref:
description: Git ref (branch, tag, or commit SHA)
type: string
default: ''
required: false
version:
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
type: string
required: false
permissions:
contents: write
packages: write
id-token: write
attestations: write
concurrency:
group: release-relay-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/fluxer-relay
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
SOURCE_REF: >-
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|| 'canary' }}
jobs:
meta:
name: resolve build metadata
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
version: ${{ steps.meta.outputs.version }}
channel: ${{ steps.meta.outputs.channel }}
source_ref: ${{ steps.meta.outputs.source_ref }}
sha_short: ${{ steps.meta.outputs.sha_short }}
timestamp: ${{ steps.meta.outputs.timestamp }}
date: ${{ steps.meta.outputs.date }}
build_number: ${{ steps.meta.outputs.build_number }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ env.SOURCE_REF }}
- name: metadata
id: meta
run: >-
python3 scripts/ci/workflows/release_relay.py
--step metadata
--version-input "${{ github.event.inputs.version }}"
--channel "${{ env.CHANNEL }}"
--source-ref "${{ env.SOURCE_REF }}"
build:
name: build fluxer relay
needs: meta
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
image_tags: ${{ steps.docker_meta.outputs.tags }}
image_digest: ${{ steps.build.outputs.digest }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: set up buildx
uses: docker/setup-buildx-action@v3
- name: login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: docker metadata
id: docker_meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
- name: build and push
id: build
uses: docker/build-push-action@v6
with:
context: fluxer_relay
file: fluxer_relay/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.docker_meta.outputs.tags }}
labels: |
${{ steps.docker_meta.outputs.labels }}
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
dev.fluxer.build.sha=${{ github.sha }}
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
build-args: |
BUILD_SHA=${{ github.sha }}
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
cache-from: type=gha,scope=relay-${{ needs.meta.outputs.channel }}
cache-to: type=gha,mode=max,scope=relay-${{ needs.meta.outputs.channel }}
provenance: true
sbom: true
- name: attest
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
create-release:
name: create release
needs: [meta, build]
if: |
always() &&
needs.meta.outputs.version != '' &&
needs.build.result == 'success'
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: stable release
if: needs.meta.outputs.channel == 'stable'
uses: softprops/action-gh-release@v2
with:
tag_name: relay-v${{ needs.meta.outputs.version }}
name: Fluxer Relay v${{ needs.meta.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
body: |
Fluxer Relay
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${{ needs.meta.outputs.version }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: stable
Docs: https://docs.fluxer.app/federation
- name: nightly release
if: needs.meta.outputs.channel == 'nightly'
uses: softprops/action-gh-release@v2
with:
tag_name: relay-nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
name: Relay nightly ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
draft: false
prerelease: true
generate_release_notes: true
body: |
Nightly Fluxer Relay image from canary.
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.meta.outputs.date }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ needs.meta.outputs.sha_short }}
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: nightly
- branch: canary
release-summary:
name: release summary
needs: [meta, build]
if: always()
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: summary
run: >-
python3 scripts/ci/workflows/release_relay.py
--step summary
--build-result "${{ needs.build.result }}"
--channel "${{ needs.meta.outputs.channel }}"
--version "${{ needs.meta.outputs.version }}"
--build-number "${{ needs.meta.outputs.build_number }}"
--sha-short "${{ needs.meta.outputs.sha_short }}"
--timestamp "${{ needs.meta.outputs.timestamp }}"
--date-ymd "${{ needs.meta.outputs.date }}"
--source-ref "${{ needs.meta.outputs.source_ref }}"
--image-tags "${{ needs.build.outputs.image_tags }}"
--image-digest "${{ needs.build.outputs.image_digest }}"
--registry "${{ env.REGISTRY }}"
--image-name "${{ env.IMAGE_NAME }}"
================================================
FILE: .github/workflows/release-server.yaml
================================================
name: release server
on:
push:
branches: [canary]
paths:
- packages/**
- fluxer_server/**
- fluxer_gateway/**
- pnpm-lock.yaml
- .github/workflows/release-server.yaml
workflow_dispatch:
inputs:
channel:
description: Release channel
type: choice
options: [stable, nightly]
default: nightly
required: false
ref:
description: Git ref (branch, tag, or commit SHA)
type: string
default: ''
required: false
version:
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
type: string
required: false
build_server:
description: Build Fluxer Server
type: boolean
default: true
required: false
permissions:
contents: write
packages: write
id-token: write
attestations: write
concurrency:
group: release-server-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
REGISTRY: ghcr.io
IMAGE_NAME_SERVER: ${{ github.repository_owner }}/fluxer-server
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
SOURCE_REF: >-
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|| 'canary' }}
jobs:
meta:
name: resolve build metadata
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
version: ${{ steps.meta.outputs.version }}
channel: ${{ steps.meta.outputs.channel }}
source_ref: ${{ steps.meta.outputs.source_ref }}
sha_short: ${{ steps.meta.outputs.sha_short }}
timestamp: ${{ steps.meta.outputs.timestamp }}
date: ${{ steps.meta.outputs.date }}
build_number: ${{ steps.meta.outputs.build_number }}
build_server: ${{ steps.should_build.outputs.server }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ env.SOURCE_REF }}
- name: metadata
id: meta
run: >-
python3 scripts/ci/workflows/release_server.py
--step metadata
--version-input "${{ github.event.inputs.version }}"
--channel "${{ env.CHANNEL }}"
--source-ref "${{ env.SOURCE_REF }}"
- name: determine build targets
id: should_build
run: >-
python3 scripts/ci/workflows/release_server.py
--step determine_build_targets
--event-name "${{ github.event_name }}"
--build-server-input "${{ github.event.inputs.build_server }}"
build-server:
name: build fluxer server
needs: meta
if: needs.meta.outputs.build_server == 'true'
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
outputs:
image_tags: ${{ steps.docker_meta.outputs.tags }}
image_digest: ${{ steps.build.outputs.digest }}
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: set up buildx
uses: docker/setup-buildx-action@v3
- name: login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: docker metadata
id: docker_meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}
tags: |
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
- name: build and push
id: build
uses: docker/build-push-action@v6
with:
context: .
file: fluxer_server/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.docker_meta.outputs.tags }}
labels: |
${{ steps.docker_meta.outputs.labels }}
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
dev.fluxer.build.sha=${{ github.sha }}
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
build-args: |
BUILD_SHA=${{ github.sha }}
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
cache-from: type=gha,scope=server-${{ needs.meta.outputs.channel }}
cache-to: type=gha,mode=max,scope=server-${{ needs.meta.outputs.channel }}
provenance: true
sbom: true
- name: attest
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
create-release:
name: create release
needs: [meta, build-server]
if: |
always() &&
needs.meta.outputs.version != '' &&
(needs.build-server.result == 'success' || needs.build-server.result == 'skipped')
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.meta.outputs.source_ref }}
- name: stable release
if: needs.meta.outputs.channel == 'stable'
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.meta.outputs.version }}
name: Fluxer Server v${{ needs.meta.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
body: |
Fluxer Server
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:v${{ needs.meta.outputs.version }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:latest
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: stable
Docs: https://docs.fluxer.app/self-hosting
- name: nightly release
if: needs.meta.outputs.channel == 'nightly'
uses: softprops/action-gh-release@v2
with:
tag_name: nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
name: Nightly build ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
draft: false
prerelease: true
generate_release_notes: true
body: |
Nightly Fluxer Server image from canary.
Pull:
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:nightly
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:nightly-${{ needs.meta.outputs.date }}
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:sha-${{ needs.meta.outputs.sha_short }}
```
Build:
- version: v${{ needs.meta.outputs.version }}
- build: ${{ needs.meta.outputs.build_number }}
- sha: ${{ github.sha }}
- time: ${{ needs.meta.outputs.timestamp }}
- channel: nightly
- branch: canary
release-summary:
name: release summary
needs: [meta, build-server]
if: always()
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: summary
run: >-
python3 scripts/ci/workflows/release_server.py
--step summary
--build-result "${{ needs.build-server.result }}"
--channel "${{ needs.meta.outputs.channel }}"
--version "${{ needs.meta.outputs.version }}"
--build-number "${{ needs.meta.outputs.build_number }}"
--sha-short "${{ needs.meta.outputs.sha_short }}"
--timestamp "${{ needs.meta.outputs.timestamp }}"
--date-ymd "${{ needs.meta.outputs.date }}"
--source-ref "${{ needs.meta.outputs.source_ref }}"
--image-tags "${{ needs.build-server.outputs.image_tags }}"
--image-digest "${{ needs.build-server.outputs.image_digest }}"
--registry "${{ env.REGISTRY }}"
--image-name-server "${{ env.IMAGE_NAME_SERVER }}"
================================================
FILE: .github/workflows/restart-gateway.yaml
================================================
name: restart gateway
on:
workflow_dispatch:
inputs:
confirmation:
description: this will cause service interruption for all users. type RESTART to confirm.
required: true
type: string
concurrency:
group: restart-gateway
cancel-in-progress: true
permissions:
contents: read
env:
SERVICE_NAME: fluxer-gateway
IMAGE_NAME: fluxer-gateway
CONTEXT_DIR: fluxer_gateway
COMPOSE_STACK: fluxer-gateway
RELEASE_CHANNEL: ${{ github.ref_name == 'canary' && 'staging' || 'production' }}
jobs:
restart:
name: Restart gateway
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Validate confirmation
if: ${{ github.event.inputs.confirmation != 'RESTART' }}
run: python3 scripts/ci/workflows/restart_gateway.py --step validate_confirmation --confirmation "${{ github.event.inputs.confirmation }}"
- uses: actions/checkout@v6
- name: Record deploy commit
run: python3 scripts/ci/workflows/restart_gateway.py --step record_deploy_commit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build image
uses: docker/build-push-action@v6
with:
context: ${{ env.CONTEXT_DIR }}
file: ${{ env.CONTEXT_DIR }}/Dockerfile
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
load: true
platforms: linux/amd64
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
- name: Install docker-pussh
run: python3 scripts/ci/workflows/restart_gateway.py --step install_docker_pussh
- name: Set up SSH agent
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
- name: Add server to known hosts
run: python3 scripts/ci/workflows/restart_gateway.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
- name: Push image and deploy
env:
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
run: python3 scripts/ci/workflows/restart_gateway.py --step push_and_deploy
================================================
FILE: .github/workflows/sync-desktop.yaml
================================================
name: sync desktop
on:
push:
branches:
- main
- canary
paths:
- 'fluxer_desktop/**'
workflow_dispatch:
inputs:
branch:
description: Branch to sync (main or canary)
required: false
default: ''
type: string
concurrency:
group: sync-desktop-${{ github.ref_name }}
cancel-in-progress: true
permissions:
contents: read
jobs:
sync:
name: Sync to fluxerapp/fluxer_desktop
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout CI scripts
uses: actions/checkout@v6
with:
sparse-checkout: scripts/ci
sparse-checkout-cone-mode: false
- name: Create GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.SYNC_APP_ID }}
private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }}
owner: fluxerapp
repositories: fluxer_desktop
- name: Get GitHub App user ID
id: get-user-id
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step get_user_id
--app-slug "${{ steps.app-token.outputs.app-slug }}"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Checkout source repository
uses: actions/checkout@v6
with:
path: source
fetch-depth: 1
- name: Determine target branch
id: branch
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step determine_branch
--input-branch "${{ inputs.branch }}"
--ref-name "${{ github.ref_name }}"
- name: Clone target repository
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step clone_target
--token "${{ steps.app-token.outputs.token }}"
- name: Configure git
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step configure_git
--app-slug "${{ steps.app-token.outputs.app-slug }}"
--user-id "${{ steps.get-user-id.outputs.user-id }}"
- name: Checkout or create target branch
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step checkout_or_create_branch
--branch-name "${{ steps.branch.outputs.name }}"
- name: Sync files
run: python3 scripts/ci/workflows/sync_desktop.py --step sync_files
- name: Commit and push
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step commit_and_push
--branch-name "${{ steps.branch.outputs.name }}"
- name: Summary
run: >-
python3 scripts/ci/workflows/sync_desktop.py
--step summary
--branch-name "${{ steps.branch.outputs.name }}"
================================================
FILE: .github/workflows/sync-static.yaml
================================================
name: sync static-bucket
on:
push:
branches:
- main
paths:
- 'fluxer_static/**'
workflow_dispatch:
concurrency:
group: sync-fluxer-static
cancel-in-progress: true
jobs:
push:
runs-on: ubuntu-latest
timeout-minutes: 25
permissions:
contents: read
env:
RCLONE_REMOTE: ovh
RCLONE_BUCKET: fluxer-static
RCLONE_SOURCE: fluxer_static
RCLONE_ENDPOINT: https://s3.us-east-va.io.cloud.ovh.us
RCLONE_REGION: us-east-1
RCLONE_SOURCE_DIR: fluxer_static
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
lfs: true
fetch-depth: 0
- name: Install rclone
run: python3 scripts/ci/workflows/sync_static.py --step install_rclone
- name: Push repo contents to bucket
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: python3 scripts/ci/workflows/sync_static.py --step push
================================================
FILE: .github/workflows/test-cassandra-backup.yaml
================================================
name: test cassandra-backup
on:
workflow_dispatch:
schedule:
- cron: '0 */2 * * *'
concurrency:
group: test-cassandra-backup
cancel-in-progress: true
permissions:
contents: read
jobs:
test-backup:
name: Test latest Cassandra backup
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 45
env:
CASSANDRA_IMAGE: cassandra:5.0.6
CASS_CONTAINER: cass-${{ github.run_id }}-${{ github.run_attempt }}
UTIL_CONTAINER: cass-util-${{ github.run_id }}-${{ github.run_attempt }}
CASS_VOLUME: cassandra-data-${{ github.run_id }}-${{ github.run_attempt }}
BACKUP_VOLUME: cassandra-backup-${{ github.run_id }}-${{ github.run_attempt }}
MAX_HEAP_SIZE: 2G
HEAP_NEWSIZE: 512M
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set temp paths
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step set_temp_paths
- name: Pre-clean
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step pre_clean
- name: Install tools
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step install_tools
- name: Find latest backup, validate freshness, download, decrypt, extract into Docker volume
env:
B2_KEY_ID: ${{ secrets.B2_KEY_ID }}
B2_APPLICATION_KEY: ${{ secrets.B2_APPLICATION_KEY }}
AGE_PRIVATE_KEY: ${{ secrets.CASSANDRA_AGE_PRIVATE_KEY }}
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step fetch_backup
- name: Create data volume
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step create_data_volume
- name: Restore keyspaces into volume and promote snapshot SSTables
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step restore_keyspaces
- name: Start Cassandra
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step start_cassandra
- name: Verify data
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step verify_data
- name: Cleanup
if: always()
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step cleanup
- name: Report status
if: always()
env:
JOB_STATUS: ${{ job.status }}
run: >-
python3 scripts/ci/workflows/test_cassandra_backup.py
--step report_status
================================================
FILE: .github/workflows/update-word-lists.yaml
================================================
name: update word-lists
on:
schedule:
- cron: '0 3 1 * *'
workflow_dispatch:
jobs:
update-word-lists:
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: canary
- name: Download latest word lists
run: python3 scripts/ci/workflows/update_word_lists.py --step download
- name: Check for changes
id: check_changes
run: python3 scripts/ci/workflows/update_word_lists.py --step check_changes
- name: Update word lists
if: steps.check_changes.outputs.changes_detected == 'true'
run: python3 scripts/ci/workflows/update_word_lists.py --step update
- name: Create pull request for updated word lists
if: steps.check_changes.outputs.changes_detected == 'true'
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: word-lists-update-${{ github.run_id }}
base: canary
title: 'chore: update word lists from Tailscale upstream'
body: |
Automated update of scales.txt and tails.txt from the Tailscale repository.
These files are used to generate connection IDs for voice connections.
Source:
- https://github.com/tailscale/tailscale/blob/main/words/scales.txt
- https://github.com/tailscale/tailscale/blob/main/words/tails.txt
commit-message: 'chore: update word lists from Tailscale upstream'
files: |
fluxer_api/src/words/scales.txt
fluxer_api/src/words/tails.txt
labels: automation
- name: No changes detected
if: steps.check_changes.outputs.changes_detected == 'false'
run: python3 scripts/ci/workflows/update_word_lists.py --step no_changes
================================================
FILE: .gitignore
================================================
*.tsbuildinfo
**/*.beam
**/*.css.d.ts
**/*.dump
**/dump.rdb
**/*.iml
**/*.log
**/*.o
**/*.plt
**/*.source
**/*.swo
**/*.swp
**/*.tmp
**/*~
**/.*cache
**/.cache
**/__pycache__
**/.dev-runner/
**/.devenv
.devenv.flake.nix
devenv.local.nix
**/.direnv
/dev/livekit.yaml
/dev/bluesky_oauth_key.pem
/dev/meilisearch_master_key
/dev/data/
**/.dev.vars
**/.DS_Store
**/.env
**/.env.*.local
**/.env.local
**/.erlang.cookie
**/.eunit
**/.idea
**/.next
**/.next/cache
**/.pnp
**/.pnp.js
**/.pnpm-store
**/.rebar
**/.rebar3
**/.source
**/.swc
**/.turbo
**/.vercel
**/_build
**/_checkouts
**/_vendor
**/certificates
**/coverage
**/dist
**/ebin
**/erl_crash.dump
**/fluxer.env
**/generated
**/log
**/logs
**/node_modules
**/npm-debug.log*
**/out
**/pnpm-debug.log*
**/rebar3.crashdump
**/secrets.env
**/target
**/test-results.json
**/Thumbs.db
**/yarn-debug.log*
**/yarn-error.log*
/.devserver-cache.json
**/.devserver-cache.json
/.fluxer/
/config/config.json
/fluxer_app/src/assets/emoji-sprites/
/fluxer_app/src/components/uikit/AvatarStatusGeometry.ts
/fluxer_app/src/components/uikit/SVGMasks.tsx
/fluxer_app/src/locales/*/messages.js
/fluxer_app/src/locales/*/messages.mjs
/fluxer_app/src/locales/*/messages.ts
/fluxer_admin/public/static/app.css
/fluxer_gateway/config/sys.config
/fluxer_gateway/config/vm.args
/fluxer_marketing/public/static/app.css
/fluxer_server/data/
/packages/admin/public/static/app.css
/packages/marketing/public/static/app.css
/packages/config/src/ConfigSchema.json
/packages/config/src/MasterZodSchema.generated.tsx
AGENTS.md
CLAUDE.md
fluxer.yaml
GEMINI.md
geoip_data
next-env.d.ts
.github/agents
.github/prompts
================================================
FILE: .gitmodules
================================================
[submodule "fluxer_static"]
path = fluxer_static
url = https://github.com/fluxerapp/static.git
================================================
FILE: .ignore
================================================
!fluxer_app/scripts/build
*.tsbuildinfo
**/*.beam
**/*.css.d.ts
**/*.dump
**/dump.rdb
**/*.iml
**/*.lock
**/*.log
**/*.o
**/*.plt
**/*.source
**/*.swo
**/*.swp
**/*.tmp
**/*~
**/.*cache
**/.cache
**/__pycache__
**/.dev.vars
**/.direnv
.devenv.flake.nix
**/.env
**/.env.*.local
**/.env.local
**/.erlang.cookie
**/.eunit
**/.next
**/.next/cache
**/.pnp
**/.pnp.js
**/.pnpm-store
**/.rebar
**/.rebar3
**/.source
**/.swc
**/.turbo
**/.vercel
**/_build
**/_checkouts
**/_vendor
**/build
**/certificates
**/coverage
**/dist
**/ebin
**/erl_crash.dump
**/fluxer.env
**/generated
**/log
**/logs
**/node_modules
**/npm-debug.log*
**/out
**/pnpm-debug.log*
**/rebar3.crashdump
**/secrets.env
**/target
**/yarn-debug.log*
**/yarn-error.log*
/.fluxer/
/fluxer_app/src/assets/emoji-sprites/
/fluxer_app/src/locales/*/messages.js
/fluxer_admin/public/static/app.css
fluxer.yaml
fluxer_app/dist/
/fluxer_marketing/public/static/app.css
/fluxer_server/data/
fluxer_static
geoip_data
livekit.yaml
next-env.d.ts
/packages/marketing/public/static/app.css
================================================
FILE: .npmrc
================================================
update-notifier=false
================================================
FILE: .nvmrc
================================================
24
================================================
FILE: .prettierignore
================================================
*.log
**/*.css.d.ts
**/.cache
**/.pnpm-store
**/.swc
**/.turbo
**/node_modules
**/package-lock.json
**/pnpm-lock.yaml
.fluxer/
fluxer_app/dist
fluxer_app/pkgs/libfluxcore
fluxer_app/pkgs/libfluxcore/**
fluxer_app/src/assets/emoji-sprites
fluxer_app/src/locales/*/messages.js
fluxer_app_proxy/assets
fluxer_gateway/_build
fluxer_marketing/build
fluxer_static/**
node_modules
package-lock.json
pnpm-lock.yaml
================================================
FILE: .tool-versions
================================================
================================================
FILE: .vscode/extensions.json
================================================
{
"recommendations": [
"TypeScriptTeam.native-preview",
"biomejs.biome",
"clinyong.vscode-css-modules",
"pgourlain.erlang",
"golang.go",
"rust-lang.rust-analyzer"
]
}
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug: fluxer_server",
"program": "${workspaceFolder}/fluxer_server/src/startServer.tsx",
"runtimeArgs": ["--import", "tsx"],
"cwd": "${workspaceFolder}/fluxer_server",
"env": {
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json",
"FLUXER_DATABASE": "sqlite"
},
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "node",
"request": "launch",
"name": "Debug: fluxer_api (standalone)",
"program": "${workspaceFolder}/fluxer_api/src/AppEntrypoint.tsx",
"runtimeArgs": ["--import", "tsx"],
"cwd": "${workspaceFolder}/fluxer_api",
"env": {
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json",
"FLUXER_DATABASE": "sqlite"
},
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "node",
"request": "launch",
"name": "Debug: fluxer_marketing",
"program": "${workspaceFolder}/fluxer_marketing/src/index.tsx",
"runtimeArgs": ["--import", "tsx"],
"cwd": "${workspaceFolder}/fluxer_marketing",
"env": {
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json"
},
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "node",
"request": "launch",
"name": "Debug: fluxer_app (DevServer)",
"program": "${workspaceFolder}/fluxer_app/scripts/DevServer.tsx",
"runtimeArgs": ["--import", "tsx"],
"cwd": "${workspaceFolder}/fluxer_app",
"env": {
"FLUXER_APP_DEV_PORT": "49427",
"FORCE_COLOR": "1"
},
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "node",
"request": "launch",
"name": "Debug: Test Current File",
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
"args": ["run", "--no-coverage", "${relativeFile}"],
"autoAttachChildProcesses": true,
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Node Process",
"port": 9229,
"restart": true,
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
}
],
"compounds": [
{
"name": "Debug: Server + App",
"configurations": ["Debug: fluxer_server", "Debug: fluxer_app (DevServer)"]
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"typescript.preferences.includePackageJsonAutoImports": "auto",
"typescript.suggest.autoImports": true,
"typescript.experimental.useTsgo": true
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- demonstrating empathy and kindness toward other people
- being respectful of differing opinions, viewpoints, and experiences
- giving and gracefully accepting constructive feedback
- accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- the use of sexualized language or imagery, and sexual attention or advances of any kind
- trolling, insulting or derogatory comments, and personal or political attacks
- public or private harassment
- publishing others' private information, such as a physical or email address, without their explicit permission
- other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Reporting
If you experience or witness unacceptable behavior, please report it as soon as possible.
How to report:
- Email the maintainers at: developers@fluxer.app
- If your report involves someone who may have access to that inbox, you can instead contact a maintainer privately on GitHub.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1) Correction
Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2) Warning
Community Impact: A violation through a single incident or series of actions.
Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3) Temporary Ban
Community Impact: A serious violation of community standards, including sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4) Permanent Ban
Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at:
- https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
For answers to common questions about this code of conduct, see the FAQ:
- https://www.contributor-covenant.org/faq
Translations are available at:
- https://www.contributor-covenant.org/translations
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Fluxer
Thanks for contributing. This document explains how we work so your changes can land smoothly and nobody wastes time on work we can't merge.
## Quick rules (please read)
### 1) All PRs must target `canary`
`canary` is our trunk branch. Open all pull requests against `canary`. PRs targeting other branches will be closed or retargeted.
### 2) All PRs must include a short description
Every PR must include a short description covering:
- what changed
- why it changed
- anything reviewers should pay attention to
A few bullets is fine.
### 3) Open an issue before submitting a PR
We strongly prefer that every PR addresses an existing issue. If one doesn't exist yet, open one describing the problem or improvement and your proposed approach. This gives maintainers a chance to weigh in on direction before you invest time, and avoids the mutual displeasure of:
- you doing significant work, and
- us having to reject or postpone the change because it doesn't align with current goals, or because we aren't ready to maintain what it introduces
For small, obvious fixes (typos, broken links, trivial one-liners) you can skip the issue and go straight to a PR.
Ways to coordinate on larger work:
- open an issue describing the problem and your proposed approach
- open a draft PR early to confirm direction
- discuss with a maintainer in any channel you already share
If you're unsure whether something needs an issue first, it probably does.
### 4) Understand the code you submit
You should understand every change in your PR well enough to explain and defend it during review. You don’t need to write an essay, but you should be able to give a brief summary of what the patch does and why it’s correct. You may not use AI to generate a bug report, pull request description, or GitHub comment in any form, except for a 1:1 translation if English isn't your native language.
The maintainer [uses LLMs in a limited capacity](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/#:~:text=The%20LLMephant%20in%20the%20room). That’s how he was able to build the final version of Fluxer largely on his own over five years, with help from a supportive group of early testers. Without limited, controlled LLM use, he likely would have needed more starting capital to achieve the same result and hire a team of engineers.
If you use LLMs, use them responsibly. They can be helpful for rubber-ducking and for scaffolding boilerplate from thorough specifications, detailed guidance, and test coverage that verifies behaviour rather than implementation. This kind of platform cannot be built via autonomous code generation. Please disclose any LLM usage in your contribution.
We also ask contributors to treat each other with respect on this topic. People hold a wide range of views on LLMs, often rooted in ethical conviction. A contribution that is reviewable, understandable, and properly tested should be evaluated on its merits.
## Workflow
1. Fork the repo (or create a branch if you have access).
2. Create a feature branch from `canary`.
3. Make changes.
4. Open a PR into `canary` with a short description.
5. Address review feedback and CI results.
6. We squash-merge approved PRs into `canary`.
We strongly prefer small, focused PRs that are easy to review.
### Commit style and history
We squash-merge PRs, so the PR title becomes the single commit message on `canary`. For that reason:
- PR titles must follow Conventional Commits.
- Individual commits inside the PR don't need to follow Conventional Commits.
If you like to commit in small increments, feel free. If you prefer a tidier PR history, force-pushes are welcome (for example, to squash or reorder commits before review). Just avoid rewriting history in a way that makes it hard for reviewers to follow along.
## Conventional Commits (required for PR titles)
Because the PR title becomes the squash commit message, we require Conventional Commits for PR titles.
We prefer type/subject to be mostly lowercase.
Format:
- `type(scope optional): short description`
Examples:
- `fix: handle empty response from api`
- `feat(auth): add passkey login`
- `docs: clarify canary workflow`
- `refactor: simplify retry logic`
- `chore(ci): speed up checks`
Breaking changes:
- `feat!: remove legacy auth endpoints`
- `refactor(api)!: change pagination shape`
Common types:
`feat`, `fix`, `docs`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`, `revert`
## Tests (guidance)
We care about confidence more than ceremony. Add tests when they provide real value.
### Backend changes
For backend changes, add a unit test.
- If a unit test would require heavy mocking to be meaningful, restructure the code so it can be tested cleanly through its interfaces.
- If you're unsure how to approach this, discuss it with a maintainer before investing time.
### Frontend changes
We don't generally encourage new unit tests for frontend code unless:
- the area already has unit tests, or
- the change is complex or sensitive, and a unit test clearly reduces risk
In most cases, clear PR notes and practical verification are more valuable.
## Formatting and linting
Don't block on formatting or linting before opening a PR. CI enforces required checks and will tell you what needs fixing before merge.
Open the PR when it's ready for review, then iterate based on CI and feedback.
## PR checklist
Before requesting review:
- [ ] PR targets `canary`
- [ ] PR title follows Conventional Commits (mostly lowercase)
- [ ] PR includes a short description of what/why
- [ ] You understand every change in the PR and can explain it during review
- [ ] Tests added or updated where it makes sense (especially backend changes)
- [ ] CI is green (or you're actively addressing failures)
Optional but helpful:
- screenshots or a short recording for UI changes
- manual verification steps
## Code of Conduct
This project follows a Code of Conduct. By participating, you're expected to uphold it:
- See [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)
## Security
Please don't report security issues via public GitHub issues.
Use our security policy and reporting instructions here:
- https://fluxer.app/security
================================================
FILE: LICENSE
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
================================================
FILE: LICENSING.md
================================================
# Licensing
Fluxer is licensed under the **GNU Affero General Public License v3.0 (AGPLv3)**. See [`LICENSE`](./LICENSE).
AGPLv3 is a strong copyleft licence designed to keep improvements available to the community, including when the software is used over a network.
## Self-hosting: fully unlocked
If you self-host Fluxer on your own hardware, all features are available by default. We don't charge to unlock functionality, remove limits, or increase instance caps for deployments you run yourself.
If Fluxer is useful to you, please consider [donating to support development](https://fluxer.app/donate).
## Commercial licensing
Some organisations can't use AGPLv3 due to policy or compliance requirements, or because they don't want to take on AGPL obligations for private modifications.
In these cases, Fluxer Platform AB can offer Fluxer under a separate commercial licence (sometimes called dual licensing). This is the same software, but the commercial terms remove AGPLv3's copyleft obligations for internal deployments.
Fluxer remains AGPLv3 and publicly available. The only difference is your obligations for private modifications. Under the commercial licence, you may keep internal modifications private rather than being required to publish them solely because you run the modified software.
A core requirement of the commercial licence is internal use only. You may not redistribute a modified version (or your modifications) to third parties under the commercial licence.
If you want to share changes, you can upstream them to this repository under Fluxer's AGPLv3 licence. The commercial licence makes upstreaming optional rather than required, but it doesn't grant permission to distribute modifications under any other licence.
To request a commercial licence, email [support@fluxer.app](mailto:support@fluxer.app) and include your employee count so we can provide an initial estimate. Commercial licences are offered at a custom price point.
## Contributor License Agreement
Code contributions require a signed contributor licence agreement: see [`CLA.md`](./CLA.md). You will be prompted to sign electronically via CLA Assistant when you open your first pull request.
Our CLA is based on the widely used Harmony Individual CLA. It is intended to be clear and fair:
- You keep ownership of your contribution and can still use it elsewhere.
- You grant Fluxer Platform AB the rights needed to distribute your contribution as part of Fluxer, including a patent licence to reduce patent-related risk for users.
- It includes standard warranty and liability disclaimers that protect contributors.
It also includes an outbound licensing clause. If Fluxer Platform AB relicenses your contribution (including commercially), Fluxer Platform AB will continue to license your contribution under the project licence(s) that applied when you contributed. Signing the CLA doesn't remove Fluxer from the community.
## Our FOSS commitment
Fluxer is committed to remaining 100% FOSS for public development and distribution.
The CLA doesn't change that. It ensures Fluxer Platform AB has the legal permission to offer a commercial licence to organisations that need different terms, while keeping the community version open, fully featured, and AGPLv3-licensed.
================================================
FILE: README.md
================================================
> [!CAUTION]
> I'm repeating it again: Holy smokes, what a ride. Fluxer is taking off much earlier than I'd expected.
>
> I know it's hard to resist, but please wait a little longer before you dive deep into the current codebase or try to set up self-hosting. I'm aware the current stack isn't very lightweight. I'm working on making self-hosting as straightforward as possible and the development environment likewise.
>
> Self-hosted deployments won't include any traces of Plutonium, and nothing is paywalled. You can still configure your own tiers and limits in the admin panel.
>
> Thanks for bearing with me. Development on Fluxer is about to get much easier, and the project will be made sustainable through community contributions and bounties for development work. Stay tuned – there's not much left now.
>
> I thought I could take it a bit easier while shipping this stabilising update, but Discord's announcement in Februrary has changed things.
>
> There's just been a lot of work involved in keeping the production deployment up and running, handling trust & safety concerns, answering support emails, handling billing issues, and working on the refactor at the same time. I'm really excited to open up development and make it easier for others to contribute, and I can't wait to see what the community builds on Fluxer!
>
> As soon as the refactor is ready (not much longer now!), I'll enable PRs and interact more actively and push updates to this repository more frequently. The remaining parts of the refactor are currently being worked on and being tested live in production that has over 125,000 users (and we're only two full-time employees for now). After that, all work will happen openly in public.
>
> The team is also growing, though we remain small and can't offer very competitive salaries just yet – but if you want to work part-time or contract on projects, or you think you're a great fit for the roles we're hiring for (though not as actively across all roles at this time, but we'll keep you on file for when we are), check out the [careers page](https://fluxer.app/careers) :D
>
> ❤️
> [!NOTE]
> Learn about the developer behind Fluxer, the goals of the project, the tech stack, and what's coming next.
>
> [Read the launch blog post](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/) · [View full roadmap](https://blog.fluxer.app/roadmap-2026/)
<p align="center">
<img src="./media/logo-graphic.png" alt="Fluxer graphic logo" width="400">
</p>
<p align="center">
<a href="https://fluxer.app/donate">
<img src="https://img.shields.io/badge/Donate-fluxer.app%2Fdonate-brightgreen" alt="Donate" /></a>
<a href="https://docs.fluxer.app">
<img src="https://img.shields.io/badge/Docs-docs.fluxer.app-blue" alt="Documentation" /></a>
<a href="./LICENSE">
<img src="https://img.shields.io/badge/License-AGPLv3-purple" alt="AGPLv3 License" /></a>
</p>
# Fluxer
Fluxer is a **free and open source instant messaging and VoIP platform** for friends, groups, and communities. Self-host it and every feature is unlocked.
## Quick links
- [Self-hosting guide](https://docs.fluxer.app/self-hosting)
- [Documentation](https://docs.fluxer.app)
- [Donate to support development](https://fluxer.app/donate)
- [Security](https://fluxer.app/security)
## Features
<img src="./media/app-showcase.png" alt="Fluxer showcase" align="right" width="45%" />
**Real-time messaging** – typing indicators, reactions, and threaded replies.
**Voice & video** – calls in communities and DMs with screen sharing, powered by LiveKit.
**Rich media** – link previews, image and video attachments, and GIF search via KLIPY.
**Communities and channels** – text and voice channels organised into categories with granular permissions.
**Custom expressions** – upload custom emojis and stickers for your community.
**Self-hostable** – run your own instance with full control of your data and no vendor lock-in.
> [!NOTE]
> Native mobile apps and federation are top priorities. If you'd like to support this work, [donations](https://fluxer.app/donate) are greatly appreciated. You can also share feedback by emailing developers@fluxer.app.
## Self-hosting
> [!NOTE]
> New to Fluxer? Follow the [self-hosting guide](https://docs.fluxer.app/self-hosting) for step-by-step setup instructions.
TBD
### Deployment helpers
- [`livekitctl`](./fluxer_devops/livekitctl/README.md) – bootstrap a LiveKit SFU for voice and video
## Development
### Tech stack
- [TypeScript](https://www.typescriptlang.org/) and [Node.js](https://nodejs.org/) for backend services
- [Hono](https://hono.dev/) as the web framework for all HTTP services
- [Erlang/OTP](https://www.erlang.org/) for the real-time WebSocket gateway (message routing and presence)
- [React](https://react.dev/) and [Electron](https://www.electronjs.org/) for the desktop and web client
- [Rust](https://www.rust-lang.org/) compiled to WebAssembly for performance-critical client code
- [SQLite](https://www.sqlite.org/) for storage by default, with optional [Cassandra](https://cassandra.apache.org/) for distributed deployments
- [Meilisearch](https://www.meilisearch.com/) for full-text search and indexing
- [Valkey](https://valkey.io/) (Redis-compatible) for caching, rate limiting, and ephemeral coordination
- [LiveKit](https://livekit.io/) for voice and video infrastructure
### Devenv development environment
Fluxer supports development through **devenv** only. It provides a reproducible Nix environment and a single, declarative process manager for the dev stack.
1. Install Nix and devenv using the [devenv getting started guide](https://devenv.sh/getting-started/).
2. Enter the environment:
```bash
devenv shell
```
If you use direnv, the repo includes a `.envrc` that loads devenv automatically – run `direnv allow` once.
### Getting started
Start all services and the development server with:
```bash
devenv up
```
Open the instance in a browser at your dev server URL (e.g. `http://localhost:48763/`).
Emails sent during development (verification codes, notifications, etc.) are captured by a local Mailpit instance. Access the inbox at your dev server URL + `/mailpit/` (e.g. `http://localhost:48763/mailpit/`).
### Voice on a remote VM
If you develop on a remote VM behind Cloudflare Tunnels (or a similar HTTP-only tunnel), voice and video won't work out of the box. Cloudflare Tunnels only proxy HTTP/WebSocket traffic, so WebRTC media transport needs a direct path to the server. Open these ports on the VM's firewall:
| Port | Protocol | Purpose |
| ----------- | -------- | ---------------- |
| 3478 | UDP | TURN/STUN |
| 7881 | TCP | ICE-TCP fallback |
| 50000-50100 | UDP | RTP/RTCP media |
The bootstrap script configures LiveKit automatically based on `domain.base_domain` in your `config.json`. When set to a non-localhost domain, it enables external IP discovery so clients can connect directly for media while signaling continues through the tunnel.
### Devcontainer (experimental)
There is experimental support for developing in a **VS Code Dev Container** / GitHub Codespace without Nix. The `.devcontainer/` directory provides a Docker Compose setup with all required tooling and backing services.
```bash
# Inside the dev container, start all processes:
process-compose -f .devcontainer/process-compose.yml up
```
Open the app at `http://localhost:48763` and the dev email inbox at `http://localhost:48763/mailpit/`. Predefined VS Code debugging targets are available in `.vscode/launch.json`.
> [!WARNING]
> Bluesky OAuth is disabled in the devcontainer because it requires HTTPS. All other features work normally.
### Documentation
To develop the documentation site with live preview:
```bash
pnpm dev:docs
```
## Contributing
Fluxer is **free and open source software** licensed under **AGPLv3**. Contributions are welcome.
See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for development processes and how to propose changes, and [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) for community guidelines.
## Security
Report vulnerabilities at [fluxer.app/security](https://fluxer.app/security). Do not use public issues for security reports.
<details>
<summary><strong>License</strong></summary>
<br>
Copyright (c) 2026 Fluxer Contributors
Licensed under the [GNU Affero General Public License v3](./LICENSE):
```text
Copyright (c) 2026 Fluxer Contributors
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see https://www.gnu.org/licenses/
```
See [`LICENSING.md`](./LICENSING.md) for details on commercial licensing and the CLA.
</details>
================================================
FILE: SECURITY.md
================================================
# Security Policy
Please **do not** report security vulnerabilities via public GitHub issues.
Report security issues here: https://fluxer.app/security
================================================
FILE: biome.json
================================================
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "tab",
"lineWidth": 120,
"lineEnding": "lf",
"bracketSpacing": false
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": false,
"bracketSameLine": false
},
"globals": ["React"]
},
"json": {
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 120
},
"parser": {
"allowComments": true,
"allowTrailingCommas": true
}
},
"css": {
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 120,
"quoteStyle": "single"
},
"parser": {
"cssModules": true,
"tailwindDirectives": true
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noForEach": "off",
"noImportantStyles": "off",
"useLiteralKeys": "off"
},
"correctness": {
"noUndeclaredVariables": "error",
"noUnusedVariables": "error",
"noInvalidUseBeforeDeclaration": "off",
"useExhaustiveDependencies": "off"
},
"suspicious": {
"noArrayIndexKey": "off",
"noAssignInExpressions": "off",
"noExplicitAny": "off",
"noThenProperty": "off",
"noDoubleEquals": {
"level": "error",
"options": {
"ignoreNull": true
}
},
"noVar": "error",
"useAdjacentOverloadSignatures": "off",
"useIterableCallbackReturn": "off"
},
"style": {
"useConsistentArrayType": {
"level": "error",
"options": {
"syntax": "generic"
}
},
"useConst": "error",
"noNonNullAssertion": "off",
"noParameterAssign": "off"
},
"a11y": {
"recommended": true,
"useAriaPropsForRole": "error",
"useValidAriaRole": "error",
"useValidAriaValues": "error",
"useValidAriaProps": "error",
"useAltText": "error",
"useAnchorContent": "error",
"useButtonType": "error",
"useKeyWithClickEvents": "error",
"useKeyWithMouseEvents": "error",
"useSemanticElements": "off",
"noAriaUnsupportedElements": "error",
"noNoninteractiveElementToInteractiveRole": "error",
"noNoninteractiveTabindex": "error",
"noRedundantAlt": "error",
"noRedundantRoles": "error",
"noInteractiveElementToNoninteractiveRole": "error",
"noAutofocus": "warn",
"noAccessKey": "warn",
"useAriaActivedescendantWithTabindex": "error",
"noSvgWithoutTitle": "off"
},
"nursery": {
"useSortedClasses": "error"
}
}
},
"assist": {"actions": {"source": {"organizeImports": "on"}}},
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": [
"**",
"!**/.git",
"!**/app.css",
"!fluxer_admin/public/static/app.css",
"!**/build",
"fluxer_app/scripts/build",
"!**/dist",
"!**/fluxer_app/src/data/emojis.json",
"!**/fluxer_app/src/locales/*/messages.js",
"!**/fluxer_app/src/env.d.ts",
"!**/node_modules",
"!**/tailwind.css",
"!**/*.html",
"!**/*.module.css.d.ts",
"!**/fluxer_app/src/components/uikit/SVGMasks.tsx",
"!fluxer_marketing/public/static/app.css",
"!packages/marketing/public/static/app.css",
"!fluxer_static",
"!fluxer_docs/api-reference/openapi.json"
],
"ignoreUnknown": true
}
}
================================================
FILE: compose.yaml
================================================
x-logging: &default-logging
driver: json-file
options:
max-size: '10m'
max-file: '5'
services:
valkey:
image: valkey/valkey:8.0.6-alpine
container_name: valkey
restart: unless-stopped
command: ['valkey-server', '--appendonly', 'yes', '--save', '60', '1', '--loglevel', 'warning']
volumes:
- valkey_data:/data
healthcheck:
test: ['CMD', 'valkey-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
logging: *default-logging
fluxer_server:
image: ${FLUXER_SERVER_IMAGE:-ghcr.io/fluxerapp/fluxer-server:stable}
container_name: fluxer_server
restart: unless-stopped
init: true
environment:
FLUXER_CONFIG: /usr/src/app/config/config.json
NODE_ENV: production
ports:
- '${FLUXER_HTTP_PORT:-8080}:8080'
depends_on:
valkey:
condition: service_healthy
volumes:
- ./config:/usr/src/app/config:ro
- fluxer_data:/usr/src/app/data
healthcheck:
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:8080/_health || exit 1']
interval: 15s
timeout: 5s
retries: 5
start_period: 15s
logging: *default-logging
meilisearch:
image: getmeili/meilisearch:v1.14
container_name: meilisearch
profiles: ['search']
restart: unless-stopped
environment:
MEILI_ENV: production
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?Set MEILI_MASTER_KEY in .env or environment}
MEILI_DB_PATH: /meili_data
MEILI_HTTP_ADDR: 0.0.0.0:7700
ports:
- '${MEILI_PORT:-7700}:7700'
volumes:
- meilisearch_data:/meili_data
healthcheck:
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:7700/health || exit 1']
interval: 15s
timeout: 5s
retries: 5
logging: *default-logging
elasticsearch:
image: elasticsearch:8.19.11
container_name: elasticsearch
profiles: ['search']
restart: unless-stopped
environment:
discovery.type: single-node
xpack.security.enabled: 'false'
xpack.security.http.ssl.enabled: 'false'
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
ports:
- '${ELASTICSEARCH_PORT:-9200}:9200'
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
healthcheck:
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:9200/_cluster/health || exit 1']
interval: 15s
timeout: 5s
retries: 5
logging: *default-logging
livekit:
image: livekit/livekit-server:v1.9.11
container_name: livekit
profiles: ['voice']
restart: unless-stopped
command: ['--config', '/etc/livekit/livekit.yaml']
volumes:
- ./config/livekit.yaml:/etc/livekit/livekit.yaml:ro
ports:
- '${LIVEKIT_PORT:-7880}:7880'
- '7881:7881'
- '3478:3478/udp'
- '50000-50100:50000-50100/udp'
healthcheck:
test: ['CMD-SHELL', 'wget -qO- http://127.0.0.1:7880 || exit 1']
interval: 15s
timeout: 5s
retries: 5
logging: *default-logging
volumes:
valkey_data:
fluxer_data:
meilisearch_data:
elasticsearch_data:
================================================
FILE: config/config.dev.template.json
================================================
{
"$schema": "../packages/config/src/ConfigSchema.json",
"env": "development",
"domain": {
"base_domain": "localhost",
"public_port": 48763
},
"database": {
"backend": "sqlite",
"sqlite_path": "./data/dev.db"
},
"internal": {
"kv": "redis://127.0.0.1:6379/0",
"kv_mode": "standalone"
},
"s3": {
"access_key_id": "",
"secret_access_key": "",
"endpoint": "http://127.0.0.1:49319/s3"
},
"services": {
"server": {
"port": 49319,
"host": "0.0.0.0"
},
"media_proxy": {
"secret_key": ""
},
"admin": {
"secret_key_base": "",
"oauth_client_secret": ""
},
"marketing": {
"enabled": true,
"port": 49531,
"host": "0.0.0.0",
"secret_key_base": ""
},
"gateway": {
"port": 49107,
"admin_reload_secret": "",
"media_proxy_endpoint": "http://localhost:49319/media",
"logger_level": "debug"
},
"nats": {
"core_url": "nats://127.0.0.1:4222",
"jetstream_url": "nats://127.0.0.1:4223"
}
},
"auth": {
"sudo_mode_secret": "",
"connection_initiation_secret": "",
"vapid": {
"public_key": "",
"private_key": ""
},
"bluesky": {
"enabled": true,
"keys": []
}
},
"discovery": {
"min_member_count": 1
},
"dev": {
"disable_rate_limits": true
},
"integrations": {
"email": {
"enabled": true,
"provider": "smtp",
"from_email": "noreply@localhost",
"smtp": {
"host": "localhost",
"port": 49621,
"username": "dev",
"password": "",
"secure": false
}
},
"gif": {
"provider": "klipy"
},
"klipy": {
"api_key": ""
},
"tenor": {
"api_key": ""
},
"voice": {
"enabled": true,
"api_key": "",
"api_secret": "",
"url": "ws://localhost:7880",
"webhook_url": "http://localhost:49319/api/webhooks/livekit",
"default_region": {
"id": "default",
"name": "Default",
"emoji": "\ud83c\udf10",
"latitude": 0.0,
"longitude": 0.0
}
},
"search": {
"engine": "meilisearch",
"url": "http://127.0.0.1:7700",
"api_key": ""
}
},
"instance": {
"private_key_path": ""
},
"federation": {
"enabled": false
}
}
================================================
FILE: config/config.production.template.json
================================================
{
"$schema": "../packages/config/src/ConfigSchema.json",
"env": "production",
"domain": {
"base_domain": "chat.example.com",
"public_scheme": "https",
"public_port": 443
},
"database": {
"backend": "sqlite",
"sqlite_path": "./data/fluxer.db"
},
"internal": {
"kv": "redis://valkey:6379/0",
"kv_mode": "standalone"
},
"s3": {
"access_key_id": "YOUR_S3_ACCESS_KEY",
"secret_access_key": "YOUR_S3_SECRET_KEY",
"endpoint": "http://127.0.0.1:8080/s3"
},
"services": {
"server": {
"port": 8080,
"host": "0.0.0.0"
},
"media_proxy": {
"secret_key": "GENERATE_A_64_CHAR_HEX_SECRET"
},
"admin": {
"secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET",
"oauth_client_secret": "GENERATE_A_64_CHAR_HEX_SECRET"
},
"marketing": {
"enabled": true,
"secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET"
},
"gateway": {
"port": 8082,
"admin_reload_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
"media_proxy_endpoint": "http://127.0.0.1:8080/media"
},
"nats": {
"core_url": "nats://nats:4222",
"jetstream_url": "nats://nats:4222",
"auth_token": "GENERATE_A_NATS_AUTH_TOKEN"
}
},
"auth": {
"sudo_mode_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
"connection_initiation_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
"vapid": {
"public_key": "YOUR_VAPID_PUBLIC_KEY",
"private_key": "YOUR_VAPID_PRIVATE_KEY"
}
},
"integrations": {
"search": {
"engine": "meilisearch",
"url": "http://meilisearch:7700",
"api_key": "YOUR_MEILISEARCH_API_KEY"
}
}
}
================================================
FILE: config/config.schema.json
================================================
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "../packages/config/src/ConfigSchema.json"
}
================================================
FILE: config/config.test.json
================================================
{
"env": "test",
"instance": {
"self_hosted": false
},
"domain": {
"base_domain": "localhost"
},
"database": {
"backend": "sqlite",
"sqlite_path": "./data/test.db"
},
"s3": {
"access_key_id": "test-access-key",
"secret_access_key": "test-secret-key"
},
"services": {
"media_proxy": {
"secret_key": "test-media-proxy-secret-key-minimum-32-chars"
},
"admin": {
"secret_key_base": "test-admin-secret-key-base-minimum-32-chars",
"oauth_client_secret": "test-oauth-client-secret"
},
"gateway": {
"admin_reload_secret": "test-gateway-admin-reload-secret-32-chars",
"media_proxy_endpoint": "http://localhost:8088/media"
}
},
"auth": {
"sudo_mode_secret": "test-sudo-mode-secret-minimum-32-chars",
"connection_initiation_secret": "test-connection-initiation-secret-32ch",
"vapid": {
"public_key": "test-vapid-public-key",
"private_key": "test-vapid-private-key"
},
"bluesky": {
"enabled": true,
"keys": []
}
},
"discovery": {
"min_member_count": 1
},
"dev": {
"disable_rate_limits": true,
"test_mode_enabled": true,
"relax_registration_rate_limits": true
},
"proxy": {
"trust_cf_connecting_ip": false
},
"integrations": {
"search": {
"url": "http://127.0.0.1:7700",
"api_key": "test-meilisearch-master-key"
},
"photo_dna": {
"enabled": true,
"hash_service_url": "https://api.microsoftmoderator.com/photodna/v1.0/Hash",
"hash_service_timeout_ms": 30000,
"match_endpoint": "https://api.microsoftmoderator.com/photodna/v1.0/Match",
"subscription_key": "test-subscription-key",
"match_enhance": false,
"rate_limit_rps": 10
},
"stripe": {
"enabled": true,
"secret_key": "sk_test_mock_key_for_testing",
"webhook_secret": "whsec_test_mock_webhook_secret"
}
}
}
================================================
FILE: config/livekit.example.yaml
================================================
port: 7880
keys:
'<replace-with-api-key>': '<replace-with-api-secret>'
rtc:
tcp_port: 7881
turn:
enabled: true
udp_port: 3478
room:
auto_create: true
max_participants: 100
empty_timeout: 300
================================================
FILE: dev/Caddyfile.dev
================================================
{
auto_https off
admin off
}
:48763 {
handle /_caddy_health {
respond "OK" 200
}
@gateway path /gateway /gateway/*
handle @gateway {
uri strip_prefix /gateway
reverse_proxy 127.0.0.1:49107
}
@marketing path /marketing /marketing/*
handle @marketing {
uri strip_prefix /marketing
reverse_proxy 127.0.0.1:49531
}
@server path /admin /admin/* /api /api/* /s3 /s3/* /queue /queue/* /media /media/* /_health /_ready /_live /.well-known/fluxer
handle @server {
reverse_proxy 127.0.0.1:49319
}
@livekit path /livekit /livekit/*
handle @livekit {
uri strip_prefix /livekit
reverse_proxy 127.0.0.1:7880
}
redir /mailpit /mailpit/
handle_path /mailpit/* {
rewrite * /mailpit{path}
reverse_proxy 127.0.0.1:49667
}
handle {
reverse_proxy 127.0.0.1:49427 {
header_up Connection {http.request.header.Connection}
header_up Upgrade {http.request.header.Upgrade}
}
}
log {
output stdout
format console
}
}
======
Showing preview only (266K chars total). Download the full file or copy to clipboard to get everything.
gitextract_5eknctna/ ├── .devcontainer/ │ ├── Caddyfile.dev │ ├── Dockerfile │ ├── devcontainer.json │ ├── docker-compose.yml │ ├── livekit.yaml │ ├── on-create.sh │ └── process-compose.yml ├── .dockerignore ├── .editorconfig ├── .envrc ├── .gitattributes ├── .github/ │ ├── DISCUSSION_TEMPLATE/ │ │ └── ideas.yaml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── docs.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── build-desktop.yaml │ ├── channel-vars.yaml │ ├── ci.yaml │ ├── deploy-admin.yaml │ ├── deploy-api.yaml │ ├── deploy-app.yaml │ ├── deploy-gateway.yaml │ ├── deploy-marketing.yaml │ ├── deploy-media-proxy.yaml │ ├── deploy-relay-directory.yaml │ ├── deploy-relay.yaml │ ├── deploy-static-proxy.yaml │ ├── migrate-cassandra.yaml │ ├── promote-canary-to-main.yaml │ ├── release-livekitctl.yaml │ ├── release-relay-directory.yaml │ ├── release-relay.yaml │ ├── release-server.yaml │ ├── restart-gateway.yaml │ ├── sync-desktop.yaml │ ├── sync-static.yaml │ ├── test-cassandra-backup.yaml │ └── update-word-lists.yaml ├── .gitignore ├── .gitmodules ├── .ignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .tool-versions ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── LICENSING.md ├── README.md ├── SECURITY.md ├── biome.json ├── compose.yaml ├── config/ │ ├── config.dev.template.json │ ├── config.production.template.json │ ├── config.schema.json │ ├── config.test.json │ └── livekit.example.yaml ├── dev/ │ ├── Caddyfile.dev │ └── livekit.template.yaml ├── devenv.nix ├── devenv.yaml ├── fluxer_admin/ │ ├── Dockerfile │ ├── package.json │ ├── public/ │ │ └── static/ │ │ └── .gitkeep │ ├── src/ │ │ ├── Config.tsx │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ └── index.tsx │ └── tsconfig.json ├── fluxer_api/ │ ├── Dockerfile │ ├── package.json │ ├── scripts/ │ │ ├── CassandraMigrate.tsx │ │ ├── Dockerfile.cassandra-migrate │ │ └── LicenseEnforcer.tsx │ ├── src/ │ │ ├── App.tsx │ │ ├── AppEntrypoint.tsx │ │ ├── Config.tsx │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ └── WorkerEntrypoint.tsx │ ├── tsconfig.json │ └── tsconfig.worker.json ├── fluxer_app/ │ ├── crates/ │ │ └── libfluxcore/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── animation.rs │ │ ├── apng.rs │ │ ├── gateway.rs │ │ ├── gif.rs │ │ ├── lib.rs │ │ └── static_image.rs │ ├── index.html │ ├── lingui.config.js │ ├── package.json │ ├── postcss.config.js │ ├── rspack.config.mjs │ ├── rust-toolchain.toml │ ├── scripts/ │ │ ├── DevServer.tsx │ │ ├── GenerateAvatarMasks.tsx │ │ ├── GenerateColorSystem.tsx │ │ ├── GenerateEmojiSprites.tsx │ │ ├── auto-i18n.mjs │ │ ├── build/ │ │ │ ├── Config.tsx │ │ │ ├── rspack/ │ │ │ │ ├── externals.mjs │ │ │ │ ├── lingui.mjs │ │ │ │ ├── po-loader.mjs │ │ │ │ ├── static-files.mjs │ │ │ │ └── wasm.mjs │ │ │ ├── tsconfig.json │ │ │ ├── types.d.ts │ │ │ └── utils/ │ │ │ ├── Assets.tsx │ │ │ ├── CssDts.tsx │ │ │ ├── Html.tsx │ │ │ ├── Resolve.tsx │ │ │ ├── ServiceWorker.tsx │ │ │ └── Sourcemaps.tsx │ │ ├── build-sw.mjs │ │ └── translate-i18n.mjs │ ├── src/ │ │ ├── App.module.css │ │ ├── App.tsx │ │ ├── AppConstants.tsx │ │ ├── Config.tsx │ │ ├── Endpoints.tsx │ │ ├── I18n.tsx │ │ ├── Router.tsx │ │ ├── Routes.tsx │ │ ├── actions/ │ │ │ ├── AccessibilityActionCreators.tsx │ │ │ ├── AuthSessionActionCreators.tsx │ │ │ ├── AuthenticationActionCreators.tsx │ │ │ ├── CallActionCreators.tsx │ │ │ ├── ChannelActionCreators.tsx │ │ │ ├── ChannelPinsActionCreators.tsx │ │ │ ├── ChannelStickerActionCreators.tsx │ │ │ ├── ConnectionActionCreators.tsx │ │ │ ├── ContextMenuActionCreators.tsx │ │ │ ├── DeveloperOptionsActionCreators.tsx │ │ │ ├── DimensionActionCreators.tsx │ │ │ ├── DiscoveryActionCreators.tsx │ │ │ ├── DraftActionCreators.tsx │ │ │ ├── EmojiActionCreators.tsx │ │ │ ├── EmojiPickerActionCreators.tsx │ │ │ ├── ExpressionPickerActionCreators.tsx │ │ │ ├── FavoriteMemeActionCreators.tsx │ │ │ ├── FavoritesActionCreators.tsx │ │ │ ├── GifActionCreators.tsx │ │ │ ├── GiftActionCreators.tsx │ │ │ ├── GuildActionCreators.tsx │ │ │ ├── GuildEmojiActionCreators.tsx │ │ │ ├── GuildMemberActionCreators.tsx │ │ │ ├── GuildNSFWActionCreators.tsx │ │ │ ├── GuildStickerActionCreators.tsx │ │ │ ├── HighlightActionCreators.tsx │ │ │ ├── IARActionCreators.tsx │ │ │ ├── InboxActionCreators.tsx │ │ │ ├── InviteActionCreators.tsx │ │ │ ├── KlipyActionCreators.tsx │ │ │ ├── LayoutActionCreators.tsx │ │ │ ├── MediaViewerActionCreators.tsx │ │ │ ├── MessageActionCreators.tsx │ │ │ ├── MfaActionCreators.tsx │ │ │ ├── ModalActionCreators.tsx │ │ │ ├── ModalRender.tsx │ │ │ ├── NagbarActionCreators.tsx │ │ │ ├── NavigationActionCreators.tsx │ │ │ ├── NotificationActionCreators.tsx │ │ │ ├── OAuth2AuthorizationActionCreators.tsx │ │ │ ├── PackActionCreators.tsx │ │ │ ├── PackInviteActionCreators.tsx │ │ │ ├── PiPActionCreators.tsx │ │ │ ├── PopoutActionCreators.tsx │ │ │ ├── PremiumActionCreators.tsx │ │ │ ├── PremiumModalActionCreators.tsx │ │ │ ├── PrivateChannelActionCreators.tsx │ │ │ ├── QuickSwitcherActionCreators.tsx │ │ │ ├── ReactionActionCreators.tsx │ │ │ ├── ReadStateActionCreators.tsx │ │ │ ├── RecentMentionActionCreators.tsx │ │ │ ├── RelationshipActionCreators.tsx │ │ │ ├── SavedMessageActionCreators.tsx │ │ │ ├── ScheduledMessageActionCreators.tsx │ │ │ ├── SlowmodeActionCreators.tsx │ │ │ ├── SoundActionCreators.tsx │ │ │ ├── StickerPickerActionCreators.tsx │ │ │ ├── TextCopyActionCreators.tsx │ │ │ ├── ThemeActionCreators.tsx │ │ │ ├── ThemePreferenceActionCreators.tsx │ │ │ ├── ToastActionCreators.tsx │ │ │ ├── TrustedDomainActionCreators.tsx │ │ │ ├── TypingActionCreators.tsx │ │ │ ├── UnsavedChangesActionCreators.tsx │ │ │ ├── UserActionCreators.tsx │ │ │ ├── UserGuildSettingsActionCreators.tsx │ │ │ ├── UserNoteActionCreators.tsx │ │ │ ├── UserProfileActionCreators.tsx │ │ │ ├── UserSettingsActionCreators.tsx │ │ │ ├── VoiceCallLayoutActionCreators.tsx │ │ │ ├── VoiceSettingsActionCreators.tsx │ │ │ ├── VoiceStateActionCreators.tsx │ │ │ ├── WebhookActionCreators.tsx │ │ │ └── WindowActionCreators.tsx │ │ ├── bootstrap/ │ │ │ └── SetupHttpClient.tsx │ │ ├── components/ │ │ │ ├── AppBadge.tsx │ │ │ ├── BootstrapErrorScreen.tsx │ │ │ ├── ErrorFallback.module.css │ │ │ ├── ErrorFallback.tsx │ │ │ ├── LongPressable.tsx │ │ │ ├── NetworkErrorScreen.tsx │ │ │ ├── accounts/ │ │ │ │ ├── AccountListItem.module.css │ │ │ │ ├── AccountListItem.tsx │ │ │ │ ├── AccountRow.module.css │ │ │ │ ├── AccountRow.tsx │ │ │ │ ├── AccountSelector.module.css │ │ │ │ ├── AccountSelector.tsx │ │ │ │ ├── AccountSwitcherModal.module.css │ │ │ │ └── AccountSwitcherModal.tsx │ │ │ ├── alerts/ │ │ │ │ ├── CallNotRingableModal.tsx │ │ │ │ ├── CameraPermissionDeniedModal.tsx │ │ │ │ ├── ChannelPermissionsUpdateFailedModal.tsx │ │ │ │ ├── DMCloseFailedModal.tsx │ │ │ │ ├── FeatureTemporarilyDisabledModal.tsx │ │ │ │ ├── FileSizeTooLargeModal.tsx │ │ │ │ ├── GenericErrorModal.tsx │ │ │ │ ├── GroupLeaveFailedModal.tsx │ │ │ │ ├── GroupOwnershipTransferFailedModal.tsx │ │ │ │ ├── GroupRemoveUserFailedModal.tsx │ │ │ │ ├── GuildAtCapacityModal.tsx │ │ │ │ ├── InviteAcceptFailedModal.tsx │ │ │ │ ├── InviteRevokeFailedModal.tsx │ │ │ │ ├── InvitesDisabledModal.tsx │ │ │ │ ├── InvitesLoadFailedModal.tsx │ │ │ │ ├── MaxBookmarksModal.tsx │ │ │ │ ├── MaxFavoriteMemesModal.tsx │ │ │ │ ├── MaxGuildsModal.tsx │ │ │ │ ├── MessageDeleteFailedModal.tsx │ │ │ │ ├── MessageDeleteTooQuickModal.tsx │ │ │ │ ├── MessageEditFailedModal.tsx │ │ │ │ ├── MessageEditTooQuickModal.tsx │ │ │ │ ├── MessageForwardFailedModal.tsx │ │ │ │ ├── MessageSendFailedModal.tsx │ │ │ │ ├── MessageSendTooQuickModal.tsx │ │ │ │ ├── MicrophonePermissionDeniedModal.tsx │ │ │ │ ├── NSFWContentRejectedModal.tsx │ │ │ │ ├── PinFailedModal.tsx │ │ │ │ ├── RateLimitedConfirmModal.tsx │ │ │ │ ├── ReactionInteractionDisabledModal.tsx │ │ │ │ ├── RoleCreateFailedModal.tsx │ │ │ │ ├── RoleDeleteFailedModal.tsx │ │ │ │ ├── RoleNameBlankModal.tsx │ │ │ │ ├── RoleUpdateFailedModal.tsx │ │ │ │ ├── ScreenRecordingPermissionDeniedModal.tsx │ │ │ │ ├── ScreenShareUnsupportedModal.tsx │ │ │ │ ├── SlowmodeRateLimitedModal.tsx │ │ │ │ ├── TemporaryInviteRequiresPresenceModal.tsx │ │ │ │ ├── TooManyAttachmentsModal.tsx │ │ │ │ ├── TooManyReactionsModal.tsx │ │ │ │ ├── TtsUnsupportedModal.tsx │ │ │ │ ├── UserBannedFromGuildModal.tsx │ │ │ │ ├── UserIpBannedFromGuildModal.tsx │ │ │ │ ├── VoiceChannelFullModal.tsx │ │ │ │ ├── VoiceConnectionConfirmModal.module.css │ │ │ │ └── VoiceConnectionConfirmModal.tsx │ │ │ ├── auth/ │ │ │ │ ├── AuthBackground.tsx │ │ │ │ ├── AuthBottomLink.tsx │ │ │ │ ├── AuthCardContainer.module.css │ │ │ │ ├── AuthCardContainer.tsx │ │ │ │ ├── AuthErrorState.tsx │ │ │ │ ├── AuthLoadingState.tsx │ │ │ │ ├── AuthLoginLayout.tsx │ │ │ │ ├── AuthMinimalRegisterFormCore.tsx │ │ │ │ ├── AuthPageHeader.tsx │ │ │ │ ├── AuthPageStyles.module.css │ │ │ │ ├── AuthRegisterFormCore.tsx │ │ │ │ ├── AuthRouterLink.tsx │ │ │ │ ├── BrowserLoginHandoffModal.module.css │ │ │ │ ├── BrowserLoginHandoffModal.tsx │ │ │ │ ├── DateOfBirthField.module.css │ │ │ │ ├── DateOfBirthField.tsx │ │ │ │ ├── DesktopDeepLinkPrompt.module.css │ │ │ │ ├── DesktopDeepLinkPrompt.tsx │ │ │ │ ├── DesktopHandoffAccountSelector.tsx │ │ │ │ ├── FormField.tsx │ │ │ │ ├── GiftHeader.tsx │ │ │ │ ├── HandoffCodeDisplay.module.css │ │ │ │ ├── HandoffCodeDisplay.tsx │ │ │ │ ├── InstanceSelector.module.css │ │ │ │ ├── InstanceSelector.tsx │ │ │ │ ├── InviteHeader.tsx │ │ │ │ ├── IpAuthorizationScreen.module.css │ │ │ │ ├── IpAuthorizationScreen.tsx │ │ │ │ ├── MfaScreen.module.css │ │ │ │ ├── MfaScreen.tsx │ │ │ │ ├── MockMinimalRegisterForm.tsx │ │ │ │ ├── SubmitTooltip.module.css │ │ │ │ ├── SubmitTooltip.tsx │ │ │ │ └── auth_login_core/ │ │ │ │ ├── AuthLoginEmailPasswordForm.tsx │ │ │ │ ├── AuthLoginPasskeyActions.tsx │ │ │ │ └── useDesktopHandoffFlow.tsx │ │ │ ├── bottomsheets/ │ │ │ │ ├── CategoryBottomSheet.tsx │ │ │ │ ├── ChannelBottomSheet.tsx │ │ │ │ ├── ChannelDetailsBottomSheet.module.css │ │ │ │ ├── ChannelDetailsBottomSheet.tsx │ │ │ │ ├── ChannelPinsBottomSheet.tsx │ │ │ │ ├── ChannelSearchBottomSheet.tsx │ │ │ │ ├── CreateDMBottomSheet.module.css │ │ │ │ ├── CreateDMBottomSheet.tsx │ │ │ │ ├── DMBottomSheet.tsx │ │ │ │ ├── DirectCallLobbyBottomSheet.module.css │ │ │ │ ├── DirectCallLobbyBottomSheet.tsx │ │ │ │ ├── EmojiInfoBottomSheet.module.css │ │ │ │ ├── EmojiInfoBottomSheet.tsx │ │ │ │ ├── FavoritesGuildHeaderBottomSheet.tsx │ │ │ │ ├── GuildHeaderBottomSheet.module.css │ │ │ │ ├── GuildHeaderBottomSheet.tsx │ │ │ │ ├── MuteDurationSheet.tsx │ │ │ │ ├── QuickSwitcherBottomSheet.module.css │ │ │ │ ├── QuickSwitcherBottomSheet.tsx │ │ │ │ ├── VoiceLobbyBottomSheet.module.css │ │ │ │ ├── VoiceLobbyBottomSheet.tsx │ │ │ │ ├── VoiceParticipantBottomSheet.tsx │ │ │ │ ├── VoiceSettingsBottomSheets.tsx │ │ │ │ └── shared.module.css │ │ │ ├── captcha/ │ │ │ │ └── TurnstileWidget.tsx │ │ │ ├── channel/ │ │ │ │ ├── Autocomplete.module.css │ │ │ │ ├── Autocomplete.tsx │ │ │ │ ├── AutocompleteChannel.module.css │ │ │ │ ├── AutocompleteChannel.tsx │ │ │ │ ├── AutocompleteCommand.tsx │ │ │ │ ├── AutocompleteEmoji.module.css │ │ │ │ ├── AutocompleteEmoji.tsx │ │ │ │ ├── AutocompleteGif.module.css │ │ │ │ ├── AutocompleteGif.tsx │ │ │ │ ├── AutocompleteItem.module.css │ │ │ │ ├── AutocompleteItem.tsx │ │ │ │ ├── AutocompleteMeme.tsx │ │ │ │ ├── AutocompleteMention.module.css │ │ │ │ ├── AutocompleteMention.tsx │ │ │ │ ├── AutocompleteSticker.tsx │ │ │ │ ├── BlockedMessageGroups.module.css │ │ │ │ ├── BlockedMessageGroups.tsx │ │ │ │ ├── CallMessage.module.css │ │ │ │ ├── CallMessage.tsx │ │ │ │ ├── ChannelAttachmentArea.module.css │ │ │ │ ├── ChannelAttachmentArea.tsx │ │ │ │ ├── ChannelChatLayout.module.css │ │ │ │ ├── ChannelChatLayout.tsx │ │ │ │ ├── ChannelHeader.module.css │ │ │ │ ├── ChannelHeader.tsx │ │ │ │ ├── ChannelIconChangeMessage.tsx │ │ │ │ ├── ChannelIndexPage.module.css │ │ │ │ ├── ChannelIndexPage.tsx │ │ │ │ ├── ChannelLayout.module.css │ │ │ │ ├── ChannelLayout.tsx │ │ │ │ ├── ChannelMembers.module.css │ │ │ │ ├── ChannelMembers.tsx │ │ │ │ ├── ChannelMessageStream.tsx │ │ │ │ ├── ChannelNameChangeMessage.tsx │ │ │ │ ├── ChannelSearchHighlight.css │ │ │ │ ├── ChannelSearchResults.module.css │ │ │ │ ├── ChannelSearchResults.tsx │ │ │ │ ├── ChannelSourcePreview.module.css │ │ │ │ ├── ChannelSourcePreview.tsx │ │ │ │ ├── ChannelStickersArea.module.css │ │ │ │ ├── ChannelStickersArea.tsx │ │ │ │ ├── ChannelTextarea.tsx │ │ │ │ ├── ChannelWelcomeSection.module.css │ │ │ │ ├── ChannelWelcomeSection.tsx │ │ │ │ ├── Divider.module.css │ │ │ │ ├── Divider.tsx │ │ │ │ ├── EditBar.module.css │ │ │ │ ├── EditBar.tsx │ │ │ │ ├── EditingMessageInput.module.css │ │ │ │ ├── EditingMessageInput.tsx │ │ │ │ ├── EmojiPicker.module.css │ │ │ │ ├── EmojiPicker.tsx │ │ │ │ ├── ExpressionPickerShared.module.css │ │ │ │ ├── GifPicker.module.css │ │ │ │ ├── GifVideoPool.tsx │ │ │ │ ├── GiftEmbed.module.css │ │ │ │ ├── GiftEmbed.tsx │ │ │ │ ├── GuildJoinMessage.module.css │ │ │ │ ├── GuildJoinMessage.tsx │ │ │ │ ├── GuildMembersPage.module.css │ │ │ │ ├── GuildMembersPage.tsx │ │ │ │ ├── InviteEmbed.module.css │ │ │ │ ├── InviteEmbed.tsx │ │ │ │ ├── MasonryListComputer.tsx │ │ │ │ ├── MediaActionBottomSheet.tsx │ │ │ │ ├── MemberListContainer.module.css │ │ │ │ ├── MemberListContainer.tsx │ │ │ │ ├── MemberListItem.module.css │ │ │ │ ├── MemberListItem.tsx │ │ │ │ ├── MemesPicker.module.css │ │ │ │ ├── MentionEveryonePopout.module.css │ │ │ │ ├── MentionEveryonePopout.tsx │ │ │ │ ├── Message.tsx │ │ │ │ ├── MessageActionBar.module.css │ │ │ │ ├── MessageActionBar.tsx │ │ │ │ ├── MessageActionBottomSheet.module.css │ │ │ │ ├── MessageActionBottomSheet.tsx │ │ │ │ ├── MessageActionMenu.tsx │ │ │ │ ├── MessageActionUtils.tsx │ │ │ │ ├── MessageAttachmentStateUtils.tsx │ │ │ │ ├── MessageAttachmentUtils.tsx │ │ │ │ ├── MessageAttachments.module.css │ │ │ │ ├── MessageAttachments.tsx │ │ │ │ ├── MessageAuthorInfo.tsx │ │ │ │ ├── MessageAvatar.tsx │ │ │ │ ├── MessageCharacterCounter.module.css │ │ │ │ ├── MessageCharacterCounter.tsx │ │ │ │ ├── MessageGroup.tsx │ │ │ │ ├── MessageReactions.module.css │ │ │ │ ├── MessageReactions.tsx │ │ │ │ ├── MessageReactionsSheet.module.css │ │ │ │ ├── MessageReactionsSheet.tsx │ │ │ │ ├── MessageUploadProgress.module.css │ │ │ │ ├── MessageUploadProgress.tsx │ │ │ │ ├── MessageUsername.tsx │ │ │ │ ├── MessageViewContext.tsx │ │ │ │ ├── Messages.module.css │ │ │ │ ├── Messages.tsx │ │ │ │ ├── MobileEmojiPicker.module.css │ │ │ │ ├── MobileEmojiPicker.tsx │ │ │ │ ├── MobileMemesPicker.tsx │ │ │ │ ├── MobileStickersPicker.tsx │ │ │ │ ├── MuteOptions.tsx │ │ │ │ ├── NSFWChannelGate.module.css │ │ │ │ ├── NSFWChannelGate.tsx │ │ │ │ ├── NewMessagesBar.tsx │ │ │ │ ├── PinSystemMessage.tsx │ │ │ │ ├── PreloadableUserPopout.tsx │ │ │ │ ├── PremiumUpsellBanner.module.css │ │ │ │ ├── PremiumUpsellBanner.tsx │ │ │ │ ├── QuickReactionsRow.module.css │ │ │ │ ├── QuickReactionsRow.tsx │ │ │ │ ├── RecipientAddMessage.module.css │ │ │ │ ├── RecipientAddMessage.tsx │ │ │ │ ├── RecipientRemoveMessage.module.css │ │ │ │ ├── RecipientRemoveMessage.tsx │ │ │ │ ├── ReplyBar.module.css │ │ │ │ ├── ReplyBar.tsx │ │ │ │ ├── ReplyPreview.tsx │ │ │ │ ├── ScheduledMessageEditBar.module.css │ │ │ │ ├── ScheduledMessageEditBar.tsx │ │ │ │ ├── ScrollFillerSkeleton.module.css │ │ │ │ ├── ScrollFillerSkeleton.tsx │ │ │ │ ├── SearchResultsUtils.tsx │ │ │ │ ├── SearchScopeOptions.tsx │ │ │ │ ├── SlowmodeIndicator.module.css │ │ │ │ ├── SlowmodeIndicator.tsx │ │ │ │ ├── StickersPicker.module.css │ │ │ │ ├── StickersPicker.tsx │ │ │ │ ├── SystemMessage.tsx │ │ │ │ ├── SystemMessageUsername.tsx │ │ │ │ ├── ThemeEmbed.module.css │ │ │ │ ├── ThemeEmbed.tsx │ │ │ │ ├── TimestampWithTooltip.module.css │ │ │ │ ├── TimestampWithTooltip.tsx │ │ │ │ ├── Typing.tsx │ │ │ │ ├── TypingUsers.module.css │ │ │ │ ├── TypingUsers.tsx │ │ │ │ ├── UnknownMessage.tsx │ │ │ │ ├── UnreadDividerSlot.tsx │ │ │ │ ├── UploadManager.tsx │ │ │ │ ├── UserMessage.tsx │ │ │ │ ├── UserTag.module.css │ │ │ │ ├── UserTag.tsx │ │ │ │ ├── VerificationBarrier.tsx │ │ │ │ ├── VoiceMessageRecorder.module.css │ │ │ │ ├── VoiceMessageRecorder.tsx │ │ │ │ ├── active_now/ │ │ │ │ │ ├── ActiveNowSidebar.module.css │ │ │ │ │ ├── ActiveNowSidebar.tsx │ │ │ │ │ └── useActiveFriendVoiceStates.tsx │ │ │ │ ├── barriers/ │ │ │ │ │ ├── BarrierComponents.module.css │ │ │ │ │ └── BarrierComponents.tsx │ │ │ │ ├── channel_header/ │ │ │ │ │ └── useChannelHeaderData.tsx │ │ │ │ ├── channel_header_components/ │ │ │ │ │ ├── CallButtons.tsx │ │ │ │ │ ├── ChannelHeaderIcon.tsx │ │ │ │ │ ├── ChannelNotificationSettingsButton.tsx │ │ │ │ │ ├── ChannelNotificationSettingsDropdown.tsx │ │ │ │ │ ├── ChannelPinsButton.tsx │ │ │ │ │ ├── UpdaterIcon.tsx │ │ │ │ │ └── UtilityButtons.tsx │ │ │ │ ├── channel_view/ │ │ │ │ │ ├── ChannelViewScaffold.tsx │ │ │ │ │ ├── DMChannelView.tsx │ │ │ │ │ ├── GuildChannelView.tsx │ │ │ │ │ ├── useCallHeaderState.tsx │ │ │ │ │ └── useChannelSearchState.tsx │ │ │ │ ├── direct_message/ │ │ │ │ │ ├── AddFriendForm.module.css │ │ │ │ │ ├── AddFriendForm.tsx │ │ │ │ │ ├── AddFriendView.module.css │ │ │ │ │ ├── AddFriendView.tsx │ │ │ │ │ ├── DMChannelView.module.css │ │ │ │ │ ├── DMFriendsView.module.css │ │ │ │ │ ├── DMFriendsView.tsx │ │ │ │ │ ├── DMLayout.module.css │ │ │ │ │ ├── DMLayout.tsx │ │ │ │ │ ├── DMList.module.css │ │ │ │ │ ├── DMList.tsx │ │ │ │ │ ├── DMWelcomeSection.module.css │ │ │ │ │ ├── DMWelcomeSection.tsx │ │ │ │ │ ├── GroupDMWelcomeSection.module.css │ │ │ │ │ ├── GroupDMWelcomeSection.tsx │ │ │ │ │ ├── PersonalNotesWelcomeSection.module.css │ │ │ │ │ └── PersonalNotesWelcomeSection.tsx │ │ │ │ ├── embeds/ │ │ │ │ │ ├── AltTextBadge.module.css │ │ │ │ │ ├── AltTextBadge.tsx │ │ │ │ │ ├── Embed.module.css │ │ │ │ │ ├── Embed.tsx │ │ │ │ │ ├── EmbedUtils.tsx │ │ │ │ │ ├── NSFWBlurOverlay.module.css │ │ │ │ │ ├── NSFWBlurOverlay.tsx │ │ │ │ │ ├── attachments/ │ │ │ │ │ │ ├── Attachment.module.css │ │ │ │ │ │ ├── Attachment.tsx │ │ │ │ │ │ ├── AttachmentFile.tsx │ │ │ │ │ │ ├── AttachmentGridItem.tsx │ │ │ │ │ │ ├── AttachmentLayoutGrid.tsx │ │ │ │ │ │ ├── AttachmentMosaic.tsx │ │ │ │ │ │ ├── AttachmentSingleMedia.tsx │ │ │ │ │ │ ├── TextualAttachmentCodePanel.tsx │ │ │ │ │ │ ├── TextualAttachmentLanguagePopout.tsx │ │ │ │ │ │ ├── TextualAttachmentPreview.module.css │ │ │ │ │ │ ├── TextualAttachmentPreview.tsx │ │ │ │ │ │ ├── TextualAttachmentPreviewBottomSheet.module.css │ │ │ │ │ │ ├── TextualAttachmentPreviewBottomSheet.tsx │ │ │ │ │ │ ├── TextualAttachmentPreviewFooter.tsx │ │ │ │ │ │ ├── TextualAttachmentPreviewModal.tsx │ │ │ │ │ │ ├── TextualAttachmentPreviewUtils.tsx │ │ │ │ │ │ └── TextualPreviewContextMenu.tsx │ │ │ │ │ └── media/ │ │ │ │ │ ├── EmbedAudio.module.css │ │ │ │ │ ├── EmbedAudio.tsx │ │ │ │ │ ├── EmbedGifv.module.css │ │ │ │ │ ├── EmbedGifv.tsx │ │ │ │ │ ├── EmbedImage.module.css │ │ │ │ │ ├── EmbedImage.tsx │ │ │ │ │ ├── EmbedVideo.module.css │ │ │ │ │ ├── EmbedVideo.tsx │ │ │ │ │ ├── EmbedYouTube.module.css │ │ │ │ │ ├── EmbedYouTube.tsx │ │ │ │ │ ├── GifIndicator.module.css │ │ │ │ │ ├── GifIndicator.tsx │ │ │ │ │ ├── MediaButtonUtils.tsx │ │ │ │ │ ├── MediaButtons.module.css │ │ │ │ │ ├── MediaButtons.tsx │ │ │ │ │ ├── MediaContainer.module.css │ │ │ │ │ ├── MediaContainer.tsx │ │ │ │ │ ├── MediaTypes.tsx │ │ │ │ │ ├── VoiceMessagePlayer.module.css │ │ │ │ │ └── VoiceMessagePlayer.tsx │ │ │ │ ├── emoji_picker/ │ │ │ │ │ ├── EmojiPickerCategoryList.tsx │ │ │ │ │ ├── EmojiPickerConstants.tsx │ │ │ │ │ ├── EmojiPickerInspector.tsx │ │ │ │ │ ├── EmojiPickerSearchBar.module.css │ │ │ │ │ ├── EmojiPickerSearchBar.tsx │ │ │ │ │ ├── EmojiRenderer.tsx │ │ │ │ │ ├── SkinToneSelector.tsx │ │ │ │ │ ├── VirtualRow.tsx │ │ │ │ │ └── hooks/ │ │ │ │ │ ├── useEmojiCategories.tsx │ │ │ │ │ └── useVirtualRows.tsx │ │ │ │ ├── friends/ │ │ │ │ │ ├── ActionButton.module.css │ │ │ │ │ ├── ActionButton.tsx │ │ │ │ │ ├── EmptyStateView.module.css │ │ │ │ │ ├── EmptyStateView.tsx │ │ │ │ │ ├── FriendListItem.module.css │ │ │ │ │ ├── FriendListItem.tsx │ │ │ │ │ ├── FriendsTypes.tsx │ │ │ │ │ ├── ListSection.module.css │ │ │ │ │ ├── ListSection.tsx │ │ │ │ │ ├── MobileFriendRequestItem.module.css │ │ │ │ │ ├── MobileFriendRequestItem.tsx │ │ │ │ │ └── views/ │ │ │ │ │ ├── FriendsList.module.css │ │ │ │ │ ├── FriendsList.tsx │ │ │ │ │ ├── PendingFriendsView.module.css │ │ │ │ │ └── PendingFriendsView.tsx │ │ │ │ ├── invite_embed/ │ │ │ │ │ └── InviteEmbedUtils.tsx │ │ │ │ ├── message_search_bar/ │ │ │ │ │ ├── AutocompleteOption.tsx │ │ │ │ │ ├── ChannelsSection.tsx │ │ │ │ │ ├── DateSection.tsx │ │ │ │ │ ├── FilterOption.tsx │ │ │ │ │ ├── HistorySection.tsx │ │ │ │ │ ├── MessageSearchBar.module.css │ │ │ │ │ ├── MessageSearchBar.tsx │ │ │ │ │ ├── UsersSection.tsx │ │ │ │ │ └── ValuesSection.tsx │ │ │ │ ├── pickers/ │ │ │ │ │ ├── gif/ │ │ │ │ │ │ ├── GifPicker.tsx │ │ │ │ │ │ ├── GifPickerGrid.tsx │ │ │ │ │ │ ├── GifPickerGridItem.tsx │ │ │ │ │ │ ├── GifPickerHeader.tsx │ │ │ │ │ │ ├── GifPickerStore.tsx │ │ │ │ │ │ ├── GifPickerTypes.tsx │ │ │ │ │ │ └── GifPickerView.tsx │ │ │ │ │ ├── memes/ │ │ │ │ │ │ ├── MediaFormat.tsx │ │ │ │ │ │ ├── MemeGridItem.tsx │ │ │ │ │ │ ├── MemesGrid.tsx │ │ │ │ │ │ ├── MemesPicker.tsx │ │ │ │ │ │ ├── MemesPickerHeader.tsx │ │ │ │ │ │ └── MemesPickerView.tsx │ │ │ │ │ └── shared/ │ │ │ │ │ ├── ComputeColumns.tsx │ │ │ │ │ ├── MasonryVirtualGrid.tsx │ │ │ │ │ ├── PickerConstants.tsx │ │ │ │ │ ├── usePooledVideo.tsx │ │ │ │ │ └── useScrollerViewport.tsx │ │ │ │ ├── shared/ │ │ │ │ │ ├── MemberListUnavailableFallback.module.css │ │ │ │ │ ├── MemberListUnavailableFallback.tsx │ │ │ │ │ ├── PickerEmptyState.tsx │ │ │ │ │ ├── PickerSearchInput.module.css │ │ │ │ │ └── PickerSearchInput.tsx │ │ │ │ ├── sticker_picker/ │ │ │ │ │ ├── StickerPickerCategoryList.tsx │ │ │ │ │ ├── StickerPickerConstants.tsx │ │ │ │ │ ├── StickerPickerInspector.tsx │ │ │ │ │ ├── StickerPickerSearchBar.tsx │ │ │ │ │ ├── VirtualRow.module.css │ │ │ │ │ ├── VirtualRow.tsx │ │ │ │ │ └── hooks/ │ │ │ │ │ ├── useStickerCategories.tsx │ │ │ │ │ └── useVirtualRows.tsx │ │ │ │ └── textarea/ │ │ │ │ ├── HoldToRecordButton.tsx │ │ │ │ ├── InputWrapper.module.css │ │ │ │ ├── MobileTextareaLayout.module.css │ │ │ │ ├── MobileTextareaLayout.tsx │ │ │ │ ├── MobileTextareaPlusBottomSheet.tsx │ │ │ │ ├── TextareaButton.module.css │ │ │ │ ├── TextareaButton.tsx │ │ │ │ ├── TextareaButtons.module.css │ │ │ │ ├── TextareaButtons.tsx │ │ │ │ ├── TextareaContextMenu.tsx │ │ │ │ ├── TextareaInput.module.css │ │ │ │ ├── TextareaInputField.tsx │ │ │ │ └── TextareaPlusMenu.tsx │ │ │ ├── common/ │ │ │ │ ├── ExpiryFootnote.module.css │ │ │ │ ├── ExpiryFootnote.tsx │ │ │ │ ├── ExpiryFootnoteContextMenu.tsx │ │ │ │ ├── ExternalLink.module.css │ │ │ │ ├── ExternalLink.tsx │ │ │ │ ├── FriendSelector.module.css │ │ │ │ ├── FriendSelector.tsx │ │ │ │ ├── GroupDMAvatar.module.css │ │ │ │ ├── GroupDMAvatar.tsx │ │ │ │ ├── InstanceBadge.module.css │ │ │ │ ├── InstanceBadge.tsx │ │ │ │ ├── SpoilerOverlay.module.css │ │ │ │ ├── SpoilerOverlay.tsx │ │ │ │ └── custom_status_display/ │ │ │ │ ├── CustomStatusDisplay.module.css │ │ │ │ └── CustomStatusDisplay.tsx │ │ │ ├── debug/ │ │ │ │ ├── ChannelDebugModal.tsx │ │ │ │ ├── DebugModal.module.css │ │ │ │ ├── DebugModal.tsx │ │ │ │ ├── GuildDebugModal.tsx │ │ │ │ ├── GuildMemberDebugModal.tsx │ │ │ │ ├── MessageDebugModal.tsx │ │ │ │ └── UserDebugModal.tsx │ │ │ ├── embeds/ │ │ │ │ └── embed_card/ │ │ │ │ ├── EmbedCard.module.css │ │ │ │ ├── EmbedCard.tsx │ │ │ │ └── useEmbedSkeletonOverride.tsx │ │ │ ├── emojis/ │ │ │ │ ├── EmojiAttributionSubtext.tsx │ │ │ │ ├── EmojiInfoContent.module.css │ │ │ │ ├── EmojiInfoContent.tsx │ │ │ │ ├── EmojiListItem.module.css │ │ │ │ └── EmojiListItem.tsx │ │ │ ├── favorites/ │ │ │ │ ├── FavoritesWelcomeSection.module.css │ │ │ │ └── FavoritesWelcomeSection.tsx │ │ │ ├── form/ │ │ │ │ ├── ColorPickerField.module.css │ │ │ │ ├── ColorPickerField.tsx │ │ │ │ ├── DateTimePickerField.module.css │ │ │ │ ├── DateTimePickerField.tsx │ │ │ │ ├── Form.tsx │ │ │ │ ├── FormErrorText.module.css │ │ │ │ ├── FormErrorText.tsx │ │ │ │ ├── FormSurface.module.css │ │ │ │ ├── Input.module.css │ │ │ │ ├── Input.tsx │ │ │ │ ├── Select.module.css │ │ │ │ ├── Select.tsx │ │ │ │ ├── SelectBottomSheet.module.css │ │ │ │ ├── SelectBottomSheet.tsx │ │ │ │ ├── Switch.module.css │ │ │ │ ├── Switch.tsx │ │ │ │ ├── UsernameValidationRules.module.css │ │ │ │ └── UsernameValidationRules.tsx │ │ │ ├── guild/ │ │ │ │ ├── GuildBadge.module.css │ │ │ │ ├── GuildBadge.tsx │ │ │ │ ├── RoleManagement.module.css │ │ │ │ ├── RoleManagement.tsx │ │ │ │ ├── UploadDropZone.module.css │ │ │ │ ├── UploadDropZone.tsx │ │ │ │ ├── UploadSlotInfo.module.css │ │ │ │ └── UploadSlotInfo.tsx │ │ │ ├── icons/ │ │ │ │ ├── BlueskyIcon.tsx │ │ │ │ ├── FluxerIcon.tsx │ │ │ │ ├── FluxerSymbol.tsx │ │ │ │ ├── InboxIcon.tsx │ │ │ │ ├── NSFWIcon.tsx │ │ │ │ ├── UnverifiedConnectionIcon.tsx │ │ │ │ └── VerifiedConnectionIcon.tsx │ │ │ ├── invites/ │ │ │ │ ├── DisableInvitesButton.module.css │ │ │ │ ├── DisableInvitesButton.tsx │ │ │ │ ├── InviteDateToggle.module.css │ │ │ │ ├── InviteDateToggle.tsx │ │ │ │ ├── InviteListItem.module.css │ │ │ │ └── InviteListItem.tsx │ │ │ ├── keybinds/ │ │ │ │ ├── KeybindRecorder.module.css │ │ │ │ └── KeybindRecorder.tsx │ │ │ ├── layout/ │ │ │ │ ├── AppLayout.module.css │ │ │ │ ├── AppLayout.tsx │ │ │ │ ├── AuthLayout.module.css │ │ │ │ ├── AuthLayout.tsx │ │ │ │ ├── ChannelItem.module.css │ │ │ │ ├── ChannelItem.tsx │ │ │ │ ├── ChannelItemContent.tsx │ │ │ │ ├── ChannelItemIcon.module.css │ │ │ │ ├── ChannelItemIcon.tsx │ │ │ │ ├── ChannelItemSurface.module.css │ │ │ │ ├── ChannelListContent.module.css │ │ │ │ ├── ChannelListContent.tsx │ │ │ │ ├── ChannelListSkeleton.tsx │ │ │ │ ├── CollapsedCategoryVoiceParticipants.module.css │ │ │ │ ├── CollapsedCategoryVoiceParticipants.tsx │ │ │ │ ├── DndContext.tsx │ │ │ │ ├── DropIndicator.module.css │ │ │ │ ├── DropIndicator.tsx │ │ │ │ ├── FavoritesChannelListContent.module.css │ │ │ │ ├── FavoritesChannelListContent.tsx │ │ │ │ ├── FavoritesGuildHeader.module.css │ │ │ │ ├── FavoritesGuildHeader.tsx │ │ │ │ ├── FavoritesLayout.tsx │ │ │ │ ├── FrameContext.tsx │ │ │ │ ├── GenericChannelItem.tsx │ │ │ │ ├── GlobalOverlays.tsx │ │ │ │ ├── GroupedVoiceParticipant.module.css │ │ │ │ ├── GroupedVoiceParticipant.tsx │ │ │ │ ├── GuildDetachedBanner.module.css │ │ │ │ ├── GuildDetachedBanner.tsx │ │ │ │ ├── GuildHeader.module.css │ │ │ │ ├── GuildHeader.tsx │ │ │ │ ├── GuildHeaderShell.tsx │ │ │ │ ├── GuildLayout.module.css │ │ │ │ ├── GuildLayout.tsx │ │ │ │ ├── GuildNavbar.module.css │ │ │ │ ├── GuildNavbar.tsx │ │ │ │ ├── GuildNavbarSkeleton.module.css │ │ │ │ ├── GuildNavbarSkeleton.tsx │ │ │ │ ├── GuildSidebar.tsx │ │ │ │ ├── GuildsLayout.module.css │ │ │ │ ├── GuildsLayout.tsx │ │ │ │ ├── KeyboardModeListener.tsx │ │ │ │ ├── MobileBottomNav.module.css │ │ │ │ ├── MobileBottomNav.tsx │ │ │ │ ├── Nagbar.module.css │ │ │ │ ├── Nagbar.tsx │ │ │ │ ├── NagbarButton.module.css │ │ │ │ ├── NagbarButton.tsx │ │ │ │ ├── NagbarContent.module.css │ │ │ │ ├── NagbarContent.tsx │ │ │ │ ├── NativeDragRegion.module.css │ │ │ │ ├── NativeDragRegion.tsx │ │ │ │ ├── NativeTitlebar.module.css │ │ │ │ ├── NativeTitlebar.tsx │ │ │ │ ├── NativeTrafficLightsBackdrop.module.css │ │ │ │ ├── NativeTrafficLightsBackdrop.tsx │ │ │ │ ├── NullSpaceDropIndicator.module.css │ │ │ │ ├── NullSpaceDropIndicator.tsx │ │ │ │ ├── OutlineFrame.module.css │ │ │ │ ├── OutlineFrame.tsx │ │ │ │ ├── ScrollIndicatorOverlay.module.css │ │ │ │ ├── ScrollIndicatorOverlay.tsx │ │ │ │ ├── SplashScreen.module.css │ │ │ │ ├── SplashScreen.tsx │ │ │ │ ├── UserArea.module.css │ │ │ │ ├── UserArea.tsx │ │ │ │ ├── VoiceChannelUserCount.module.css │ │ │ │ ├── VoiceChannelUserCount.tsx │ │ │ │ ├── VoiceParticipantItem.module.css │ │ │ │ ├── VoiceParticipantItem.tsx │ │ │ │ ├── VoiceParticipantsList.module.css │ │ │ │ ├── VoiceParticipantsList.tsx │ │ │ │ ├── VoiceStateIcons.module.css │ │ │ │ ├── VoiceStateIcons.tsx │ │ │ │ ├── app_layout/ │ │ │ │ │ ├── AppLayoutHooks.tsx │ │ │ │ │ ├── AppLayoutTypes.tsx │ │ │ │ │ ├── NagbarContainer.module.css │ │ │ │ │ ├── NagbarContainer.tsx │ │ │ │ │ ├── TopNagbarContext.tsx │ │ │ │ │ └── nagbars/ │ │ │ │ │ ├── DesktopDownloadNagbar.module.css │ │ │ │ │ ├── DesktopDownloadNagbar.tsx │ │ │ │ │ ├── DesktopNotificationNagbar.module.css │ │ │ │ │ ├── DesktopNotificationNagbar.tsx │ │ │ │ │ ├── EmailVerificationNagbar.tsx │ │ │ │ │ ├── GiftInventoryNagbar.tsx │ │ │ │ │ ├── GuildMembershipCtaNagbar.tsx │ │ │ │ │ ├── MobileDownloadNagbar.module.css │ │ │ │ │ ├── MobileDownloadNagbar.tsx │ │ │ │ │ ├── PendingBulkDeletionNagbar.tsx │ │ │ │ │ ├── PremiumExpiredNagbar.tsx │ │ │ │ │ ├── PremiumGracePeriodNagbar.tsx │ │ │ │ │ ├── PremiumOnboardingNagbar.tsx │ │ │ │ │ ├── UnclaimedAccountNagbar.tsx │ │ │ │ │ └── VisionaryMfaNagbar.tsx │ │ │ │ ├── dnd/ │ │ │ │ │ └── DndDropPosition.tsx │ │ │ │ ├── guild_list/ │ │ │ │ │ ├── AddGuildButton.module.css │ │ │ │ │ ├── AddGuildButton.tsx │ │ │ │ │ ├── DiscoveryButton.module.css │ │ │ │ │ ├── DiscoveryButton.tsx │ │ │ │ │ ├── DownloadButton.module.css │ │ │ │ │ ├── DownloadButton.tsx │ │ │ │ │ ├── FavoritesButton.tsx │ │ │ │ │ ├── FluxerButton.tsx │ │ │ │ │ ├── GuildFolderItem.module.css │ │ │ │ │ ├── GuildFolderItem.tsx │ │ │ │ │ ├── GuildListDMItem.module.css │ │ │ │ │ ├── GuildListDMItem.tsx │ │ │ │ │ ├── GuildListItem.tsx │ │ │ │ │ ├── HelpButton.module.css │ │ │ │ │ ├── HelpButton.tsx │ │ │ │ │ └── VoiceBadge.tsx │ │ │ │ ├── types/ │ │ │ │ │ └── DndTypes.tsx │ │ │ │ └── utils/ │ │ │ │ ├── ChannelMoveOperation.test.tsx │ │ │ │ ├── ChannelMoveOperation.tsx │ │ │ │ ├── ChannelOrganization.tsx │ │ │ │ └── ChannelUnreadState.tsx │ │ │ ├── media_player/ │ │ │ │ ├── AudioPlayer.module.css │ │ │ │ ├── InlineAudioPlayer.module.css │ │ │ │ ├── MediaPlayButton.module.css │ │ │ │ ├── MediaPlaybackRate.module.css │ │ │ │ ├── MediaProgressBar.module.css │ │ │ │ ├── MediaTimeDisplay.module.css │ │ │ │ ├── MediaVerticalVolumeControl.module.css │ │ │ │ ├── MediaVolumeControl.module.css │ │ │ │ ├── VideoPlayer.module.css │ │ │ │ ├── components/ │ │ │ │ │ ├── AudioPlayer.tsx │ │ │ │ │ ├── InlineAudioPlayer.tsx │ │ │ │ │ ├── MediaFullscreenButton.tsx │ │ │ │ │ ├── MediaPipButton.tsx │ │ │ │ │ ├── MediaPlayButton.tsx │ │ │ │ │ ├── MediaPlaybackRate.tsx │ │ │ │ │ ├── MediaProgressBar.tsx │ │ │ │ │ ├── MediaTimeDisplay.tsx │ │ │ │ │ ├── MediaVerticalVolumeControl.tsx │ │ │ │ │ ├── MediaVolumeControl.tsx │ │ │ │ │ └── VideoPlayer.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── useControlsVisibility.tsx │ │ │ │ │ ├── useMediaFullscreen.tsx │ │ │ │ │ ├── useMediaKeyboard.tsx │ │ │ │ │ ├── useMediaPiP.tsx │ │ │ │ │ ├── useMediaPlayer.tsx │ │ │ │ │ ├── useMediaProgress.tsx │ │ │ │ │ └── useMediaVolume.tsx │ │ │ │ └── utils/ │ │ │ │ └── MediaConstants.tsx │ │ │ ├── modals/ │ │ │ │ ├── AccountDeleteModal.module.css │ │ │ │ ├── AccountDeleteModal.tsx │ │ │ │ ├── AccountDisableModal.module.css │ │ │ │ ├── AccountDisableModal.tsx │ │ │ │ ├── AddConnectionModal.module.css │ │ │ │ ├── AddConnectionModal.tsx │ │ │ │ ├── AddFavoriteChannelModal.module.css │ │ │ │ ├── AddFavoriteChannelModal.tsx │ │ │ │ ├── AddFavoriteMemeModal.tsx │ │ │ │ ├── AddFriendSheet.module.css │ │ │ │ ├── AddFriendSheet.tsx │ │ │ │ ├── AddFriendsToGroupModal.tsx │ │ │ │ ├── AddGuildModal.module.css │ │ │ │ ├── AddGuildModal.tsx │ │ │ │ ├── AddGuildStickerModal.module.css │ │ │ │ ├── AddGuildStickerModal.tsx │ │ │ │ ├── AssetCropModal.tsx │ │ │ │ ├── AttachmentEditModal.module.css │ │ │ │ ├── AttachmentEditModal.tsx │ │ │ │ ├── AudioPlaybackPermissionModal.tsx │ │ │ │ ├── BackgroundImageGalleryModal.module.css │ │ │ │ ├── BackgroundImageGalleryModal.tsx │ │ │ │ ├── BackupCodesModal.module.css │ │ │ │ ├── BackupCodesModal.tsx │ │ │ │ ├── BackupCodesRegenerateModal.tsx │ │ │ │ ├── BackupCodesViewModal.tsx │ │ │ │ ├── BanDetailsModal.module.css │ │ │ │ ├── BanDetailsModal.tsx │ │ │ │ ├── BanMemberModal.module.css │ │ │ │ ├── BanMemberModal.tsx │ │ │ │ ├── BaseChangeNicknameModal.module.css │ │ │ │ ├── BaseChangeNicknameModal.tsx │ │ │ │ ├── BookmarksBottomSheet.module.css │ │ │ │ ├── BookmarksBottomSheet.tsx │ │ │ │ ├── CameraPreviewModal.module.css │ │ │ │ ├── CameraPreviewModal.tsx │ │ │ │ ├── CaptchaModal.module.css │ │ │ │ ├── CaptchaModal.tsx │ │ │ │ ├── CategoryCreateModal.tsx │ │ │ │ ├── ChangeFriendNicknameModal.tsx │ │ │ │ ├── ChangeGroupDMNicknameModal.tsx │ │ │ │ ├── ChangeNicknameModal.tsx │ │ │ │ ├── ChannelCreateModal.module.css │ │ │ │ ├── ChannelCreateModal.tsx │ │ │ │ ├── ChannelDeleteModal.tsx │ │ │ │ ├── ChannelSettingsModal.tsx │ │ │ │ ├── ChannelTopicModal.module.css │ │ │ │ ├── ChannelTopicModal.tsx │ │ │ │ ├── ClaimAccountModal.module.css │ │ │ │ ├── ClaimAccountModal.tsx │ │ │ │ ├── ConfirmModal.module.css │ │ │ │ ├── ConfirmModal.tsx │ │ │ │ ├── CreateDMModal.tsx │ │ │ │ ├── CreateFavoriteCategoryModal.tsx │ │ │ │ ├── CreatePackModal.module.css │ │ │ │ ├── CreatePackModal.tsx │ │ │ │ ├── CustomStatusBottomSheet.module.css │ │ │ │ ├── CustomStatusBottomSheet.tsx │ │ │ │ ├── CustomStatusModal.module.css │ │ │ │ ├── CustomStatusModal.tsx │ │ │ │ ├── DeviceRevokeModal.tsx │ │ │ │ ├── DisablePiPConfirmModal.module.css │ │ │ │ ├── DisablePiPConfirmModal.tsx │ │ │ │ ├── DiscoveryModal.module.css │ │ │ │ ├── DiscoveryModal.tsx │ │ │ │ ├── DuplicateGroupConfirmModal.module.css │ │ │ │ ├── DuplicateGroupConfirmModal.tsx │ │ │ │ ├── EditAltTextModal.tsx │ │ │ │ ├── EditConnectionModal.tsx │ │ │ │ ├── EditFavoriteMemeModal.module.css │ │ │ │ ├── EditFavoriteMemeModal.tsx │ │ │ │ ├── EditGroupBottomSheet.module.css │ │ │ │ ├── EditGroupBottomSheet.tsx │ │ │ │ ├── EditGroupModal.module.css │ │ │ │ ├── EditGroupModal.tsx │ │ │ │ ├── EditGuildStickerModal.module.css │ │ │ │ ├── EditGuildStickerModal.tsx │ │ │ │ ├── EditPackModal.tsx │ │ │ │ ├── EmailChangeModal.module.css │ │ │ │ ├── EmailChangeModal.tsx │ │ │ │ ├── EmojiUploadModal.module.css │ │ │ │ ├── EmojiUploadModal.tsx │ │ │ │ ├── ExpressionPickerSheet.module.css │ │ │ │ ├── ExpressionPickerSheet.tsx │ │ │ │ ├── ExternalLinkWarningModal.module.css │ │ │ │ ├── ExternalLinkWarningModal.tsx │ │ │ │ ├── FluxerTagChangeModal.module.css │ │ │ │ ├── FluxerTagChangeModal.tsx │ │ │ │ ├── ForwardModal.module.css │ │ │ │ ├── ForwardModal.tsx │ │ │ │ ├── GiftAcceptModal.module.css │ │ │ │ ├── GiftAcceptModal.tsx │ │ │ │ ├── GroupInvitesBottomSheet.module.css │ │ │ │ ├── GroupInvitesBottomSheet.tsx │ │ │ │ ├── GroupInvitesModal.module.css │ │ │ │ ├── GroupInvitesModal.tsx │ │ │ │ ├── GuildDeleteModal.tsx │ │ │ │ ├── GuildFolderSettingsModal.tsx │ │ │ │ ├── GuildNotificationSettingsModal.module.css │ │ │ │ ├── GuildNotificationSettingsModal.tsx │ │ │ │ ├── GuildOwnershipWarningModal.module.css │ │ │ │ ├── GuildOwnershipWarningModal.tsx │ │ │ │ ├── GuildPrivacySettingsModal.module.css │ │ │ │ ├── GuildPrivacySettingsModal.tsx │ │ │ │ ├── GuildSettingsModal.module.css │ │ │ │ ├── GuildSettingsModal.tsx │ │ │ │ ├── HideOwnCameraConfirmModal.module.css │ │ │ │ ├── HideOwnCameraConfirmModal.tsx │ │ │ │ ├── HideOwnScreenShareConfirmModal.tsx │ │ │ │ ├── IARModal.module.css │ │ │ │ ├── IARModal.tsx │ │ │ │ ├── ImageCropModal.module.css │ │ │ │ ├── ImageCropModal.tsx │ │ │ │ ├── InputMonitoringCTAModal.tsx │ │ │ │ ├── InviteAcceptModal.module.css │ │ │ │ ├── InviteAcceptModal.tsx │ │ │ │ ├── InviteAcceptModalPreview.tsx │ │ │ │ ├── InviteModal.module.css │ │ │ │ ├── InviteModal.tsx │ │ │ │ ├── InvitePagePreviewModal.module.css │ │ │ │ ├── InvitePagePreviewModal.tsx │ │ │ │ ├── KeyboardModeIntroModal.module.css │ │ │ │ ├── KeyboardModeIntroModal.tsx │ │ │ │ ├── KickMemberModal.tsx │ │ │ │ ├── MediaModal.module.css │ │ │ │ ├── MediaModal.tsx │ │ │ │ ├── MediaViewerModal.module.css │ │ │ │ ├── MediaViewerModal.tsx │ │ │ │ ├── MessageHistoryThresholdModal.tsx │ │ │ │ ├── MessageReactionsModal.module.css │ │ │ │ ├── MessageReactionsModal.tsx │ │ │ │ ├── MfaTotpDisableModal.tsx │ │ │ │ ├── MfaTotpEnableModal.module.css │ │ │ │ ├── MfaTotpEnableModal.tsx │ │ │ │ ├── MobileVideoViewer.module.css │ │ │ │ ├── MobileVideoViewer.tsx │ │ │ │ ├── Modal.module.css │ │ │ │ ├── Modal.tsx │ │ │ │ ├── Modals.module.css │ │ │ │ ├── Modals.tsx │ │ │ │ ├── NoteEditSheet.module.css │ │ │ │ ├── NoteEditSheet.tsx │ │ │ │ ├── PackInviteModal.module.css │ │ │ │ ├── PackInviteModal.tsx │ │ │ │ ├── PasskeyNameModal.tsx │ │ │ │ ├── PasswordChangeModal.module.css │ │ │ │ ├── PasswordChangeModal.tsx │ │ │ │ ├── PhoneAddModal.module.css │ │ │ │ ├── PhoneAddModal.tsx │ │ │ │ ├── PremiumModal.module.css │ │ │ │ ├── PremiumModal.tsx │ │ │ │ ├── RemoveTimeoutModal.module.css │ │ │ │ ├── RemoveTimeoutModal.tsx │ │ │ │ ├── RenameChannelModal.tsx │ │ │ │ ├── RequiredActionModal.module.css │ │ │ │ ├── RequiredActionModal.tsx │ │ │ │ ├── ScheduleMessageModal.tsx │ │ │ │ ├── ScreenShareSettingsModal.module.css │ │ │ │ ├── ScreenShareSettingsModal.tsx │ │ │ │ ├── ScreenShareSourceModal.module.css │ │ │ │ ├── ScreenShareSourceModal.tsx │ │ │ │ ├── ShareThemeModal.module.css │ │ │ │ ├── ShareThemeModal.tsx │ │ │ │ ├── StatusChangeBottomSheet.module.css │ │ │ │ ├── StatusChangeBottomSheet.tsx │ │ │ │ ├── SudoVerificationModal.module.css │ │ │ │ ├── SudoVerificationModal.tsx │ │ │ │ ├── ThemeAcceptModal.module.css │ │ │ │ ├── ThemeAcceptModal.tsx │ │ │ │ ├── TimeoutMemberModal.module.css │ │ │ │ ├── TimeoutMemberModal.tsx │ │ │ │ ├── TimeoutMemberOptions.tsx │ │ │ │ ├── TimeoutMemberSheet.module.css │ │ │ │ ├── TimeoutMemberSheet.tsx │ │ │ │ ├── TransferOwnershipModal.module.css │ │ │ │ ├── TransferOwnershipModal.tsx │ │ │ │ ├── UploadDropModal.module.css │ │ │ │ ├── UploadDropModal.tsx │ │ │ │ ├── UserProfileActionsSheet.module.css │ │ │ │ ├── UserProfileActionsSheet.tsx │ │ │ │ ├── UserProfileMobileSheet.module.css │ │ │ │ ├── UserProfileMobileSheet.tsx │ │ │ │ ├── UserProfileModal.module.css │ │ │ │ ├── UserProfileModal.tsx │ │ │ │ ├── UserProfileUtils.tsx │ │ │ │ ├── UserSettingsModal.module.css │ │ │ │ ├── UserSettingsModal.tsx │ │ │ │ ├── channel_tabs/ │ │ │ │ │ ├── ChannelInvitesTab.module.css │ │ │ │ │ ├── ChannelInvitesTab.tsx │ │ │ │ │ ├── ChannelOverviewTab.module.css │ │ │ │ │ ├── ChannelOverviewTab.tsx │ │ │ │ │ ├── ChannelPermissionsTab.module.css │ │ │ │ │ ├── ChannelPermissionsTab.tsx │ │ │ │ │ ├── ChannelWebhooksTab.module.css │ │ │ │ │ └── ChannelWebhooksTab.tsx │ │ │ │ ├── components/ │ │ │ │ │ ├── AllSettingsRenderer.module.css │ │ │ │ │ ├── AllSettingsRenderer.tsx │ │ │ │ │ ├── ClientInfo.module.css │ │ │ │ │ ├── ClientInfo.tsx │ │ │ │ │ ├── ComparisonCheckRow.module.css │ │ │ │ │ ├── ComparisonCheckRow.tsx │ │ │ │ │ ├── ComparisonRow.module.css │ │ │ │ │ ├── ComparisonRow.tsx │ │ │ │ │ ├── DesktopChannelSettingsView.tsx │ │ │ │ │ ├── DesktopGuildSettingsView.tsx │ │ │ │ │ ├── DesktopSettingsView.module.css │ │ │ │ │ ├── DesktopSettingsView.tsx │ │ │ │ │ ├── EmailVerificationAlert.tsx │ │ │ │ │ ├── FeatureComparisonTable.module.css │ │ │ │ │ ├── FeatureComparisonTable.tsx │ │ │ │ │ ├── LogoutModal.tsx │ │ │ │ │ ├── MobileChannelSettingsView.tsx │ │ │ │ │ ├── MobileGuildSettingsView.module.css │ │ │ │ │ ├── MobileGuildSettingsView.tsx │ │ │ │ │ ├── MobileSettingsView.module.css │ │ │ │ │ ├── MobileSettingsView.tsx │ │ │ │ │ ├── PerksButton.module.css │ │ │ │ │ ├── PerksButton.tsx │ │ │ │ │ ├── PlutoniumContent.module.css │ │ │ │ │ ├── PlutoniumContent.tsx │ │ │ │ │ ├── PricingCard.module.css │ │ │ │ │ ├── PricingCard.tsx │ │ │ │ │ ├── PricingGrid.module.css │ │ │ │ │ ├── PurchaseDisclaimer.module.css │ │ │ │ │ ├── PurchaseDisclaimer.tsx │ │ │ │ │ ├── SettingsModalHeader.module.css │ │ │ │ │ ├── SettingsModalHeader.tsx │ │ │ │ │ ├── SettingsSearch.module.css │ │ │ │ │ ├── SettingsSearch.tsx │ │ │ │ │ ├── SettingsSearchHighlight.css │ │ │ │ │ ├── Slate.module.css │ │ │ │ │ ├── Slate.tsx │ │ │ │ │ ├── ToggleButton.module.css │ │ │ │ │ ├── ToggleButton.tsx │ │ │ │ │ ├── UnclaimedAccountAlert.tsx │ │ │ │ │ └── plutonium/ │ │ │ │ │ ├── BottomCTASection.module.css │ │ │ │ │ ├── BottomCTASection.tsx │ │ │ │ │ ├── GiftInventoryBanner.module.css │ │ │ │ │ ├── GiftInventoryBanner.tsx │ │ │ │ │ ├── GiftSection.module.css │ │ │ │ │ ├── GiftSection.tsx │ │ │ │ │ ├── PlutoniumUpsellBanner.tsx │ │ │ │ │ ├── PricingSection.module.css │ │ │ │ │ ├── PricingSection.tsx │ │ │ │ │ ├── PurchaseDisabledWrapper.tsx │ │ │ │ │ ├── PurchaseHistorySection.module.css │ │ │ │ │ ├── PurchaseHistorySection.tsx │ │ │ │ │ ├── SectionHeader.module.css │ │ │ │ │ ├── SectionHeader.tsx │ │ │ │ │ ├── SubscriptionCard.module.css │ │ │ │ │ ├── SubscriptionCard.tsx │ │ │ │ │ └── hooks/ │ │ │ │ │ ├── useCheckoutActions.tsx │ │ │ │ │ ├── useCommunityActions.tsx │ │ │ │ │ ├── usePremiumData.tsx │ │ │ │ │ ├── useSubscriptionActions.tsx │ │ │ │ │ └── useSubscriptionStatus.tsx │ │ │ │ ├── discovery/ │ │ │ │ │ ├── DiscoveryGuildCard.module.css │ │ │ │ │ └── DiscoveryGuildCard.tsx │ │ │ │ ├── guild_tabs/ │ │ │ │ │ ├── BannedUserActionsSheet.tsx │ │ │ │ │ ├── GuildAuditLogTab.Components.tsx │ │ │ │ │ ├── GuildAuditLogTab.Constants.tsx │ │ │ │ │ ├── GuildAuditLogTab.Renderers.tsx │ │ │ │ │ ├── GuildAuditLogTab.Utils.tsx │ │ │ │ │ ├── GuildAuditLogTab.module.css │ │ │ │ │ ├── GuildAuditLogTab.tsx │ │ │ │ │ ├── GuildBansTab.tsx │ │ │ │ │ ├── GuildDiscoveryTab.module.css │ │ │ │ │ ├── GuildDiscoveryTab.tsx │ │ │ │ │ ├── GuildEmojiTab.module.css │ │ │ │ │ ├── GuildEmojiTab.tsx │ │ │ │ │ ├── GuildInvitesTab.module.css │ │ │ │ │ ├── GuildInvitesTab.tsx │ │ │ │ │ ├── GuildMemberActionsSheet.module.css │ │ │ │ │ ├── GuildMemberActionsSheet.tsx │ │ │ │ │ ├── GuildMembersDateRangeModal.tsx │ │ │ │ │ ├── GuildModerationTab.module.css │ │ │ │ │ ├── GuildModerationTab.tsx │ │ │ │ │ ├── GuildRolesTab.module.css │ │ │ │ │ ├── GuildRolesTab.tsx │ │ │ │ │ ├── GuildStickersTab.module.css │ │ │ │ │ ├── GuildStickersTab.tsx │ │ │ │ │ ├── GuildVanityURLTab.module.css │ │ │ │ │ ├── GuildVanityURLTab.tsx │ │ │ │ │ ├── GuildWebhooksTab.module.css │ │ │ │ │ ├── GuildWebhooksTab.tsx │ │ │ │ │ ├── MemberListStyles.module.css │ │ │ │ │ ├── RoleMoveOperation.tsx │ │ │ │ │ ├── UserListItem.tsx │ │ │ │ │ └── guild_overview_tab/ │ │ │ │ │ ├── GuildOverviewTab.module.css │ │ │ │ │ ├── GuildOverviewTypes.tsx │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── SettingsSection.tsx │ │ │ │ │ ├── fields/ │ │ │ │ │ │ ├── GuildBannerUploadField.tsx │ │ │ │ │ │ ├── GuildEmbedSplashUploadField.tsx │ │ │ │ │ │ ├── GuildIconUploadField.tsx │ │ │ │ │ │ ├── GuildInviteSplashSettingsField.tsx │ │ │ │ │ │ └── GuildInviteSplashUploadField.tsx │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ └── useGuildImageAssetField.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── sections/ │ │ │ │ │ │ ├── BrandingSection.tsx │ │ │ │ │ │ ├── DefaultNotificationsSection.tsx │ │ │ │ │ │ ├── IdleSettingsSection.tsx │ │ │ │ │ │ ├── MessageHistoryCutoffSection.tsx │ │ │ │ │ │ ├── MessageHistoryThresholdContent.tsx │ │ │ │ │ │ ├── SystemWelcomeSection.tsx │ │ │ │ │ │ └── TextChannelNamesSection.tsx │ │ │ │ │ └── utils/ │ │ │ │ │ └── ImageAsset.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── ScrollSpyContext.tsx │ │ │ │ │ ├── useMobileNavigation.tsx │ │ │ │ │ ├── useScrollSpy.tsx │ │ │ │ │ ├── useSettingsContentKey.tsx │ │ │ │ │ └── useUnsavedChangesFlash.tsx │ │ │ │ ├── meme_form/ │ │ │ │ │ ├── MemeFormFields.module.css │ │ │ │ │ └── MemeFormFields.tsx │ │ │ │ ├── shared/ │ │ │ │ │ ├── AddOverridePopout.module.css │ │ │ │ │ ├── AddOverridePopout.tsx │ │ │ │ │ ├── CopyLinkSection.module.css │ │ │ │ │ ├── CopyLinkSection.tsx │ │ │ │ │ ├── EmptySlate.module.css │ │ │ │ │ ├── EmptySlate.tsx │ │ │ │ │ ├── ForwardChannelSelection.tsx │ │ │ │ │ ├── GuildSelectComponents.tsx │ │ │ │ │ ├── MobileSettingsComponents.module.css │ │ │ │ │ ├── MobileSettingsComponents.tsx │ │ │ │ │ ├── PermissionComponents.module.css │ │ │ │ │ ├── PermissionComponents.tsx │ │ │ │ │ ├── RecipientList.module.css │ │ │ │ │ ├── RecipientList.tsx │ │ │ │ │ ├── SelectorModalStyles.module.css │ │ │ │ │ ├── SettingsModalLayout.module.css │ │ │ │ │ ├── SettingsModalLayout.tsx │ │ │ │ │ ├── SettingsSection.module.css │ │ │ │ │ ├── SettingsSection.tsx │ │ │ │ │ ├── SettingsTabLayout.module.css │ │ │ │ │ ├── SettingsTabLayout.tsx │ │ │ │ │ ├── StatusSlate.module.css │ │ │ │ │ └── StatusSlate.tsx │ │ │ │ ├── sticker_form/ │ │ │ │ │ ├── StickerFormFields.module.css │ │ │ │ │ ├── StickerFormFields.tsx │ │ │ │ │ ├── StickerPreview.module.css │ │ │ │ │ └── StickerPreview.tsx │ │ │ │ ├── tabs/ │ │ │ │ │ ├── AccessibilityTab.module.css │ │ │ │ │ ├── AccessibilityTab.tsx │ │ │ │ │ ├── AccountSecurityTab.module.css │ │ │ │ │ ├── AccountSecurityTab.tsx │ │ │ │ │ ├── AdvancedTab.tsx │ │ │ │ │ ├── AppearanceTab.module.css │ │ │ │ │ ├── AppearanceTab.tsx │ │ │ │ │ ├── AuthorizedAppsTab.module.css │ │ │ │ │ ├── AuthorizedAppsTab.tsx │ │ │ │ │ ├── BlockedUsersTab.module.css │ │ │ │ │ ├── BlockedUsersTab.tsx │ │ │ │ │ ├── ChatSettingsTab.module.css │ │ │ │ │ ├── ChatSettingsTab.tsx │ │ │ │ │ ├── DevicesTab.module.css │ │ │ │ │ ├── DevicesTab.tsx │ │ │ │ │ ├── ExpressionPacksTab.module.css │ │ │ │ │ ├── ExpressionPacksTab.tsx │ │ │ │ │ ├── GiftInventoryTab.module.css │ │ │ │ │ ├── GiftInventoryTab.tsx │ │ │ │ │ ├── KeybindsTab.module.css │ │ │ │ │ ├── KeybindsTab.tsx │ │ │ │ │ ├── LanguageTab.module.css │ │ │ │ │ ├── LanguageTab.tsx │ │ │ │ │ ├── LimitsConfigTab.module.css │ │ │ │ │ ├── LimitsConfigTab.tsx │ │ │ │ │ ├── LinkedAccountsTab.module.css │ │ │ │ │ ├── LinkedAccountsTab.tsx │ │ │ │ │ ├── MyProfileTab.module.css │ │ │ │ │ ├── MyProfileTab.tsx │ │ │ │ │ ├── NotificationsTab.tsx │ │ │ │ │ ├── PlutoniumTab.tsx │ │ │ │ │ ├── PrivacySafetyTab.module.css │ │ │ │ │ ├── PrivacySafetyTab.tsx │ │ │ │ │ ├── VideoTab.module.css │ │ │ │ │ ├── VideoTab.tsx │ │ │ │ │ ├── VoiceTab.module.css │ │ │ │ │ ├── VoiceTab.tsx │ │ │ │ │ ├── VoiceVideoTab.module.css │ │ │ │ │ ├── VoiceVideoTab.tsx │ │ │ │ │ ├── accessibility_tab/ │ │ │ │ │ │ ├── AnimationTab.module.css │ │ │ │ │ │ ├── AnimationTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── KeyboardTab.tsx │ │ │ │ │ │ ├── MotionTab.tsx │ │ │ │ │ │ ├── VisualTab.module.css │ │ │ │ │ │ └── VisualTab.tsx │ │ │ │ │ ├── account_security_tab/ │ │ │ │ │ │ ├── AccountTab.module.css │ │ │ │ │ │ ├── AccountTab.tsx │ │ │ │ │ │ ├── DangerZoneTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── SecurityTab.module.css │ │ │ │ │ │ └── SecurityTab.tsx │ │ │ │ │ ├── appearance_tab/ │ │ │ │ │ │ ├── ActiveNowTab.tsx │ │ │ │ │ │ ├── ChannelListTab.tsx │ │ │ │ │ │ ├── FavoritesTab.tsx │ │ │ │ │ │ ├── HdrTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── InterfaceTab.module.css │ │ │ │ │ │ ├── InterfaceTab.tsx │ │ │ │ │ │ ├── MessagesTab.module.css │ │ │ │ │ │ ├── MessagesTab.tsx │ │ │ │ │ │ ├── ScalingTab.tsx │ │ │ │ │ │ ├── ThemeTab.module.css │ │ │ │ │ │ └── ThemeTab.tsx │ │ │ │ │ ├── applications_tab/ │ │ │ │ │ │ ├── ApplicationCreateModal.tsx │ │ │ │ │ │ ├── ApplicationDetail.tsx │ │ │ │ │ │ ├── ApplicationsList.tsx │ │ │ │ │ │ ├── ApplicationsTab.module.css │ │ │ │ │ │ ├── ApplicationsTabStore.tsx │ │ │ │ │ │ ├── application_detail/ │ │ │ │ │ │ │ ├── ApplicationDetail.module.css │ │ │ │ │ │ │ ├── ApplicationDetailTypes.tsx │ │ │ │ │ │ │ ├── ApplicationHeader.tsx │ │ │ │ │ │ │ ├── ApplicationInfoSection.tsx │ │ │ │ │ │ │ ├── BotProfileSection.tsx │ │ │ │ │ │ │ ├── OAuthBuilderSection.tsx │ │ │ │ │ │ │ ├── SecretsSection.tsx │ │ │ │ │ │ │ └── SectionCard.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── chat_settings_tab/ │ │ │ │ │ │ ├── DisplayTab.module.css │ │ │ │ │ │ ├── DisplayTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── InputTab.module.css │ │ │ │ │ │ ├── InputTab.tsx │ │ │ │ │ │ ├── InteractionTab.module.css │ │ │ │ │ │ ├── InteractionTab.tsx │ │ │ │ │ │ ├── LinksTab.tsx │ │ │ │ │ │ ├── MediaTab.module.css │ │ │ │ │ │ ├── MediaTab.tsx │ │ │ │ │ │ └── SidebarTab.tsx │ │ │ │ │ ├── component_gallery_tab/ │ │ │ │ │ │ ├── ButtonsTab.module.css │ │ │ │ │ │ ├── ButtonsTab.tsx │ │ │ │ │ │ ├── ComponentGalleryTabSubsectionTitle.tsx │ │ │ │ │ │ ├── IndicatorsTab.module.css │ │ │ │ │ │ ├── IndicatorsTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── InputsTab.module.css │ │ │ │ │ │ ├── InputsTab.tsx │ │ │ │ │ │ ├── MarkdownTab.module.css │ │ │ │ │ │ ├── MarkdownTab.tsx │ │ │ │ │ │ ├── MessagesTab.module.css │ │ │ │ │ │ ├── MessagesTab.tsx │ │ │ │ │ │ ├── OverlaysTab.module.css │ │ │ │ │ │ ├── OverlaysTab.tsx │ │ │ │ │ │ ├── SelectionsTab.module.css │ │ │ │ │ │ ├── SelectionsTab.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── shared.module.css │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── EntranceSoundSection.module.css │ │ │ │ │ │ ├── EntranceSoundSection.tsx │ │ │ │ │ │ ├── InputMonitoringSection.tsx │ │ │ │ │ │ ├── MicTestSection.module.css │ │ │ │ │ │ └── MicTestSection.tsx │ │ │ │ │ ├── developer_options_tab/ │ │ │ │ │ │ ├── AccountPremiumTab.module.css │ │ │ │ │ │ ├── AccountPremiumTab.tsx │ │ │ │ │ │ ├── DeveloperOptionsToggleGroups.tsx │ │ │ │ │ │ ├── GeneralTab.module.css │ │ │ │ │ │ ├── GeneralTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── MockingTab.module.css │ │ │ │ │ │ ├── MockingTab.tsx │ │ │ │ │ │ ├── NagbarControls.tsx │ │ │ │ │ │ ├── NagbarsTab.module.css │ │ │ │ │ │ ├── NagbarsTab.tsx │ │ │ │ │ │ ├── PremiumScenarioOptions.tsx │ │ │ │ │ │ ├── ToolsTab.module.css │ │ │ │ │ │ ├── ToolsTab.tsx │ │ │ │ │ │ ├── TypographyTab.module.css │ │ │ │ │ │ ├── TypographyTab.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ ├── useEntranceSound.tsx │ │ │ │ │ │ ├── useMediaPermission.tsx │ │ │ │ │ │ └── useMicTest.tsx │ │ │ │ │ ├── my_profile_tab/ │ │ │ │ │ │ ├── AccentColorPicker.module.css │ │ │ │ │ │ ├── AccentColorPicker.tsx │ │ │ │ │ │ ├── AvatarUploader.module.css │ │ │ │ │ │ ├── AvatarUploader.tsx │ │ │ │ │ │ ├── BannerUploader.module.css │ │ │ │ │ │ ├── BannerUploader.tsx │ │ │ │ │ │ ├── BioEditor.module.css │ │ │ │ │ │ ├── BioEditor.tsx │ │ │ │ │ │ ├── PerGuildPremiumUpsell.tsx │ │ │ │ │ │ ├── PremiumBadgeSettings.module.css │ │ │ │ │ │ ├── PremiumBadgeSettings.tsx │ │ │ │ │ │ ├── ProfileTypeSelector.module.css │ │ │ │ │ │ ├── ProfileTypeSelector.tsx │ │ │ │ │ │ ├── UsernameSection.module.css │ │ │ │ │ │ └── UsernameSection.tsx │ │ │ │ │ ├── notifications_tab/ │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ ├── Inline.tsx │ │ │ │ │ │ ├── Notifications.module.css │ │ │ │ │ │ ├── Notifications.tsx │ │ │ │ │ │ ├── PushSettings.module.css │ │ │ │ │ │ ├── PushSettings.tsx │ │ │ │ │ │ ├── Sounds.module.css │ │ │ │ │ │ ├── Sounds.tsx │ │ │ │ │ │ ├── TextToSpeech.module.css │ │ │ │ │ │ ├── TextToSpeech.tsx │ │ │ │ │ │ └── useSoundSettings.tsx │ │ │ │ │ ├── privacy_safety_tab/ │ │ │ │ │ │ ├── CommunicationTab.module.css │ │ │ │ │ │ ├── CommunicationTab.tsx │ │ │ │ │ │ ├── ConnectionsTab.module.css │ │ │ │ │ │ ├── ConnectionsTab.tsx │ │ │ │ │ │ ├── DataDeletionTab.module.css │ │ │ │ │ │ ├── DataDeletionTab.tsx │ │ │ │ │ │ ├── DataExportTab.tsx │ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ │ └── Inline.tsx │ │ │ │ │ └── voice_video_tab/ │ │ │ │ │ ├── Inline.module.css │ │ │ │ │ └── Inline.tsx │ │ │ │ └── utils/ │ │ │ │ ├── AppZoomLevelUtils.tsx │ │ │ │ ├── ChannelSettingsConstants.tsx │ │ │ │ ├── DesktopSettingsTabs.tsx │ │ │ │ ├── GuildSettingsConstants.tsx │ │ │ │ ├── SettingsConstants.tsx │ │ │ │ ├── SettingsSearchIndex.tsx │ │ │ │ ├── SettingsSectionRegistry.tsx │ │ │ │ └── SettingsTabFilters.tsx │ │ │ ├── pages/ │ │ │ │ ├── AuthorizeIPPage.module.css │ │ │ │ ├── AuthorizeIPPage.tsx │ │ │ │ ├── ConnectionCallbackPage.module.css │ │ │ │ ├── ConnectionCallbackPage.tsx │ │ │ │ ├── EmailRevertPage.tsx │ │ │ │ ├── ForgotPasswordPage.module.css │ │ │ │ ├── ForgotPasswordPage.tsx │ │ │ │ ├── GiftLoginPage.tsx │ │ │ │ ├── GiftRegisterPage.tsx │ │ │ │ ├── InviteLoginPage.tsx │ │ │ │ ├── InviteRegisterPage.tsx │ │ │ │ ├── LoginPage.module.css │ │ │ │ ├── LoginPage.tsx │ │ │ │ ├── MessageListPage.module.css │ │ │ │ ├── MessageListPage.tsx │ │ │ │ ├── NotFoundPage.module.css │ │ │ │ ├── NotFoundPage.tsx │ │ │ │ ├── NotificationsPage.module.css │ │ │ │ ├── NotificationsPage.tsx │ │ │ │ ├── OAuthAuthorizePage.module.css │ │ │ │ ├── OAuthAuthorizePage.tsx │ │ │ │ ├── PremiumCallbackPage.module.css │ │ │ │ ├── PremiumCallbackPage.tsx │ │ │ │ ├── RecentMentionsPage.module.css │ │ │ │ ├── RecentMentionsPage.tsx │ │ │ │ ├── RegisterPage.tsx │ │ │ │ ├── ReportPage.module.css │ │ │ │ ├── ReportPage.tsx │ │ │ │ ├── ResetPasswordPage.module.css │ │ │ │ ├── ResetPasswordPage.tsx │ │ │ │ ├── SavedMessagesPage.module.css │ │ │ │ ├── SavedMessagesPage.tsx │ │ │ │ ├── SsoCallbackPage.tsx │ │ │ │ ├── ThemeLoginPage.tsx │ │ │ │ ├── ThemeRegisterPage.tsx │ │ │ │ ├── VerifyEmailPage.module.css │ │ │ │ ├── VerifyEmailPage.tsx │ │ │ │ ├── YouPage.module.css │ │ │ │ ├── YouPage.tsx │ │ │ │ └── report/ │ │ │ │ ├── OptionDescriptors.tsx │ │ │ │ ├── ReportBreadcrumbs.tsx │ │ │ │ ├── ReportStepComplete.tsx │ │ │ │ ├── ReportStepDetails.tsx │ │ │ │ ├── ReportStepEmail.tsx │ │ │ │ ├── ReportStepSelection.tsx │ │ │ │ ├── ReportStepVerification.tsx │ │ │ │ ├── ReportTypes.tsx │ │ │ │ ├── State.tsx │ │ │ │ └── Validators.tsx │ │ │ ├── panels/ │ │ │ │ ├── ExpressionPickerPanel.tsx │ │ │ │ └── panels/ │ │ │ │ └── GuildExpressionPickerPanel.tsx │ │ │ ├── popouts/ │ │ │ │ ├── ChannelPinsPopout.module.css │ │ │ │ ├── ChannelPinsPopout.tsx │ │ │ │ ├── ColorPickerPopout.module.css │ │ │ │ ├── ColorPickerPopout.tsx │ │ │ │ ├── EmojiPickerPopout.tsx │ │ │ │ ├── ExpressionPickerPopout.module.css │ │ │ │ ├── ExpressionPickerPopout.tsx │ │ │ │ ├── FavoritesGuildHeaderPopout.tsx │ │ │ │ ├── GuildHeaderPopout.module.css │ │ │ │ ├── GuildHeaderPopout.tsx │ │ │ │ ├── GuildIcon.module.css │ │ │ │ ├── GuildIcon.tsx │ │ │ │ ├── InboxMessageHeader.module.css │ │ │ │ ├── InboxMessageHeader.tsx │ │ │ │ ├── InboxPopout.module.css │ │ │ │ ├── InboxPopout.tsx │ │ │ │ ├── ReactionTooltip.module.css │ │ │ │ ├── ReactionTooltip.tsx │ │ │ │ ├── RecentMentionsContent.module.css │ │ │ │ ├── RecentMentionsContent.tsx │ │ │ │ ├── SavedMessagesContent.module.css │ │ │ │ ├── SavedMessagesContent.tsx │ │ │ │ ├── ScheduledMessagesContent.module.css │ │ │ │ ├── ScheduledMessagesContent.tsx │ │ │ │ ├── UnreadChannelsContent.module.css │ │ │ │ ├── UnreadChannelsContent.tsx │ │ │ │ ├── UserAreaPopout.module.css │ │ │ │ ├── UserAreaPopout.tsx │ │ │ │ ├── UserProfileBadges.module.css │ │ │ │ ├── UserProfileBadges.tsx │ │ │ │ ├── UserProfileDataWarning.tsx │ │ │ │ ├── UserProfilePopout.module.css │ │ │ │ ├── UserProfilePopout.tsx │ │ │ │ ├── UserProfileShared.module.css │ │ │ │ └── UserProfileShared.tsx │ │ │ ├── profile/ │ │ │ │ ├── ProfilePreview.module.css │ │ │ │ ├── ProfilePreview.tsx │ │ │ │ ├── VoiceActivityCard.module.css │ │ │ │ ├── VoiceActivityCard.tsx │ │ │ │ ├── VoiceActivitySection.module.css │ │ │ │ ├── VoiceActivitySection.tsx │ │ │ │ ├── profile_card/ │ │ │ │ │ ├── ProfileCardActions.module.css │ │ │ │ │ ├── ProfileCardActions.tsx │ │ │ │ │ ├── ProfileCardBanner.module.css │ │ │ │ │ ├── ProfileCardBanner.tsx │ │ │ │ │ ├── ProfileCardContent.module.css │ │ │ │ │ ├── ProfileCardContent.tsx │ │ │ │ │ ├── ProfileCardFooter.module.css │ │ │ │ │ ├── ProfileCardFooter.tsx │ │ │ │ │ ├── ProfileCardLayout.module.css │ │ │ │ │ ├── ProfileCardLayout.tsx │ │ │ │ │ ├── ProfileCardUserInfo.module.css │ │ │ │ │ └── ProfileCardUserInfo.tsx │ │ │ │ └── useProfileCardDisplayState.tsx │ │ │ ├── quick_switcher/ │ │ │ │ ├── QuickSwitcherConstants.tsx │ │ │ │ ├── QuickSwitcherModal.module.css │ │ │ │ └── QuickSwitcherModal.tsx │ │ │ ├── search/ │ │ │ │ ├── HasFilterSheet.module.css │ │ │ │ ├── HasFilterSheet.tsx │ │ │ │ ├── ScopeSheet.module.css │ │ │ │ ├── ScopeSheet.tsx │ │ │ │ ├── SearchFilterChip.module.css │ │ │ │ ├── SearchFilterChip.tsx │ │ │ │ ├── SortModeSheet.module.css │ │ │ │ ├── SortModeSheet.tsx │ │ │ │ ├── UserFilterSheet.module.css │ │ │ │ └── UserFilterSheet.tsx │ │ │ ├── shared/ │ │ │ │ ├── ChannelPinsContent.tsx │ │ │ │ ├── ImagePreviewField.module.css │ │ │ │ ├── ImagePreviewField.tsx │ │ │ │ ├── MessagePreview.module.css │ │ │ │ ├── MessageReactionsContent.module.css │ │ │ │ ├── MessageReactionsContent.tsx │ │ │ │ ├── SavedMessageMissingCard.tsx │ │ │ │ └── message_context_prefix/ │ │ │ │ ├── MessageContextPrefix.module.css │ │ │ │ └── MessageContextPrefix.tsx │ │ │ ├── stickers/ │ │ │ │ ├── StickerGridItem.module.css │ │ │ │ └── StickerGridItem.tsx │ │ │ ├── uikit/ │ │ │ │ ├── Avatar.tsx │ │ │ │ ├── AvatarStatusGeometry.tsx │ │ │ │ ├── AvatarStatusLayout.tsx │ │ │ │ ├── BaseAvatar.module.css │ │ │ │ ├── BaseAvatar.tsx │ │ │ │ ├── FocusRingWrapper.tsx │ │ │ │ ├── InlineEdit.module.css │ │ │ │ ├── InlineEdit.tsx │ │ │ │ ├── KeyboardKey.module.css │ │ │ │ ├── KeyboardKey.tsx │ │ │ │ ├── LiveBadge.module.css │ │ │ │ ├── LiveBadge.tsx │ │ │ │ ├── MentionBadge.module.css │ │ │ │ ├── MentionBadge.tsx │ │ │ │ ├── MockAvatar.tsx │ │ │ │ ├── QRCodeCanvas.tsx │ │ │ │ ├── Scroller.module.css │ │ │ │ ├── Scroller.tsx │ │ │ │ ├── Slider.module.css │ │ │ │ ├── Slider.tsx │ │ │ │ ├── SliderTooltip.module.css │ │ │ │ ├── Spinner.module.css │ │ │ │ ├── Spinner.tsx │ │ │ │ ├── StatusAwareAvatar.tsx │ │ │ │ ├── StatusIndicator.module.css │ │ │ │ ├── StatusIndicator.tsx │ │ │ │ ├── SwitchGroup.module.css │ │ │ │ ├── SwitchGroup.tsx │ │ │ │ ├── TypingConstants.tsx │ │ │ │ ├── accordion/ │ │ │ │ │ ├── Accordion.module.css │ │ │ │ │ └── Accordion.tsx │ │ │ │ ├── alt_text_tooltip/ │ │ │ │ │ ├── AltTextTooltip.module.css │ │ │ │ │ └── AltTextTooltip.tsx │ │ │ │ ├── avatars/ │ │ │ │ │ ├── AvatarStack.module.css │ │ │ │ │ ├── AvatarStack.tsx │ │ │ │ │ ├── AvatarWithPresence.module.css │ │ │ │ │ ├── AvatarWithPresence.tsx │ │ │ │ │ ├── StackUserAvatar.module.css │ │ │ │ │ └── StackUserAvatar.tsx │ │ │ │ ├── bottom_sheet/ │ │ │ │ │ └── BottomSheet.tsx │ │ │ │ ├── button/ │ │ │ │ │ ├── Button.module.css │ │ │ │ │ └── Button.tsx │ │ │ │ ├── card_alignment_controls/ │ │ │ │ │ ├── CardAlignmentControls.module.css │ │ │ │ │ └── CardAlignmentControls.tsx │ │ │ │ ├── character_counter/ │ │ │ │ │ ├── CharacterCounter.module.css │ │ │ │ │ └── CharacterCounter.tsx │ │ │ │ ├── checkbox/ │ │ │ │ │ ├── Checkbox.module.css │ │ │ │ │ └── Checkbox.tsx │ │ │ │ ├── context_menu/ │ │ │ │ │ ├── BannedUserContextMenu.tsx │ │ │ │ │ ├── CategoryContextMenu.tsx │ │ │ │ │ ├── ChannelContextMenu.tsx │ │ │ │ │ ├── ChannelListContextMenu.tsx │ │ │ │ │ ├── ContextMenu.module.css │ │ │ │ │ ├── ContextMenu.tsx │ │ │ │ │ ├── ContextMenuIcons.tsx │ │ │ │ │ ├── DMContextMenu.tsx │ │ │ │ │ ├── DataMenuRenderer.tsx │ │ │ │ │ ├── FavoritesCategoryContextMenu.tsx │ │ │ │ │ ├── FavoritesChannelContextMenu.tsx │ │ │ │ │ ├── FavoritesChannelListContextMenu.tsx │ │ │ │ │ ├── FavoritesGuildContextMenu.tsx │ │ │ │ │ ├── GroupDMContextMenu.tsx │ │ │ │ │ ├── GuildContextMenu.tsx │ │ │ │ │ ├── GuildFolderContextMenu.tsx │ │ │ │ │ ├── GuildMemberContextMenu.tsx │ │ │ │ │ ├── MediaContextMenu.tsx │ │ │ │ │ ├── MenuGroup.tsx │ │ │ │ │ ├── MenuGroups.tsx │ │ │ │ │ ├── MenuItem.module.css │ │ │ │ │ ├── MenuItem.tsx │ │ │ │ │ ├── MenuItemRadio.module.css │ │ │ │ │ ├── MenuItemRadio.tsx │ │ │ │ │ ├── MenuItemSlider.tsx │ │ │ │ │ ├── MenuItemSubmenu.tsx │ │ │ │ │ ├── MessageContextMenu.tsx │ │ │ │ │ ├── SettingsContextMenu.tsx │ │ │ │ │ ├── UserContextMenu.tsx │ │ │ │ │ ├── VoiceParticipantContextMenu.tsx │ │ │ │ │ ├── WebhookContextMenu.tsx │ │ │ │ │ └── items/ │ │ │ │ │ ├── ActionsSubmenu.tsx │ │ │ │ │ ├── CallMenuItems.tsx │ │ │ │ │ ├── CategoryMenuData.tsx │ │ │ │ │ ├── CategoryMenuItems.tsx │ │ │ │ │ ├── ChannelMenuData.tsx │ │ │ │ │ ├── ChannelMenuItems.tsx │ │ │ │ │ ├── CopyMenuItems.tsx │ │ │ │ │ ├── DMMenuData.tsx │ │ │ │ │ ├── DMMenuItems.tsx │ │ │ │ │ ├── DebugMenuItems.tsx │ │ │ │ │ ├── GuildMemberMenuItems.tsx │ │ │ │ │ ├── GuildMenuData.tsx │ │ │ │ │ ├── GuildMenuItems.tsx │ │ │ │ │ ├── InviteMenuItems.tsx │ │ │ │ │ ├── MediaMenuData.tsx │ │ │ │ │ ├── MentionUserMenuItem.tsx │ │ │ │ │ ├── MenuItems.module.css │ │ │ │ │ ├── MessageMenuItems.tsx │ │ │ │ │ ├── MessageUserMenuItem.tsx │ │ │ │ │ ├── ModerationSubmenu.tsx │ │ │ │ │ ├── MoveToChannelSubmenu.tsx │ │ │ │ │ ├── RelationshipMenuItems.tsx │ │ │ │ │ ├── ReportGuildMenuItem.tsx │ │ │ │ │ ├── ReportMessageMenuItem.tsx │ │ │ │ │ ├── UserNoteMenuItems.tsx │ │ │ │ │ ├── UserProfileMenuItem.tsx │ │ │ │ │ ├── VoiceParticipantMenuData.tsx │ │ │ │ │ └── VoiceParticipantMenuItems.tsx │ │ │ │ ├── emoji_tooltip_content/ │ │ │ │ │ ├── EmojiTooltipContent.module.css │ │ │ │ │ └── EmojiTooltipContent.tsx │ │ │ │ ├── focus_ring/ │ │ │ │ │ ├── FocusRing.module.css │ │ │ │ │ ├── FocusRing.tsx │ │ │ │ │ ├── FocusRingContext.tsx │ │ │ │ │ ├── FocusRingManager.tsx │ │ │ │ │ ├── FocusRingScope.tsx │ │ │ │ │ └── FocusRingTypes.tsx │ │ │ │ ├── keybind_hint/ │ │ │ │ │ ├── KeybindHint.module.css │ │ │ │ │ └── KeybindHint.tsx │ │ │ │ ├── menu_bottom_sheet/ │ │ │ │ │ ├── MenuBottomSheet.module.css │ │ │ │ │ └── MenuBottomSheet.tsx │ │ │ │ ├── plutonium_link/ │ │ │ │ │ ├── PlutoniumLink.module.css │ │ │ │ │ └── PlutoniumLink.tsx │ │ │ │ ├── plutonium_upsell/ │ │ │ │ │ ├── PlutoniumUpsell.module.css │ │ │ │ │ └── PlutoniumUpsell.tsx │ │ │ │ ├── popout/ │ │ │ │ │ ├── Popout.module.css │ │ │ │ │ ├── Popout.tsx │ │ │ │ │ ├── Popouts.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── searchable_list_popout/ │ │ │ │ │ ├── SearchableListPopout.module.css │ │ │ │ │ └── SearchableListPopout.tsx │ │ │ │ ├── radio_group/ │ │ │ │ │ ├── RadioGroup.module.css │ │ │ │ │ └── RadioGroup.tsx │ │ │ │ ├── scroller/ │ │ │ │ │ ├── ScrollerMath.tsx │ │ │ │ │ ├── ScrollerTrack.module.css │ │ │ │ │ ├── ScrollerTrack.tsx │ │ │ │ │ └── useScrollerThumb.tsx │ │ │ │ ├── segmented_tabs/ │ │ │ │ │ ├── SegmentedTabs.module.css │ │ │ │ │ └── SegmentedTabs.tsx │ │ │ │ ├── sheet/ │ │ │ │ │ ├── Sheet.module.css │ │ │ │ │ └── Sheet.tsx │ │ │ │ ├── tabs/ │ │ │ │ │ ├── Tabs.module.css │ │ │ │ │ └── Tabs.tsx │ │ │ │ ├── toast/ │ │ │ │ │ ├── Toast.module.css │ │ │ │ │ ├── Toast.tsx │ │ │ │ │ ├── Toasts.module.css │ │ │ │ │ ├── Toasts.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── tooltip/ │ │ │ │ │ ├── Tooltip.module.css │ │ │ │ │ └── Tooltip.tsx │ │ │ │ └── warning_alert/ │ │ │ │ ├── WarningAlert.module.css │ │ │ │ └── WarningAlert.tsx │ │ │ ├── voice/ │ │ │ │ ├── CompactVoiceCallView.module.css │ │ │ │ ├── CompactVoiceCallView.tsx │ │ │ │ ├── FeedHiddenOverlay.module.css │ │ │ │ ├── FeedHiddenOverlay.tsx │ │ │ │ ├── GetPlaceholderAvatarColor.tsx │ │ │ │ ├── HiddenStreamPlaceholder.module.css │ │ │ │ ├── HiddenStreamPlaceholder.tsx │ │ │ │ ├── IncomingCallManager.module.css │ │ │ │ ├── IncomingCallManager.tsx │ │ │ │ ├── IncomingCallOverlayConstants.tsx │ │ │ │ ├── IncomingCallPortal.tsx │ │ │ │ ├── IncomingCallUI.module.css │ │ │ │ ├── IncomingCallUI.tsx │ │ │ │ ├── NewDeviceMonitoringManager.tsx │ │ │ │ ├── OwnStreamPreviewState.tsx │ │ │ │ ├── PiPOverlay.module.css │ │ │ │ ├── PiPOverlay.tsx │ │ │ │ ├── SignalStrengthIcon.module.css │ │ │ │ ├── SignalStrengthIcon.tsx │ │ │ │ ├── StreamFocusHeaderInfo.tsx │ │ │ │ ├── StreamInfoPill.module.css │ │ │ │ ├── StreamInfoPill.tsx │ │ │ │ ├── StreamKeys.tsx │ │ │ │ ├── StreamSpectatorsPopout.module.css │ │ │ │ ├── StreamSpectatorsPopout.tsx │ │ │ │ ├── StreamWatchHoverCard.module.css │ │ │ │ ├── StreamWatchHoverCard.tsx │ │ │ │ ├── StreamWatchHoverPopout.tsx │ │ │ │ ├── VoiceCallFullscreenFeatureFlag.tsx │ │ │ │ ├── VoiceCallLayoutContent.tsx │ │ │ │ ├── VoiceCallView.module.css │ │ │ │ ├── VoiceCallView.tsx │ │ │ │ ├── VoiceConnectionStatus.module.css │ │ │ │ ├── VoiceConnectionStatus.tsx │ │ │ │ ├── VoiceControlBar.module.css │ │ │ │ ├── VoiceControlBar.tsx │ │ │ │ ├── VoiceGridLayout.module.css │ │ │ │ ├── VoiceGridLayout.tsx │ │ │ │ ├── VoiceParticipantAvatarList.module.css │ │ │ │ ├── VoiceParticipantAvatarList.tsx │ │ │ │ ├── VoiceParticipantSortUtils.tsx │ │ │ │ ├── VoiceParticipantSpeakingUtils.tsx │ │ │ │ ├── VoiceParticipantTile.module.css │ │ │ │ ├── VoiceParticipantTile.tsx │ │ │ │ ├── VoiceReconnectionManager.tsx │ │ │ │ ├── VoiceRegionSelector.module.css │ │ │ │ ├── VoiceRegionSelector.tsx │ │ │ │ ├── VoiceSettingsMenus.module.css │ │ │ │ ├── VoiceSettingsMenus.tsx │ │ │ │ ├── VoiceStatsOverlay.module.css │ │ │ │ ├── VoiceStatsOverlay.tsx │ │ │ │ ├── usePinnedTrackRef.tsx │ │ │ │ ├── useStreamPreview.tsx │ │ │ │ ├── useStreamSpectators.tsx │ │ │ │ ├── useStreamTrackInfo.tsx │ │ │ │ ├── useStreamWatchState.tsx │ │ │ │ ├── useVoiceCallAppFullscreen.tsx │ │ │ │ └── useVoiceCallTracksAndLayout.tsx │ │ │ └── webhooks/ │ │ │ ├── WebhookListItem.module.css │ │ │ └── WebhookListItem.tsx │ │ ├── constants/ │ │ │ ├── AuditLogConstants.tsx │ │ │ ├── HelpCenterConstants.tsx │ │ │ ├── IARConstants.tsx │ │ │ └── TimeWindowPresets.tsx │ │ ├── contexts/ │ │ │ ├── AuthLayoutContext.tsx │ │ │ ├── AuthRegisterDraftContext.tsx │ │ │ └── LayoutVariantContext.tsx │ │ ├── data/ │ │ │ ├── CountryCodes.tsx │ │ │ ├── emoji-shortcuts.json │ │ │ └── emojis.json │ │ ├── devtools/ │ │ │ └── ShowMyselfTypingHelper.tsx │ │ ├── env.d.ts │ │ ├── global.css │ │ ├── hooks/ │ │ │ ├── useActivityRecorder.tsx │ │ │ ├── useAntiShiftFloating.tsx │ │ │ ├── useAudioSettingsMenu.tsx │ │ │ ├── useAuthBackground.tsx │ │ │ ├── useAuthForm.tsx │ │ │ ├── useAutoplayExpandedProfileAnimations.tsx │ │ │ ├── useBottomSheetBackHandler.tsx │ │ │ ├── useCaptcha.tsx │ │ │ ├── useChannelMemberListVisibility.tsx │ │ │ ├── useChannelSearch.tsx │ │ │ ├── useChannelSearchVisibility.tsx │ │ │ ├── useCloudUpload.tsx │ │ │ ├── useCommands.tsx │ │ │ ├── useConnectedVoiceSession.tsx │ │ │ ├── useContextMenuHoverState.tsx │ │ │ ├── useCursorAtEnd.tsx │ │ │ ├── useDeleteAttachment.tsx │ │ │ ├── useElectronScreenSharePicker.tsx │ │ │ ├── useFluxerDocumentTitle.tsx │ │ │ ├── useForceUpdate.tsx │ │ │ ├── useForm.tsx │ │ │ ├── useFormSubmit.tsx │ │ │ ├── useHashParam.tsx │ │ │ ├── useHover.tsx │ │ │ ├── useInputFocusManagement.tsx │ │ │ ├── useInviteCountdown.tsx │ │ │ ├── useInviteRevoke.tsx │ │ │ ├── useLeaveGroup.tsx │ │ │ ├── useLeaveGuild.tsx │ │ │ ├── useListNavigation.tsx │ │ │ ├── useLoginFlow.tsx │ │ │ ├── useMarkdownKeybinds.tsx │ │ │ ├── useMasonryGridNavigation.tsx │ │ │ ├── useMediaDevices.tsx │ │ │ ├── useMediaFavorite.tsx │ │ │ ├── useMediaLoading.tsx │ │ │ ├── useMemberListCustomStatus.tsx │ │ │ ├── useMemberListPresence.tsx │ │ │ ├── useMemberListSubscription.tsx │ │ │ ├── useMemberListVisible.tsx │ │ │ ├── useMergeRefs.tsx │ │ │ ├── useMessageListKeyboardNavigation.tsx │ │ │ ├── useMessageReactionsState.tsx │ │ │ ├── useMessageSubmission.tsx │ │ │ ├── useMuteSheet.tsx │ │ │ ├── useNSFWMedia.tsx │ │ │ ├── useNativePlatform.tsx │ │ │ ├── usePendingVoiceConnection.tsx │ │ │ ├── usePopout.tsx │ │ │ ├── usePremiumUpsellData.tsx │ │ │ ├── usePresenceCustomStatus.tsx │ │ │ ├── usePressable.tsx │ │ │ ├── usePushSubscriptions.tsx │ │ │ ├── useReactionTooltip.tsx │ │ │ ├── useRoleHierarchy.tsx │ │ │ ├── useRovingFocusList.tsx │ │ │ ├── useSearchInputAutofocus.tsx │ │ │ ├── useSlowmode.tsx │ │ │ ├── useStickerAnimation.tsx │ │ │ ├── useStreamWatchDoubleClick.tsx │ │ │ ├── useSudo.tsx │ │ │ ├── useSystemMessageData.tsx │ │ │ ├── useTextInputContextMenu.tsx │ │ │ ├── useTextOverflow.tsx │ │ │ ├── useTextareaAutocomplete.tsx │ │ │ ├── useTextareaAutocompleteKeyboard.tsx │ │ │ ├── useTextareaAutofocus.tsx │ │ │ ├── useTextareaDraftAndTyping.tsx │ │ │ ├── useTextareaEditing.tsx │ │ │ ├── useTextareaEmojiPicker.tsx │ │ │ ├── useTextareaExpressionHandlers.tsx │ │ │ ├── useTextareaExpressionPicker.tsx │ │ │ ├── useTextareaKeyboard.tsx │ │ │ ├── useTextareaPaste.tsx │ │ │ ├── useTextareaSegments.tsx │ │ │ ├── useTextareaSubmit.tsx │ │ │ ├── useThemeExists.tsx │ │ │ ├── useUserVoiceActivities.tsx │ │ │ ├── useUsernameSuggestions.tsx │ │ │ ├── useVoiceJoinEligibility.tsx │ │ │ ├── useWebhookUpdates.tsx │ │ │ └── useWindowFocusVideoControl.tsx │ │ ├── images/ │ │ │ └── i-like-food.d.svg.ts │ │ ├── index.tsx │ │ ├── lib/ │ │ │ ├── AccountStorage.tsx │ │ │ ├── AppStorage.tsx │ │ │ ├── AutofocusUtils.tsx │ │ │ ├── CaptchaInterceptor.tsx │ │ │ ├── ChannelMessages.test.tsx │ │ │ ├── ChannelMessages.tsx │ │ │ ├── CloudUpload.tsx │ │ │ ├── ComponentDispatch.tsx │ │ │ ├── CustomStatus.tsx │ │ │ ├── CustomStatusEmitter.tsx │ │ │ ├── E2EEncryption.tsx │ │ │ ├── Env.tsx │ │ │ ├── ExponentialBackoff.tsx │ │ │ ├── ExpressionPickerUtils.tsx │ │ │ ├── FocusManager.tsx │ │ │ ├── GatewayCompression.tsx │ │ │ ├── GatewaySocket.tsx │ │ │ ├── HttpClient.tsx │ │ │ ├── HttpError.tsx │ │ │ ├── HttpTypes.tsx │ │ │ ├── InputFocusManager.tsx │ │ │ ├── IsTextInputKeyEvent.tsx │ │ │ ├── KeybindManager.tsx │ │ │ ├── LibFluxcore.Worker.tsx │ │ │ ├── LibFluxcore.tsx │ │ │ ├── Logger.tsx │ │ │ ├── MediaDeviceCache.tsx │ │ │ ├── MessageQueue.tsx │ │ │ ├── MobXPersistence.tsx │ │ │ ├── MultiAccountGatewaySocket.tsx │ │ │ ├── PasswordManagerAutocomplete.tsx │ │ │ ├── PlaceholderSpecs.tsx │ │ │ ├── Platform.tsx │ │ │ ├── Queue.tsx │ │ │ ├── ReadStateCleanup.tsx │ │ │ ├── RelayClient.tsx │ │ │ ├── RemoteInstanceAuth.tsx │ │ │ ├── ScrollManager.tsx │ │ │ ├── SessionManager.tsx │ │ │ ├── StickerSendUtils.tsx │ │ │ ├── TextareaAutosize.tsx │ │ │ ├── UnicodeEmojis.tsx │ │ │ ├── Versioning.tsx │ │ │ ├── VoiceStatsDB.tsx │ │ │ ├── markdown/ │ │ │ │ ├── EmojiProviderSetup.tsx │ │ │ │ ├── MarkdownTableParsingConfig.tsx │ │ │ │ ├── Plaintext.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── renderers/ │ │ │ │ │ ├── EmojiRenderer.tsx │ │ │ │ │ ├── LinkRenderer.tsx │ │ │ │ │ ├── MentionRenderer.tsx │ │ │ │ │ ├── MessageJumpLink.module.css │ │ │ │ │ ├── RendererTypes.tsx │ │ │ │ │ ├── TextRenderer.tsx │ │ │ │ │ ├── TimestampRenderer.test.tsx │ │ │ │ │ ├── TimestampRenderer.tsx │ │ │ │ │ ├── common/ │ │ │ │ │ │ ├── BlockElements.tsx │ │ │ │ │ │ ├── CodeElements.tsx │ │ │ │ │ │ └── FormattingElements.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── utils/ │ │ │ │ ├── DateFormatter.test.tsx │ │ │ │ ├── DateFormatter.tsx │ │ │ │ ├── EmojiDetector.tsx │ │ │ │ ├── JumboDetector.tsx │ │ │ │ ├── TimestampValidation.test.tsx │ │ │ │ └── TimestampValidation.tsx │ │ │ ├── router/ │ │ │ │ ├── Builder.tsx │ │ │ │ ├── Core.tsx │ │ │ │ ├── History.tsx │ │ │ │ ├── React.tsx │ │ │ │ ├── RouterErrors.tsx │ │ │ │ └── RouterTypes.tsx │ │ │ └── scroll/ │ │ │ └── ScrollPosition.tsx │ │ ├── locales/ │ │ │ ├── ar/ │ │ │ │ └── messages.po │ │ │ ├── bg/ │ │ │ │ └── messages.po │ │ │ ├── cs/ │ │ │ │ └── messages.po │ │ │ ├── da/ │ │ │ │ └── messages.po │ │ │ ├── de/ │ │ │ │ └── messages.po │ │ │ ├── el/ │ │ │ │ └── messages.po │ │ │ ├── en-GB/ │ │ │ │ └── messages.po │ │ │ ├── en-US/ │ │ │ │ └── messages.po │ │ │ ├── es-419/ │ │ │ │ └── messages.po │ │ │ ├── es-ES/ │ │ │ │ └── messages.po │ │ │ ├── fi/ │ │ │ │ └── messages.po │ │ │ ├── fr/ │ │ │ │ └── messages.po │ │ │ ├── he/ │ │ │ │ └── messages.po │ │ │ ├── hi/ │ │ │ │ └── messages.po │ │ │ ├── hr/ │ │ │ │ └── messages.po │ │ │ ├── hu/ │ │ │ │ └── messages.po │ │ │ ├── id/ │ │ │ │ └── messages.po │ │ │ ├── it/ │ │ │ │ └── messages.po │ │ │ ├── ja/ │ │ │ │ └── messages.po │ │ │ ├── ko/ │ │ │ │ └── messages.po │ │ │ ├── lt/ │ │ │ │ └── messages.po │ │ │ ├── nl/ │ │ │ │ └── messages.po │ │ │ ├── no/ │ │ │ │ └── messages.po │ │ │ ├── pl/ │ │ │ │ └── messages.po │ │ │ ├── pt-BR/ │ │ │ │ └── messages.po │ │ │ ├── ro/ │ │ │ │ └── messages.po │ │ │ ├── ru/ │ │ │ │ └── messages.po │ │ │ ├── sv-SE/ │ │ │ │ └── messages.po │ │ │ ├── th/ │ │ │ │ └── messages.po │ │ │ ├── tr/ │ │ │ │ └── messages.po │ │ │ ├── uk/ │ │ │ │ └── messages.po │ │ │ ├── vi/ │ │ │ │ └── messages.po │ │ │ ├── zh-CN/ │ │ │ │ └── messages.po │ │ │ └── zh-TW/ │ │ │ └── messages.po │ │ ├── records/ │ │ │ ├── AuthSessionRecord.tsx │ │ │ ├── ChannelRecord.tsx │ │ │ ├── ConnectionRecord.tsx │ │ │ ├── DeveloperApplicationRecord.tsx │ │ │ ├── FavoriteMemeRecord.tsx │ │ │ ├── GuildEmojiRecord.tsx │ │ │ ├── GuildMemberRecord.tsx │ │ │ ├── GuildRecord.tsx │ │ │ ├── GuildRoleRecord.tsx │ │ │ ├── GuildStickerRecord.tsx │ │ │ ├── MessageRecord.tsx │ │ │ ├── ProfileRecord.tsx │ │ │ ├── RelationshipRecord.tsx │ │ │ ├── SavedMessageEntryRecord.tsx │ │ │ ├── ScheduledMessageRecord.tsx │ │ │ ├── UserGuildSettingsRecord.tsx │ │ │ ├── UserRecord.tsx │ │ │ └── WebhookRecord.tsx │ │ ├── router/ │ │ │ ├── RouterConstants.tsx │ │ │ ├── components/ │ │ │ │ ├── GuildChannelRouter.tsx │ │ │ │ └── RootComponent.tsx │ │ │ └── routes/ │ │ │ ├── AppRoutes.tsx │ │ │ ├── AuthRoutes.tsx │ │ │ ├── RootRoutes.tsx │ │ │ └── Routes.tsx │ │ ├── service_worker/ │ │ │ ├── Register.tsx │ │ │ └── Worker.tsx │ │ ├── services/ │ │ │ └── push/ │ │ │ └── PushSubscriptionService.tsx │ │ ├── stores/ │ │ │ ├── AccessibilityOverrideStore.tsx │ │ │ ├── AccessibilityStore.tsx │ │ │ ├── AccountManager.tsx │ │ │ ├── AudioVolumeStore.tsx │ │ │ ├── AuthSessionStore.tsx │ │ │ ├── AuthenticationStore.tsx │ │ │ ├── AutoAckStore.tsx │ │ │ ├── AutocompleteStore.tsx │ │ │ ├── CallAvailabilityStore.tsx │ │ │ ├── CallInitiatorStore.tsx │ │ │ ├── CallMediaPrefsStore.tsx │ │ │ ├── CallStateStore.tsx │ │ │ ├── ChannelDisplayNameStore.tsx │ │ │ ├── ChannelPinsStore.tsx │ │ │ ├── ChannelSearchStore.tsx │ │ │ ├── ChannelStickerStore.tsx │ │ │ ├── ChannelStore.tsx │ │ │ ├── CompactVoiceCallHeightStore.tsx │ │ │ ├── CompactVoiceCallPiPPositionStore.tsx │ │ │ ├── ContextMenuStore.tsx │ │ │ ├── CountryCodeStore.tsx │ │ │ ├── DeveloperModeStore.tsx │ │ │ ├── DeveloperOptionsStore.tsx │ │ │ ├── DimensionStore.tsx │ │ │ ├── DiscoveryStore.tsx │ │ │ ├── DismissedUpsellStore.tsx │ │ │ ├── DraftStore.tsx │ │ │ ├── EmojiPickerStore.tsx │ │ │ ├── EmojiStickerLayoutStore.tsx │ │ │ ├── EmojiStore.test.tsx │ │ │ ├── EmojiStore.tsx │ │ │ ├── ExpressionPickerStore.tsx │ │ │ ├── FavoriteMemeStore.tsx │ │ │ ├── FavoritesStore.tsx │ │ │ ├── FriendsTabStore.tsx │ │ │ ├── GeoIPStore.tsx │ │ │ ├── GiftStore.tsx │ │ │ ├── GuildAvailabilityStore.tsx │ │ │ ├── GuildExpressionTabCache.tsx │ │ │ ├── GuildFolderExpandedStore.tsx │ │ │ ├── GuildListStore.tsx │ │ │ ├── GuildMemberLayoutStore.tsx │ │ │ ├── GuildMemberStore.tsx │ │ │ ├── GuildNSFWAgreeStore.tsx │ │ │ ├── GuildReadStateStore.tsx │ │ │ ├── GuildSettingsModalStore.tsx │ │ │ ├── GuildStore.tsx │ │ │ ├── GuildVerificationStore.tsx │ │ │ ├── IdleStore.tsx │ │ │ ├── InboxStore.tsx │ │ │ ├── InitializationStore.tsx │ │ │ ├── InputMonitoringPromptsStore.tsx │ │ │ ├── InstanceConfigStore.tsx │ │ │ ├── InviteStore.tsx │ │ │ ├── KeybindStore.tsx │ │ │ ├── KeyboardModeStore.tsx │ │ │ ├── LayerManager.tsx │ │ │ ├── LimitOverrideStore.tsx │ │ │ ├── LocalPresenceStore.tsx │ │ │ ├── LocalVoiceStateStore.tsx │ │ │ ├── LocationStore.tsx │ │ │ ├── MediaPermissionStore.tsx │ │ │ ├── MediaViewerStore.tsx │ │ │ ├── MemberListStore.tsx │ │ │ ├── MemberPresenceSubscriptionStore.tsx │ │ │ ├── MemberSearchStore.tsx │ │ │ ├── MemberSidebarStore.test.tsx │ │ │ ├── MemberSidebarStore.tsx │ │ │ ├── MemesPickerStore.tsx │ │ │ ├── MessageEditMobileStore.tsx │ │ │ ├── MessageEditStore.tsx │ │ │ ├── MessageFocusStore.tsx │ │ │ ├── MessageReactionsStore.tsx │ │ │ ├── MessageReferenceStore.tsx │ │ │ ├── MessageReplyStore.tsx │ │ │ ├── MessageStore.tsx │ │ │ ├── MobileLayoutStore.tsx │ │ │ ├── MockIncomingCallStore.tsx │ │ │ ├── ModalStore.tsx │ │ │ ├── NagbarStore.tsx │ │ │ ├── NativePermissionStore.tsx │ │ │ ├── NativeWindowStateStore.tsx │ │ │ ├── NavigationSideEffectsStore.tsx │ │ │ ├── NavigationStore.tsx │ │ │ ├── NewDeviceMonitoringStore.tsx │ │ │ ├── NotificationStore.tsx │ │ │ ├── OverlayStackStore.tsx │ │ │ ├── PackStore.tsx │ │ │ ├── ParticipantVolumeStore.tsx │ │ │ ├── PermissionLayoutStore.tsx │ │ │ ├── PermissionStore.tsx │ │ │ ├── PiPStore.tsx │ │ │ ├── PopoutStore.tsx │ │ │ ├── PresenceStore.tsx │ │ │ ├── PrivacyPreferencesStore.tsx │ │ │ ├── QuickSwitcherStore.tsx │ │ │ ├── ReadStateStore.test.tsx │ │ │ ├── ReadStateStore.tsx │ │ │ ├── RecentMentionsStore.tsx │ │ │ ├── RelationshipStore.tsx │ │ │ ├── RtcRegionsStore.tsx │ │ │ ├── RuntimeConfigStore.tsx │ │ │ ├── RuntimeCrashStore.tsx │ │ │ ├── SavedMessagesStore.tsx │ │ │ ├── ScheduledMessageEditorStore.tsx │ │ │ ├── ScheduledMessagesStore.tsx │ │ │ ├── SearchHistoryStore.tsx │ │ │ ├── SelectedChannelStore.tsx │ │ │ ├── SelectedGuildStore.tsx │ │ │ ├── SettingsSidebarStore.tsx │ │ │ ├── SlowmodeStore.tsx │ │ │ ├── SoundStore.tsx │ │ │ ├── SpellcheckStore.tsx │ │ │ ├── StatusExpiryStore.tsx │ │ │ ├── StickerPickerStore.tsx │ │ │ ├── StickerStore.tsx │ │ │ ├── StreamAudioPrefsStore.tsx │ │ │ ├── SudoPromptStore.tsx │ │ │ ├── SudoStore.tsx │ │ │ ├── TextualPreviewStore.tsx │ │ │ ├── ThemeStore.tsx │ │ │ ├── ToastStore.tsx │ │ │ ├── TransientPresenceStore.tsx │ │ │ ├── TrustedDomainStore.tsx │ │ │ ├── TypingStore.tsx │ │ │ ├── UnreadChannelsStore.tsx │ │ │ ├── UnsavedChangesStore.tsx │ │ │ ├── UpdaterStore.tsx │ │ │ ├── UserConnectionStore.tsx │ │ │ ├── UserGuildSettingsStore.tsx │ │ │ ├── UserNoteStore.tsx │ │ │ ├── UserPinnedDMStore.tsx │ │ │ ├── UserProfileMobileStore.tsx │ │ │ ├── UserProfileStore.tsx │ │ │ ├── UserSettingsStore.tsx │ │ │ ├── UserStore.tsx │ │ │ ├── VideoVolumeStore.tsx │ │ │ ├── VoiceCallLayoutStore.tsx │ │ │ ├── VoicePromptsStore.tsx │ │ │ ├── VoiceSettingsStore.tsx │ │ │ ├── WebhookStore.tsx │ │ │ ├── WindowStore.tsx │ │ │ ├── gateway/ │ │ │ │ ├── GatewayConnectionStore.tsx │ │ │ │ └── handlers/ │ │ │ │ ├── Ready.tsx │ │ │ │ ├── Resumed.tsx │ │ │ │ ├── call/ │ │ │ │ │ ├── CallCreate.tsx │ │ │ │ │ ├── CallDelete.tsx │ │ │ │ │ └── CallUpdate.tsx │ │ │ │ ├── channel/ │ │ │ │ │ ├── ChannelCreate.tsx │ │ │ │ │ ├── ChannelDelete.tsx │ │ │ │ │ ├── ChannelPinsAck.tsx │ │ │ │ │ ├── ChannelPinsUpdate.tsx │ │ │ │ │ ├── ChannelRecipientAdd.tsx │ │ │ │ │ ├── ChannelRecipientRemove.tsx │ │ │ │ │ ├── ChannelUpdate.tsx │ │ │ │ │ └── ChannelUpdateBulk.tsx │ │ │ │ ├── guild/ │ │ │ │ │ ├── GuildBan.tsx │ │ │ │ │ ├── GuildCreate.tsx │ │ │ │ │ ├── GuildDelete.tsx │ │ │ │ │ ├── GuildEmojisUpdate.tsx │ │ │ │ │ ├── GuildMemberAdd.tsx │ │ │ │ │ ├── GuildMemberListUpdate.tsx │ │ │ │ │ ├── GuildMemberRemove.tsx │ │ │ │ │ ├── GuildMemberUpdate.tsx │ │ │ │ │ ├── GuildMembersChunk.tsx │ │ │ │ │ ├── GuildRoleCreate.tsx │ │ │ │ │ ├── GuildRoleDelete.tsx │ │ │ │ │ ├── GuildRoleUpdate.tsx │ │ │ │ │ ├── GuildRoleUpdateBulk.tsx │ │ │ │ │ ├── GuildStickersUpdate.tsx │ │ │ │ │ ├── GuildSync.tsx │ │ │ │ │ ├── GuildUpdate.tsx │ │ │ │ │ └── PassiveUpdates.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── invite/ │ │ │ │ │ ├── InviteCreate.tsx │ │ │ │ │ └── InviteDelete.tsx │ │ │ │ ├── message/ │ │ │ │ │ ├── MessageAck.tsx │ │ │ │ │ ├── MessageCreate.tsx │ │ │ │ │ ├── MessageDelete.tsx │ │ │ │ │ ├── MessageDeleteBulk.tsx │ │ │ │ │ ├── MessageReactionAdd.tsx │ │ │ │ │ ├── MessageReactionAddMany.tsx │ │ │ │ │ ├── MessageReactionRemove.tsx │ │ │ │ │ ├── MessageReactionRemoveAll.tsx │ │ │ │ │ ├── MessageReactionRemoveEmoji.tsx │ │ │ │ │ ├── MessageUpdate.tsx │ │ │ │ │ ├── RecentMentionDelete.tsx │ │ │ │ │ ├── SavedMessageCreate.tsx │ │ │ │ │ ├── SavedMessageDelete.tsx │ │ │ │ │ └── TypingStart.tsx │ │ │ │ ├── misc/ │ │ │ │ │ ├── FavoriteMemeCreate.tsx │ │ │ │ │ ├── FavoriteMemeDelete.tsx │ │ │ │ │ ├── FavoriteMemeUpdate.tsx │ │ │ │ │ └── WebhooksUpdate.tsx │ │ │ │ ├── presence/ │ │ │ │ │ ├── PresenceUpdate.tsx │ │ │ │ │ └── PresenceUpdateBulk.tsx │ │ │ │ ├── relationship/ │ │ │ │ │ ├── RelationshipAdd.tsx │ │ │ │ │ ├── RelationshipRemove.tsx │ │ │ │ │ └── RelationshipUpdate.tsx │ │ │ │ ├── user/ │ │ │ │ │ ├── AuthSessionChange.tsx │ │ │ │ │ ├── UserConnectionsUpdate.tsx │ │ │ │ │ ├── UserGuildSettingsUpdate.tsx │ │ │ │ │ ├── UserNoteUpdate.tsx │ │ │ │ │ ├── UserPinnedDmsUpdate.tsx │ │ │ │ │ ├── UserSettingsUpdate.tsx │ │ │ │ │ └── UserUpdate.tsx │ │ │ │ └── voice/ │ │ │ │ ├── VoiceServerUpdate.tsx │ │ │ │ └── VoiceStateUpdate.tsx │ │ │ └── voice/ │ │ │ ├── MediaEngineFacade.tsx │ │ │ ├── ScreenShareSubscriptionManager.tsx │ │ │ ├── VideoSubscriptionManager.tsx │ │ │ ├── VoiceAudioManager.tsx │ │ │ ├── VoiceChannelConnector.tsx │ │ │ ├── VoiceConnectionManager.tsx │ │ │ ├── VoiceConnectionThrottle.tsx │ │ │ ├── VoiceDevicePermissionStore.tsx │ │ │ ├── VoiceEntranceSoundManager.tsx │ │ │ ├── VoiceMediaEngineBridge.tsx │ │ │ ├── VoiceMediaManager.tsx │ │ │ ├── VoiceMediaStateCoordinator.tsx │ │ │ ├── VoiceParticipantManager.tsx │ │ │ ├── VoicePermissionManager.tsx │ │ │ ├── VoiceReconnectManager.tsx │ │ │ ├── VoiceRoomEventBinder.tsx │ │ │ ├── VoiceScreenShareManager.tsx │ │ │ ├── VoiceStateGatewayHandler.tsx │ │ │ ├── VoiceStateManager.tsx │ │ │ ├── VoiceStateSyncManager.tsx │ │ │ ├── VoiceStatsManager.tsx │ │ │ └── VoiceSubscriptionManager.tsx │ │ ├── styles/ │ │ │ ├── AttachmentFile.module.css │ │ │ ├── AttachmentGridItem.module.css │ │ │ ├── AttachmentLayoutGrid.module.css │ │ │ ├── AttachmentMosaic.module.css │ │ │ ├── AttachmentSingleMedia.module.css │ │ │ ├── ChannelSearchBottomSheet.module.css │ │ │ ├── CodeElements.module.css │ │ │ ├── Markup.module.css │ │ │ ├── MentionRenderer.module.css │ │ │ ├── Message.module.css │ │ │ ├── Scroller.module.css │ │ │ ├── TimestampRenderer.module.css │ │ │ ├── Typing.module.css │ │ │ └── preflight.css │ │ ├── test/ │ │ │ ├── LibfluxcoreMock.tsx │ │ │ ├── LibfluxcoreMock.wasm │ │ │ ├── Setup.tsx │ │ │ └── StyleMock.ts │ │ ├── types/ │ │ │ ├── BrandedTypes.tsx │ │ │ ├── Browser.tsx │ │ │ ├── Combokeys.d.ts │ │ │ ├── ElectronTypes.tsx │ │ │ ├── EmojiTypes.tsx │ │ │ ├── InviteTypes.tsx │ │ │ ├── Media.d.ts │ │ │ ├── Sudo.tsx │ │ │ ├── VerificationError.tsx │ │ │ ├── assets.d.ts │ │ │ ├── browser.d.ts │ │ │ ├── dom-augmentations.d.ts │ │ │ ├── electron.d.ts │ │ │ ├── favico.d.ts │ │ │ ├── gateway/ │ │ │ │ ├── GatewayGuildTypes.tsx │ │ │ │ ├── GatewayPresenceTypes.tsx │ │ │ │ └── GatewayVoiceTypes.tsx │ │ │ ├── lingui-react-macro.d.ts │ │ │ └── phosphor-icons-augmentations.d.ts │ │ ├── utils/ │ │ │ ├── AccentColorUtils.tsx │ │ │ ├── AnimatedImageUtils.tsx │ │ │ ├── ApiErrorUtils.tsx │ │ │ ├── AppProtocol.tsx │ │ │ ├── AttachmentExpiryUtils.tsx │ │ │ ├── AttachmentPreviewUtils.tsx │ │ │ ├── AttachmentUtils.tsx │ │ │ ├── AutostartUtils.tsx │ │ │ ├── AvatarUtils.tsx │ │ │ ├── BackgroundImageDB.tsx │ │ │ ├── CSSHighlightSearch.tsx │ │ │ ├── CallUtils.tsx │ │ │ ├── ChannelSearchHighlight.tsx │ │ │ ├── ChannelShared.tsx │ │ │ ├── ChannelUtils.tsx │ │ │ ├── ClientInfoUtils.tsx │ │ │ ├── CodeLinkUtils.tsx │ │ │ ├── ColorUtils.test.tsx │ │ │ ├── ColorUtils.tsx │ │ │ ├── CommandUtils.test.tsx │ │ │ ├── CommandUtils.tsx │ │ │ ├── ContextMenuUtils.tsx │ │ │ ├── CopyLinkHandlers.tsx │ │ │ ├── CustomSoundDB.tsx │ │ │ ├── DateUtils.tsx │ │ │ ├── DeepLinkUtils.test.tsx │ │ │ ├── DeepLinkUtils.tsx │ │ │ ├── DesktopRpcClient.tsx │ │ │ ├── DimensionUtils.test.tsx │ │ │ ├── DimensionUtils.tsx │ │ │ ├── DmChannelUtils.tsx │ │ │ ├── EmbeddableImageTypes.tsx │ │ │ ├── EmojiCodepointUtils.tsx │ │ │ ├── EmojiUtils.test.tsx │ │ │ ├── EmojiUtils.tsx │ │ │ ├── ExpressionPermissionUtils.tsx │ │ │ ├── ExpressionPremiumSummary.tsx │ │ │ ├── FavoriteMemeUtils.tsx │ │ │ ├── FileDownloadUtils.tsx │ │ │ ├── FilePickerUtils.tsx │ │ │ ├── FileUploadUtils.tsx │ │ │ ├── FileUtils.test.tsx │ │ │ ├── FileUtils.tsx │ │ │ ├── FormUtils.tsx │ │ │ ├── ForwardedMessageUtils.tsx │ │ │ ├── GeoUtils.tsx │ │ │ ├── GiftCodeUtils.tsx │ │ │ ├── GiftUtils.tsx │ │ │ ├── GroupDMColorUtils.test.tsx │ │ │ ├── GroupDMColorUtils.tsx │ │ │ ├── GroupDmUtils.tsx │ │ │ ├── GuildInitialsUtils.test.tsx │ │ │ ├── GuildInitialsUtils.tsx │ │ │ ├── HelpCenterUtils.tsx │ │ │ ├── ImageCacheUtils.tsx │ │ │ ├── ImageCropUtils.tsx │ │ │ ├── InviteUtils.tsx │ │ │ ├── KeybindUtils.tsx │ │ │ ├── KeyboardUtils.tsx │ │ │ ├── KlipyUtils.tsx │ │ │ ├── LinkSuppressionUtils.test.tsx │ │ │ ├── LinkSuppressionUtils.tsx │ │ │ ├── LocaleUtils.tsx │ │ │ ├── MarkdownToSegmentUtils.tsx │ │ │ ├── MediaDeviceRefresh.tsx │ │ │ ├── MediaDimensionConfig.tsx │ │ │ ├── MediaProxyUtils.tsx │ │ │ ├── MediaViewerItemUtils.tsx │ │ │ ├── MemberListLayout.test.tsx │ │ │ ├── MemberListLayout.tsx │ │ │ ├── MemberListUtils.tsx │ │ │ ├── MessageAttachmentUtils.tsx │ │ │ ├── MessageComponentUtils.tsx │ │ │ ├── MessageGroupingUtils.test.tsx │ │ │ ├── MessageGroupingUtils.tsx │ │ │ ├── MessageLinkUtils.tsx │ │ │ ├── MessageNavigator.tsx │ │ │ ├── MessageRequestUtils.test.tsx │ │ │ ├── MessageRequestUtils.tsx │ │ │ ├── MessageSelectionCopyUtils.test.tsx │ │ │ ├── MessageSelectionCopyUtils.tsx │ │ │ ├── MessageSubmitUtils.tsx │ │ │ ├── MessageUtils.tsx │ │ │ ├── MfaUtils.tsx │ │ │ ├── MobileExperience.tsx │ │ │ ├── MobileNavigation.tsx │ │ │ ├── NativePermissions.tsx │ │ │ ├── NativeUtils.tsx │ │ │ ├── NicknameUtils.tsx │ │ │ ├── NotificationUtils.tsx │ │ │ ├── PasteSegmentUtils.tsx │ │ │ ├── PermissionUtils.tsx │ │ │ ├── PlaceholderUtils.test.tsx │ │ │ ├── PlaceholderUtils.tsx │ │ │ ├── Positioning.tsx │ │ │ ├── PremiumUtils.tsx │ │ │ ├── PricingUtils.tsx │ │ │ ├── ProfileDisplayUtils.tsx │ │ │ ├── ProfileUtils.tsx │ │ │ ├── PwaUtils.tsx │ │ │ ├── React.tsx │ │ │ ├── ReactionUtils.tsx │ │ │ ├── ReducedMotionAnimation.tsx │ │ │ ├── RegexUtils.test.tsx │ │ │ ├── RegexUtils.tsx │ │ │ ├── RelationshipActionUtils.tsx │ │ │ ├── ReplaceCommandUtils.tsx │ │ │ ├── RouterUtils.tsx │ │ │ ├── ScreenShareUtils.tsx │ │ │ ├── ScrollbarDragState.tsx │ │ │ ├── SearchQueryParser.tsx │ │ │ ├── SearchQueryTokenizer.tsx │ │ │ ├── SearchSegmentManager.tsx │ │ │ ├── SearchUtils.tsx │ │ │ ├── SelectUtils.tsx │ │ │ ├── SkinToneUtils.tsx │ │ │ ├── SlashCommandUtils.test.tsx │ │ │ ├── SlashCommandUtils.tsx │ │ │ ├── SnowflakeUtils.test.tsx │ │ │ ├── SoundLabels.tsx │ │ │ ├── SoundUtils.tsx │ │ │ ├── SpoilerUtils.tsx │ │ │ ├── StreamPreviewPermissionUtils.test.tsx │ │ │ ├── StreamPreviewPermissionUtils.tsx │ │ │ ├── StringUtils.test.tsx │ │ │ ├── StringUtils.tsx │ │ │ ├── SystemMessageUtils.tsx │ │ │ ├── TenorUtils.tsx │ │ │ ├── TextareaAutocompleteFlow.test.tsx │ │ │ ├── TextareaInsertMentionFlow.test.tsx │ │ │ ├── TextareaSegmentManager.test.tsx │ │ │ ├── TextareaSegmentManager.tsx │ │ │ ├── TextareaStateManager.test.tsx │ │ │ ├── TextareaStateManager.tsx │ │ │ ├── ThemeUtils.tsx │ │ │ ├── TtsSpeechUtils.tsx │ │ │ ├── TtsTextFormatter.tsx │ │ │ ├── TtsUtils.tsx │ │ │ ├── TypingUtils.tsx │ │ │ ├── UiohookKeycodes.tsx │ │ │ ├── UrlUtils.tsx │ │ │ ├── VideoBackgroundProcessor.tsx │ │ │ ├── VoiceDeviceManager.tsx │ │ │ ├── VoiceMessageRecordingUtils.tsx │ │ │ ├── VoiceMessageSendUtils.tsx │ │ │ ├── VoiceVolumeUtils.test.tsx │ │ │ ├── VoiceVolumeUtils.tsx │ │ │ ├── WebAuthnUtils.tsx │ │ │ ├── WebhookUtils.tsx │ │ │ ├── WindowStateUtils.tsx │ │ │ ├── __tests__/ │ │ │ │ └── SearchQueryParser.test.tsx │ │ │ ├── accounts/ │ │ │ │ └── AccountSwitcherModalUtils.tsx │ │ │ ├── alerts/ │ │ │ │ └── VoiceConnectionConfirmModalUtils.tsx │ │ │ ├── errors/ │ │ │ │ └── ScreenRecordingPermissionDeniedError.tsx │ │ │ ├── friends/ │ │ │ │ ├── FriendsListUtils.module.css │ │ │ │ └── FriendsListUtils.tsx │ │ │ ├── invite/ │ │ │ │ ├── GroupDmInviteCounts.tsx │ │ │ │ └── GuildInviteActionState.tsx │ │ │ ├── limits/ │ │ │ │ ├── GlobalLimits.tsx │ │ │ │ ├── LimitContext.tsx │ │ │ │ ├── LimitResolverAdapter.tsx │ │ │ │ ├── LimitUtils.tsx │ │ │ │ └── UserLimits.tsx │ │ │ ├── modals/ │ │ │ │ ├── AddFriendsToGroupModalUtils.tsx │ │ │ │ ├── AnimatedAvifModalUtils.tsx │ │ │ │ ├── ChannelCreateModalUtils.tsx │ │ │ │ ├── ChannelDeleteModalUtils.tsx │ │ │ │ ├── ChannelSettingsModalUtils.tsx │ │ │ │ ├── ChannelTopicModalUtils.tsx │ │ │ │ ├── CreateDMModalUtils.tsx │ │ │ │ ├── ModalUtils.tsx │ │ │ │ ├── PremiumModalUtils.tsx │ │ │ │ ├── ScreenShareSettingsModalUtils.tsx │ │ │ │ ├── SettingsModalLayoutUtils.tsx │ │ │ │ └── guild_tabs/ │ │ │ │ ├── GuildAuditLogTabUtils.tsx │ │ │ │ └── GuildOverviewTabUtils.tsx │ │ │ └── quick_switcher/ │ │ │ └── QuickSwitcherModalUtils.tsx │ │ ├── videos/ │ │ │ └── banned.webm │ │ ├── viewmodels/ │ │ │ └── auth/ │ │ │ ├── AuthFlow.test.tsx │ │ │ └── AuthFlow.tsx │ │ ├── vite-env.d.ts │ │ └── workers/ │ │ ├── AnimatedImageCrop.Worker.tsx │ │ ├── AnimatedImageCropWorkerManager.tsx │ │ ├── AnimatedImageCropWorkerPool.tsx │ │ └── MemberSearch.Worker.tsx │ ├── tsconfig.json │ └── vitest.config.ts ├── fluxer_app_proxy/ │ ├── Dockerfile │ ├── package.json │ ├── src/ │ │ ├── Config.tsx │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ └── index.tsx │ └── tsconfig.json ├── fluxer_desktop/ │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── build_resources/ │ │ ├── entitlements.mac.canary.plist │ │ ├── entitlements.mac.inherit.plist │ │ ├── entitlements.mac.stable.plist │ │ ├── icons-canary/ │ │ │ ├── AppIcon.icon/ │ │ │ │ └── icon.json │ │ │ └── _compiled/ │ │ │ ├── AppIcon.icns │ │ │ ├── Assets.car │ │ │ ├── assetcatalog_generated_info.plist │ │ │ └── icon.part.plist │ │ ├── icons-stable/ │ │ │ ├── AppIcon.icon/ │ │ │ │ └── icon.json │ │ │ └── _compiled/ │ │ │ ├── AppIcon.icns │ │ │ ├── Assets.car │ │ │ ├── assetcatalog_generated_info.plist │ │ │ └── icon.part.plist │ │ ├── notarize.js │ │ └── profiles/ │ │ ├── Fluxer.provisionprofile │ │ └── Fluxer_Canary.provisionprofile │ ├── electron-builder.config.cjs │ ├── package.json │ ├── packaging/ │ │ ├── aur/ │ │ │ ├── PKGBUILD │ │ │ └── README.md │ │ ├── homebrew/ │ │ │ ├── README.md │ │ │ └── fluxer.rb │ │ ├── linux/ │ │ │ ├── README.md │ │ │ ├── app.fluxer.Fluxer.desktop │ │ │ └── app.fluxer.Fluxer.metainfo.xml │ │ └── winget/ │ │ ├── Fluxer.Fluxer.installer.yaml │ │ ├── Fluxer.Fluxer.locale.en-US.yaml │ │ ├── Fluxer.Fluxer.yaml │ │ └── README.md │ ├── pnpm-workspace.yaml │ ├── scripts/ │ │ ├── build.mjs │ │ └── set-build-channel.mjs │ ├── src/ │ │ ├── common/ │ │ │ ├── BrandedTypes.tsx │ │ │ ├── BuildChannel.tsx │ │ │ ├── Constants.tsx │ │ │ ├── DesktopConfig.tsx │ │ │ ├── Logger.tsx │ │ │ ├── Types.tsx │ │ │ └── UserDataPath.tsx │ │ ├── main/ │ │ │ ├── Autostart.tsx │ │ │ ├── DeepLinks.tsx │ │ │ ├── GlobalKeyHook.tsx │ │ │ ├── IpcHandlers.tsx │ │ │ ├── Menu.tsx │ │ │ ├── RpcServer.tsx │ │ │ ├── Spellcheck.tsx │ │ │ ├── Updater.tsx │ │ │ ├── Window.tsx │ │ │ ├── WindowsBadge.tsx │ │ │ └── index.tsx │ │ └── preload/ │ │ └── index.tsx │ └── tsconfig.json ├── fluxer_devops/ │ ├── caddy/ │ │ ├── Caddyfile.global │ │ └── compose.yaml │ ├── caddy-gateway/ │ │ ├── Caddyfile.global │ │ └── compose.yaml │ ├── cassandra/ │ │ ├── Dockerfile.backup │ │ ├── RESTORE.md │ │ ├── backup.sh │ │ ├── compose.yaml │ │ ├── conf/ │ │ │ ├── cassandra.yaml │ │ │ └── jvm-server.options │ │ └── migrations/ │ │ ├── 20251019182829_init.cql │ │ ├── 20251020105255_visionary_gifts.cql │ │ ├── 20251020111123_beta_code_allowance.cql │ │ ├── 20251020162124_premium_cancel.cql │ │ ├── 20251020162528_premium_cycle.cql │ │ ├── 20251021024919_payments_v2.cql │ │ ├── 20251021141627_gift_inventory_ack.cql │ │ ├── 20251021172928_visionary_slots_v2.cql │ │ ├── 20251022154916_favorite_meme_gifv.cql │ │ ├── 20251023131948_pinned_dms.cql │ │ ├── 20251027204850_voice_regions_v2.cql │ │ ├── 20251030154245_incoming_call_flags.cql │ │ ├── 20251030181703_group_dm_add_permission_flags.cql │ │ ├── 20251103134142_favorite_meme_tenor_id.cql │ │ ├── 20251106171446_global_names.cql │ │ ├── 20251106222624_premium_onboarding_dismiss.cql │ │ ├── 20251111164136_oauth.cql │ │ ├── 20251112093000_favorite_meme_tenor_id_str.cql │ │ ├── 20251112134500_oidc_keys_refactor.cql │ │ ├── 20251125170255_guild_member_profile_flags.cql │ │ ├── 20251202000000_push_devices.cql │ │ ├── 20251203135719_push_devices_by_fcm_token.cql │ │ ├── 20251203141656_add_ttls_devices_subscriptions.cql │ │ ├── 20251203144440_applications_and_bots.cql │ │ ├── 20251203145112_oauth_bot_tokens_by_client.cql │ │ ├── 20251204115402_oauth2_v2.cql │ │ ├── 20251205000000_fix_authorized_ips_schema.cql │ │ ├── 20251205231839_add_guild_banner_height.cql │ │ ├── 20251205233545_add_guild_banner_width.cql │ │ ├── 20251206120000_add_bot_is_public_to_applications.cql │ │ ├── 20251206163442_add_admin_archives.cql │ │ ├── 20251206164609_adjust_oauth2_access_token_ttl_7d.cql │ │ ├── 20251206180000_attachment_decay.cql │ │ ├── 20251207120000_email_change.cql │ │ ├── 20251208120000_email_change_original_proof.cql │ │ ├── 20251212120000_user_contact_change_logs.cql │ │ ├── 20251213100000_user_avatar_banner_color.cql │ │ ├── 20251214191436_guild_audit_logs_v2.cql │ │ ├── 20251215120000_pending_bulk_message_deletion.cql │ │ ├── 20251215130000_add_guild_splash_dimensions.cql │ │ ├── 20251215140000_add_guild_embed_splash.cql │ │ ├── 20251216233434_channel_state_and_bucket_index.cql │ │ ├── 20251217020455_empty_buckets.cql │ │ ├── 20251217173221_payments_version.cql │ │ ├── 20251217180000_add_version_columns.cql │ │ ├── 20251219003157_guild_splash_card_alignment.cql │ │ ├── 20251223200236_messages_has_reaction.cql │ │ ├── 20251224122758_instance_configuration.cql │ │ ├── 20251225000000_expression_packs.cql │ │ ├── 20251225012439_add_pending_verification_metadata.cql │ │ ├── 20251225120000_add_auth_session_location.cql │ │ ├── 20251225170000_add_scheduled_messages.cql │ │ ├── 20251225183000_reports_dsa.cql │ │ ├── 20251225194859_expression_packs_by_creator.cql │ │ ├── 20251226120000_status_expiry.cql │ │ ├── 20251229143845_add_role_hoist_position.cql │ │ ├── 20251229154931_swish_payments.cql │ │ ├── 20260105174407_add_auth_session_user_agent_cols.cql │ │ ├── 20260106001944_user_dm_history.cql │ │ ├── 20260107131535_add_edited_timestamp_to_message_snapshot.cql │ │ ├── 20260108222247_user_traits.cql │ │ ├── 20260109000910_bot_restricted_guild_settings.cql │ │ ├── 20260109002750_system_dm_jobs.cql │ │ ├── 20260109193656_admin_api_keys.cql │ │ ├── 20260109200406_add_admin_api_key_acls.cql │ │ ├── 20260109233843_relationships_by_target.cql │ │ ├── 20260110232608_fix_messages_by_author_clustering_key.cql │ │ ├── 20260113011925_csam_evidence_hold.cql │ │ ├── 20260113020449_csam_scan_jobs.cql │ │ ├── 20260114000000_csam_evidence_expirations.cql │ │ ├── 20260114120000_sticker_animated.cql │ │ ├── 20260114150000_message_sticker_item_animated.cql │ │ ├── 20260116171533_ncmec_submissions.cql │ │ ├── 20260122123000_voice_messages.cql │ │ ├── 20260129195639_add_klipy_slug_to_favorite_memes.cql │ │ ├── 20260130142437_trusted_domains.cql │ │ ├── 20260130160000_default_hide_muted_channels.cql │ │ ├── 20260205224843_guild_folder_flags_and_icon.cql │ │ ├── 20260206172322_message_embed_children.cql │ │ ├── 20260207140000_guild_message_history_cutoff.cql │ │ ├── 20260207160000_guild_members_indexed_at.cql │ │ ├── 20260207160233_user_connections.cql │ │ ├── 20260208165214_donation_system_unified.cql │ │ ├── 20260214120000_password_change_tickets.cql │ │ ├── 20260214123000_bot_require_code_grant.cql │ │ └── 20260217140000_guild_discovery.cql │ ├── clamav/ │ │ ├── compose.yaml │ │ └── conf/ │ │ └── clamd.conf │ ├── ghost_blog/ │ │ └── compose.yaml │ ├── livekitctl/ │ │ ├── README.md │ │ ├── cmd/ │ │ │ ├── bootstrap.go │ │ │ ├── logs.go │ │ │ ├── restart.go │ │ │ ├── root.go │ │ │ ├── status.go │ │ │ └── webhook.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── internal/ │ │ │ ├── configgen/ │ │ │ │ └── configgen.go │ │ │ ├── constants/ │ │ │ │ └── constants.go │ │ │ ├── dnswait/ │ │ │ │ └── dnswait.go │ │ │ ├── download/ │ │ │ │ └── download.go │ │ │ ├── errors/ │ │ │ │ └── errors.go │ │ │ ├── firewall/ │ │ │ │ └── firewall.go │ │ │ ├── install/ │ │ │ │ └── install.go │ │ │ ├── netutil/ │ │ │ │ └── netutil.go │ │ │ ├── ops/ │ │ │ │ └── ops.go │ │ │ ├── platform/ │ │ │ │ └── platform.go │ │ │ ├── secrets/ │ │ │ │ └── secrets.go │ │ │ ├── state/ │ │ │ │ └── state.go │ │ │ ├── util/ │ │ │ │ └── util.go │ │ │ └── validate/ │ │ │ └── validate.go │ │ ├── main.go │ │ └── scripts/ │ │ └── install.sh │ ├── nats_core/ │ │ ├── compose.yaml │ │ └── nats.conf │ ├── nats_jetstream/ │ │ ├── compose.yaml │ │ └── nats.conf │ ├── nginx/ │ │ └── nginx.conf │ ├── signoz/ │ │ ├── compose.yaml │ │ ├── conf/ │ │ │ ├── clickhouse/ │ │ │ │ ├── cluster.xml │ │ │ │ ├── config.d/ │ │ │ │ │ └── keeper.xml │ │ │ │ ├── config.xml │ │ │ │ ├── custom-function.xml │ │ │ │ ├── user_scripts/ │ │ │ │ │ └── .gitkeep │ │ │ │ └── users.xml │ │ │ └── signoz/ │ │ │ ├── otel-collector-config.yaml │ │ │ ├── otel-collector-opamp-config.yaml │ │ │ └── prometheus.yml │ │ ├── dashboards/ │ │ │ └── .gitkeep │ │ └── deploy.sh │ ├── turborepo_cache/ │ │ └── compose.yaml │ ├── valkey/ │ │ ├── compose.yaml │ │ ├── conf/ │ │ │ └── valkey.conf.template │ │ └── entrypoint.sh │ └── weblate/ │ └── compose.yaml ├── fluxer_docs/ │ ├── .gitignore │ ├── .npmrc │ ├── LICENSE │ ├── api-reference/ │ │ ├── introduction.mdx │ │ └── openapi.json │ ├── docs.json │ ├── gateway/ │ │ ├── close_codes.mdx │ │ ├── connection_lifecycle.mdx │ │ ├── events.mdx │ │ ├── opcodes.mdx │ │ └── overview.mdx │ ├── index.mdx │ ├── introduction/ │ │ └── authentication.mdx │ ├── media-proxy-api/ │ │ └── openapi.json │ ├── quickstart.mdx │ ├── relay-api/ │ │ └── openapi.json │ ├── resources/ │ │ ├── admin.mdx │ │ ├── auth.mdx │ │ ├── billing.mdx │ │ ├── channels.mdx │ │ ├── common.mdx │ │ ├── gateway.mdx │ │ ├── gifts.mdx │ │ ├── guilds.mdx │ │ ├── instance.mdx │ │ ├── invites.mdx │ │ ├── klipy.mdx │ │ ├── media_proxy.mdx │ │ ├── oauth2.mdx │ │ ├── overview.mdx │ │ ├── packs.mdx │ │ ├── premium.mdx │ │ ├── read_states.mdx │ │ ├── reports.mdx │ │ ├── saved_media.mdx │ │ ├── search.mdx │ │ ├── themes.mdx │ │ ├── users.mdx │ │ └── webhooks.mdx │ ├── schemas/ │ │ └── events/ │ │ ├── AUTH_SESSION_CHANGE.json │ │ ├── CALL_CREATE.json │ │ ├── CALL_DELETE.json │ │ ├── CALL_UPDATE.json │ │ ├── CHANNEL_CREATE.json │ │ ├── CHANNEL_DELETE.json │ │ ├── CHANNEL_PINS_ACK.json │ │ ├── CHANNEL_PINS_UPDATE.json │ │ ├── CHANNEL_RECIPIENT_ADD.json │ │ ├── CHANNEL_RECIPIENT_REMOVE.json │ │ ├── CHANNEL_UPDATE.json │ │ ├── CHANNEL_UPDATE_BULK.json │ │ ├── FAVORITE_MEME_CREATE.json │ │ ├── FAVORITE_MEME_DELETE.json │ │ ├── FAVORITE_MEME_UPDATE.json │ │ ├── GUILD_BAN_ADD.json │ │ ├── GUILD_BAN_REMOVE.json │ │ ├── GUILD_CREATE.json │ │ ├── GUILD_DELETE.json │ │ ├── GUILD_EMOJIS_UPDATE.json │ │ ├── GUILD_MEMBER_ADD.json │ │ ├── GUILD_MEMBER_REMOVE.json │ │ ├── GUILD_MEMBER_UPDATE.json │ │ ├── GUILD_ROLE_CREATE.json │ │ ├── GUILD_ROLE_DELETE.json │ │ ├── GUILD_ROLE_UPDATE.json │ │ ├── GUILD_ROLE_UPDATE_BULK.json │ │ ├── GUILD_STICKERS_UPDATE.json │ │ ├── GUILD_UPDATE.json │ │ ├── INVITE_CREATE.json │ │ ├── INVITE_DELETE.json │ │ ├── MESSAGE_ACK.json │ │ ├── MESSAGE_CREATE.json │ │ ├── MESSAGE_DELETE.json │ │ ├── MESSAGE_DELETE_BULK.json │ │ ├── MESSAGE_REACTION_ADD.json │ │ ├── MESSAGE_REACTION_ADD_MANY.json │ │ ├── MESSAGE_REACTION_REMOVE.json │ │ ├── MESSAGE_REACTION_REMOVE_ALL.json │ │ ├── MESSAGE_REACTION_REMOVE_EMOJI.json │ │ ├── MESSAGE_UPDATE.json │ │ ├── PRESENCE_UPDATE.json │ │ ├── READY.json │ │ ├── RECENT_MENTION_DELETE.json │ │ ├── RELATIONSHIP_ADD.json │ │ ├── RELATIONSHIP_REMOVE.json │ │ ├── RELATIONSHIP_UPDATE.json │ │ ├── RESUMED.json │ │ ├── SAVED_MESSAGE_CREATE.json │ │ ├── SAVED_MESSAGE_DELETE.json │ │ ├── SESSIONS_REPLACE.json │ │ ├── TYPING_START.json │ │ ├── USER_GUILD_SETTINGS_UPDATE.json │ │ ├── USER_NOTE_UPDATE.json │ │ ├── USER_PINNED_DMS_UPDATE.json │ │ ├── USER_SETTINGS_UPDATE.json │ │ ├── USER_UPDATE.json │ │ ├── VOICE_SERVER_UPDATE.json │ │ ├── VOICE_STATE_UPDATE.json │ │ └── WEBHOOKS_UPDATE.json │ ├── scripts/ │ │ ├── check_broken_links.mjs │ │ ├── generate_config.mjs │ │ ├── generate_error_codes.mjs │ │ ├── generate_gateway.mjs │ │ ├── generate_media_proxy.mjs │ │ ├── generate_permissions.mjs │ │ ├── generate_resources.mjs │ │ ├── generate_scopes.mjs │ │ └── shared.mjs │ ├── self-hosting/ │ │ ├── architecture.mdx │ │ ├── configuration.mdx │ │ ├── index.mdx │ │ ├── quickstart.mdx │ │ ├── upgrading.mdx │ │ └── voice.mdx │ ├── style.css │ └── topics/ │ ├── audit_log.mdx │ ├── error_codes.mdx │ ├── media_proxy.mdx │ ├── oauth2.mdx │ ├── permissions.mdx │ ├── rate_limits.mdx │ ├── snowflakes.mdx │ └── voice.mdx ├── fluxer_gateway/ │ ├── Dockerfile │ ├── config/ │ │ ├── sys.config.template │ │ ├── vm.args.src │ │ └── vm.args.template │ ├── dialyzer.ignore-warnings │ ├── include/ │ │ ├── timeout_config.hrl │ │ └── voice_state.hrl │ ├── rebar.config │ ├── scripts/ │ │ ├── docker_entrypoint.sh │ │ ├── rebar3_wrapper.sh │ │ ├── run_compile.sh │ │ ├── run_dialyzer.sh │ │ ├── run_eunit.sh │ │ ├── run_fmt.sh │ │ └── run_prod_compile.sh │ └── src/ │ ├── call/ │ │ ├── call.erl │ │ └── call_manager.erl │ ├── fluxer_gateway.app.src │ ├── gateway/ │ │ ├── fluxer_gateway_app.erl │ │ ├── fluxer_gateway_config.erl │ │ ├── fluxer_gateway_crypto.erl │ │ ├── fluxer_gateway_env.erl │ │ ├── fluxer_gateway_sup.erl │ │ ├── gateway_codec.erl │ │ ├── gateway_compress.erl │ │ ├── gateway_errors.erl │ │ ├── gateway_handler.erl │ │ ├── gateway_http_client.erl │ │ ├── gateway_nats_rpc.erl │ │ ├── gateway_rpc_call.erl │ │ ├── gateway_rpc_guild.erl │ │ ├── gateway_rpc_misc.erl │ │ ├── gateway_rpc_presence.erl │ │ ├── gateway_rpc_push.erl │ │ ├── gateway_rpc_router.erl │ │ ├── gateway_rpc_voice.erl │ │ ├── health_handler.erl │ │ ├── hot_reload.erl │ │ ├── hot_reload_handler.erl │ │ ├── rendezvous_router.erl │ │ └── rpc_client.erl │ ├── guild/ │ │ ├── guild.erl │ │ ├── guild_availability.erl │ │ ├── guild_client.erl │ │ ├── guild_common.erl │ │ ├── guild_counts_cache.erl │ │ ├── guild_data.erl │ │ ├── guild_data_index.erl │ │ ├── guild_dispatch.erl │ │ ├── guild_ets_utils.erl │ │ ├── guild_manager.erl │ │ ├── guild_manager_shard.erl │ │ ├── guild_member_list.erl │ │ ├── guild_member_list_common.erl │ │ ├── guild_member_storage.erl │ │ ├── guild_members.erl │ │ ├── guild_passive_sync.erl │ │ ├── guild_permission_cache.erl │ │ ├── guild_permissions.erl │ │ ├── guild_presence.erl │ │ ├── guild_query_handler.erl │ │ ├── guild_request_members.erl │ │ ├── guild_sessions.erl │ │ ├── guild_state.erl │ │ ├── guild_subscription_handler.erl │ │ ├── guild_subscriptions.erl │ │ ├── guild_unified_subscriptions.erl │ │ ├── guild_user_data.erl │ │ ├── guild_virtual_channel_access.erl │ │ ├── guild_visibility.erl │ │ ├── guild_voice_handler.erl │ │ ├── passive_sync_registry.erl │ │ ├── very_large_guild.erl │ │ ├── very_large_guild_member_list.erl │ │ └── voice/ │ │ ├── dm_voice.erl │ │ ├── guild_voice.erl │ │ ├── guild_voice_broadcast.erl │ │ ├── guild_voice_connection.erl │ │ ├── guild_voice_disconnect.erl │ │ ├── guild_voice_member.erl │ │ ├── guild_voice_move.erl │ │ ├── guild_voice_permission_sync.erl │ │ ├── guild_voice_permissions.erl │ │ ├── guild_voice_region.erl │ │ ├── guild_voice_server.erl │ │ ├── guild_voice_state.erl │ │ ├── guild_voice_unclaimed_account_utils.erl │ │ ├── voice_disconnect_common.erl │ │ ├── voice_pending_common.erl │ │ ├── voice_state_utils.erl │ │ └── voice_utils.erl │ ├── presence/ │ │ ├── presence.erl │ │ ├── presence_bus.erl │ │ ├── presence_bus_shard.erl │ │ ├── presence_cache.erl │ │ ├── presence_cache_shard.erl │ │ ├── presence_manager.erl │ │ ├── presence_manager_shard.erl │ │ ├── presence_payload.erl │ │ ├── presence_session.erl │ │ ├── presence_status.erl │ │ ├── presence_targets.erl │ │ └── presence_utils.erl │ ├── push/ │ │ ├── push.erl │ │ ├── push_cache.erl │ │ ├── push_core.erl │ │ ├── push_dispatcher.erl │ │ ├── push_eligibility.erl │ │ ├── push_notification.erl │ │ ├── push_sender.erl │ │ ├── push_subscriptions.erl │ │ └── push_utils.erl │ ├── session/ │ │ ├── session.erl │ │ ├── session_connection.erl │ │ ├── session_dispatch.erl │ │ ├── session_manager.erl │ │ ├── session_manager_shard.erl │ │ ├── session_monitor.erl │ │ ├── session_passive.erl │ │ ├── session_ready.erl │ │ └── session_voice.erl │ ├── telemetry/ │ │ ├── gateway_metrics_collector.erl │ │ ├── gateway_tracing.erl │ │ ├── guild_crash_logger.erl │ │ ├── otel_metrics.erl │ │ ├── process_memory_stats.erl │ │ └── process_registry.erl │ └── utils/ │ ├── backoff_utils.erl │ ├── constants.erl │ ├── custom_status_validation.erl │ ├── event_atoms.erl │ ├── list_ops.erl │ ├── map_utils.erl │ ├── snowflake_util.erl │ ├── type_conv.erl │ ├── user_utils.erl │ ├── utils.erl │ └── validation.erl ├── fluxer_integration/ │ ├── docker/ │ │ ├── compose.yaml │ │ ├── config.json │ │ └── livekit.yaml │ ├── package.json │ ├── scripts/ │ │ ├── run_integration.sh │ │ ├── server_logs.sh │ │ ├── server_start.sh │ │ └── server_stop.sh │ ├── src/ │ │ ├── Config.tsx │ │ ├── Setup.tsx │ │ ├── gateway/ │ │ │ ├── GatewayClient.tsx │ │ │ ├── GatewayConnection.test.tsx │ │ │ ├── GatewayGuildEvents.test.tsx │ │ │ ├── GatewayTypes.tsx │ │ │ └── GatewayVoiceState.test.tsx │ │ ├── globalSetup.tsx │ │ ├── globalTeardown.tsx │ │ └── helpers/ │ │ ├── AccountHelper.tsx │ │ ├── ApiClient.tsx │ │ ├── GuildHelper.tsx │ │ └── VoiceHelper.tsx │ ├── tsconfig.json │ └── vitest.config.ts ├── fluxer_marketing/ │ ├── Dockerfile │ ├── package.json │ ├── src/ │ │ ├── App.tsx │ │ ├── Config.tsx │ │ ├── HonoJsx.d.ts │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ └── index.tsx │ └── tsconfig.json ├── fluxer_media_proxy/ │ ├── Dockerfile │ ├── data/ │ │ └── model.onnx │ ├── package.json │ ├── src/ │ │ ├── App.tsx │ │ ├── AppMain.tsx │ │ ├── Config.tsx │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ ├── Metrics.tsx │ │ └── Tracing.tsx │ └── tsconfig.json ├── fluxer_relay/ │ ├── Dockerfile │ ├── config/ │ │ ├── relay.json │ │ ├── sys.config.src │ │ └── vm.args.src │ ├── rebar.config │ └── src/ │ ├── fluxer_relay.app.src │ └── relay/ │ ├── fluxer_relay_app.erl │ ├── fluxer_relay_config.erl │ ├── fluxer_relay_connection_manager.erl │ ├── fluxer_relay_env.erl │ ├── fluxer_relay_health_handler.erl │ ├── fluxer_relay_http_handler.erl │ ├── fluxer_relay_instance_discovery.erl │ ├── fluxer_relay_sup.erl │ └── fluxer_relay_ws_handler.erl ├── fluxer_relay_directory/ │ ├── Dockerfile │ ├── config/ │ │ └── directory.json │ ├── package.json │ ├── scripts/ │ │ └── GenerateOpenAPI.tsx │ ├── src/ │ │ ├── App.tsx │ │ ├── Config.tsx │ │ ├── Logger.tsx │ │ ├── controllers/ │ │ │ └── RelayController.tsx │ │ ├── database/ │ │ │ └── Database.tsx │ │ ├── index.tsx │ │ ├── middleware/ │ │ │ ├── ServiceMiddleware.tsx │ │ │ └── Validator.tsx │ │ ├── repositories/ │ │ │ └── RelayRepository.tsx │ │ └── services/ │ │ ├── GeoSelectionService.tsx │ │ ├── HealthCheckService.tsx │ │ └── RelayRegistryService.tsx │ └── tsconfig.json ├── fluxer_server/ │ ├── .dockerignore │ ├── Dockerfile │ ├── Dockerfile.dev │ ├── package.json │ ├── src/ │ │ ├── Config.tsx │ │ ├── HealthCheck.tsx │ │ ├── Instrument.tsx │ │ ├── Logger.tsx │ │ ├── Routes.tsx │ │ ├── ServiceInitializer.tsx │ │ ├── index.tsx │ │ ├── startServer.tsx │ │ └── utils/ │ │ ├── ConfigUtils.tsx │ │ ├── GatewayProcessManager.tsx │ │ └── GatewayProxy.tsx │ └── tsconfig.json ├── knip.json ├── package.json ├── packages/ │ ├── admin/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── AccessControlList.tsx │ │ │ ├── AdminPackageConstants.tsx │ │ │ ├── App.tsx │ │ │ ├── HonoJsx.d.ts │ │ │ ├── Navigation.tsx │ │ │ ├── Oauth2.tsx │ │ │ ├── PublicDir.tsx │ │ │ ├── SelfHostedOverride.tsx │ │ │ ├── Session.tsx │ │ │ ├── api/ │ │ │ │ ├── AdminApiKeys.tsx │ │ │ │ ├── Archives.tsx │ │ │ │ ├── Assets.tsx │ │ │ │ ├── Audit.tsx │ │ │ │ ├── Bans.tsx │ │ │ │ ├── Bulk.tsx │ │ │ │ ├── Client.tsx │ │ │ │ ├── Codes.tsx │ │ │ │ ├── Discovery.tsx │ │ │ │ ├── Errors.tsx │ │ │ │ ├── GuildAssets.tsx │ │ │ │ ├── Guilds.tsx │ │ │ │ ├── InstanceConfig.tsx │ │ │ │ ├── JsonTypes.tsx │ │ │ │ ├── LimitConfig.tsx │ │ │ │ ├── Messages.tsx │ │ │ │ ├── Reports.tsx │ │ │ │ ├── Search.tsx │ │ │ │ ├── System.tsx │ │ │ │ ├── SystemDm.tsx │ │ │ │ ├── Users.tsx │ │ │ │ ├── VisionarySlots.tsx │ │ │ │ └── Voice.tsx │ │ │ ├── components/ │ │ │ │ ├── ErrorDisplay.tsx │ │ │ │ ├── Icons.tsx │ │ │ │ ├── Layout.tsx │ │ │ │ ├── MessageList.tsx │ │ │ │ ├── UserProfileBadges.tsx │ │ │ │ ├── VoiceComponents.tsx │ │ │ │ └── ui/ │ │ │ │ ├── Alert.tsx │ │ │ │ ├── Badge.tsx │ │ │ │ ├── Card.tsx │ │ │ │ ├── CardBody.tsx │ │ │ │ ├── CardFooter.tsx │ │ │ │ ├── CardHeader.tsx │ │ │ │ ├── Chip.tsx │ │ │ │ ├── CodeBlock.tsx │ │ │ │ ├── Container.tsx │ │ │ │ ├── EmptyState.tsx │ │ │ │ ├── Form/ │ │ │ │ │ ├── FormActions.tsx │ │ │ │ │ ├── FormCard.tsx │ │ │ │ │ ├── FormFieldGroup.tsx │ │ │ │ │ ├── FormRow.tsx │ │ │ │ │ └── FormSection.tsx │ │ │ │ ├── Grid.tsx │ │ │ │ ├── InlineStack.tsx │ │ │ │ ├── Input.tsx │ │ │ │ ├── Layout/ │ │ │ │ │ ├── Box.tsx │ │ │ │ │ ├── DetailPageLayout.tsx │ │ │ │ │ ├── Flex.tsx │ │ │ │ │ ├── FormGrid.tsx │ │ │ │ │ ├── HStack.tsx │ │ │ │ │ ├── PageContainer.tsx │ │ │ │ │ ├── PageHeader.tsx │ │ │ │ │ ├── PageLayout.tsx │ │ │ │ │ ├── SearchListPageLayout.tsx │ │ │ │ │ ├── TwoColumnGrid.tsx │ │ │ │ │ └── VStack.tsx │ │ │ │ ├── MetadataRow.tsx │ │ │ │ ├── NavLink.tsx │ │ │ │ ├── Pill.tsx │ │ │ │ ├── ResourceLink.tsx │ │ │ │ ├── Select.tsx │ │ │ │ ├── Stack.tsx │ │ │ │ ├── StatusBadge.tsx │ │ │ │ ├── Table.tsx │ │ │ │ ├── TableBody.tsx │ │ │ │ ├── TableCell.tsx │ │ │ │ ├── TableContainer.tsx │ │ │ │ ├── TableHeader.tsx │ │ │ │ ├── TableHeaderCell.tsx │ │ │ │ ├── TableRow.tsx │ │ │ │ ├── TextLink.tsx │ │ │ │ ├── Textarea.tsx │ │ │ │ └── Typography.tsx │ │ │ ├── hooks/ │ │ │ │ └── usePaginationUrl.ts │ │ │ ├── middleware/ │ │ │ │ ├── Auth.tsx │ │ │ │ ├── Csrf.tsx │ │ │ │ └── ErrorHandler.tsx │ │ │ ├── navigation/ │ │ │ │ └── NavigationTypes.tsx │ │ │ ├── pages/ │ │ │ │ ├── AdminApiKeysPage.tsx │ │ │ │ ├── ArchivesPage.tsx │ │ │ │ ├── AssetPurgePage.tsx │ │ │ │ ├── AuditLogsPage.tsx │ │ │ │ ├── BanManagementPage.tsx │ │ │ │ ├── BulkActionsPage.tsx │ │ │ │ ├── DiscoveryPage.tsx │ │ │ │ ├── GatewayPage.tsx │ │ │ │ ├── GiftCodesPage.tsx │ │ │ │ ├── GuildDetailPage.tsx │ │ │ │ ├── GuildsPage.tsx │ │ │ │ ├── InstanceConfigPage.tsx │ │ │ │ ├── LimitConfigPage.tsx │ │ │ │ ├── LoginPage.tsx │ │ │ │ ├── MessagesPage.tsx │ │ │ │ ├── ReportDetailPage.tsx │ │ │ │ ├── ReportsPage.tsx │ │ │ │ ├── SearchIndexPage.tsx │ │ │ │ ├── StrangePlacePage.tsx │ │ │ │ ├── SystemDmPage.tsx │ │ │ │ ├── UserDetailPage.tsx │ │ │ │ ├── UsersPage.tsx │ │ │ │ ├── VisionarySlotsPage.tsx │ │ │ │ ├── VoiceRegionsPage.tsx │ │ │ │ ├── VoiceServersPage.tsx │ │ │ │ ├── guild_detail/ │ │ │ │ │ ├── Forms.tsx │ │ │ │ │ └── tabs/ │ │ │ │ │ ├── EmojisTab.tsx │ │ │ │ │ ├── FeaturesTab.tsx │ │ │ │ │ ├── MembersTab.tsx │ │ │ │ │ ├── ModerationTab.tsx │ │ │ │ │ ├── OverviewTab.tsx │ │ │ │ │ ├── SettingsTab.tsx │ │ │ │ │ └── StickersTab.tsx │ │ │ │ └── user_detail/ │ │ │ │ ├── Forms.tsx │ │ │ │ └── tabs/ │ │ │ │ ├── AccountTab.tsx │ │ │ │ ├── DmHistoryTab.tsx │ │ │ │ ├── GuildsTab.tsx │ │ │ │ ├── ModerationTab.tsx │ │ │ │ └── OverviewTab.tsx │ │ │ ├── routes/ │ │ │ │ ├── Admin.tsx │ │ │ │ ├── Auth.tsx │ │ │ │ ├── Bans.tsx │ │ │ │ ├── Codes.tsx │ │ │ │ ├── Discovery.tsx │ │ │ │ ├── Guilds.tsx │ │ │ │ ├── Messages.tsx │ │ │ │ ├── Reports.tsx │ │ │ │ ├── RouteContext.tsx │ │ │ │ ├── RouteTypes.tsx │ │ │ │ ├── System.tsx │ │ │ │ ├── Users.tsx │ │ │ │ ├── VisionarySlots.tsx │ │ │ │ └── Voice.tsx │ │ │ ├── styles/ │ │ │ │ └── app.css │ │ │ ├── types/ │ │ │ │ ├── App.tsx │ │ │ │ └── Config.tsx │ │ │ └── utils/ │ │ │ ├── Bigint.tsx │ │ │ ├── ClassNames.tsx │ │ │ ├── Forms.tsx │ │ │ └── User.tsx │ │ └── tsconfig.json │ ├── api/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.tsx │ │ │ ├── BrandedTypes.tsx │ │ │ ├── Config.tsx │ │ │ ├── ILogger.tsx │ │ │ ├── Logger.tsx │ │ │ ├── RateLimitConfig.tsx │ │ │ ├── SearchFactory.tsx │ │ │ ├── Tables.tsx │ │ │ ├── Telemetry.tsx │ │ │ ├── Validator.tsx │ │ │ ├── ZodErrorMap.tsx │ │ │ ├── admin/ │ │ │ │ ├── AdminRepository.tsx │ │ │ │ ├── AdminService.tsx │ │ │ │ ├── IAdminRepository.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ ├── AdminApiKeyAdminController.tsx │ │ │ │ │ ├── ArchiveAdminController.tsx │ │ │ │ │ ├── AssetAdminController.tsx │ │ │ │ │ ├── AuditLogAdminController.tsx │ │ │ │ │ ├── BanAdminController.tsx │ │ │ │ │ ├── BulkAdminController.tsx │ │ │ │ │ ├── ChildSafetyAdminController.tsx │ │ │ │ │ ├── CodesAdminController.tsx │ │ │ │ │ ├── DiscoveryAdminController.tsx │ │ │ │ │ ├── GatewayAdminController.tsx │ │ │ │ │ ├── GuildAdminController.tsx │ │ │ │ │ ├── InstanceConfigAdminController.tsx │ │ │ │ │ ├── LimitConfigAdminController.tsx │ │ │ │ │ ├── MessageAdminController.tsx │ │ │ │ │ ├── ReportAdminController.tsx │ │ │ │ │ ├── SearchAdminController.tsx │ │ │ │ │ ├── SnowflakeReservationAdminController.tsx │ │ │ │ │ ├── SystemDmAdminController.tsx │ │ │ │ │ ├── UserAdminController.tsx │ │ │ │ │ ├── VisionarySlotAdminController.tsx │ │ │ │ │ ├── VoiceAdminController.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── models/ │ │ │ │ │ ├── AdminArchiveModel.tsx │ │ │ │ │ ├── GuildTypes.tsx │ │ │ │ │ └── UserTypes.tsx │ │ │ │ ├── repositories/ │ │ │ │ │ ├── AdminApiKeyRepository.tsx │ │ │ │ │ ├── AdminArchiveRepository.tsx │ │ │ │ │ ├── IAdminApiKeyRepository.tsx │ │ │ │ │ └── SystemDmJobRepository.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── AdminApiKeyService.tsx │ │ │ │ │ ├── AdminArchiveService.tsx │ │ │ │ │ ├── AdminAssetPurgeService.tsx │ │ │ │ │ ├── AdminAuditService.tsx │ │ │ │ │ ├── AdminBanManagementService.tsx │ │ │ │ │ ├── AdminCodeGenerationService.tsx │ │ │ │ │ ├── AdminGuildService.tsx │ │ │ │ │ ├── AdminMessageDeletionService.tsx │ │ │ │ │ ├── AdminMessageService.tsx │ │ │ │ │ ├── AdminMessageShredService.tsx │ │ │ │ │ ├── AdminReportService.tsx │ │ │ │ │ ├── AdminSearchService.tsx │ │ │ │ │ ├── AdminSnowflakeReservationService.tsx │ │ │ │ │ ├── AdminUserBanService.tsx │ │ │ │ │ ├── AdminUserDeletionService.tsx │ │ │ │ │ ├── AdminUserLookupService.tsx │ │ │ │ │ ├── AdminUserProfileService.tsx │ │ │ │ │ ├── AdminUserSecurityService.tsx │ │ │ │ │ ├── AdminUserService.tsx │ │ │ │ │ ├── AdminUserUpdatePropagator.tsx │ │ │ │ │ ├── AdminVisionarySlotService.tsx │ │ │ │ │ ├── AdminVoiceService.tsx │ │ │ │ │ ├── SystemDmService.tsx │ │ │ │ │ └── guild/ │ │ │ │ │ ├── AdminGuildBulkService.tsx │ │ │ │ │ ├── AdminGuildLookupService.tsx │ │ │ │ │ ├── AdminGuildManagementService.tsx │ │ │ │ │ ├── AdminGuildMembershipService.tsx │ │ │ │ │ ├── AdminGuildUpdatePropagator.tsx │ │ │ │ │ ├── AdminGuildUpdateService.tsx │ │ │ │ │ └── AdminGuildVanityService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── AdminApiKeyACLValidation.test.tsx │ │ │ │ ├── AdminApiKeyAuthentication.test.tsx │ │ │ │ ├── AdminApiKeyAuthorization.test.tsx │ │ │ │ ├── AdminApiKeyLifecycle.test.tsx │ │ │ │ ├── AdminApiKeyManagement.test.tsx │ │ │ │ ├── AdminApiKeyRevocation.test.tsx │ │ │ │ ├── AdminArchivesList.test.tsx │ │ │ │ ├── AdminEndpointsAuthorization.test.tsx │ │ │ │ ├── AdminOAuth2ScopeRequirement.test.tsx │ │ │ │ ├── AdminSearchEndpoints.test.tsx │ │ │ │ ├── AdminSearchFieldCoverage.test.tsx │ │ │ │ ├── AdminTestUtils.tsx │ │ │ │ ├── DiscoveryAdminOperations.test.tsx │ │ │ │ ├── SecurityAccessControl.test.tsx │ │ │ │ └── VisionarySlotManagement.test.tsx │ │ │ ├── alert/ │ │ │ │ └── AlertService.tsx │ │ │ ├── app/ │ │ │ │ ├── APILifecycle.tsx │ │ │ │ ├── ControllerRegistry.tsx │ │ │ │ └── MiddlewarePipeline.tsx │ │ │ ├── attachment/ │ │ │ │ ├── AttachmentDecayRepository.tsx │ │ │ │ └── AttachmentDecayService.tsx │ │ │ ├── auth/ │ │ │ │ ├── AuthController.tsx │ │ │ │ ├── AuthModel.tsx │ │ │ │ ├── AuthRequestService.tsx │ │ │ │ ├── AuthService.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── AuthEmailRevertService.tsx │ │ │ │ │ ├── AuthEmailService.tsx │ │ │ │ │ ├── AuthLoginService.tsx │ │ │ │ │ ├── AuthMfaService.tsx │ │ │ │ │ ├── AuthPasswordService.tsx │ │ │ │ │ ├── AuthPhoneService.tsx │ │ │ │ │ ├── AuthRegistrationService.tsx │ │ │ │ │ ├── AuthSessionService.tsx │ │ │ │ │ ├── AuthUtilityService.tsx │ │ │ │ │ ├── DesktopHandoffService.tsx │ │ │ │ │ ├── SsoService.tsx │ │ │ │ │ ├── SsoUtils.tsx │ │ │ │ │ ├── SudoModeService.tsx │ │ │ │ │ └── SudoVerificationService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── AppStoreReviewerBypass.test.tsx │ │ │ │ ├── AppStoreReviewerMultiFlag.test.tsx │ │ │ │ ├── AuthSudoMFAMethods.test.tsx │ │ │ │ ├── AuthSudoPasswordVerification.test.tsx │ │ │ │ ├── AuthSudoRequiredOperations.test.tsx │ │ │ │ ├── AuthSudoTOTPVerification.test.tsx │ │ │ │ ├── AuthTestUtils.tsx │ │ │ │ ├── BouncedEmailRecoveryFlow.test.tsx │ │ │ │ ├── CaseInsensitiveEmail.test.tsx │ │ │ │ ├── ConcurrentSessions.test.tsx │ │ │ │ ├── DesktopHandoffCodeNormalization.test.tsx │ │ │ │ ├── DesktopHandoffFlow.test.tsx │ │ │ │ ├── DesktopHandoffNegative.test.tsx │ │ │ │ ├── DesktopHandoffUsage.test.tsx │ │ │ │ ├── EmailChangeFlow.test.tsx │ │ │ │ ├── EmailChangeResendCooldown.test.tsx │ │ │ │ ├── EmailRevertFlow.test.tsx │ │ │ │ ├── EmailVerificationFlow.test.tsx │ │ │ │ ├── EmailVerificationSuspiciousFlags.test.tsx │ │ │ │ ├── IPAuthBypassFlags.test.tsx │ │ │ │ ├── IPAuthFlow.test.tsx │ │ │ │ ├── IPAuthMultipleIPs.test.tsx │ │ │ │ ├── IPAuthPoll.test.tsx │ │ │ │ ├── IPAuthResend.test.tsx │ │ │ │ ├── IPAuthStream.test.tsx │ │ │ │ ├── IPAuthTicket.test.tsx │ │ │ │ ├── IPAuthTokenValidation.test.tsx │ │ │ │ ├── LoginAndSessions.test.tsx │ │ │ │ ├── LoginDisabledFlagRecovery.test.tsx │ │ │ │ ├── LoginInvalidCredentials.test.tsx │ │ │ │ ├── LoginInviteAutoJoin.test.tsx │ │ │ │ ├── LoginInviteInvalidCode.test.tsx │ │ │ │ ├── LoginSelfDeletedRecovery.test.tsx │ │ │ │ ├── MfaConsistency.test.tsx │ │ │ │ ├── MfaEndpoints.test.tsx │ │ │ │ ├── MfaSmsEnableDisable.test.tsx │ │ │ │ ├── MfaSmsLoginFlow.test.tsx │ │ │ │ ├── MfaTicketExpiryAndReuse.test.tsx │ │ │ │ ├── MfaTotpFlag.test.tsx │ │ │ │ ├── MfaTotpWithoutSecret.test.tsx │ │ │ │ ├── PasswordChange.test.tsx │ │ │ │ ├── PasswordReset.test.tsx │ │ │ │ ├── PhoneVerificationFlow.test.tsx │ │ │ │ ├── Registration.test.tsx │ │ │ │ ├── RegistrationValidation.test.tsx │ │ │ │ ├── ResetPasswordRequiresMfa.test.tsx │ │ │ │ ├── SecurityFlagsSuspiciousActivity.test.tsx │ │ │ │ ├── SettingsDefaults.test.tsx │ │ │ │ ├── SsoFlow.test.tsx │ │ │ │ ├── SudoModeNegativeCases.test.tsx │ │ │ │ ├── TokenValidation.test.tsx │ │ │ │ ├── UnclaimedAccountRestrictions.test.tsx │ │ │ │ ├── UnclaimedClaimFlow.test.tsx │ │ │ │ ├── WebAuthnAuthenticationReplay.test.tsx │ │ │ │ ├── WebAuthnAuthenticationWrongChallenge.test.tsx │ │ │ │ ├── WebAuthnCredentialDelete.test.tsx │ │ │ │ ├── WebAuthnCredentialList.test.tsx │ │ │ │ ├── WebAuthnCredentialRegister.test.tsx │ │ │ │ ├── WebAuthnCredentialRename.test.tsx │ │ │ │ ├── WebAuthnErrorLocalization.test.tsx │ │ │ │ ├── WebAuthnMfaConsistency.test.tsx │ │ │ │ ├── WebAuthnMfaLogin.test.tsx │ │ │ │ ├── WebAuthnPasswordlessLogin.test.tsx │ │ │ │ ├── WebAuthnRegistrationUserHandle.test.tsx │ │ │ │ ├── WebAuthnTestUtils.tsx │ │ │ │ └── WebAuthnUserVerificationRequired.test.tsx │ │ │ ├── bluesky/ │ │ │ │ ├── BlueskyOAuthController.tsx │ │ │ │ ├── BlueskyOAuthService.tsx │ │ │ │ ├── BlueskyOAuthStores.tsx │ │ │ │ ├── IBlueskyOAuthService.tsx │ │ │ │ └── tests/ │ │ │ │ └── BlueskyOAuth.test.tsx │ │ │ ├── bot/ │ │ │ │ └── tests/ │ │ │ │ ├── BotAuthorizeAllowsNoRedirect.test.tsx │ │ │ │ ├── BotAuthorizeWithGuildSelectionRedirects.test.tsx │ │ │ │ ├── BotTestUtils.tsx │ │ │ │ ├── BotTokenReset.test.tsx │ │ │ │ └── BotTokenResetWithMfaSudoMode.test.tsx │ │ │ ├── channel/ │ │ │ │ ├── AttachmentDTOs.tsx │ │ │ │ ├── ChannelController.tsx │ │ │ │ ├── ChannelMappers.tsx │ │ │ │ ├── ChannelRepository.tsx │ │ │ │ ├── EmbedTypes.tsx │ │ │ │ ├── IChannelRepository.tsx │ │ │ │ ├── MessageMappers.tsx │ │ │ │ ├── MessageTypes.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ ├── CallController.tsx │ │ │ │ │ ├── ChannelController.tsx │ │ │ │ │ ├── MessageController.tsx │ │ │ │ │ ├── MessageInteractionController.tsx │ │ │ │ │ ├── ScheduledMessageController.tsx │ │ │ │ │ ├── ScheduledMessageParsing.tsx │ │ │ │ │ ├── StreamController.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── repositories/ │ │ │ │ │ ├── ChannelDataRepository.tsx │ │ │ │ │ ├── ChannelRepository.tsx │ │ │ │ │ ├── IChannelDataRepository.tsx │ │ │ │ │ ├── IChannelRepositoryAggregate.tsx │ │ │ │ │ ├── IMessageInteractionRepository.tsx │ │ │ │ │ ├── IMessageRepository.tsx │ │ │ │ │ ├── MessageInteractionRepository.tsx │ │ │ │ │ ├── MessageRepository.tsx │ │ │ │ │ └── message/ │ │ │ │ │ ├── BucketScanEngine.tsx │ │ │ │ │ ├── MessageAttachmentRepository.tsx │ │ │ │ │ ├── MessageAuthorRepository.tsx │ │ │ │ │ ├── MessageDataRepository.tsx │ │ │ │ │ └── MessageDeletionRepository.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── AttachmentUploadService.tsx │ │ │ │ │ ├── AuthenticatedChannel.tsx │ │ │ │ │ ├── BaseChannelAuthService.tsx │ │ │ │ │ ├── CallService.tsx │ │ │ │ │ ├── ChannelDataService.tsx │ │ │ │ │ ├── ChannelRequestService.tsx │ │ │ │ │ ├── ChannelService.tsx │ │ │ │ │ ├── DMPermissionValidator.tsx │ │ │ │ │ ├── GroupDmService.tsx │ │ │ │ │ ├── MessageInteractionService.tsx │ │ │ │ │ ├── MessageService.tsx │ │ │ │ │ ├── ScheduledMessageService.tsx │ │ │ │ │ ├── StreamPreviewService.tsx │ │ │ │ │ ├── StreamService.tsx │ │ │ │ │ ├── channel_data/ │ │ │ │ │ │ ├── ChannelAuthService.tsx │ │ │ │ │ │ ├── ChannelOperationsService.tsx │ │ │ │ │ │ ├── ChannelUtilsService.tsx │ │ │ │ │ │ └── GroupDmUpdateService.tsx │ │ │ │ │ ├── group_dm/ │ │ │ │ │ │ ├── GroupDmHelpers.tsx │ │ │ │ │ │ └── GroupDmOperationsService.tsx │ │ │ │ │ ├── interaction/ │ │ │ │ │ │ ├── MessageInteractionAuthService.tsx │ │ │ │ │ │ ├── MessageInteractionBase.tsx │ │ │ │ │ │ ├── MessagePinService.tsx │ │ │ │ │ │ ├── MessageReactionService.tsx │ │ │ │ │ │ └── MessageReadStateService.tsx │ │ │ │ │ └── message/ │ │ │ │ │ ├── AttachmentProcessingService.tsx │ │ │ │ │ ├── DmScopeUtils.tsx │ │ │ │ │ ├── MessageAnonymizationService.tsx │ │ │ │ │ ├── MessageChannelAuthService.tsx │ │ │ │ │ ├── MessageContentService.tsx │ │ │ │ │ ├── MessageDeleteService.tsx │ │ │ │ │ ├── MessageDispatchService.tsx │ │ │ │ │ ├── MessageEditService.tsx │ │ │ │ │ ├── MessageEmbedAttachmentResolver.tsx │ │ │ │ │ ├── MessageHelpers.tsx │ │ │ │ │ ├── MessageMentionService.tsx │ │ │ │ │ ├── MessageOperationsHelpers.tsx │ │ │ │ │ ├── MessageOperationsService.tsx │ │ │ │ │ ├── MessagePersistenceService.tsx │ │ │ │ │ ├── MessageProcessingService.tsx │ │ │ │ │ ├── MessageRequestParser.tsx │ │ │ │ │ ├── MessageRequestService.tsx │ │ │ │ │ ├── MessageRetrievalService.tsx │ │ │ │ │ ├── MessageSearchService.tsx │ │ │ │ │ ├── MessageSendService.tsx │ │ │ │ │ ├── MessageStickerService.tsx │ │ │ │ │ ├── MessageSystemService.tsx │ │ │ │ │ ├── MessageValidationService.tsx │ │ │ │ │ └── ReadStateHelpers.tsx │ │ │ │ └── tests/ │ │ │ │ ├── AttachmentDecay.test.tsx │ │ │ │ ├── AttachmentTestUtils.tsx │ │ │ │ ├── AttachmentUploadValidation.test.tsx │ │ │ │ ├── BulkDeleteMessages.test.tsx │ │ │ │ ├── CallEndpoints.test.tsx │ │ │ │ ├── ChannelOperationPermissions.test.tsx │ │ │ │ ├── ChannelOperationValidation.test.tsx │ │ │ │ ├── ChannelPermissionOverwrites.test.tsx │ │ │ │ ├── ChannelTestUtils.tsx │ │ │ │ ├── DMBlockingBehaviors.test.tsx │ │ │ │ ├── DMChannelManagement.test.tsx │ │ │ │ ├── DMCreationAllowedWithFriendship.test.tsx │ │ │ │ ├── DMCreationAllowedWithMutualGuild.test.tsx │ │ │ │ ├── DMCreationRequiresFriendshipOrMutualGuild.test.tsx │ │ │ │ ├── EmbedAttachmentUrlResolution.test.tsx │ │ │ │ ├── GroupDMNameUpdate.test.tsx │ │ │ │ ├── GroupDMNicknameUpdate.test.tsx │ │ │ │ ├── GroupDMSecurityBoundaries.test.tsx │ │ │ │ ├── GroupDmAddRecipientPermissions.test.tsx │ │ │ │ ├── GroupDmLimit.test.tsx │ │ │ │ ├── GroupDmManagement.test.tsx │ │ │ │ ├── GroupDmRecipientLimit.test.tsx │ │ │ │ ├── MessageCustomEmojiSanitization.test.tsx │ │ │ │ ├── ScheduledMessageTestUtils.tsx │ │ │ │ ├── ScheduledMessageTraitGated.test.tsx │ │ │ │ ├── ScheduledMessageValidation.test.tsx │ │ │ │ ├── ScheduledMessageWorkerLifecycle.test.tsx │ │ │ │ ├── ScheduledMessagesListInvalidEntry.test.tsx │ │ │ │ ├── ScheduledMessagesListLifecycle.test.tsx │ │ │ │ ├── StreamPreviewAuth.test.tsx │ │ │ │ └── TypingIndicators.test.tsx │ │ │ ├── config/ │ │ │ │ └── APIConfig.tsx │ │ │ ├── connection/ │ │ │ │ ├── ConnectionController.tsx │ │ │ │ ├── ConnectionInitiationToken.tsx │ │ │ │ ├── ConnectionMappers.tsx │ │ │ │ ├── ConnectionRepository.tsx │ │ │ │ ├── ConnectionRequestService.tsx │ │ │ │ ├── ConnectionService.tsx │ │ │ │ ├── IConnectionRepository.tsx │ │ │ │ ├── IConnectionService.tsx │ │ │ │ ├── errors/ │ │ │ │ │ ├── BlueskyOAuthAuthorizationFailedError.tsx │ │ │ │ │ ├── BlueskyOAuthCallbackFailedError.tsx │ │ │ │ │ ├── BlueskyOAuthNotEnabledError.tsx │ │ │ │ │ ├── BlueskyOAuthSessionExpiredError.tsx │ │ │ │ │ ├── BlueskyOAuthStateInvalidError.tsx │ │ │ │ │ ├── ConnectionAlreadyExistsError.tsx │ │ │ │ │ ├── ConnectionInitiationTokenInvalidError.tsx │ │ │ │ │ ├── ConnectionInvalidTypeError.tsx │ │ │ │ │ ├── ConnectionLimitReachedError.tsx │ │ │ │ │ ├── ConnectionNotFoundError.tsx │ │ │ │ │ └── ConnectionVerificationFailedError.tsx │ │ │ │ ├── tests/ │ │ │ │ │ ├── ConnectionCrud.test.tsx │ │ │ │ │ ├── ConnectionTestUtils.tsx │ │ │ │ │ └── ConnectionVerification.test.tsx │ │ │ │ └── verification/ │ │ │ │ ├── BlueskyOAuthVerifier.tsx │ │ │ │ ├── DomainConnectionVerifier.tsx │ │ │ │ └── IConnectionVerifier.tsx │ │ │ ├── constants/ │ │ │ │ ├── Channel.tsx │ │ │ │ ├── Core.tsx │ │ │ │ ├── Gateway.tsx │ │ │ │ ├── InstanceConfig.tsx │ │ │ │ ├── IpBan.tsx │ │ │ │ └── LimitConfig.tsx │ │ │ ├── csam/ │ │ │ │ ├── CsamEvidenceRetentionService.tsx │ │ │ │ ├── CsamEvidenceService.tsx │ │ │ │ ├── CsamLegalHoldService.tsx │ │ │ │ ├── CsamReportSnapshotService.tsx │ │ │ │ ├── CsamResponseService.tsx │ │ │ │ ├── CsamScanJobService.tsx │ │ │ │ ├── CsamScanQueueService.tsx │ │ │ │ ├── CsamTypes.tsx │ │ │ │ ├── ICsamEvidenceService.tsx │ │ │ │ ├── ICsamReportSnapshotService.tsx │ │ │ │ ├── ISynchronousCsamScanner.tsx │ │ │ │ ├── NcmecReporter.tsx │ │ │ │ ├── NcmecSubmissionService.tsx │ │ │ │ ├── PhotoDnaHashClient.tsx │ │ │ │ ├── PhotoDnaMatchService.tsx │ │ │ │ ├── SynchronousCsamScanner.tsx │ │ │ │ ├── providers/ │ │ │ │ │ ├── ArachnidShieldProvider.tsx │ │ │ │ │ ├── CsamProviderFactory.tsx │ │ │ │ │ ├── ICsamScanProvider.tsx │ │ │ │ │ ├── PhotoDnaProvider.tsx │ │ │ │ │ └── tests/ │ │ │ │ │ ├── ArachnidShieldProvider.test.tsx │ │ │ │ │ └── PhotoDnaProvider.test.tsx │ │ │ │ └── tests/ │ │ │ │ ├── CsamBlockingBehavior.test.tsx │ │ │ │ ├── CsamEvidenceRetentionService.test.tsx │ │ │ │ ├── CsamLegalHoldExpiry.test.tsx │ │ │ │ ├── CsamLegalHoldService.test.tsx │ │ │ │ ├── CsamReportSnapshotService.test.tsx │ │ │ │ ├── CsamScanQueueService.test.tsx │ │ │ │ ├── CsamTestUtils.tsx │ │ │ │ ├── NcmecReporter.test.tsx │ │ │ │ ├── NcmecSubmissionService.test.tsx │ │ │ │ └── SynchronousCsamScanner.test.tsx │ │ │ ├── database/ │ │ │ │ ├── Cassandra.tsx │ │ │ │ ├── SqliteKV.tsx │ │ │ │ └── types/ │ │ │ │ ├── AdminArchiveTypes.tsx │ │ │ │ ├── AdminAuthTypes.tsx │ │ │ │ ├── AuthTypes.tsx │ │ │ │ ├── ChannelTypes.tsx │ │ │ │ ├── ConnectionTypes.tsx │ │ │ │ ├── CsamTypes.tsx │ │ │ │ ├── DatabaseRowTypes.tsx │ │ │ │ ├── DonationTypes.tsx │ │ │ │ ├── GuildDiscoveryTypes.tsx │ │ │ │ ├── GuildTypes.tsx │ │ │ │ ├── InstanceConfigTypes.tsx │ │ │ │ ├── MessageTypes.tsx │ │ │ │ ├── OAuth2Types.tsx │ │ │ │ ├── PaymentTypes.tsx │ │ │ │ ├── ReportTypes.tsx │ │ │ │ ├── SystemDmJobTypes.tsx │ │ │ │ ├── UserTypes.tsx │ │ │ │ └── VoiceTypes.tsx │ │ │ ├── donation/ │ │ │ │ ├── DonationController.tsx │ │ │ │ ├── DonationRepository.tsx │ │ │ │ ├── DonationService.tsx │ │ │ │ ├── DonationTables.tsx │ │ │ │ ├── IDonationRepository.tsx │ │ │ │ ├── IDonationService.tsx │ │ │ │ ├── models/ │ │ │ │ │ ├── Donor.tsx │ │ │ │ │ └── DonorMagicLinkToken.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── DonationCheckoutService.tsx │ │ │ │ │ └── DonationMagicLinkService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── DonationCheckout.test.tsx │ │ │ │ ├── DonationManage.test.tsx │ │ │ │ ├── DonationRequestLink.test.tsx │ │ │ │ └── DonationTestUtils.tsx │ │ │ ├── download/ │ │ │ │ ├── DownloadController.tsx │ │ │ │ ├── DownloadService.tsx │ │ │ │ └── tests/ │ │ │ │ └── DownloadService.test.tsx │ │ │ ├── email/ │ │ │ │ └── EmailProviderFactory.tsx │ │ │ ├── emoji/ │ │ │ │ └── tests/ │ │ │ │ ├── EmojiBulkCreate.test.tsx │ │ │ │ ├── EmojiNameValidation.test.tsx │ │ │ │ ├── EmojiPermissions.test.tsx │ │ │ │ ├── EmojiReactions.test.tsx │ │ │ │ ├── EmojiTestUtils.tsx │ │ │ │ ├── EmojiUploadValidPng.test.tsx │ │ │ │ ├── EmojiUploadValidation.test.tsx │ │ │ │ ├── StickerPermissions.test.tsx │ │ │ │ ├── StickerUploadValidation.test.tsx │ │ │ │ └── TypingIndicatorsPermissions.test.tsx │ │ │ ├── favorite_meme/ │ │ │ │ ├── FavoriteMemeController.tsx │ │ │ │ ├── FavoriteMemeModel.tsx │ │ │ │ ├── FavoriteMemeRepository.tsx │ │ │ │ ├── FavoriteMemeRequestService.tsx │ │ │ │ ├── FavoriteMemeService.tsx │ │ │ │ ├── IFavoriteMemeRepository.tsx │ │ │ │ └── tests/ │ │ │ │ └── FavoriteMemeExtended.test.tsx │ │ │ ├── federation/ │ │ │ │ ├── EncryptionMiddleware.tsx │ │ │ │ ├── KeyManager.tsx │ │ │ │ └── tests/ │ │ │ │ ├── EncryptionMiddleware.test.tsx │ │ │ │ └── KeyManager.test.tsx │ │ │ ├── gateway/ │ │ │ │ ├── GatewayController.tsx │ │ │ │ ├── GatewayRequestService.tsx │ │ │ │ └── tests/ │ │ │ │ └── GatewayRpcService.test.tsx │ │ │ ├── guild/ │ │ │ │ ├── GuildAuditLogService.tsx │ │ │ │ ├── GuildAuditLogTypes.tsx │ │ │ │ ├── GuildController.tsx │ │ │ │ ├── GuildFeatureUtils.tsx │ │ │ │ ├── GuildMemberLimitUtils.tsx │ │ │ │ ├── GuildModel.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ ├── GuildAuditLogController.tsx │ │ │ │ │ ├── GuildBaseController.tsx │ │ │ │ │ ├── GuildChannelController.tsx │ │ │ │ │ ├── GuildDiscoveryController.tsx │ │ │ │ │ ├── GuildEmojiController.tsx │ │ │ │ │ ├── GuildMemberController.tsx │ │ │ │ │ ├── GuildMemberSearchController.tsx │ │ │ │ │ ├── GuildRoleController.tsx │ │ │ │ │ ├── GuildStickerController.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── repositories/ │ │ │ │ │ ├── GuildContentRepository.tsx │ │ │ │ │ ├── GuildDataRepository.tsx │ │ │ │ │ ├── GuildDiscoveryRepository.tsx │ │ │ │ │ ├── GuildMemberRepository.tsx │ │ │ │ │ ├── GuildModerationRepository.tsx │ │ │ │ │ ├── GuildRepository.tsx │ │ │ │ │ ├── GuildRoleRepository.tsx │ │ │ │ │ ├── IGuildContentRepository.tsx │ │ │ │ │ ├── IGuildDataRepository.tsx │ │ │ │ │ ├── IGuildMemberRepository.tsx │ │ │ │ │ ├── IGuildModerationRepository.tsx │ │ │ │ │ ├── IGuildRepositoryAggregate.tsx │ │ │ │ │ └── IGuildRoleRepository.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── GuildChannelService.tsx │ │ │ │ │ ├── GuildContentService.tsx │ │ │ │ │ ├── GuildDataService.tsx │ │ │ │ │ ├── GuildDiscoveryService.tsx │ │ │ │ │ ├── GuildMemberService.tsx │ │ │ │ │ ├── GuildModerationService.tsx │ │ │ │ │ ├── GuildRoleService.tsx │ │ │ │ │ ├── GuildSearchService.tsx │ │ │ │ │ ├── GuildService.tsx │ │ │ │ │ ├── channel/ │ │ │ │ │ │ ├── ChannelHelpers.tsx │ │ │ │ │ │ └── ChannelOperationsService.tsx │ │ │ │ │ ├── content/ │ │ │ │ │ │ ├── ContentHelpers.tsx │ │ │ │ │ │ ├── EmojiService.tsx │ │ │ │ │ │ ├── ExpressionAssetPurger.tsx │ │ │ │ │ │ └── StickerService.tsx │ │ │ │ │ ├── data/ │ │ │ │ │ │ ├── GuildDataHelpers.tsx │ │ │ │ │ │ ├── GuildOperationsService.tsx │ │ │ │ │ │ ├── GuildOwnershipService.tsx │ │ │ │ │ │ └── GuildVanityService.tsx │ │ │ │ │ └── member/ │ │ │ │ │ ├── GuildMemberAuditService.tsx │ │ │ │ │ ├── GuildMemberAuthService.tsx │ │ │ │ │ ├── GuildMemberEventService.tsx │ │ │ │ │ ├── GuildMemberOperationsService.tsx │ │ │ │ │ ├── GuildMemberRoleService.tsx │ │ │ │ │ ├── GuildMemberSearchIndexService.tsx │ │ │ │ │ └── GuildMemberValidationService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── DiscoveryApplicationLifecycle.test.tsx │ │ │ │ ├── DiscoveryApplicationValidation.test.tsx │ │ │ │ ├── DiscoverySearchAndJoin.test.tsx │ │ │ │ ├── GuildAssetUpload.test.tsx │ │ │ │ ├── GuildAuditLogs.test.tsx │ │ │ │ ├── GuildChannelManagement.test.tsx │ │ │ │ ├── GuildChannelPositions.test.tsx │ │ │ │ ├── GuildFeatures.test.tsx │ │ │ │ ├── GuildFolderOperations.test.tsx │ │ │ │ ├── GuildMemberManagement.test.tsx │ │ │ │ ├── GuildMfaLevel.test.tsx │ │ │ │ ├── GuildOperationPermissions.test.tsx │ │ │ │ ├── GuildOperationValidation.test.tsx │ │ │ │ ├── GuildOwnershipTransfer.test.tsx │ │ │ │ ├── GuildRoleManagement.test.tsx │ │ │ │ ├── GuildRoleOperations.test.tsx │ │ │ │ ├── GuildRoleReorder.test.tsx │ │ │ │ ├── GuildTestUtils.tsx │ │ │ │ ├── GuildUnavailableFeatureAccess.test.tsx │ │ │ │ ├── InvitePermissions.test.tsx │ │ │ │ ├── InviteSecurity.test.tsx │ │ │ │ ├── InviteValidation.test.tsx │ │ │ │ ├── RoleHierarchyEnforcement.test.tsx │ │ │ │ └── RolePermissionAssignmentHierarchy.test.tsx │ │ │ ├── infrastructure/ │ │ │ │ ├── AssetDeletionQueue.tsx │ │ │ │ ├── AvatarService.tsx │ │ │ │ ├── ClamAV.tsx │ │ │ │ ├── CloudflarePurgeQueue.tsx │ │ │ │ ├── DirectMediaService.tsx │ │ │ │ ├── DirectS3ExpirationManager.tsx │ │ │ │ ├── DirectS3ExpirationStore.tsx │ │ │ │ ├── DirectS3StorageService.tsx │ │ │ │ ├── DisabledLiveKitService.tsx │ │ │ │ ├── DisabledVirusScanService.tsx │ │ │ │ ├── DiscriminatorService.tsx │ │ │ │ ├── ElasticsearchSearchProvider.tsx │ │ │ │ ├── EmailDnsValidationService.tsx │ │ │ │ ├── EmbedService.tsx │ │ │ │ ├── EntityAssetService.tsx │ │ │ │ ├── ErrorI18nService.tsx │ │ │ │ ├── GatewayRpcClient.tsx │ │ │ │ ├── GatewayRpcError.tsx │ │ │ │ ├── GatewayService.tsx │ │ │ │ ├── IAssetDeletionQueue.tsx │ │ │ │ ├── IEmailDnsValidationService.tsx │ │ │ │ ├── IGatewayRpcTransport.tsx │ │ │ │ ├── IGatewayService.tsx │ │ │ │ ├── IKlipyService.tsx │ │ │ │ ├── ILiveKitService.tsx │ │ │ │ ├── IMediaService.tsx │ │ │ │ ├── IMetricsService.tsx │ │ │ │ ├── ISnowflakeService.tsx │ │ │ │ ├── IStorageService.tsx │ │ │ │ ├── ITenorService.tsx │ │ │ │ ├── IUnfurlerService.tsx │ │ │ │ ├── IVoiceRoomStore.tsx │ │ │ │ ├── InMemoryVoiceRoomStore.tsx │ │ │ │ ├── KVAccountDeletionQueueService.tsx │ │ │ │ ├── KVActivityTracker.tsx │ │ │ │ ├── KVBulkMessageDeletionQueueService.tsx │ │ │ │ ├── LiveKitService.tsx │ │ │ │ ├── LiveKitWebhookService.tsx │ │ │ │ ├── MediaService.tsx │ │ │ │ ├── MeilisearchSearchProvider.tsx │ │ │ │ ├── MetricsService.tsx │ │ │ │ ├── NatsGatewayRpcTransport.tsx │ │ │ │ ├── NullSearchProvider.tsx │ │ │ │ ├── SnowflakeService.tsx │ │ │ │ ├── StorageObjectHelpers.tsx │ │ │ │ ├── StorageService.tsx │ │ │ │ ├── StorageServiceFactory.tsx │ │ │ │ ├── UnfurlerService.tsx │ │ │ │ ├── UserCacheService.tsx │ │ │ │ ├── VirusScanService.tsx │ │ │ │ ├── VoiceRoomContext.tsx │ │ │ │ ├── VoiceRoomStore.tsx │ │ │ │ ├── error_i18n/ │ │ │ │ │ └── index.tsx │ │ │ │ └── tests/ │ │ │ │ └── EmailDnsValidationService.test.tsx │ │ │ ├── instance/ │ │ │ │ ├── InstanceConfigRepository.tsx │ │ │ │ ├── InstanceController.tsx │ │ │ │ ├── SnowflakeReservationRepository.tsx │ │ │ │ └── SnowflakeReservationService.tsx │ │ │ ├── invite/ │ │ │ │ ├── IInviteRepository.tsx │ │ │ │ ├── InviteController.tsx │ │ │ │ ├── InviteModel.tsx │ │ │ │ ├── InviteRepository.tsx │ │ │ │ ├── InviteRequestService.tsx │ │ │ │ ├── InviteService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── GroupDMInviteRecipientsSerialization.test.tsx │ │ │ │ ├── InviteGuildMemberLimit.test.tsx │ │ │ │ ├── InvitePermissions.test.tsx │ │ │ │ ├── InviteSecurityChecks.test.tsx │ │ │ │ ├── InviteTestUtils.tsx │ │ │ │ └── InviteValidation.test.tsx │ │ │ ├── klipy/ │ │ │ │ ├── KlipyController.tsx │ │ │ │ └── KlipyService.tsx │ │ │ ├── limits/ │ │ │ │ ├── LimitConfigService.tsx │ │ │ │ ├── LimitConfigUtils.tsx │ │ │ │ ├── LimitMatchContextBuilder.tsx │ │ │ │ └── tests/ │ │ │ │ ├── LimitConfigDefaults.test.tsx │ │ │ │ └── LimitWireFormat.test.tsx │ │ │ ├── message/ │ │ │ │ └── tests/ │ │ │ │ ├── AllowedMentions.test.tsx │ │ │ │ ├── MessageAck.test.tsx │ │ │ │ ├── MessageAttachmentDeleteLastAttachmentEmptyMessage.test.tsx │ │ │ │ ├── MessageAttachmentUploadAuthorTypes.test.tsx │ │ │ │ ├── MessageEditAddNewAttachmentWithEmbed.test.tsx │ │ │ │ ├── MessageEditAttachmentDescription.test.tsx │ │ │ │ ├── MessageEditAttachmentsReplaced.test.tsx │ │ │ │ ├── MessageEditEmbedReferenceMissingAttachment.test.tsx │ │ │ │ ├── MessageEditValidation.test.tsx │ │ │ │ ├── MessageEditWithEmbedAttachmentUrl.test.tsx │ │ │ │ ├── MessageFetch.test.tsx │ │ │ │ ├── MessageFetchBeforeSingleBucket.test.tsx │ │ │ │ ├── MessageFetchEmptyChannel.test.tsx │ │ │ │ ├── MessageFetchPaginationNoDuplicates.test.tsx │ │ │ │ ├── MessageForwardingAccessControl.test.tsx │ │ │ │ ├── MessageForwardingBetweenChannels.test.tsx │ │ │ │ ├── MessageForwardingInGuildChannels.test.tsx │ │ │ │ ├── MessageForwardingPermissions.test.tsx │ │ │ │ ├── MessageForwardingSuppressedEmbeds.test.tsx │ │ │ │ ├── MessageForwardingValidationErrorsContent.test.tsx │ │ │ │ ├── MessageForwardingValidationErrorsGuildMismatch.test.tsx │ │ │ │ ├── MessageHistoryCutoff.test.tsx │ │ │ │ ├── MessageOperationValidation.test.tsx │ │ │ │ ├── MessagePermissions.test.tsx │ │ │ │ ├── MessagePins.test.tsx │ │ │ │ ├── MessageReactionOperations.test.tsx │ │ │ │ ├── MessageReactionPermissions.test.tsx │ │ │ │ ├── MessageReactionValidation.test.tsx │ │ │ │ ├── MessageShred.test.tsx │ │ │ │ ├── MessageState.test.tsx │ │ │ │ ├── MessageStickerDMPremium.test.tsx │ │ │ │ ├── MessageSuppressNotificationsFlag.test.tsx │ │ │ │ ├── MessageTestUtils.tsx │ │ │ │ └── VoiceMessageValidation.test.tsx │ │ │ ├── middleware/ │ │ │ │ ├── AdminMiddleware.tsx │ │ │ │ ├── AuditLogMiddleware.tsx │ │ │ │ ├── AuthMiddleware.tsx │ │ │ │ ├── BlockAppOriginMiddleware.tsx │ │ │ │ ├── CaptchaMiddleware.tsx │ │ │ │ ├── ConcurrencyLimitMiddleware.tsx │ │ │ │ ├── GuildAvailabilityMiddleware.tsx │ │ │ │ ├── IpBanMiddleware.tsx │ │ │ │ ├── LocalAuthMiddleware.tsx │ │ │ │ ├── LocaleMiddleware.tsx │ │ │ │ ├── MetricsMiddleware.tsx │ │ │ │ ├── OAuth2ScopeMiddleware.tsx │ │ │ │ ├── RateLimitMiddleware.tsx │ │ │ │ ├── RequestCacheMiddleware.tsx │ │ │ │ ├── RequireXForwardedForMiddleware.tsx │ │ │ │ ├── ResponseTypeMiddleware.tsx │ │ │ │ ├── ServiceMiddleware.tsx │ │ │ │ ├── ServiceRegistry.tsx │ │ │ │ ├── SudoModeMiddleware.tsx │ │ │ │ ├── UserMiddleware.tsx │ │ │ │ └── tests/ │ │ │ │ ├── GlobalRateLimitRevokesSession.test.tsx │ │ │ │ └── IpBanMiddleware.test.tsx │ │ │ ├── models/ │ │ │ │ ├── AdminApiKey.tsx │ │ │ │ ├── Application.tsx │ │ │ │ ├── Attachment.tsx │ │ │ │ ├── AuthSession.tsx │ │ │ │ ├── CallInfo.tsx │ │ │ │ ├── Channel.tsx │ │ │ │ ├── ChannelPermissionOverwrite.tsx │ │ │ │ ├── EmailRevertToken.tsx │ │ │ │ ├── EmailVerificationToken.tsx │ │ │ │ ├── Embed.tsx │ │ │ │ ├── EmbedAuthor.tsx │ │ │ │ ├── EmbedField.tsx │ │ │ │ ├── EmbedFooter.tsx │ │ │ │ ├── EmbedMedia.tsx │ │ │ │ ├── EmbedProvider.tsx │ │ │ │ ├── ExpressionPack.tsx │ │ │ │ ├── FavoriteMeme.tsx │ │ │ │ ├── GiftCode.tsx │ │ │ │ ├── Guild.tsx │ │ │ │ ├── GuildAuditLog.tsx │ │ │ │ ├── GuildBan.tsx │ │ │ │ ├── GuildChannelOverride.tsx │ │ │ │ ├── GuildEmoji.tsx │ │ │ │ ├── GuildMember.tsx │ │ │ │ ├── GuildRole.tsx │ │ │ │ ├── GuildSticker.tsx │ │ │ │ ├── Invite.tsx │ │ │ │ ├── Message.tsx │ │ │ │ ├── MessageReaction.tsx │ │ │ │ ├── MessageRef.tsx │ │ │ │ ├── MessageSnapshot.tsx │ │ │ │ ├── MfaBackupCode.tsx │ │ │ │ ├── MuteConfiguration.tsx │ │ │ │ ├── OAuth2AccessToken.tsx │ │ │ │ ├── OAuth2AuthorizationCode.tsx │ │ │ │ ├── OAuth2RefreshToken.tsx │ │ │ │ ├── PasswordResetToken.tsx │ │ │ │ ├── Payment.tsx │ │ │ │ ├── PushSubscription.tsx │ │ │ │ ├── ReadState.tsx │ │ │ │ ├── RecentMention.tsx │ │ │ │ ├── Relationship.tsx │ │ │ │ ├── SavedMessage.tsx │ │ │ │ ├── ScheduledMessage.tsx │ │ │ │ ├── StickerItem.tsx │ │ │ │ ├── User.tsx │ │ │ │ ├── UserCustomStatus.tsx │ │ │ │ ├── UserGuildFolder.tsx │ │ │ │ ├── UserGuildSettings.tsx │ │ │ │ ├── UserNote.tsx │ │ │ │ ├── UserSettings.tsx │ │ │ │ ├── VisionarySlot.tsx │ │ │ │ ├── WebAuthnCredential.tsx │ │ │ │ ├── Webhook.tsx │ │ │ │ └── tests/ │ │ │ │ └── EmbedIconUrlSanitization.test.tsx │ │ │ ├── moderation/ │ │ │ │ └── tests/ │ │ │ │ ├── BannedUserRestrictions.test.tsx │ │ │ │ ├── BlockedUserCannotInteract.test.tsx │ │ │ │ ├── ModerationTestUtils.tsx │ │ │ │ └── TimeoutModerationGuards.test.tsx │ │ │ ├── oauth/ │ │ │ │ ├── ApplicationMessageAuthorAnonymization.tsx │ │ │ │ ├── ApplicationService.tsx │ │ │ │ ├── BotAuthService.tsx │ │ │ │ ├── BotMfaMirrorService.tsx │ │ │ │ ├── OAuth2ApplicationsController.tsx │ │ │ │ ├── OAuth2ApplicationsRequestService.tsx │ │ │ │ ├── OAuth2Controller.tsx │ │ │ │ ├── OAuth2Mappers.tsx │ │ │ │ ├── OAuth2RedirectURI.tsx │ │ │ │ ├── OAuth2RequestService.tsx │ │ │ │ ├── OAuth2Service.tsx │ │ │ │ ├── OAuth2Types.tsx │ │ │ │ ├── repositories/ │ │ │ │ │ ├── ApplicationRepository.tsx │ │ │ │ │ ├── IApplicationRepository.tsx │ │ │ │ │ ├── IOAuth2TokenRepository.tsx │ │ │ │ │ └── OAuth2TokenRepository.tsx │ │ │ │ ├── tests/ │ │ │ │ │ ├── OAuth2ApplicationCreate.test.tsx │ │ │ │ │ ├── OAuth2ApplicationDelete.test.tsx │ │ │ │ │ ├── OAuth2ApplicationGet.test.tsx │ │ │ │ │ ├── OAuth2ApplicationList.test.tsx │ │ │ │ │ ├── OAuth2ApplicationUpdate.test.tsx │ │ │ │ │ ├── OAuth2AuthorizationsDeauthorize.test.tsx │ │ │ │ │ ├── OAuth2AuthorizationsList.test.tsx │ │ │ │ │ ├── OAuth2AuthorizationsRequiresAuth.test.tsx │ │ │ │ │ ├── OAuth2AuthorizeCodeFlow.test.tsx │ │ │ │ │ ├── OAuth2AuthorizeRedirectURI.test.tsx │ │ │ │ │ ├── OAuth2AuthorizeStateParameter.test.tsx │ │ │ │ │ ├── OAuth2BotGuildAdd.test.tsx │ │ │ │ │ ├── OAuth2BotToken.test.tsx │ │ │ │ │ ├── OAuth2ClientSecret.test.tsx │ │ │ │ │ ├── OAuth2CodeReplay.test.tsx │ │ │ │ │ ├── OAuth2ScopeEnforcement.test.tsx │ │ │ │ │ ├── OAuth2ScopeMiddleware.test.tsx │ │ │ │ │ ├── OAuth2ScopeValidation.test.tsx │ │ │ │ │ ├── OAuth2Scopes.test.tsx │ │ │ │ │ ├── OAuth2TestUtils.tsx │ │ │ │ │ ├── OAuth2TokenExchange.test.tsx │ │ │ │ │ ├── OAuth2TokenExpiration.test.tsx │ │ │ │ │ ├── OAuth2TokenIntrospection.test.tsx │ │ │ │ │ ├── OAuth2TokenRefresh.test.tsx │ │ │ │ │ ├── OAuth2TokenRevocation.test.tsx │ │ │ │ │ └── OAuthTestUtils.tsx │ │ │ │ └── utils/ │ │ │ │ └── ParseClientCredentials.tsx │ │ │ ├── oauth2/ │ │ │ │ └── tests/ │ │ │ │ ├── OAuth2ApplicationOperations.test.tsx │ │ │ │ ├── OAuth2AuthorizationFlow.test.tsx │ │ │ │ ├── OAuth2BotOperations.test.tsx │ │ │ │ ├── OAuth2Me.test.tsx │ │ │ │ └── OAuth2TokenRevoke.test.tsx │ │ │ ├── pack/ │ │ │ │ ├── PackExpressionAccessResolver.tsx │ │ │ │ ├── PackModel.tsx │ │ │ │ ├── PackRepository.tsx │ │ │ │ ├── PackRequestService.tsx │ │ │ │ ├── PackService.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ ├── PackController.tsx │ │ │ │ │ ├── PackEmojiController.tsx │ │ │ │ │ ├── PackStickerController.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── tests/ │ │ │ │ ├── PackInviteFlow.test.tsx │ │ │ │ ├── PackPremiumRequirements.test.tsx │ │ │ │ └── PackTestUtils.tsx │ │ │ ├── rate_limit_configs/ │ │ │ │ ├── AdminRateLimitConfig.tsx │ │ │ │ ├── AuthRateLimitConfig.tsx │ │ │ │ ├── ChannelRateLimitConfig.tsx │ │ │ │ ├── ConnectionRateLimitConfig.tsx │ │ │ │ ├── DiscoveryRateLimitConfig.tsx │ │ │ │ ├── DonationRateLimitConfig.tsx │ │ │ │ ├── GuildRateLimitConfig.tsx │ │ │ │ ├── IntegrationRateLimitConfig.tsx │ │ │ │ ├── InviteRateLimitConfig.tsx │ │ │ │ ├── MiscRateLimitConfig.tsx │ │ │ │ ├── OAuthRateLimitConfig.tsx │ │ │ │ ├── PackRateLimitConfig.tsx │ │ │ │ ├── RateLimitHelpers.tsx │ │ │ │ ├── UserRateLimitConfig.tsx │ │ │ │ └── WebhookRateLimitConfig.tsx │ │ │ ├── read_state/ │ │ │ │ ├── IReadStateRepository.tsx │ │ │ │ ├── ReadStateController.tsx │ │ │ │ ├── ReadStateRepository.tsx │ │ │ │ ├── ReadStateRequestService.tsx │ │ │ │ └── ReadStateService.tsx │ │ │ ├── report/ │ │ │ │ ├── IReportRepository.tsx │ │ │ │ ├── ReportController.tsx │ │ │ │ ├── ReportRepository.tsx │ │ │ │ ├── ReportRequestService.tsx │ │ │ │ ├── ReportService.tsx │ │ │ │ └── tests/ │ │ │ │ └── ContentReporting.test.tsx │ │ │ ├── rpc/ │ │ │ │ ├── NatsApiRpcListener.tsx │ │ │ │ ├── RpcService.tsx │ │ │ │ └── tests/ │ │ │ │ └── RpcGuildMemberCountRepair.test.tsx │ │ │ ├── search/ │ │ │ │ ├── BuildMessageSearchFilters.tsx │ │ │ │ ├── ChannelIndexingUtils.tsx │ │ │ │ ├── GlobalSearchService.tsx │ │ │ │ ├── IAuditLogSearchService.tsx │ │ │ │ ├── IGuildMemberSearchService.tsx │ │ │ │ ├── IGuildSearchService.tsx │ │ │ │ ├── IMessageSearchService.tsx │ │ │ │ ├── IReportSearchService.tsx │ │ │ │ ├── ISearchProvider.tsx │ │ │ │ ├── IUserSearchService.tsx │ │ │ │ ├── MessageSearchResponseMapper.tsx │ │ │ │ ├── SearchConstants.tsx │ │ │ │ ├── SearchService.tsx │ │ │ │ ├── SearchTaskTracker.tsx │ │ │ │ ├── SearchWarmup.tsx │ │ │ │ ├── auditlog/ │ │ │ │ │ └── AuditLogSearchSerializer.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ └── SearchController.tsx │ │ │ │ ├── elasticsearch/ │ │ │ │ │ ├── ElasticsearchAuditLogSearchService.tsx │ │ │ │ │ ├── ElasticsearchGuildMemberSearchService.tsx │ │ │ │ │ ├── ElasticsearchGuildSearchService.tsx │ │ │ │ │ ├── ElasticsearchMessageSearchService.tsx │ │ │ │ │ ├── ElasticsearchReportSearchService.tsx │ │ │ │ │ ├── ElasticsearchSearchServiceBase.tsx │ │ │ │ │ └── ElasticsearchUserSearchService.tsx │ │ │ │ ├── guild/ │ │ │ │ │ └── GuildSearchSerializer.tsx │ │ │ │ ├── guild_member/ │ │ │ │ │ └── GuildMemberSearchSerializer.tsx │ │ │ │ ├── meilisearch/ │ │ │ │ │ ├── MeilisearchAuditLogSearchService.tsx │ │ │ │ │ ├── MeilisearchGuildMemberSearchService.tsx │ │ │ │ │ ├── MeilisearchGuildSearchService.tsx │ │ │ │ │ ├── MeilisearchMessageSearchService.tsx │ │ │ │ │ ├── MeilisearchReportSearchService.tsx │ │ │ │ │ ├── MeilisearchSearchServiceBase.tsx │ │ │ │ │ └── MeilisearchUserSearchService.tsx │ │ │ │ ├── message/ │ │ │ │ │ ├── MessageSearchSerializer.tsx │ │ │ │ │ └── tests/ │ │ │ │ │ └── MessageSearchSerializer.test.tsx │ │ │ │ ├── report/ │ │ │ │ │ └── ReportSearchSerializer.tsx │ │ │ │ ├── tests/ │ │ │ │ │ ├── GuildMemberSearchEndpoint.test.tsx │ │ │ │ │ ├── MessageSearchEndpoint.test.tsx │ │ │ │ │ ├── MessageSearchExactPhrase.test.tsx │ │ │ │ │ ├── MessageSearchFilters.test.tsx │ │ │ │ │ ├── MessageSearchPermissions.test.tsx │ │ │ │ │ └── MessageSearchSorting.test.tsx │ │ │ │ └── user/ │ │ │ │ └── UserSearchSerializer.tsx │ │ │ ├── sticker/ │ │ │ │ └── tests/ │ │ │ │ └── StickerUploadValidation.test.tsx │ │ │ ├── stripe/ │ │ │ │ ├── ProductRegistry.tsx │ │ │ │ ├── StripeController.tsx │ │ │ │ ├── StripeModel.tsx │ │ │ │ ├── StripeService.tsx │ │ │ │ ├── StripeSubscriptionPeriod.tsx │ │ │ │ ├── StripeUtils.tsx │ │ │ │ ├── VisionarySlotInitializer.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── StripeCheckoutService.tsx │ │ │ │ │ ├── StripeGiftService.tsx │ │ │ │ │ ├── StripePremiumService.tsx │ │ │ │ │ ├── StripeSubscriptionService.tsx │ │ │ │ │ └── StripeWebhookService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── StripeCheckoutService.test.tsx │ │ │ │ ├── StripeGiftService.test.tsx │ │ │ │ ├── StripePremiumService.test.tsx │ │ │ │ ├── StripeSubscriptionService.test.tsx │ │ │ │ ├── StripeUtils.test.tsx │ │ │ │ ├── StripeWebhookCheckout.test.tsx │ │ │ │ ├── StripeWebhookCore.test.tsx │ │ │ │ ├── StripeWebhookDispute.test.tsx │ │ │ │ ├── StripeWebhookEdgeCases.test.tsx │ │ │ │ ├── StripeWebhookIdempotency.test.tsx │ │ │ │ ├── StripeWebhookInvoice.test.tsx │ │ │ │ ├── StripeWebhookRefund.test.tsx │ │ │ │ ├── StripeWebhookSubscription.test.tsx │ │ │ │ └── StripeWebhookTestUtils.tsx │ │ │ ├── system_dm/ │ │ │ │ └── TargetFinder.tsx │ │ │ ├── telemetry/ │ │ │ │ ├── BusinessSpans.tsx │ │ │ │ ├── CsamTelemetry.tsx │ │ │ │ ├── MessageTelemetry.tsx │ │ │ │ └── Tracing.tsx │ │ │ ├── tenor/ │ │ │ │ ├── TenorController.tsx │ │ │ │ └── TenorService.tsx │ │ │ ├── test/ │ │ │ │ ├── ApiTestHarness.tsx │ │ │ │ ├── NoopGatewayService.tsx │ │ │ │ ├── NoopWorkerService.tsx │ │ │ │ ├── Setup.tsx │ │ │ │ ├── TestConstants.tsx │ │ │ │ ├── TestHarnessController.tsx │ │ │ │ ├── TestHarnessReset.tsx │ │ │ │ ├── TestMediaService.tsx │ │ │ │ ├── TestRequestBuilder.tsx │ │ │ │ ├── TestS3Service.tsx │ │ │ │ ├── fixtures/ │ │ │ │ │ └── ncmec/ │ │ │ │ │ └── NcmecXmlFixtures.tsx │ │ │ │ ├── meilisearch/ │ │ │ │ │ └── MeilisearchTestServer.tsx │ │ │ │ ├── mocks/ │ │ │ │ │ ├── MockAssetDeletionQueue.tsx │ │ │ │ │ ├── MockBlueskyOAuthService.tsx │ │ │ │ │ ├── MockCsamEvidenceService.tsx │ │ │ │ │ ├── MockCsamReportSnapshotService.tsx │ │ │ │ │ ├── MockCsamScanQueueService.tsx │ │ │ │ │ ├── MockGatewayRpcTransport.tsx │ │ │ │ │ ├── MockGatewayService.tsx │ │ │ │ │ ├── MockKVProvider.tsx │ │ │ │ │ ├── MockLiveKitService.tsx │ │ │ │ │ ├── MockMediaService.tsx │ │ │ │ │ ├── MockNcmecReporter.tsx │ │ │ │ │ ├── MockPhotoDnaHashClient.tsx │ │ │ │ │ ├── MockSnowflakeService.tsx │ │ │ │ │ ├── MockStorageService.tsx │ │ │ │ │ ├── MockSynchronousCsamScanner.tsx │ │ │ │ │ ├── MockVirusScanService.tsx │ │ │ │ │ └── NoopLogger.tsx │ │ │ │ └── msw/ │ │ │ │ ├── handlers/ │ │ │ │ │ ├── ArachnidShieldHandlers.tsx │ │ │ │ │ ├── BlueskyApiHandlers.tsx │ │ │ │ │ ├── DockerEngineHandlers.tsx │ │ │ │ │ ├── MeilisearchHandlers.tsx │ │ │ │ │ ├── NcmecHandlers.tsx │ │ │ │ │ ├── PhotoDnaHandlers.tsx │ │ │ │ │ ├── PwnedPasswordsHandlers.tsx │ │ │ │ │ ├── StripeApiHandlers.tsx │ │ │ │ │ └── WikipediaApiHandlers.tsx │ │ │ │ └── server.tsx │ │ │ ├── tests/ │ │ │ │ └── Smoke.test.tsx │ │ │ ├── theme/ │ │ │ │ ├── ThemeController.tsx │ │ │ │ ├── ThemeService.tsx │ │ │ │ └── tests/ │ │ │ │ ├── ThemeAuthRequired.test.tsx │ │ │ │ ├── ThemeBotUserDenied.test.tsx │ │ │ │ ├── ThemeCreation.test.tsx │ │ │ │ ├── ThemeCssSizeLimit.test.tsx │ │ │ │ └── ThemeValidation.test.tsx │ │ │ ├── types/ │ │ │ │ ├── AttachmentDecayTypes.tsx │ │ │ │ └── HonoEnv.tsx │ │ │ ├── typing/ │ │ │ │ └── tests/ │ │ │ │ ├── TypingInDMChannel.test.tsx │ │ │ │ ├── TypingInGuildChannel.test.tsx │ │ │ │ ├── TypingPermissions.test.tsx │ │ │ │ └── TypingTestUtils.tsx │ │ │ ├── unfurler/ │ │ │ │ ├── resolvers/ │ │ │ │ │ ├── AudioResolver.tsx │ │ │ │ │ ├── BaseResolver.tsx │ │ │ │ │ ├── BlueskyResolver.tsx │ │ │ │ │ ├── DefaultResolver.tsx │ │ │ │ │ ├── HackerNewsResolver.tsx │ │ │ │ │ ├── ImageResolver.tsx │ │ │ │ │ ├── KlipyResolver.tsx │ │ │ │ │ ├── TenorResolver.tsx │ │ │ │ │ ├── VideoResolver.tsx │ │ │ │ │ ├── WikipediaResolver.tsx │ │ │ │ │ ├── XkcdResolver.tsx │ │ │ │ │ ├── YouTubeResolver.tsx │ │ │ │ │ ├── bluesky/ │ │ │ │ │ │ ├── BlueskyApiClient.tsx │ │ │ │ │ │ ├── BlueskyEmbedProcessor.tsx │ │ │ │ │ │ ├── BlueskyTextFormatter.tsx │ │ │ │ │ │ └── BlueskyTypes.tsx │ │ │ │ │ ├── media/ │ │ │ │ │ │ └── MediaMetadataHelpers.tsx │ │ │ │ │ └── subresolvers/ │ │ │ │ │ ├── ActivityPubFetcher.tsx │ │ │ │ │ ├── ActivityPubFormatter.tsx │ │ │ │ │ ├── ActivityPubResolver.tsx │ │ │ │ │ ├── ActivityPubTypes.tsx │ │ │ │ │ └── ActivityPubUtils.tsx │ │ │ │ └── tests/ │ │ │ │ ├── ActivityPubFetcher.test.tsx │ │ │ │ ├── ActivityPubFormatter.test.tsx │ │ │ │ ├── ActivityPubResolver.test.tsx │ │ │ │ ├── AudioResolver.test.tsx │ │ │ │ ├── BaseResolver.test.tsx │ │ │ │ ├── BlueskyEmbedProcessor.test.tsx │ │ │ │ ├── BlueskyResolver.test.tsx │ │ │ │ ├── DefaultResolver.test.tsx │ │ │ │ ├── HackerNewsResolver.test.tsx │ │ │ │ ├── ImageResolver.test.tsx │ │ │ │ ├── KlipyResolver.test.tsx │ │ │ │ ├── ResolverTestUtils.tsx │ │ │ │ ├── TenorResolver.test.tsx │ │ │ │ ├── VideoResolver.test.tsx │ │ │ │ ├── WikipediaResolver.test.tsx │ │ │ │ ├── XkcdResolver.test.tsx │ │ │ │ └── YouTubeResolver.test.tsx │ │ │ ├── user/ │ │ │ │ ├── IUserRepository.tsx │ │ │ │ ├── UserCacheHelpers.tsx │ │ │ │ ├── UserHarvestModel.tsx │ │ │ │ ├── UserHarvestRepository.tsx │ │ │ │ ├── UserHelpers.tsx │ │ │ │ ├── UserMappers.tsx │ │ │ │ ├── UserModel.tsx │ │ │ │ ├── controllers/ │ │ │ │ │ ├── UserAccountController.tsx │ │ │ │ │ ├── UserAuthController.tsx │ │ │ │ │ ├── UserChannelController.tsx │ │ │ │ │ ├── UserContentController.tsx │ │ │ │ │ ├── UserController.tsx │ │ │ │ │ ├── UserRelationshipController.tsx │ │ │ │ │ └── UserScheduledMessageController.tsx │ │ │ │ ├── repositories/ │ │ │ │ │ ├── GiftCodeRepository.tsx │ │ │ │ │ ├── IUserAccountRepository.tsx │ │ │ │ │ ├── IUserAuthRepository.tsx │ │ │ │ │ ├── IUserChannelRepository.tsx │ │ │ │ │ ├── IUserContentRepository.tsx │ │ │ │ │ ├── IUserRelationshipRepository.tsx │ │ │ │ │ ├── IUserRepositoryAggregate.tsx │ │ │ │ │ ├── IUserSettingsRepository.tsx │ │ │ │ │ ├── PaymentRepository.tsx │ │ │ │ │ ├── PushSubscriptionRepository.tsx │ │ │ │ │ ├── RecentMentionRepository.tsx │ │ │ │ │ ├── SavedMessageRepository.tsx │ │ │ │ │ ├── ScheduledMessageRepository.tsx │ │ │ │ │ ├── UserAccountRepository.tsx │ │ │ │ │ ├── UserAuthRepository.tsx │ │ │ │ │ ├── UserChannelRepository.tsx │ │ │ │ │ ├── UserContactChangeLogRepository.tsx │ │ │ │ │ ├── UserContentRepository.tsx │ │ │ │ │ ├── UserRelationshipRepository.tsx │ │ │ │ │ ├── UserRepository.tsx │ │ │ │ │ ├── UserSettingsRepository.tsx │ │ │ │ │ ├── VisionarySlotRepository.tsx │ │ │ │ │ ├── account/ │ │ │ │ │ │ ├── UserAccountRepository.tsx │ │ │ │ │ │ ├── UserDeletionRepository.tsx │ │ │ │ │ │ ├── UserGuildRepository.tsx │ │ │ │ │ │ ├── UserLookupRepository.tsx │ │ │ │ │ │ └── crud/ │ │ │ │ │ │ ├── UserDataRepository.tsx │ │ │ │ │ │ ├── UserIndexRepository.tsx │ │ │ │ │ │ └── UserSearchRepository.tsx │ │ │ │ │ └── auth/ │ │ │ │ │ ├── AuthSessionRepository.tsx │ │ │ │ │ ├── EmailChangeRepository.tsx │ │ │ │ │ ├── IpAuthorizationRepository.tsx │ │ │ │ │ ├── MfaBackupCodeRepository.tsx │ │ │ │ │ ├── PasswordChangeRepository.tsx │ │ │ │ │ ├── TokenRepository.tsx │ │ │ │ │ └── WebAuthnRepository.tsx │ │ │ │ ├── services/ │ │ │ │ │ ├── BaseUserUpdatePropagator.tsx │ │ │ │ │ ├── CustomStatusValidator.tsx │ │ │ │ │ ├── EmailChangeService.tsx │ │ │ │ │ ├── PasswordChangeService.tsx │ │ │ │ │ ├── UserAccountLifecycleService.tsx │ │ │ │ │ ├── UserAccountLookupService.tsx │ │ │ │ │ ├── UserAccountNotesService.tsx │ │ │ │ │ ├── UserAccountProfileService.tsx │ │ │ │ │ ├── UserAccountRequestService.tsx │ │ │ │ │ ├── UserAccountSecurityService.tsx │ │ │ │ │ ├── UserAccountService.tsx │ │ │ │ │ ├── UserAccountSettingsService.tsx │ │ │ │ │ ├── UserAccountUpdatePropagator.tsx │ │ │ │ │ ├── UserAuthRequestService.tsx │ │ │ │ │ ├── UserAuthService.tsx │ │ │ │ │ ├── UserChannelRequestService.tsx │ │ │ │ │ ├── UserChannelService.tsx │ │ │ │ │ ├── UserContactChangeLogService.tsx │ │ │ │ │ ├── UserContentRequestService.tsx │ │ │ │ │ ├── UserContentService.tsx │ │ │ │ │ ├── UserDeletionEligibilityService.tsx │ │ │ │ │ ├── UserDeletionService.tsx │ │ │ │ │ ├── UserRelationshipRequestService.tsx │ │ │ │ │ ├── UserRelationshipService.tsx │ │ │ │ │ └── UserService.tsx │ │ │ │ ├── tests/ │ │ │ │ │ ├── AccountDeleteAutoCancelOnLogin.test.tsx │ │ │ │ │ ├── AccountDeleteGracePeriod.test.tsx │ │ │ │ │ ├── AccountDeleteMentionResolution.test.tsx │ │ │ │ │ ├── AccountDeleteMessagePagination.test.tsx │ │ │ │ │ ├── AccountDeletePermanent.test.tsx │ │ │ │ │ ├── AccountDisable.test.tsx │ │ │ │ │ ├── FavoriteMemeLimits.test.tsx │ │ │ │ │ ├── FavoriteMemeOperations.test.tsx │ │ │ │ │ ├── FavoriteMemeTestUtils.tsx │ │ │ │ │ ├── HarvestDownloadExpirationBoundary.test.tsx │ │ │ │ │ ├── HarvestDownloadExpired.test.tsx │ │ │ │ │ ├── HarvestDownloadNotExpired.test.tsx │ │ │ │ │ ├── HarvestTestUtils.tsx │ │ │ │ │ ├── InactivityDeletion.test.tsx │ │ │ │ │ ├── PasswordChangeFlow.test.tsx │ │ │ │ │ ├── ProfileImageUpload.test.tsx │ │ │ │ │ ├── PushSubscriptionLifecycle.test.tsx │ │ │ │ │ ├── RelationshipAcceptAfterPrivacyChangeAllowsExistingRequest.test.tsx │ │ │ │ │ ├── RelationshipBlocking.test.tsx │ │ │ │ │ ├── RelationshipBlockingBehaviors.test.tsx │ │ │ │ │ ├── RelationshipNicknameUpdate.test.tsx │ │ │ │ │ ├── RelationshipTestUtils.tsx │ │ │ │ │ ├── UnclaimedAccountRestrictions.test.tsx │ │ │ │ │ ├── UserAccountAndSettings.test.tsx │ │ │ │ │ ├── UserAuthorizedIps.test.tsx │ │ │ │ │ ├── UserChannelService.test.tsx │ │ │ │ │ ├── UserContactChangeLogService.test.tsx │ │ │ │ │ ├── UserCustomStatusEmojiPremium.test.tsx │ │ │ │ │ ├── UserDeletionEligibilityService.test.tsx │ │ │ │ │ ├── UserDisableAndDeleteEndpoints.test.tsx │ │ │ │ │ ├── UserFlagsResponse.test.tsx │ │ │ │ │ ├── UserNoteLifecycle.test.tsx │ │ │ │ │ ├── UserPremiumReset.test.tsx │ │ │ │ │ ├── UserProfileConnectionVisibility.test.tsx │ │ │ │ │ ├── UserProfileImageValidation.test.tsx │ │ │ │ │ ├── UserProfileTextValidation.test.tsx │ │ │ │ │ ├── UserRelationshipEndpoints.test.tsx │ │ │ │ │ ├── UserRelationshipStateTransitions.test.tsx │ │ │ │ │ ├── UserReservedDiscriminatorRoll.test.tsx │ │ │ │ │ ├── UserSettingsGuildFolders.test.tsx │ │ │ │ │ ├── UserSettingsValidation.test.tsx │ │ │ │ │ ├── UserTestUtils.tsx │ │ │ │ │ └── UserUsernameCaseUpdate.test.tsx │ │ │ │ └── utils/ │ │ │ │ └── GuildFolderUtils.tsx │ │ │ ├── utils/ │ │ │ │ ├── AgeUtils.tsx │ │ │ │ ├── AttachmentDecay.tsx │ │ │ │ ├── AuditSerializationUtils.tsx │ │ │ │ ├── AvatarColorUtils.tsx │ │ │ │ ├── CurrencyUtils.tsx │ │ │ │ ├── DOMUtils.tsx │ │ │ │ ├── EmojiUtils.tsx │ │ │ │ ├── FetchUtils.tsx │ │ │ │ ├── GeoUtils.tsx │ │ │ │ ├── GuildVerificationUtils.tsx │ │ │ │ ├── IdUtils.tsx │ │ │ │ ├── InviteUtils.tsx │ │ │ │ ├── IpRangeUtils.tsx │ │ │ │ ├── IpUtils.tsx │ │ │ │ ├── LosslessJsonParser.tsx │ │ │ │ ├── PasswordUtils.tsx │ │ │ │ ├── PermissionUtils.tsx │ │ │ │ ├── RandomUtils.tsx │ │ │ │ ├── RegexUtils.tsx │ │ │ │ ├── RequestPathUtils.tsx │ │ │ │ ├── StringUtils.tsx │ │ │ │ ├── SudoCookieUtils.tsx │ │ │ │ ├── TotpGenerator.tsx │ │ │ │ ├── UnfurlerUtils.tsx │ │ │ │ ├── UrlSanitizer.tsx │ │ │ │ ├── UserAgentUtils.tsx │ │ │ │ ├── UserPermissionUtils.tsx │ │ │ │ ├── UsernameGenerator.tsx │ │ │ │ ├── UsernameSuggestionUtils.tsx │ │ │ │ ├── featureUtils.tsx │ │ │ │ └── tests/ │ │ │ │ ├── AgeUtils.test.tsx │ │ │ │ ├── BucketUtils.test.tsx │ │ │ │ ├── CurrencyUtils.test.tsx │ │ │ │ ├── DOMUtils.test.tsx │ │ │ │ ├── GeoUtils.test.tsx │ │ │ │ ├── IdUtils.test.tsx │ │ │ │ ├── IpRangeUtils.test.tsx │ │ │ │ ├── LosslessJsonParser.test.tsx │ │ │ │ ├── RegexUtils.test.tsx │ │ │ │ ├── StringUtils.test.tsx │ │ │ │ └── UrlSanitizer.test.tsx │ │ │ ├── validation/ │ │ │ │ └── tests/ │ │ │ │ └── ValidationErrorInterpolation.test.tsx │ │ │ ├── voice/ │ │ │ │ ├── IVoiceRepository.tsx │ │ │ │ ├── VoiceAvailabilityService.tsx │ │ │ │ ├── VoiceConstants.tsx │ │ │ │ ├── VoiceDataInitializer.tsx │ │ │ │ ├── VoiceModel.tsx │ │ │ │ ├── VoiceReconciliationWorker.tsx │ │ │ │ ├── VoiceRegionSelection.tsx │ │ │ │ ├── VoiceRepository.tsx │ │ │ │ ├── VoiceService.tsx │ │ │ │ ├── VoiceTopology.tsx │ │ │ │ └── tests/ │ │ │ │ ├── VoiceAvailabilityService.test.tsx │ │ │ │ ├── VoiceCallEligibility.test.tsx │ │ │ │ ├── VoiceCallRinging.test.tsx │ │ │ │ ├── VoiceCallUpdate.test.tsx │ │ │ │ ├── VoiceChannelPermissions.test.tsx │ │ │ │ ├── VoiceChannelRtcRegion.test.tsx │ │ │ │ ├── VoiceRegionSelection.test.tsx │ │ │ │ ├── VoiceTestUtils.tsx │ │ │ │ ├── VoiceTopology.test.tsx │ │ │ │ └── VoiceUnclaimedAccountRestrictions.test.tsx │ │ │ ├── webhook/ │ │ │ │ ├── IWebhookRepository.tsx │ │ │ │ ├── SweegoWebhookService.tsx │ │ │ │ ├── WebhookController.tsx │ │ │ │ ├── WebhookModel.tsx │ │ │ │ ├── WebhookRepository.tsx │ │ │ │ ├── WebhookRequestService.tsx │ │ │ │ ├── WebhookService.tsx │ │ │ │ ├── tests/ │ │ │ │ │ ├── GitHubCheckTransformer.test.tsx │ │ │ │ │ ├── GitHubCommitTransformer.test.tsx │ │ │ │ │ ├── GitHubIssueTransformer.test.tsx │ │ │ │ │ ├── GitHubPullRequestTransformer.test.tsx │ │ │ │ │ ├── GitHubPushTransformer.test.tsx │ │ │ │ │ ├── GitHubRepositoryTransformer.test.tsx │ │ │ │ │ ├── GitHubTransformer.test.tsx │ │ │ │ │ ├── SentryTransformer.test.tsx │ │ │ │ │ ├── SlackTransformer.test.tsx │ │ │ │ │ ├── SweegoWebhookService.test.tsx │ │ │ │ │ ├── WebhookChannelValidation.test.tsx │ │ │ │ │ ├── WebhookCompareUser.test.tsx │ │ │ │ │ ├── WebhookEmojiBypass.test.tsx │ │ │ │ │ ├── WebhookExecution.test.tsx │ │ │ │ │ ├── WebhookExecutionAdvanced.test.tsx │ │ │ │ │ ├── WebhookGitHub.test.tsx │ │ │ │ │ ├── WebhookLimits.test.tsx │ │ │ │ │ ├── WebhookMultipartAttachmentUploads.test.tsx │ │ │ │ │ ├── WebhookOperations.test.tsx │ │ │ │ │ ├── WebhookPermissions.test.tsx │ │ │ │ │ ├── WebhookSentry.test.tsx │ │ │ │ │ ├── WebhookStickerBypass.test.tsx │ │ │ │ │ ├── WebhookTestUtils.tsx │ │ │ │ │ ├── Webhook
Showing preview only (2,282K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (23025 symbols across 3622 files)
FILE: fluxer_admin/src/Config.tsx
type Config (line 51) | type Config = typeof Config;
FILE: fluxer_admin/src/Logger.tsx
type Logger (line 23) | type Logger = FluxerLogger;
FILE: fluxer_api/scripts/CassandraMigrate.tsx
constant MIGRATION_TABLE (line 27) | const MIGRATION_TABLE = 'schema_migrations';
constant MIGRATION_KEYSPACE (line 28) | const MIGRATION_KEYSPACE = process.env['CASSANDRA_KEYSPACE'] ?? 'fluxer';
constant MIGRATIONS_DIR (line 29) | const MIGRATIONS_DIR = '../fluxer_devops/cassandra/migrations';
type ForbiddenPattern (line 31) | interface ForbiddenPattern {
constant FORBIDDEN_PATTERNS (line 36) | const FORBIDDEN_PATTERNS: Array<ForbiddenPattern> = [
function getMigrationsDir (line 52) | function getMigrationsDir(): string {
function getMigrationPath (line 56) | function getMigrationPath(filename: string): string {
function sanitizeName (line 60) | function sanitizeName(name: string): string {
function removeComments (line 72) | function removeComments(content: string): string {
function parseStatements (line 84) | function parseStatements(content: string): Array<string> {
function calculateChecksum (line 114) | function calculateChecksum(content: string): string {
function validateMigrationContent (line 118) | function validateMigrationContent(filename: string, content: string): Ar...
function getMigrationFiles (line 135) | function getMigrationFiles(): Array<string> {
function hasSkipCi (line 152) | function hasSkipCi(filename: string): boolean {
function sleep (line 166) | async function sleep(ms: number): Promise<void> {
function createSession (line 170) | async function createSession(
function getAppliedMigrations (line 210) | async function getAppliedMigrations(session: cassandra.Client): Promise<...
function applyMigration (line 224) | async function applyMigration(session: cassandra.Client, filename: strin...
function autoAcknowledgeMigration (line 250) | async function autoAcknowledgeMigration(session: cassandra.Client, filen...
function createMigration (line 260) | function createMigration(name: string): void {
function checkMigrations (line 280) | function checkMigrations(): void {
function runMigrations (line 316) | async function runMigrations(host: string, port: number, username: strin...
function showStatus (line 380) | async function showStatus(host: string, port: number, username: string, ...
function acknowledgeMigration (line 406) | async function acknowledgeMigration(
function testConnection (line 435) | async function testConnection(host: string, port: number, username: stri...
function debugConnection (line 454) | async function debugConnection(host: string, port: number, username: str...
function printUsage (line 517) | function printUsage(): void {
function main (line 544) | async function main(): Promise<void> {
FILE: fluxer_api/scripts/LicenseEnforcer.tsx
constant TS_LICENSE_HEADER (line 23) | const TS_LICENSE_HEADER = `/*
constant ERLANG_LICENSE_HEADER (line 42) | const ERLANG_LICENSE_HEADER = `%% Copyright (C) {year} Fluxer Contributors
constant SHELL_LICENSE_HEADER (line 59) | const SHELL_LICENSE_HEADER = `# Copyright (C) {year} Fluxer Contributors
constant BLOCK_COMMENT_EXTS (line 76) | const BLOCK_COMMENT_EXTS = new Set([
constant HASH_LINE_EXTS (line 106) | const HASH_LINE_EXTS = new Set(['sh', 'bash', 'zsh', 'py', 'rb', 'ps1', ...
type HeaderStyle (line 108) | type HeaderStyle = {kind: 'block'} | {kind: 'line'; prefix: string};
type FileTemplate (line 110) | interface FileTemplate {
class Processor (line 115) | class Processor {
method constructor (line 120) | constructor() {
method loadGitignore (line 125) | private loadGitignore(): void {
method shouldIgnore (line 139) | private shouldIgnore(filePath: string): boolean {
method matchPattern (line 153) | private matchPattern(pattern: string, filePath: string): boolean {
method getTemplate (line 179) | private getTemplate(filePath: string): FileTemplate | null {
method templateForExtension (line 184) | private templateForExtension(ext: string): FileTemplate | null {
method detectLicense (line 202) | private detectLicense(content: string): {hasHeader: boolean; detectedY...
method updateYear (line 232) | private updateYear(content: string, oldYear: number): string {
method stripLicenseHeader (line 236) | private stripLicenseHeader(content: string, style: HeaderStyle): {stri...
method addHeader (line 318) | private addHeader(content: string, template: FileTemplate): string {
method processFile (line 330) | private processFile(filePath: string): void {
method walkDir (line 366) | private walkDir(dir: string): void {
method walk (line 397) | walk(): void {
method getUpdatedCount (line 401) | getUpdatedCount(): number {
function main (line 406) | function main(): void {
FILE: fluxer_api/src/App.tsx
function main (line 30) | async function main(): Promise<void> {
FILE: fluxer_api/src/Config.tsx
type ExtendedAPIConfig (line 29) | interface ExtendedAPIConfig extends APIConfig {
type Config (line 42) | type Config = typeof Config;
FILE: fluxer_api/src/Logger.tsx
type Logger (line 23) | type Logger = FluxerLogger;
FILE: fluxer_app/crates/libfluxcore/src/animation.rs
constant PNG_SIGNATURE (line 24) | const PNG_SIGNATURE: [u8; 8] = [137, 80, 78, 71, 13, 10, 26, 10];
type ImageFormat (line 26) | enum ImageFormat {
function detect_format (line 34) | fn detect_format(input: &[u8]) -> ImageFormat {
function is_animated_gif (line 53) | fn is_animated_gif(input: &[u8]) -> bool {
function has_apng_actl (line 78) | fn has_apng_actl(input: &[u8]) -> bool {
function has_webp_anim (line 100) | fn has_webp_anim(input: &[u8]) -> bool {
function is_avif_file (line 122) | fn is_avif_file(input: &[u8]) -> bool {
function has_avif_anim (line 137) | fn has_avif_anim(input: &[u8]) -> bool {
function is_animated_image (line 151) | pub fn is_animated_image(input: &[u8]) -> bool {
FILE: fluxer_app/crates/libfluxcore/src/apng.rs
function crop_and_rotate_apng (line 26) | pub fn crop_and_rotate_apng(
function process_apng (line 49) | fn process_apng(
function draw_frame_on_canvas_source (line 237) | fn draw_frame_on_canvas_source(
function draw_frame_on_canvas_over (line 260) | fn draw_frame_on_canvas_over(
function clear_rect (line 294) | fn clear_rect(canvas: &mut [u8], canvas_width: u32, x: u32, y: u32, w: u...
function crop_rgba (line 316) | fn crop_rgba(
function rotate_rgba_90 (line 341) | fn rotate_rgba_90(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, u...
function rotate_rgba_180 (line 359) | fn rotate_rgba_180(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, ...
function rotate_rgba_270 (line 373) | fn rotate_rgba_270(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, ...
function resize_rgba_nearest (line 391) | fn resize_rgba_nearest(
FILE: fluxer_app/crates/libfluxcore/src/gateway.rs
function decompress_zstd_frame (line 25) | pub fn decompress_zstd_frame(input: &[u8]) -> Result<Box<[u8]>, JsValue> {
FILE: fluxer_app/crates/libfluxcore/src/gif.rs
type EncodeError (line 26) | enum EncodeError {
method from (line 32) | fn from(value: JsValue) -> Self {
function crop_and_rotate_gif (line 39) | pub fn crop_and_rotate_gif(
type EncoderMode (line 82) | enum EncoderMode {
function process_gif (line 88) | fn process_gif(
function draw_frame_on_canvas (line 236) | fn draw_frame_on_canvas(
function clear_rect (line 272) | fn clear_rect(canvas: &mut [u8], canvas_width: u32, x: u16, y: u16, w: u...
function crop_rgba (line 292) | fn crop_rgba(
function rotate_rgba_90 (line 317) | fn rotate_rgba_90(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, u...
function rotate_rgba_180 (line 335) | fn rotate_rgba_180(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, ...
function rotate_rgba_270 (line 349) | fn rotate_rgba_270(src: &[u8], src_w: usize, src_h: usize) -> (Vec<u8>, ...
function resize_rgba_nearest (line 367) | fn resize_rgba_nearest(
function create_decoder (line 389) | fn create_decoder(input: &[u8]) -> Result<gif::Decoder<Cursor<&[u8]>>, E...
type FrameEncoder (line 398) | enum FrameEncoder {
method new (line 404) | fn new(mode: EncoderMode, width: u16, height: u16) -> Result<Self, Enc...
method write_frame (line 413) | fn write_frame(&mut self, rgba: Vec<u8>, delay: u16) -> Result<(), Enc...
method finish (line 420) | fn finish(self) -> Result<Box<[u8]>, EncodeError> {
type PaletteFrameEncoder (line 428) | struct PaletteFrameEncoder {
method new (line 435) | fn new(width: u16, height: u16) -> Result<Self, EncodeError> {
method write_frame (line 449) | fn write_frame(&mut self, rgba: Vec<u8>, delay: u16) -> Result<(), Enc...
method finish (line 468) | fn finish(self) -> Result<Box<[u8]>, EncodeError> {
type PaletteFrameData (line 474) | struct PaletteFrameData {
method from_rgba (line 481) | fn from_rgba(rgba: &[u8]) -> Result<Self, EncodeError> {
type QuantizedFrameEncoder (line 531) | struct QuantizedFrameEncoder {
method new (line 538) | fn new(width: u16, height: u16) -> Result<Self, EncodeError> {
method write_frame (line 552) | fn write_frame(&mut self, mut rgba: Vec<u8>, delay: u16) -> Result<(),...
method finish (line 558) | fn finish(self) -> Result<Box<[u8]>, EncodeError> {
function map_encoding_error (line 564) | fn map_encoding_error(err: gif::EncodingError) -> EncodeError {
function map_io_error (line 568) | fn map_io_error(err: std::io::Error) -> EncodeError {
FILE: fluxer_app/crates/libfluxcore/src/static_image.rs
function normalize_rotation (line 25) | fn normalize_rotation(rotation_deg: u32) -> u32 {
function map_format_hint (line 29) | fn map_format_hint(hint: &str) -> Result<ImageFormat, JsValue> {
function crop_and_rotate_image (line 42) | pub fn crop_and_rotate_image(
FILE: fluxer_app/rspack.config.mjs
constant ROOT_DIR (line 31) | const ROOT_DIR = path.resolve(__dirname, '.');
constant MONOREPO_ROOT (line 32) | const MONOREPO_ROOT = path.resolve(__dirname, '..');
constant SRC_DIR (line 33) | const SRC_DIR = path.join(ROOT_DIR, 'src');
constant DIST_DIR (line 34) | const DIST_DIR = path.join(ROOT_DIR, 'dist');
constant PKGS_DIR (line 35) | const PKGS_DIR = path.join(ROOT_DIR, 'pkgs');
constant PUBLIC_DIR (line 36) | const PUBLIC_DIR = path.join(ROOT_DIR, 'assets');
constant CDN_ENDPOINT (line 38) | const CDN_ENDPOINT = 'https://fluxerstatic.com';
function resolveMode (line 40) | function resolveMode() {
function isPlainObject (line 57) | function isPlainObject(value) {
function readConfig (line 61) | function readConfig() {
function getValue (line 75) | function getValue(source, path, fallback) {
function asString (line 86) | function asString(value, fallback = undefined) {
function normalizeOverride (line 99) | function normalizeOverride(value) {
function buildUrl (line 104) | function buildUrl(scheme, domain, port, path = '') {
function deriveDomain (line 114) | function deriveDomain(endpointType, config) {
function deriveEndpointsFromDomain (line 127) | function deriveEndpointsFromDomain(domainConfig, overrides) {
function stripApiSuffix (line 166) | function stripApiSuffix(url) {
function resolveAppPublic (line 173) | function resolveAppPublic(config) {
function resolveReleaseChannel (line 190) | function resolveReleaseChannel() {
function resolveBuildMetadata (line 198) | function resolveBuildMetadata() {
function getPublicEnvVar (line 221) | function getPublicEnvVar(values, name) {
FILE: fluxer_app/scripts/DevServer.tsx
constant DEFAULT_SKIP_DIRS (line 33) | const DEFAULT_SKIP_DIRS = new Set(['.git', 'node_modules', '.turbo', 'di...
type StepMetadata (line 36) | interface StepMetadata {
type Metadata (line 41) | interface Metadata {
type StepKey (line 45) | type StepKey = 'wasm' | 'colors' | 'masks' | 'cssTypes' | 'lingui';
function loadMetadata (line 47) | async function loadMetadata(): Promise<void> {
function saveMetadata (line 66) | async function saveMetadata(): Promise<void> {
function haveInputsChanged (line 75) | function haveInputsChanged(prev: Record<string, number>, next: Record<st...
function shouldRunStep (line 91) | function shouldRunStep(stepName: StepKey, inputs: Record<string, number>...
function collectFileStats (line 104) | async function collectFileStats(paths: ReadonlyArray<string>): Promise<R...
function collectDirectoryStats (line 117) | async function collectDirectoryStats(
function runCachedStep (line 162) | async function runCachedStep(
function gatherWasmInputs (line 181) | async function gatherWasmInputs(): Promise<Record<string, number>> {
function gatherColorInputs (line 185) | async function gatherColorInputs(): Promise<Record<string, number>> {
function gatherMaskInputs (line 189) | async function gatherMaskInputs(): Promise<Record<string, number>> {
function gatherCssModuleInputs (line 193) | async function gatherCssModuleInputs(): Promise<Record<string, number>> {
function gatherLinguiInputs (line 197) | async function gatherLinguiInputs(): Promise<Record<string, number>> {
function handleShutdown (line 207) | function handleShutdown(signal: NodeJS.Signals): void {
function runCommand (line 221) | function runCommand(command: string, args: ReadonlyArray<string>): Promi...
function cleanDist (line 263) | async function cleanDist(): Promise<void> {
function startCssTypeWatcher (line 272) | function startCssTypeWatcher(): void {
function runRspack (line 299) | function runRspack(): Promise<number> {
function main (line 336) | async function main(): Promise<void> {
FILE: fluxer_app/scripts/GenerateAvatarMasks.tsx
type AvatarSize (line 28) | type AvatarSize = 16 | 20 | 24 | 32 | 36 | 40 | 44 | 48 | 56 | 80 | 120;
type StatusConfig (line 30) | interface StatusConfig {
constant STATUS_CONFIG (line 36) | const STATUS_CONFIG: Record<number, StatusConfig> = {
constant DESIGN_RULES (line 50) | const DESIGN_RULES = {
constant MOBILE_SCREEN_WIDTH_TRIM_PX (line 77) | const MOBILE_SCREEN_WIDTH_TRIM_PX = 4;
constant MOBILE_SCREEN_HEIGHT_TRIM_PX (line 78) | const MOBILE_SCREEN_HEIGHT_TRIM_PX = 2;
constant MOBILE_SCREEN_X_OFFSET_PX (line 79) | const MOBILE_SCREEN_X_OFFSET_PX = 0;
constant MOBILE_SCREEN_Y_OFFSET_PX (line 80) | const MOBILE_SCREEN_Y_OFFSET_PX = 3;
function getStatusConfig (line 82) | function getStatusConfig(avatarSize: number): StatusConfig {
type StatusGeometry (line 95) | interface StatusGeometry {
type MobileStatusGeometry (line 104) | interface MobileStatusGeometry extends StatusGeometry {
function calculateStatusGeometry (line 113) | function calculateStatusGeometry(avatarSize: number, isMobile: boolean =...
function generateAvatarMaskDefault (line 156) | function generateAvatarMaskDefault(size: number): string {
function generateAvatarMaskStatusRound (line 161) | function generateAvatarMaskStatusRound(size: number): string {
function generateAvatarMaskStatusTyping (line 173) | function generateAvatarMaskStatusTyping(size: number): string {
function generateMobilePhoneMask (line 195) | function generateMobilePhoneMask(mobileStatus: MobileStatusGeometry): st...
function generateStatusOnline (line 226) | function generateStatusOnline(size: number, isMobile: boolean = false): ...
function generateStatusIdle (line 236) | function generateStatusIdle(size: number, isMobile: boolean = false): st...
function generateStatusDnd (line 256) | function generateStatusDnd(size: number, isMobile: boolean = false): str...
function generateStatusOffline (line 278) | function generateStatusOffline(size: number): string {
function generateStatusTyping (line 290) | function generateStatusTyping(size: number): string {
constant SIZES (line 303) | const SIZES: Array<AvatarSize> = [16, 20, 24, 32, 36, 40, 44, 48, 56, 80...
FILE: fluxer_app/scripts/GenerateColorSystem.tsx
type ColorFamily (line 23) | interface ColorFamily {
type ScaleStop (line 29) | interface ScaleStop {
type Scale (line 34) | interface Scale {
type TokenDef (line 41) | interface TokenDef {
type Config (line 53) | interface Config {
constant CONFIG (line 63) | const CONFIG: Config = {
type OutputToken (line 475) | interface OutputToken {
function clamp01 (line 487) | function clamp01(value: number): number {
function applyCurve (line 491) | function applyCurve(curve: Scale['curve'], t: number): number {
function buildScaleTokens (line 507) | function buildScaleTokens(scale: Scale): Array<OutputToken> {
function expandTokens (line 536) | function expandTokens(defs: Array<TokenDef>, scales: Record<string, Scal...
function formatNumber (line 573) | function formatNumber(value: number): string {
function formatTone (line 582) | function formatTone(token: OutputToken, families: Record<string, ColorFa...
function formatValue (line 626) | function formatValue(token: OutputToken, families: Record<string, ColorF...
function renderBlock (line 633) | function renderBlock(selector: string, tokens: Array<OutputToken>, famil...
function generateCSS (line 641) | function generateCSS(
function main (line 661) | function main() {
FILE: fluxer_app/scripts/GenerateEmojiSprites.tsx
constant EMOJI_SPRITES (line 25) | const EMOJI_SPRITES = {
constant EMOJI_SIZE (line 32) | const EMOJI_SIZE = 32;
constant TWEMOJI_CDN (line 33) | const TWEMOJI_CDN = 'https://fluxerstatic.com/emoji';
constant SPRITE_SCALES (line 34) | const SPRITE_SCALES = [1, 2] as const;
type EmojiObject (line 36) | interface EmojiObject {
type EmojiEntry (line 41) | interface EmojiEntry {
function fetchTwemojiSVG (line 47) | async function fetchTwemojiSVG(codepoint: string): Promise<string | null> {
function fixSVGSize (line 73) | function fixSVGSize(svg: string, size: number): string {
function renderSVGToBuffer (line 77) | async function renderSVGToBuffer(svgContent: string, size: number): Prom...
function hslToRgb (line 82) | function hslToRgb(h: number, s: number, l: number): [number, number, num...
function createPlaceholder (line 115) | async function createPlaceholder(size: number): Promise<Buffer> {
function loadEmojiImage (line 130) | async function loadEmojiImage(surrogate: string, size: number): Promise<...
function renderSpriteSheet (line 158) | async function renderSpriteSheet(
function generateMainSpriteSheet (line 212) | async function generateMainSpriteSheet(
function generateDiversitySpriteSheets (line 225) | async function generateDiversitySpriteSheets(
function generatePickerSpriteSheet (line 252) | async function generatePickerSpriteSheet(outputDir: string): Promise<voi...
function main (line 290) | async function main(): Promise<void> {
FILE: fluxer_app/scripts/auto-i18n.mjs
constant FLUXER_AUTO_I18N (line 26) | const FLUXER_AUTO_I18N = process.env.FLUXER_AUTO_I18N ?? envOverrides.FL...
constant OPENROUTER_API_KEY (line 27) | const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY ?? envOverride...
function loadEnvFromFiles (line 40) | function loadEnvFromFiles(keys) {
function parseExportLine (line 65) | function parseExportLine(line) {
function stripQuotes (line 79) | function stripQuotes(value) {
FILE: fluxer_app/scripts/build/Config.tsx
constant ROOT_DIR (line 22) | const ROOT_DIR = path.resolve(import.meta.dirname, '..', '..');
constant SRC_DIR (line 23) | const SRC_DIR = path.join(ROOT_DIR, 'src');
constant DIST_DIR (line 24) | const DIST_DIR = path.join(ROOT_DIR, 'dist');
constant ASSETS_DIR (line 25) | const ASSETS_DIR = path.join(DIST_DIR, 'assets');
constant PKGS_DIR (line 26) | const PKGS_DIR = path.join(ROOT_DIR, 'pkgs');
constant PUBLIC_DIR (line 27) | const PUBLIC_DIR = path.join(ROOT_DIR, 'assets');
constant CDN_ENDPOINT (line 29) | const CDN_ENDPOINT = 'https://fluxerstatic.com';
constant DEV_PORT (line 31) | const DEV_PORT = 3000;
constant RESOLVE_EXTENSIONS (line 33) | const RESOLVE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js', '.json', '.mjs...
constant LOCALES (line 35) | const LOCALES = [
constant FILE_LOADERS (line 72) | const FILE_LOADERS: Record<string, 'file'> = {
FILE: fluxer_app/scripts/build/rspack/externals.mjs
constant EXTERNAL_MODULES (line 20) | const EXTERNAL_MODULES = [
constant EXTERNAL_PATTERNS (line 53) | const EXTERNAL_PATTERNS = [/^node:.*/];
class ExternalsPlugin (line 55) | class ExternalsPlugin {
method apply (line 56) | apply(compiler) {
function externalsPlugin (line 63) | function externalsPlugin() {
FILE: fluxer_app/scripts/build/rspack/lingui.mjs
function getLinguiSwcPluginConfig (line 26) | function getLinguiSwcPluginConfig() {
function createPoFileRule (line 40) | function createPoFileRule() {
FILE: fluxer_app/scripts/build/rspack/po-loader.mjs
function poLoader (line 22) | function poLoader(source) {
function parsePoFile (line 54) | function parsePoFile(content) {
function splitEntries (line 67) | function splitEntries(content) {
function parseEntry (line 75) | function parseEntry(entry) {
function extractPoString (line 159) | function extractPoString(str) {
FILE: fluxer_app/scripts/build/rspack/static-files.mjs
function normalizeEndpoint (line 22) | function normalizeEndpoint(staticCdnEndpoint) {
function generateManifest (line 27) | function generateManifest(staticCdnEndpointRaw) {
function generateBrowserConfig (line 77) | function generateBrowserConfig(staticCdnEndpointRaw) {
function generateRobotsTxt (line 91) | function generateRobotsTxt() {
class StaticFilesPlugin (line 95) | class StaticFilesPlugin {
method constructor (line 96) | constructor(options) {
method apply (line 100) | apply(compiler) {
function staticFilesPlugin (line 120) | function staticFilesPlugin(options) {
FILE: fluxer_app/scripts/build/rspack/wasm.mjs
function wasmLoader (line 27) | function wasmLoader(_source) {
function wasmModuleRule (line 52) | function wasmModuleRule() {
FILE: fluxer_app/scripts/build/types.d.ts
type ProcessOptions (line 21) | interface ProcessOptions {
type Result (line 30) | interface Result {
type Plugin (line 39) | interface Plugin {
type Processor (line 54) | interface Processor {
type PostcssModulesOptions (line 64) | interface PostcssModulesOptions {
FILE: fluxer_app/scripts/build/utils/Assets.tsx
function copyPublicAssets (line 24) | async function copyPublicAssets(): Promise<void> {
function copyWasmFiles (line 42) | async function copyWasmFiles(): Promise<void> {
function removeUnusedCssAssets (line 51) | async function removeUnusedCssAssets(assetsDir: string, keepFiles: Array...
FILE: fluxer_app/scripts/build/utils/CssDts.tsx
constant RESERVED_KEYWORDS (line 26) | const RESERVED_KEYWORDS = new Set([
function isValidIdentifier (line 72) | function isValidIdentifier(name: string): boolean {
function generateDtsContent (line 79) | function generateDtsContent(classNames: Record<string, string>): string {
function findCssModuleFiles (line 88) | async function findCssModuleFiles(dir: string): Promise<Array<string>> {
function generateDtsForFile (line 111) | async function generateDtsForFile(cssPath: string): Promise<void> {
function generateCssDtsForFile (line 130) | async function generateCssDtsForFile(cssPath: string): Promise<void> {
function generateAllCssDts (line 137) | async function generateAllCssDts(): Promise<void> {
FILE: fluxer_app/scripts/build/utils/Html.tsx
type BuildOutput (line 24) | interface BuildOutput {
type GenerateHtmlOptions (line 32) | interface GenerateHtmlOptions {
function findCssModulesFile (line 37) | async function findCssModulesFile(): Promise<string | null> {
function generateHtml (line 62) | async function generateHtml(options: GenerateHtmlOptions): Promise<strin...
FILE: fluxer_app/scripts/build/utils/Resolve.tsx
function tryResolveWithExtensions (line 24) | function tryResolveWithExtensions(basePath: string): string | null {
FILE: fluxer_app/scripts/build/utils/ServiceWorker.tsx
function buildServiceWorker (line 24) | async function buildServiceWorker(production: boolean): Promise<void> {
FILE: fluxer_app/scripts/build/utils/Sourcemaps.tsx
function fileExists (line 23) | async function fileExists(filePath: string): Promise<boolean> {
function traverseDir (line 32) | async function traverseDir(dir: string, callback: (filePath: string) => ...
function cleanEmptySourceMaps (line 46) | async function cleanEmptySourceMaps(dir: string): Promise<void> {
FILE: fluxer_app/scripts/translate-i18n.mjs
constant OPENROUTER_API_KEY (line 23) | const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY;
constant LOCALES_DIR (line 29) | const LOCALES_DIR = new URL('../src/locales', import.meta.url).pathname;
constant SOURCE_LOCALE (line 30) | const SOURCE_LOCALE = 'en-US';
constant BATCH_SIZE (line 31) | const BATCH_SIZE = 20;
constant CONCURRENT_LOCALES (line 32) | const CONCURRENT_LOCALES = 10;
constant CONCURRENT_BATCHES_PER_LOCALE (line 33) | const CONCURRENT_BATCHES_PER_LOCALE = 3;
constant LOCALE_NAMES (line 35) | const LOCALE_NAMES = {
function parsePo (line 71) | function parsePo(content) {
function rebuildPo (line 124) | function rebuildPo(content, translations) {
function rebuildPoBlock (line 132) | function rebuildPoBlock(block, translationMap) {
function getFieldRange (line 161) | function getFieldRange(lines, field) {
function readFieldRawValue (line 173) | function readFieldRawValue(lines, range) {
function escapePo (line 183) | function escapePo(str) {
function unescapePo (line 187) | function unescapePo(str) {
function translateBatch (line 191) | async function translateBatch(strings, targetLocale) {
function pMap (line 251) | async function pMap(items, mapper, concurrency) {
function processLocale (line 271) | async function processLocale(locale) {
function main (line 340) | async function main() {
FILE: fluxer_app/src/App.tsx
type AppWrapperProps (line 70) | interface AppWrapperProps {
FILE: fluxer_app/src/AppConstants.tsx
function getOAuth2ScopeDescription (line 34) | function getOAuth2ScopeDescription(i18n: I18n, scope: OAuth2Scope): stri...
function getStatusTypeLabel (line 46) | function getStatusTypeLabel(i18n: I18n, statusType: StatusType | string)...
function getStatusTypeDescription (line 59) | function getStatusTypeDescription(i18n: I18n, statusType: StatusType | s...
FILE: fluxer_app/src/I18n.tsx
type LocaleCode (line 96) | type LocaleCode = (typeof supportedLocales)[number];
constant DEFAULT_LOCALE (line 97) | const DEFAULT_LOCALE: LocaleCode = 'en-US';
constant LANGUAGE_OVERRIDES (line 102) | const LANGUAGE_OVERRIDES: Record<string, LocaleCode> = {
type LocaleLoader (line 106) | type LocaleLoader = () => {messages: Messages};
function formatLocaleValue (line 145) | function formatLocaleValue(value: string): string {
function normalizeLocale (line 169) | function normalizeLocale(value?: string | null): LocaleCode {
function detectBrowserLocale (line 201) | function detectBrowserLocale(): string | null {
function detectPreferredLocale (line 209) | function detectPreferredLocale(forceLocale?: string): LocaleCode {
function loadLocaleCatalog (line 232) | function loadLocaleCatalog(localeCode: string): LocaleCode {
function initI18n (line 242) | async function initI18n(forceLocale?: string) {
FILE: fluxer_app/src/actions/AccessibilityActionCreators.tsx
function update (line 22) | function update(settings: Partial<AccessibilitySettings>): void {
FILE: fluxer_app/src/actions/AuthSessionActionCreators.tsx
function fetch (line 28) | async function fetch(): Promise<void> {
function logout (line 44) | async function logout(sessionIdHashes: Array<string>): Promise<void> {
FILE: fluxer_app/src/actions/AuthenticationActionCreators.tsx
type VerificationResult (line 48) | type VerificationResult = ValueOf<typeof VerificationResult>;
type RegisterData (line 50) | interface RegisterData {
type StandardLoginResponse (line 62) | interface StandardLoginResponse {
type MfaLoginResponse (line 69) | interface MfaLoginResponse {
type LoginResponse (line 79) | type LoginResponse = StandardLoginResponse | MfaLoginResponse;
type IpAuthorizationRequiredResponse (line 81) | interface IpAuthorizationRequiredResponse {
function isIpAuthorizationRequiredResponse (line 88) | function isIpAuthorizationRequiredResponse(
type TokenResponse (line 94) | interface TokenResponse {
type ResetPasswordResponse (line 101) | type ResetPasswordResponse = TokenResponse | MfaLoginResponse;
type DesktopHandoffInitiateResponse (line 103) | interface DesktopHandoffInitiateResponse {
type DesktopHandoffStatusResponse (line 108) | interface DesktopHandoffStatusResponse {
function login (line 114) | async function login({
function loginMfaTotp (line 168) | async function loginMfaTotp(code: string, ticket: string, inviteCode?: s...
function loginMfaSmsSend (line 192) | async function loginMfaSmsSend(ticket: string): Promise<void> {
function loginMfaSms (line 206) | async function loginMfaSms(code: string, ticket: string, inviteCode?: st...
function loginMfaWebAuthn (line 230) | async function loginMfaWebAuthn(
function getWebAuthnMfaOptions (line 260) | async function getWebAuthnMfaOptions(ticket: string): Promise<PublicKeyC...
function getWebAuthnAuthenticationOptions (line 276) | async function getWebAuthnAuthenticationOptions(): Promise<PublicKeyCred...
function authenticateWithWebAuthn (line 291) | async function authenticateWithWebAuthn(
function register (line 319) | async function register(data: RegisterData): Promise<TokenResponse> {
type UsernameSuggestionsResponse (line 341) | interface UsernameSuggestionsResponse {
function getUsernameSuggestions (line 345) | async function getUsernameSuggestions(globalName: string): Promise<Array...
function forgotPassword (line 361) | async function forgotPassword(
function resetPassword (line 383) | async function resetPassword(token: string, password: string): Promise<R...
function revertEmailChange (line 399) | async function revertEmailChange(token: string, password: string): Promi...
function verifyEmail (line 415) | async function verifyEmail(token: string): Promise<VerificationResult> {
function resendVerificationEmail (line 435) | async function resendVerificationEmail(): Promise<VerificationResult> {
function logout (line 454) | async function logout(): Promise<void> {
function authorizeIp (line 458) | async function authorizeIp(token: string): Promise<VerificationResult> {
function resendIpAuthorization (line 478) | async function resendIpAuthorization(ticket: string): Promise<void> {
type IpAuthorizationPollResult (line 486) | interface IpAuthorizationPollResult {
function pollIpAuthorization (line 492) | async function pollIpAuthorization(ticket: string): Promise<IpAuthorizat...
function initiateDesktopHandoff (line 500) | async function initiateDesktopHandoff(): Promise<DesktopHandoffInitiateR...
function pollDesktopHandoffStatus (line 508) | async function pollDesktopHandoffStatus(code: string): Promise<DesktopHa...
function completeDesktopHandoff (line 516) | async function completeDesktopHandoff({
function startSession (line 532) | function startSession(token: string, options: {startGateway?: boolean} =...
function ensureSessionStarted (line 547) | async function ensureSessionStarted(): Promise<void> {
function completeLogin (line 584) | async function completeLogin({
function startSso (line 602) | async function startSso(redirectTo?: string): Promise<{authorization_url...
function completeSso (line 611) | async function completeSso({code, state}: {code: string; state: string})...
type SetMfaTicketPayload (line 620) | interface SetMfaTicketPayload {
function setMfaTicket (line 627) | function setMfaTicket({ticket, sms, totp, webauthn}: SetMfaTicketPayload...
function clearMfaTicket (line 632) | function clearMfaTicket(): void {
FILE: fluxer_app/src/actions/CallActionCreators.tsx
type PendingRing (line 34) | interface PendingRing {
function checkCallEligibility (line 44) | async function checkCallEligibility(channelId: string): Promise<{ringabl...
function ringCallRecipients (line 49) | async function ringCallRecipients(channelId: string, recipients?: Array<...
function stopRingingCallRecipients (line 63) | async function stopRingingCallRecipients(channelId: string, recipients?:...
function ringParticipants (line 67) | async function ringParticipants(channelId: string, recipients?: Array<st...
function stopRingingParticipants (line 71) | async function stopRingingParticipants(channelId: string, recipients?: A...
function clearPendingRing (line 75) | function clearPendingRing(): void {
function setupPendingRing (line 82) | function setupPendingRing(channelId: string, recipients: Array<string>):...
function startCall (line 104) | function startCall(channelId: string, silent = false): void {
function joinCall (line 126) | function joinCall(channelId: string): void {
function leaveCall (line 136) | async function leaveCall(channelId: string): Promise<void> {
function rejectCall (line 167) | function rejectCall(channelId: string): void {
function ignoreCall (line 184) | function ignoreCall(channelId: string): void {
function fetchCallRegions (line 196) | async function fetchCallRegions(channelId: string): Promise<Array<RtcReg...
function updateCallRegion (line 205) | async function updateCallRegion(channelId: string, region: string | null...
FILE: fluxer_app/src/actions/ChannelActionCreators.tsx
type ChannelRtcRegion (line 31) | interface ChannelRtcRegion {
function create (line 37) | async function create(
function update (line 50) | async function update(
function updateGroupDMNickname (line 63) | async function updateGroupDMNickname(channelId: string, userId: string, ...
type RemoveChannelOptions (line 80) | interface RemoveChannelOptions {
function remove (line 84) | async function remove(channelId: string, silent?: boolean, options?: Rem...
function updatePermissionOverwrites (line 111) | async function updatePermissionOverwrites(
function fetchChannelInvites (line 127) | async function fetchChannelInvites(channelId: string): Promise<Array<Inv...
function fetchRtcRegions (line 141) | async function fetchRtcRegions(channelId: string): Promise<Array<Channel...
FILE: fluxer_app/src/actions/ChannelPinsActionCreators.tsx
type ApiErrorBody (line 33) | interface ApiErrorBody {
constant PIN_PAGE_SIZE (line 44) | const PIN_PAGE_SIZE = 25;
type ChannelPinResponse (line 54) | interface ChannelPinResponse {
type ChannelPinsPayload (line 58) | interface ChannelPinsPayload {
function fetch (line 63) | async function fetch(channelId: string) {
function loadMore (line 85) | async function loadMore(channelId: string): Promise<Array<Message>> {
function pin (line 128) | async function pin(channelId: string, messageId: string): Promise<void> {
function unpin (line 139) | async function unpin(channelId: string, messageId: string): Promise<void> {
FILE: fluxer_app/src/actions/ChannelStickerActionCreators.tsx
function setPendingSticker (line 23) | function setPendingSticker(channelId: string, sticker: GuildStickerRecor...
function removePendingSticker (line 27) | function removePendingSticker(channelId: string): void {
FILE: fluxer_app/src/actions/ConnectionActionCreators.tsx
function showErrorToast (line 41) | function showErrorToast(i18n: I18n, error: unknown, fallbackMessage: Mes...
function fetchConnections (line 50) | async function fetchConnections(): Promise<void> {
function initiateConnection (line 61) | async function initiateConnection(
function authorizeBlueskyConnection (line 82) | async function authorizeBlueskyConnection(i18n: I18n, handle: string): P...
function verifyAndCreateConnection (line 93) | async function verifyAndCreateConnection(
function updateConnection (line 121) | async function updateConnection(
function deleteConnection (line 143) | async function deleteConnection(i18n: I18n, type: string, connectionId: ...
function verifyConnection (line 160) | async function verifyConnection(i18n: I18n, type: string, connectionId: ...
function reorderConnections (line 177) | async function reorderConnections(i18n: I18n, connectionIds: Array<strin...
FILE: fluxer_app/src/actions/ContextMenuActionCreators.tsx
function close (line 50) | function close(): void {
type RenderFn (line 54) | type RenderFn = (props: {onClose: () => void}) => React.ReactNode;
function openAtPoint (line 56) | function openAtPoint(
function openForElement (line 72) | function openForElement(
function openFromEvent (line 81) | function openFromEvent(
function openFromElementBottomRight (line 108) | function openFromElementBottomRight(
function openFromElementTopLeft (line 133) | function openFromElementTopLeft(
function openNativeContextMenu (line 158) | function openNativeContextMenu(render: RenderFn, config?: ContextMenu['c...
FILE: fluxer_app/src/actions/DeveloperOptionsActionCreators.tsx
function updateOption (line 34) | function updateOption<K extends keyof DeveloperOptionsState>(key: K, val...
function setAttachmentMock (line 39) | function setAttachmentMock(
function clearAllAttachmentMocks (line 53) | function clearAllAttachmentMocks(): void {
function triggerMockIncomingCall (line 58) | function triggerMockIncomingCall(): void {
FILE: fluxer_app/src/actions/DimensionActionCreators.tsx
function updateChannelListScroll (line 25) | function updateChannelListScroll(guildId: string, scrollTop: number): vo...
function clearChannelListScrollTo (line 30) | function clearChannelListScrollTo(guildId: string): void {
function updateGuildListScroll (line 35) | function updateGuildListScroll(scrollTop: number): void {
FILE: fluxer_app/src/actions/DiscoveryActionCreators.tsx
type DiscoveryGuild (line 26) | interface DiscoveryGuild {
type DiscoverySearchResponse (line 38) | interface DiscoverySearchResponse {
type DiscoveryCategory (line 43) | interface DiscoveryCategory {
function searchGuilds (line 48) | async function searchGuilds(params: {
function getCategories (line 75) | async function getCategories(): Promise<Array<DiscoveryCategory>> {
function joinGuild (line 82) | async function joinGuild(guildId: string): Promise<void> {
FILE: fluxer_app/src/actions/DraftActionCreators.tsx
function createDraft (line 25) | function createDraft(channelId: string, content: string): void {
function deleteDraft (line 30) | function deleteDraft(channelId: string): void {
FILE: fluxer_app/src/actions/EmojiActionCreators.tsx
function setSkinTone (line 25) | function setSkinTone(skinTone: string): void {
FILE: fluxer_app/src/actions/EmojiPickerActionCreators.tsx
function getEmojiKey (line 23) | function getEmojiKey(emoji: FlatEmoji): string {
function trackEmojiUsage (line 30) | function trackEmojiUsage(emoji: FlatEmoji): void {
function toggleFavorite (line 34) | function toggleFavorite(emoji: FlatEmoji): void {
function toggleCategory (line 38) | function toggleCategory(category: string): void {
FILE: fluxer_app/src/actions/ExpressionPickerActionCreators.tsx
function open (line 26) | function open(channelId: string, tab?: ExpressionPickerTabType): void {
function close (line 31) | function close(): void {
function toggle (line 36) | function toggle(channelId: string, tab: ExpressionPickerTabType): void {
function setTab (line 41) | function setTab(tab: ExpressionPickerTabType): void {
FILE: fluxer_app/src/actions/FavoriteMemeActionCreators.tsx
function createFavoriteMeme (line 37) | async function createFavoriteMeme(
function createFavoriteMemeFromUrl (line 83) | async function createFavoriteMemeFromUrl(
function updateFavoriteMeme (line 128) | async function updateFavoriteMeme(
function deleteFavoriteMeme (line 162) | async function deleteFavoriteMeme(i18n: I18n, memeId: string): Promise<v...
FILE: fluxer_app/src/actions/FavoritesActionCreators.tsx
function confirmHideFavorites (line 28) | function confirmHideFavorites(onConfirm: (() => void) | undefined, i18n:...
FILE: fluxer_app/src/actions/GifActionCreators.tsx
type Gif (line 30) | interface Gif {
type GifCategory (line 40) | interface GifCategory {
type GifFeatured (line 46) | interface GifFeatured {
function getProvider (line 51) | function getProvider(): GifProvider {
function getProviderEndpoints (line 55) | function getProviderEndpoints(provider: GifProvider): {
function search (line 83) | async function search(q: string): Promise<Array<Gif>> {
function getFeatured (line 100) | async function getFeatured(): Promise<GifFeatured> {
function getTrending (line 125) | async function getTrending(): Promise<Array<Gif>> {
function registerShare (line 142) | async function registerShare(id: string, q: string): Promise<void> {
function suggest (line 155) | async function suggest(q: string): Promise<Array<string>> {
function resetFeaturedCache (line 172) | function resetFeaturedCache(): void {
FILE: fluxer_app/src/actions/GiftActionCreators.tsx
type ApiErrorResponse (line 38) | interface ApiErrorResponse {
type Gift (line 46) | interface Gift {
type GiftMetadata (line 53) | interface GiftMetadata {
function fetch (line 62) | async function fetch(code: string): Promise<Gift> {
function fetchWithCoalescing (line 79) | async function fetchWithCoalescing(code: string): Promise<Gift> {
function openAcceptModal (line 83) | async function openAcceptModal(code: string): Promise<void> {
function redeem (line 91) | async function redeem(i18n: I18n, code: string): Promise<void> {
function fetchUserGifts (line 174) | async function fetchUserGifts(): Promise<Array<GiftMetadata>> {
FILE: fluxer_app/src/actions/GuildActionCreators.tsx
type GuildAuditLogFetchParams (line 42) | interface GuildAuditLogFetchParams {
type GuildAuditLogFetchResponse (line 50) | interface GuildAuditLogFetchResponse {
type GuildBan (line 56) | interface GuildBan {
function create (line 70) | async function create(params: Pick<Guild, 'name'> & {icon?: string | nul...
function update (line 82) | async function update(
function moveChannel (line 118) | async function moveChannel(guildId: string, operation: ChannelMoveOperat...
function getVanityURL (line 140) | async function getVanityURL(guildId: string): Promise<{code: string | nu...
function updateVanityURL (line 152) | async function updateVanityURL(guildId: string, code: string | null): Pr...
function createRole (line 163) | async function createRole(guildId: string, name: string): Promise<void> {
function updateRole (line 173) | async function updateRole(guildId: string, roleId: string, patch: Partia...
function deleteRole (line 183) | async function deleteRole(guildId: string, roleId: string): Promise<void> {
function setRoleOrder (line 193) | async function setRoleOrder(guildId: string, orderedRoleIds: Array<strin...
function setRoleHoistOrder (line 205) | async function setRoleHoistOrder(guildId: string, orderedRoleIds: Array<...
function resetRoleHoistOrder (line 217) | async function resetRoleHoistOrder(guildId: string): Promise<void> {
function remove (line 227) | async function remove(guildId: string): Promise<void> {
function leave (line 237) | async function leave(guildId: string): Promise<void> {
function fetchGuildInvites (line 247) | async function fetchGuildInvites(guildId: string): Promise<Array<Invite>> {
function toggleInvitesDisabled (line 261) | async function toggleInvitesDisabled(guildId: string, disabled: boolean)...
function toggleTextChannelFlexibleNames (line 275) | async function toggleTextChannelFlexibleNames(guildId: string, enabled: ...
function toggleDetachedBanner (line 290) | async function toggleDetachedBanner(guildId: string, enabled: boolean): ...
function transferOwnership (line 302) | async function transferOwnership(guildId: string, newOwnerId: string): P...
function banMember (line 316) | async function banMember(
function unbanMember (line 339) | async function unbanMember(guildId: string, userId: string): Promise<voi...
function fetchBans (line 349) | async function fetchBans(guildId: string): Promise<Array<GuildBan>> {
function fetchGuildAuditLogs (line 361) | async function fetchGuildAuditLogs(
function getDiscoveryStatus (line 387) | async function getDiscoveryStatus(guildId: string): Promise<DiscoverySta...
function applyForDiscovery (line 398) | async function applyForDiscovery(
function updateDiscoveryApplication (line 412) | async function updateDiscoveryApplication(
function withdrawDiscoveryApplication (line 426) | async function withdrawDiscoveryApplication(guildId: string): Promise<vo...
FILE: fluxer_app/src/actions/GuildEmojiActionCreators.tsx
function sanitizeEmojiName (line 27) | function sanitizeEmojiName(fileName: string): string {
function list (line 36) | async function list(guildId: string): Promise<ReadonlyArray<GuildEmojiWi...
function bulkUpload (line 48) | async function bulkUpload(
function update (line 71) | async function update(guildId: string, emojiId: string, data: {name: str...
function remove (line 81) | async function remove(guildId: string, emojiId: string, purge = false): ...
FILE: fluxer_app/src/actions/GuildMemberActionCreators.tsx
function update (line 27) | async function update(
function addRole (line 41) | async function addRole(guildId: string, userId: string, roleId: string):...
function removeRole (line 51) | async function removeRole(guildId: string, userId: string, roleId: strin...
function updateProfile (line 61) | async function updateProfile(
function kick (line 82) | async function kick(guildId: string, userId: string): Promise<void> {
function timeout (line 92) | async function timeout(
FILE: fluxer_app/src/actions/GuildNSFWActionCreators.tsx
function agreeToChannel (line 22) | function agreeToChannel(channelId: string): void {
function agreeToGuild (line 26) | function agreeToGuild(guildId: string): void {
FILE: fluxer_app/src/actions/GuildStickerActionCreators.tsx
function sanitizeStickerName (line 27) | function sanitizeStickerName(fileName: string): string {
function list (line 36) | async function list(guildId: string): Promise<ReadonlyArray<GuildSticker...
function create (line 48) | async function create(
function update (line 61) | async function update(
function remove (line 75) | async function remove(guildId: string, stickerId: string, purge = false)...
FILE: fluxer_app/src/actions/HighlightActionCreators.tsx
function highlightChannel (line 22) | function highlightChannel(channelId: string): void {
function clearChannelHighlight (line 26) | function clearChannelHighlight(): void {
FILE: fluxer_app/src/actions/IARActionCreators.tsx
function reportMessage (line 26) | async function reportMessage(
function reportUser (line 50) | async function reportUser(
function reportGuild (line 74) | async function reportGuild(guildId: string, category: string, additional...
FILE: fluxer_app/src/actions/InboxActionCreators.tsx
function setTab (line 23) | function setTab(tab: InboxTab): void {
FILE: fluxer_app/src/actions/InviteActionCreators.tsx
function fetch (line 61) | async function fetch(code: string): Promise<Invite> {
function fetchWithCoalescing (line 72) | async function fetchWithCoalescing(code: string): Promise<Invite> {
function acceptAndTransitionToChannel (line 89) | async function acceptAndTransitionToChannel(code: string, i18n: I18n): P...
function openAcceptModal (line 197) | async function openAcceptModal(code: string): Promise<void> {
type HandlePackInviteErrorParams (line 205) | interface HandlePackInviteErrorParams {
type PackLimitPayload (line 212) | interface PackLimitPayload {
function handlePackInviteError (line 309) | function handlePackInviteError(params: HandlePackInviteErrorParams): boo...
function create (line 355) | async function create(
function list (line 369) | async function list(channelId: string): Promise<Array<Invite>> {
function remove (line 380) | async function remove(code: string): Promise<void> {
FILE: fluxer_app/src/actions/KlipyActionCreators.tsx
type KlipyGif (line 29) | interface KlipyGif {
type KlipyCategory (line 39) | interface KlipyCategory {
type KlipyFeatured (line 45) | interface KlipyFeatured {
function search (line 52) | async function search(q: string): Promise<Array<KlipyGif>> {
function getFeatured (line 68) | async function getFeatured(): Promise<KlipyFeatured> {
function getTrending (line 92) | async function getTrending(): Promise<Array<KlipyGif>> {
function registerShare (line 108) | async function registerShare(id: string, q: string): Promise<void> {
function suggest (line 118) | async function suggest(q: string): Promise<Array<string>> {
FILE: fluxer_app/src/actions/LayoutActionCreators.tsx
function updateMobileLayoutState (line 26) | function updateMobileLayoutState(navExpanded: boolean, chatExpanded: boo...
function toggleMembers (line 31) | function toggleMembers(_isOpen: boolean): void {
FILE: fluxer_app/src/actions/MediaViewerActionCreators.tsx
function openMediaViewer (line 23) | function openMediaViewer(
function closeMediaViewer (line 35) | function closeMediaViewer(): void {
function navigateMediaViewer (line 39) | function navigateMediaViewer(index: number): void {
FILE: fluxer_app/src/actions/MessageActionCreators.tsx
function shouldBlockMessageFetch (line 68) | function shouldBlockMessageFetch(channelId: string): boolean {
function makeFetchKey (line 77) | function makeFetchKey(
function requestMissingGuildMembers (line 102) | async function requestMissingGuildMembers(channelId: string, messages: A...
type SendMessageParams (line 122) | interface SendMessageParams {
function jumpToPresent (line 134) | function jumpToPresent(channelId: string, limit = MAX_MESSAGES_PER_CHANN...
function jumpToMessage (line 151) | function jumpToMessage(
function fetchMessages (line 193) | async function fetchMessages(
function send (line 302) | function send(channelId: string, params: SendMessageParams): Promise<Mes...
function edit (line 335) | function edit(channelId: string, messageId: string, content?: string, fl...
function remove (line 362) | async function remove(channelId: string, messageId: string): Promise<voi...
type ShowDeleteConfirmationOptions (line 404) | interface ShowDeleteConfirmationOptions {
function showDeleteConfirmation (line 409) | function showDeleteConfirmation(i18n: I18n, {message, onDelete}: ShowDel...
function deleteLocal (line 426) | function deleteLocal(channelId: string, messageId: string): void {
function revealMessage (line 431) | function revealMessage(channelId: string, messageId: string | null): void {
function startReply (line 436) | function startReply(channelId: string, messageId: string, mentioning: bo...
function stopReply (line 442) | function stopReply(channelId: string): void {
function setReplyMentioning (line 447) | function setReplyMentioning(channelId: string, mentioning: boolean): void {
function startEdit (line 452) | function startEdit(channelId: string, messageId: string, initialContent:...
function stopEdit (line 459) | function stopEdit(channelId: string): void {
function startEditMobile (line 464) | function startEditMobile(channelId: string, messageId: string): void {
function stopEditMobile (line 469) | function stopEditMobile(channelId: string): void {
function createOptimistic (line 474) | function createOptimistic(channelId: string, message: Message): void {
function deleteOptimistic (line 479) | function deleteOptimistic(channelId: string, messageId: string): void {
function sendError (line 484) | function sendError(channelId: string, nonce: string): void {
function retryLocal (line 489) | function retryLocal(channelId: string, messageId: string): void {
function editOptimistic (line 494) | function editOptimistic(
function editRollback (line 503) | function editRollback(
function forward (line 513) | async function forward(
function toggleSuppressEmbeds (line 550) | async function toggleSuppressEmbeds(channelId: string, messageId: string...
function deleteAttachment (line 571) | async function deleteAttachment(channelId: string, messageId: string, at...
FILE: fluxer_app/src/actions/MfaActionCreators.tsx
function enableMfaTotp (line 28) | async function enableMfaTotp(secret: string, code: string): Promise<Arra...
function disableMfaTotp (line 45) | async function disableMfaTotp(code: string): Promise<void> {
function getBackupCodes (line 56) | async function getBackupCodes(regenerate = false): Promise<Array<BackupC...
FILE: fluxer_app/src/actions/ModalActionCreators.tsx
constant BACKGROUND_MODAL_TYPES (line 31) | const BACKGROUND_MODAL_TYPES = [UserSettingsModal, GuildSettingsModal, C...
function modal (line 37) | function modal(render: () => React.ReactElement): ModalRender {
function push (line 41) | function push(modal: ModalRender): void {
function pushWithKey (line 63) | function pushWithKey(modal: ModalRender, key: string): void {
function update (line 90) | function update(key: string, updater: (currentModal: ModalRender) => Mod...
function pop (line 95) | function pop(): void {
function popWithKey (line 100) | function popWithKey(key: string): void {
function popByType (line 105) | function popByType<T>(component: React.ComponentType<T>): void {
function popAll (line 110) | function popAll(): void {
FILE: fluxer_app/src/actions/ModalRender.tsx
type ModalRender (line 22) | type ModalRender = () => React.ReactElement;
FILE: fluxer_app/src/actions/NagbarActionCreators.tsx
function dismissNagbar (line 22) | function dismissNagbar(nagbarType: NagbarToggleKey): void {
function dismissInvitesDisabledNagbar (line 26) | function dismissInvitesDisabledNagbar(guildId: string): void {
function resetNagbar (line 30) | function resetNagbar(nagbarType: NagbarToggleKey): void {
function resetAllNagbars (line 34) | function resetAllNagbars(): void {
function setForceHideNagbar (line 38) | function setForceHideNagbar(key: NagbarToggleKey, value: boolean): void {
function dismissPendingBulkDeletionNagbar (line 42) | function dismissPendingBulkDeletionNagbar(scheduleKey: string): void {
function clearPendingBulkDeletionNagbarDismissal (line 46) | function clearPendingBulkDeletionNagbarDismissal(scheduleKey: string): v...
FILE: fluxer_app/src/actions/NavigationActionCreators.tsx
type NavigationMode (line 26) | type NavigationMode = 'push' | 'replace';
function selectChannel (line 28) | function selectChannel(
function selectGuild (line 45) | function selectGuild(guildId: string, channelId?: string, mode: Navigati...
function deselectGuild (line 57) | function deselectGuild(): void {
function navigateToMessage (line 62) | function navigateToMessage(
function clearMessageIdForChannel (line 79) | function clearMessageIdForChannel(channelId: string, mode: NavigationMod...
FILE: fluxer_app/src/actions/NotificationActionCreators.tsx
function permissionDenied (line 31) | function permissionDenied(i18n: I18n, suppressModal = false): void {
function permissionGranted (line 58) | function permissionGranted(): void {
function toggleUnreadMessageBadge (line 63) | function toggleUnreadMessageBadge(enabled: boolean): void {
FILE: fluxer_app/src/actions/OAuth2AuthorizationActionCreators.tsx
type OAuth2Authorization (line 26) | interface OAuth2Authorization {
function listAuthorizations (line 38) | async function listAuthorizations(): Promise<Array<OAuth2Authorization>> {
function deauthorize (line 48) | async function deauthorize(applicationId: string): Promise<void> {
FILE: fluxer_app/src/actions/PackActionCreators.tsx
function list (line 27) | async function list(): Promise<PackDashboardResponse> {
function create (line 38) | async function create(
function update (line 56) | async function update(
function remove (line 70) | async function remove(packId: string): Promise<void> {
function install (line 80) | async function install(packId: string): Promise<void> {
function uninstall (line 90) | async function uninstall(packId: string): Promise<void> {
FILE: fluxer_app/src/actions/PackInviteActionCreators.tsx
type CreatePackInviteParams (line 27) | interface CreatePackInviteParams {
function createInvite (line 34) | async function createInvite(params: CreatePackInviteParams): Promise<Pac...
FILE: fluxer_app/src/actions/PiPActionCreators.tsx
function openPiP (line 22) | function openPiP(content: PiPContent): void {
function closePiP (line 26) | function closePiP(): void {
function showFocusedTileMirror (line 30) | function showFocusedTileMirror(content: PiPContent, corner: PiPCorner = ...
function hideFocusedTileMirror (line 34) | function hideFocusedTileMirror(): void {
FILE: fluxer_app/src/actions/PopoutActionCreators.tsx
function open (line 23) | function open(popout: Popout): void {
function close (line 27) | function close(key?: string | number): void {
function closeAll (line 31) | function closeAll(): void {
FILE: fluxer_app/src/actions/PremiumActionCreators.tsx
type PriceIds (line 27) | type PriceIds = PriceIdsResponse;
function fetchPriceIds (line 29) | async function fetchPriceIds(countryCode?: string): Promise<PriceIds> {
function createCustomerPortalSession (line 43) | async function createCustomerPortalSession(): Promise<string> {
function createCheckoutSession (line 54) | async function createCheckoutSession(priceId: string, isGift: boolean = ...
function cancelSubscriptionAtPeriodEnd (line 66) | async function cancelSubscriptionAtPeriodEnd(): Promise<void> {
function reactivateSubscription (line 76) | async function reactivateSubscription(): Promise<void> {
function rejoinVisionaryGuild (line 86) | async function rejoinVisionaryGuild(): Promise<void> {
function rejoinOperatorGuild (line 96) | async function rejoinOperatorGuild(): Promise<void> {
FILE: fluxer_app/src/actions/PremiumModalActionCreators.tsx
type OpenOptions (line 25) | interface OpenOptions {
function open (line 29) | function open(optionsOrDefaultGiftMode: OpenOptions | boolean = {}): void {
FILE: fluxer_app/src/actions/PrivateChannelActionCreators.tsx
function create (line 31) | async function create(userId: string) {
function createGroupDM (line 45) | async function createGroupDM(recipientIds: Array<string>) {
function removeRecipient (line 59) | async function removeRecipient(channelId: string, userId: string) {
function ensureDMChannel (line 70) | async function ensureDMChannel(userId: string): Promise<string> {
function openDMChannel (line 89) | async function openDMChannel(userId: string): Promise<void> {
function pinDmChannel (line 99) | async function pinDmChannel(channelId: string): Promise<void> {
function unpinDmChannel (line 110) | async function unpinDmChannel(channelId: string): Promise<void> {
function addRecipient (line 121) | async function addRecipient(channelId: string, userId: string): Promise<...
FILE: fluxer_app/src/actions/QuickSwitcherActionCreators.tsx
constant QUICK_SWITCHER_MODAL_KEY (line 34) | const QUICK_SWITCHER_MODAL_KEY = 'quick_switcher';
function hide (line 36) | function hide(): void {
function search (line 40) | function search(query: string): void {
function select (line 44) | function select(selectedIndex: number): void {
function moveSelection (line 48) | function moveSelection(direction: 'up' | 'down'): void {
function confirmSelection (line 53) | async function confirmSelection(): Promise<void> {
function switchTo (line 59) | async function switchTo(result: QuickSwitcherExecutableResult): Promise<...
function getModalKey (line 140) | function getModalKey(): string {
FILE: fluxer_app/src/actions/ReactionActionCreators.tsx
constant MAX_RETRIES (line 43) | const MAX_RETRIES = 3;
function retryWithExponentialBackoff (line 149) | async function retryWithExponentialBackoff<T>(func: () => Promise<T>, at...
function getReactions (line 201) | async function getReactions(
function addReaction (line 233) | function addReaction(i18n: I18n, channelId: string, messageId: string, e...
function removeReaction (line 245) | function removeReaction(
function removeAllReactions (line 263) | function removeAllReactions(i18n: I18n, channelId: string, messageId: st...
function removeReactionEmoji (line 276) | function removeReactionEmoji(i18n: I18n, channelId: string, messageId: s...
FILE: fluxer_app/src/actions/ReadStateActionCreators.tsx
function ack (line 30) | function ack(channelId: string, immediate = false, force = false): void {
function ackWithStickyUnread (line 35) | function ackWithStickyUnread(channelId: string): void {
function manualAck (line 40) | async function manualAck(channelId: string, messageId: string): Promise<...
function markAsUnread (line 61) | async function markAsUnread(channelId: string, messageId: string): Promi...
function clearManualAck (line 84) | function clearManualAck(channelId: string): void {
function clearStickyUnread (line 88) | function clearStickyUnread(channelId: string): void {
type BulkAckEntry (line 93) | interface BulkAckEntry {
constant BULK_ACK_BATCH_SIZE (line 98) | const BULK_ACK_BATCH_SIZE = 100;
function chunkEntries (line 100) | function chunkEntries<T>(entries: Array<T>, size: number): Array<Array<T...
function createBulkEntry (line 108) | function createBulkEntry(channelId: string): BulkAckEntry | null {
function sendBulkAck (line 119) | async function sendBulkAck(entries: Array<BulkAckEntry>): Promise<void> {
function updateReadStatesLocally (line 137) | function updateReadStatesLocally(entries: Array<BulkAckEntry>): void {
function bulkAckChannels (line 143) | async function bulkAckChannels(channelIds: Array<string>): Promise<void> {
FILE: fluxer_app/src/actions/RecentMentionActionCreators.tsx
function fetch (line 30) | async function fetch(): Promise<Array<Message>> {
function loadMore (line 55) | async function loadMore(): Promise<Array<Message>> {
function updateFilters (line 88) | function updateFilters(filters: Partial<MentionFilters>): void {
function remove (line 92) | async function remove(messageId: string): Promise<void> {
FILE: fluxer_app/src/actions/RelationshipActionCreators.tsx
function sendFriendRequest (line 27) | async function sendFriendRequest(userId: string) {
function sendFriendRequestByTag (line 36) | async function sendFriendRequestByTag(username: string, discriminator: s...
function acceptFriendRequest (line 45) | async function acceptFriendRequest(userId: string) {
function removeRelationship (line 54) | async function removeRelationship(userId: string) {
function blockUser (line 63) | async function blockUser(userId: string) {
function updateFriendNickname (line 72) | async function updateFriendNickname(userId: string, nickname: string | n...
FILE: fluxer_app/src/actions/SavedMessageActionCreators.tsx
function fetch (line 37) | async function fetch(): Promise<Array<SavedMessageEntryRecord>> {
function create (line 53) | async function create(i18n: I18n, channelId: string, messageId: string):...
function remove (line 78) | async function remove(i18n: I18n, messageId: string): Promise<void> {
FILE: fluxer_app/src/actions/ScheduledMessageActionCreators.tsx
type ScheduledMessageRequest (line 66) | type ScheduledMessageRequest = MessageCreateRequest & {
type ApiErrorBody (line 71) | interface ApiErrorBody {
type ScheduleMessageParams (line 77) | interface ScheduleMessageParams {
type UpdateScheduledMessageParams (line 90) | interface UpdateScheduledMessageParams {
function mapScheduledAttachments (line 104) | function mapScheduledAttachments(
function fetchScheduledMessages (line 119) | async function fetchScheduledMessages(): Promise<Array<ScheduledMessageR...
function scheduleMessage (line 139) | async function scheduleMessage(i18n: I18n, params: ScheduleMessageParams...
function updateScheduledMessage (line 215) | async function updateScheduledMessage(
function cancelScheduledMessage (line 265) | async function cancelScheduledMessage(i18n: I18n, scheduledMessageId: st...
function restoreDraftAfterScheduleFailure (line 280) | function restoreDraftAfterScheduleFailure(
function scheduleMessageRequest (line 297) | async function scheduleMessageRequest(
function scheduleMultipartMessage (line 319) | async function scheduleMultipartMessage(
function handleScheduleError (line 353) | function handleScheduleError(
function handleScheduleRateLimit (line 396) | function handleScheduleRateLimit(_i18n: I18n, error: HttpError): void {
function isRateLimitError (line 404) | function isRateLimitError(error: HttpError): boolean {
function isSlowmodeError (line 408) | function isSlowmodeError(error: HttpError): boolean {
function isFeatureDisabledError (line 412) | function isFeatureDisabledError(error: HttpError): boolean {
function isExplicitContentError (line 416) | function isExplicitContentError(error: HttpError): boolean {
function isFileTooLargeError (line 420) | function isFileTooLargeError(error: HttpError): boolean {
FILE: fluxer_app/src/actions/SlowmodeActionCreators.tsx
function recordMessageSend (line 23) | function recordMessageSend(channelId: string): void {
function updateSlowmodeTimestamp (line 28) | function updateSlowmodeTimestamp(channelId: string, timestamp: number): ...
FILE: fluxer_app/src/actions/SoundActionCreators.tsx
function playSound (line 23) | function playSound(sound: SoundType, loop?: boolean): void {
function stopAllSounds (line 27) | function stopAllSounds(): void {
function updateSoundSettings (line 31) | function updateSoundSettings(settings: {
FILE: fluxer_app/src/actions/StickerPickerActionCreators.tsx
function getStickerKey (line 23) | function getStickerKey(sticker: GuildStickerRecord): string {
function trackStickerUsage (line 27) | function trackStickerUsage(sticker: GuildStickerRecord): void {
function toggleFavorite (line 31) | function toggleFavorite(sticker: GuildStickerRecord): void {
function toggleCategory (line 35) | function toggleCategory(category: string): void {
FILE: fluxer_app/src/actions/TextCopyActionCreators.tsx
function copy (line 57) | async function copy(i18n: I18n, text: string, suppressToast = false): Pr...
FILE: fluxer_app/src/actions/ThemeActionCreators.tsx
function applyTheme (line 31) | function applyTheme(css: string, i18n: I18n): void {
function openAcceptModal (line 42) | function openAcceptModal(themeId: string | undefined, i18n: I18n): void {
FILE: fluxer_app/src/actions/ThemePreferenceActionCreators.tsx
function updateThemePreference (line 25) | function updateThemePreference(theme: ThemeType): void {
function setSyncAcrossDevices (line 39) | function setSyncAcrossDevices(sync: boolean): void {
FILE: fluxer_app/src/actions/ToastActionCreators.tsx
function createToast (line 23) | function createToast(data: ToastProps): string {
function destroyToast (line 27) | function destroyToast(id: string): void {
function success (line 31) | function success(message: string): string {
function error (line 35) | function error(message: string): string {
FILE: fluxer_app/src/actions/TrustedDomainActionCreators.tsx
function addTrustedDomain (line 25) | async function addTrustedDomain(domain: string): Promise<void> {
function removeTrustedDomain (line 30) | async function removeTrustedDomain(domain: string): Promise<void> {
function clearAllTrustedDomains (line 35) | async function clearAllTrustedDomains(): Promise<void> {
function setTrustAllDomains (line 40) | async function setTrustAllDomains(trustAll: boolean): Promise<void> {
function checkAndMigrateLegacyData (line 45) | function checkAndMigrateLegacyData(): void {
FILE: fluxer_app/src/actions/TypingActionCreators.tsx
function sendTyping (line 27) | async function sendTyping(channelId: string): Promise<void> {
function startTyping (line 37) | function startTyping(channelId: string, userId: string): void {
function stopTyping (line 42) | function stopTyping(channelId: string, userId: string): void {
FILE: fluxer_app/src/actions/UnsavedChangesActionCreators.tsx
function setUnsavedChanges (line 22) | function setUnsavedChanges(tabId: string, hasChanges: boolean): void {
function triggerFlashEffect (line 26) | function triggerFlashEffect(tabId: string): void {
function clearUnsavedChanges (line 30) | function clearUnsavedChanges(tabId: string): void {
function setTabData (line 34) | function setTabData(
FILE: fluxer_app/src/actions/UserActionCreators.tsx
type FluxerTagAvailabilityResponse (line 33) | interface FluxerTagAvailabilityResponse {
type WebAuthnCredential (line 37) | interface WebAuthnCredential {
type PhoneTokenResponse (line 44) | interface PhoneTokenResponse {
type EmailChangeStartResponse (line 48) | interface EmailChangeStartResponse {
type EmailChangeVerifyOriginalResponse (line 56) | interface EmailChangeVerifyOriginalResponse {
type EmailChangeRequestNewResponse (line 60) | interface EmailChangeRequestNewResponse {
type EmailChangeVerifyNewResponse (line 67) | interface EmailChangeVerifyNewResponse {
type PasswordChangeStartResponse (line 71) | interface PasswordChangeStartResponse {
type PasswordChangeVerifyResponse (line 77) | interface PasswordChangeVerifyResponse {
function update (line 81) | async function update(
function checkFluxerTagAvailability (line 115) | async function checkFluxerTagAvailability({
function sendPhoneVerification (line 135) | async function sendPhoneVerification(phone: string): Promise<void> {
function verifyPhone (line 146) | async function verifyPhone(phone: string, code: string): Promise<PhoneTo...
function addPhone (line 158) | async function addPhone(phoneToken: string): Promise<void> {
function startEmailChange (line 169) | async function startEmailChange(): Promise<EmailChangeStartResponse> {
function resendEmailChangeOriginal (line 183) | async function resendEmailChangeOriginal(ticket: string): Promise<void> {
function verifyEmailChangeOriginal (line 196) | async function verifyEmailChangeOriginal(
function requestEmailChangeNew (line 213) | async function requestEmailChangeNew(
function resendEmailChangeNew (line 231) | async function resendEmailChangeNew(ticket: string): Promise<void> {
function verifyEmailChangeNew (line 244) | async function verifyEmailChangeNew(
function requestBouncedEmailChangeNew (line 262) | async function requestBouncedEmailChangeNew(newEmail: string): Promise<E...
function resendBouncedEmailChangeNew (line 276) | async function resendBouncedEmailChangeNew(ticket: string): Promise<void> {
function verifyBouncedEmailChangeNew (line 289) | async function verifyBouncedEmailChangeNew(ticket: string, code: string)...
function startPasswordChange (line 303) | async function startPasswordChange(): Promise<PasswordChangeStartRespons...
function resendPasswordChangeCode (line 317) | async function resendPasswordChangeCode(ticket: string): Promise<void> {
function verifyPasswordChangeCode (line 330) | async function verifyPasswordChangeCode(ticket: string, code: string): P...
function completePasswordChange (line 344) | async function completePasswordChange(
function removePhone (line 366) | async function removePhone(): Promise<void> {
function enableSmsMfa (line 377) | async function enableSmsMfa(): Promise<void> {
function disableSmsMfa (line 389) | async function disableSmsMfa(): Promise<void> {
function listWebAuthnCredentials (line 400) | async function listWebAuthnCredentials(): Promise<Array<WebAuthnCredenti...
function getWebAuthnRegistrationOptions (line 413) | async function getWebAuthnRegistrationOptions(): Promise<PublicKeyCreden...
function registerWebAuthnCredential (line 429) | async function registerWebAuthnCredential(
function renameWebAuthnCredential (line 445) | async function renameWebAuthnCredential(credentialId: string, name: stri...
function deleteWebAuthnCredential (line 456) | async function deleteWebAuthnCredential(credentialId: string): Promise<v...
function disableAccount (line 467) | async function disableAccount(): Promise<void> {
function deleteAccount (line 478) | async function deleteAccount(): Promise<void> {
function forgetAuthorizedIps (line 489) | async function forgetAuthorizedIps(sudoPayload: SudoVerificationPayload)...
function bulkDeleteAllMessages (line 500) | async function bulkDeleteAllMessages(): Promise<void> {
function cancelBulkDeleteAllMessages (line 511) | async function cancelBulkDeleteAllMessages(): Promise<void> {
function testBulkDeleteAllMessages (line 522) | async function testBulkDeleteAllMessages(): Promise<void> {
function resetPremiumState (line 533) | async function resetPremiumState(): Promise<void> {
function requestDataHarvest (line 544) | async function requestDataHarvest(): Promise<{harvestId: string}> {
function getLatestHarvest (line 556) | async function getLatestHarvest(): Promise<HarvestStatusResponse | null> {
function getHarvestStatus (line 567) | async function getHarvestStatus(harvestId: string): Promise<HarvestStatu...
type PreloadedDirectMessages (line 578) | type PreloadedDirectMessages = Record<string, Message>;
function preloadDMMessages (line 580) | async function preloadDMMessages(channelIds: Array<string>): Promise<Pre...
FILE: fluxer_app/src/actions/UserGuildSettingsActionCreators.tsx
type PersistenceOptions (line 35) | interface PersistenceOptions {
function updateGuildSettings (line 112) | function updateGuildSettings(
function toggleHideMutedChannels (line 122) | function toggleHideMutedChannels(guildId: string | null): void {
function updateChannelOverride (line 128) | function updateChannelOverride(
function toggleChannelCollapsed (line 173) | function toggleChannelCollapsed(guildId: string | null, channelId: strin...
function updateMessageNotifications (line 178) | function updateMessageNotifications(
function toggleChannelMuted (line 191) | function toggleChannelMuted(guildId: string | null, channelId: string, o...
function toggleAllCategoriesCollapsed (line 196) | function toggleAllCategoriesCollapsed(guildId: string | null, categoryId...
function repairGuildNotificationInheritance (line 236) | function repairGuildNotificationInheritance(): void {
FILE: fluxer_app/src/actions/UserNoteActionCreators.tsx
function update (line 26) | async function update(userId: string, note: string | null): Promise<void> {
FILE: fluxer_app/src/actions/UserProfileActionCreators.tsx
function buildKey (line 38) | function buildKey(userId: string, guildId?: string): string {
function fetch (line 42) | async function fetch(userId: string, guildId?: string, force = false): P...
function invalidate (line 103) | function invalidate(userId: string, guildId?: string): void {
function clearCurrentUserProfiles (line 114) | function clearCurrentUserProfiles(): void {
function openUserProfile (line 131) | function openUserProfile(userId: string, guildId?: string, autoFocusNote...
FILE: fluxer_app/src/actions/UserSettingsActionCreators.tsx
function update (line 23) | async function update(settings: Partial<UserSettings>): Promise<void> {
FILE: fluxer_app/src/actions/VoiceCallLayoutActionCreators.tsx
function setLayoutMode (line 23) | function setLayoutMode(mode: LayoutMode): void {
function setPinnedParticipant (line 27) | function setPinnedParticipant(identity: string | null, source?: PinnedPa...
function markUserOverride (line 31) | function markUserOverride(): void {
FILE: fluxer_app/src/actions/VoiceSettingsActionCreators.tsx
function update (line 23) | function update(
FILE: fluxer_app/src/actions/VoiceStateActionCreators.tsx
function toggleSelfDeaf (line 40) | async function toggleSelfDeaf(_guildId: string | null = null): Promise<v...
function toggleSelfMute (line 240) | async function toggleSelfMute(_guildId: string | null = null): Promise<v...
type VoiceStateProperty (line 355) | type VoiceStateProperty = 'self_mute' | 'self_deaf' | 'self_video' | 'se...
function toggleSelfMuteForConnection (line 403) | async function toggleSelfMuteForConnection(connectionId: string): Promis...
function toggleSelfDeafenForConnection (line 412) | async function toggleSelfDeafenForConnection(connectionId: string): Prom...
function turnOffCameraForConnection (line 421) | async function turnOffCameraForConnection(connectionId: string): Promise...
function turnOffStreamForConnection (line 425) | async function turnOffStreamForConnection(connectionId: string): Promise...
function bulkMuteConnections (line 429) | async function bulkMuteConnections(connectionIds: Array<string>, mute: b...
function bulkDeafenConnections (line 433) | async function bulkDeafenConnections(connectionIds: Array<string>, deafe...
function bulkTurnOffCameras (line 437) | async function bulkTurnOffCameras(connectionIds: Array<string>): Promise...
function bulkDisconnect (line 441) | async function bulkDisconnect(connectionIds: Array<string>): Promise<voi...
function bulkMoveConnections (line 461) | async function bulkMoveConnections(connectionIds: Array<string>, targetC...
FILE: fluxer_app/src/actions/WebhookActionCreators.tsx
type CreateWebhookParams (line 28) | interface CreateWebhookParams {
type UpdateWebhookParams (line 34) | interface UpdateWebhookParams {
function fetchGuildWebhooks (line 40) | async function fetchGuildWebhooks(guildId: string): Promise<Array<Webhoo...
function fetchChannelWebhooks (line 57) | async function fetchChannelWebhooks({
function createWebhook (line 80) | async function createWebhook({channelId, name, avatar}: CreateWebhookPar...
function deleteWebhook (line 94) | async function deleteWebhook(webhookId: string): Promise<void> {
function moveWebhook (line 109) | async function moveWebhook(webhookId: string, newChannelId: string): Pro...
function updateWebhooks (line 143) | async function updateWebhooks(updates: Array<UpdateWebhookParams>): Prom...
FILE: fluxer_app/src/actions/WindowActionCreators.tsx
function focused (line 25) | function focused(focused: boolean): void {
function resized (line 35) | function resized(): void {
function visibilityChanged (line 39) | function visibilityChanged(visible: boolean): void {
FILE: fluxer_app/src/bootstrap/SetupHttpClient.tsx
function setupHttpClient (line 25) | function setupHttpClient(): void {
FILE: fluxer_app/src/components/AppBadge.tsx
constant UNREAD_INDICATOR (line 34) | const UNREAD_INDICATOR = -1;
FILE: fluxer_app/src/components/BootstrapErrorScreen.tsx
type BootstrapErrorScreenProps (line 28) | interface BootstrapErrorScreenProps {
constant PRESERVED_RESET_STORAGE_KEYS (line 32) | const PRESERVED_RESET_STORAGE_KEYS = ['DraftStore'] as const;
FILE: fluxer_app/src/components/ErrorFallback.tsx
type ErrorFallbackProps (line 36) | interface ErrorFallbackProps {
constant PRESERVED_RESET_STORAGE_KEYS (line 42) | const PRESERVED_RESET_STORAGE_KEYS = ['DraftStore'] as const;
FILE: fluxer_app/src/components/LongPressable.tsx
constant LONG_PRESS_MOVEMENT_THRESHOLD (line 22) | const LONG_PRESS_MOVEMENT_THRESHOLD = 10;
constant SWIPE_VELOCITY_THRESHOLD (line 24) | const SWIPE_VELOCITY_THRESHOLD = 0.4;
constant MIN_VELOCITY_SAMPLES (line 26) | const MIN_VELOCITY_SAMPLES = 2;
constant MAX_VELOCITY_SAMPLE_AGE (line 28) | const MAX_VELOCITY_SAMPLE_AGE = 100;
constant PRESS_HIGHLIGHT_DELAY_MS (line 30) | const PRESS_HIGHLIGHT_DELAY_MS = 100;
constant LONG_PRESS_DURATION_MS (line 32) | const LONG_PRESS_DURATION_MS = 500;
constant HAS_POINTER_EVENTS (line 34) | const HAS_POINTER_EVENTS = 'PointerEvent' in window;
type VelocitySample (line 36) | interface VelocitySample {
type LongPressEvent (line 42) | type LongPressEvent = React.PointerEvent<HTMLDivElement> | React.TouchEv...
type LongPressableProps (line 44) | interface LongPressableProps extends React.HTMLAttributes<HTMLDivElement> {
FILE: fluxer_app/src/components/accounts/AccountListItem.tsx
type AccountListItemProps (line 31) | interface AccountListItemProps {
FILE: fluxer_app/src/components/accounts/AccountRow.tsx
constant STANDARD_INSTANCES (line 35) | const STANDARD_INSTANCES = new Set(['web.fluxer.app', 'web.canary.fluxer...
function getInstanceHost (line 39) | function getInstanceHost(account: Account): string | null {
function getInstanceEndpoint (line 53) | function getInstanceEndpoint(account: Account): string | null {
type AccountRowVariant (line 57) | type AccountRowVariant = 'default' | 'manage' | 'compact';
type AccountRowProps (line 59) | interface AccountRowProps {
FILE: fluxer_app/src/components/accounts/AccountSelector.tsx
type AccountSelectorProps (line 40) | interface AccountSelectorProps {
FILE: fluxer_app/src/components/alerts/FileSizeTooLargeModal.tsx
type FileSizeTooLargeModalProps (line 31) | interface FileSizeTooLargeModalProps {
FILE: fluxer_app/src/components/alerts/GenericErrorModal.tsx
type GenericErrorModalProps (line 24) | interface GenericErrorModalProps {
FILE: fluxer_app/src/components/alerts/GroupOwnershipTransferFailedModal.tsx
type GroupOwnershipTransferFailedModalProps (line 25) | interface GroupOwnershipTransferFailedModalProps {
FILE: fluxer_app/src/components/alerts/GroupRemoveUserFailedModal.tsx
type GroupRemoveUserFailedModalProps (line 25) | interface GroupRemoveUserFailedModalProps {
FILE: fluxer_app/src/components/alerts/MaxBookmarksModal.tsx
type MaxBookmarksModalProps (line 30) | interface MaxBookmarksModalProps {
FILE: fluxer_app/src/components/alerts/MaxGuildsModal.tsx
type MaxGuildsModalProps (line 25) | interface MaxGuildsModalProps {
FILE: fluxer_app/src/components/alerts/MessageEditTooQuickModal.tsx
type MessageEditTooQuickModalProps (line 24) | interface MessageEditTooQuickModalProps {
FILE: fluxer_app/src/components/alerts/MessageSendTooQuickModal.tsx
type MessageSendTooQuickModalProps (line 24) | interface MessageSendTooQuickModalProps {
FILE: fluxer_app/src/components/alerts/PinFailedModal.tsx
type PinFailureReason (line 24) | type PinFailureReason = 'dm_restricted' | 'generic';
type PinFailedModalProps (line 26) | interface PinFailedModalProps {
FILE: fluxer_app/src/components/alerts/RateLimitedConfirmModal.tsx
type RateLimitedConfirmModalProps (line 25) | interface RateLimitedConfirmModalProps {
FILE: fluxer_app/src/components/alerts/RoleDeleteFailedModal.tsx
type RoleDeleteFailedModalProps (line 24) | interface RoleDeleteFailedModalProps {
FILE: fluxer_app/src/components/alerts/SlowmodeRateLimitedModal.tsx
type SlowmodeRateLimitedModalProps (line 25) | interface SlowmodeRateLimitedModalProps {
FILE: fluxer_app/src/components/auth/AuthBackground.tsx
type AuthBackgroundProps (line 38) | interface AuthBackgroundProps {
FILE: fluxer_app/src/components/auth/AuthBottomLink.tsx
type AuthBottomLinkProps (line 24) | interface AuthBottomLinkProps {
function AuthBottomLink (line 29) | function AuthBottomLink({variant, to}: AuthBottomLinkProps) {
type AuthBottomLinksProps (line 42) | interface AuthBottomLinksProps {
function AuthBottomLinks (line 46) | function AuthBottomLinks({children}: AuthBottomLinksProps) {
FILE: fluxer_app/src/components/auth/AuthCardContainer.tsx
type AuthCardContainerProps (line 27) | interface AuthCardContainerProps {
function AuthCardContainer (line 34) | function AuthCardContainer({showLogoSide = true, children, isInert = fal...
FILE: fluxer_app/src/components/auth/AuthErrorState.tsx
type AuthErrorStateProps (line 24) | interface AuthErrorStateProps {
function AuthErrorState (line 30) | function AuthErrorState({icon: IconComponent = QuestionIcon, title, text...
FILE: fluxer_app/src/components/auth/AuthLoadingState.tsx
function AuthLoadingState (line 24) | function AuthLoadingState(): JSX.Element {
FILE: fluxer_app/src/components/auth/AuthLoginLayout.tsx
type AuthLoginLayoutProps (line 44) | interface AuthLoginLayoutProps {
FILE: fluxer_app/src/components/auth/AuthMinimalRegisterFormCore.tsx
type AuthMinimalRegisterFormCoreProps (line 39) | interface AuthMinimalRegisterFormCoreProps {
function AuthMinimalRegisterFormCore (line 47) | function AuthMinimalRegisterFormCore({
FILE: fluxer_app/src/components/auth/AuthPageHeader.tsx
type AuthPageHeaderStatProps (line 24) | interface AuthPageHeaderStatProps {
type AuthPageHeaderProps (line 29) | interface AuthPageHeaderProps {
function AuthPageHeader (line 37) | function AuthPageHeader({icon, title, subtitle, features, stats}: AuthPa...
FILE: fluxer_app/src/components/auth/AuthRegisterFormCore.tsx
type FieldConfig (line 42) | interface FieldConfig {
type AuthRegisterFormCoreProps (line 49) | interface AuthRegisterFormCoreProps {
function AuthRegisterFormCore (line 58) | function AuthRegisterFormCore({
FILE: fluxer_app/src/components/auth/AuthRouterLink.tsx
type AuthRouterLinkProps (line 24) | interface AuthRouterLinkProps {
function AuthRouterLink (line 32) | function AuthRouterLink({ringOffset = -2, children, className, to, searc...
FILE: fluxer_app/src/components/auth/BrowserLoginHandoffModal.tsx
type LoginSuccessPayload (line 36) | interface LoginSuccessPayload {
type BrowserLoginHandoffModalProps (line 41) | interface BrowserLoginHandoffModalProps {
constant CODE_LENGTH (line 47) | const CODE_LENGTH = 8;
constant VALID_CODE_PATTERN (line 48) | const VALID_CODE_PATTERN = /^[A-Za-z0-9]{8}$/;
function normalizeInstanceOrigin (line 69) | function normalizeInstanceOrigin(raw: string): string {
function showBrowserLoginHandoffModal (line 281) | function showBrowserLoginHandoffModal(
FILE: fluxer_app/src/components/auth/DateOfBirthField.tsx
type DateFieldType (line 32) | type DateFieldType = 'month' | 'day' | 'year';
type DateOfBirthFieldProps (line 34) | interface DateOfBirthFieldProps {
type NativeDatePickerProps (line 44) | interface NativeDatePickerProps {
function NativeDatePicker (line 54) | function NativeDatePicker({
FILE: fluxer_app/src/components/auth/DesktopDeepLinkPrompt.tsx
type DesktopDeepLinkPromptProps (line 32) | interface DesktopDeepLinkPromptProps {
FILE: fluxer_app/src/components/auth/DesktopHandoffAccountSelector.tsx
type HandoffState (line 29) | type HandoffState = 'selecting' | 'generating' | 'displaying' | 'error';
type DesktopHandoffAccountSelectorProps (line 31) | interface DesktopHandoffAccountSelectorProps {
FILE: fluxer_app/src/components/auth/FormField.tsx
type FormFieldProps (line 23) | interface FormFieldProps extends Omit<React.InputHTMLAttributes<HTMLInpu...
FILE: fluxer_app/src/components/auth/GiftHeader.tsx
type GiftHeaderProps (line 26) | interface GiftHeaderProps {
function GiftHeader (line 31) | function GiftHeader({gift, variant}: GiftHeaderProps) {
FILE: fluxer_app/src/components/auth/HandoffCodeDisplay.tsx
type HandoffCodeDisplayProps (line 28) | interface HandoffCodeDisplayProps {
function HandoffCodeDisplay (line 35) | function HandoffCodeDisplay({code, isGenerating, error, onRetry}: Handof...
FILE: fluxer_app/src/components/auth/InstanceSelector.tsx
constant RECENT_INSTANCES_KEY (line 32) | const RECENT_INSTANCES_KEY = 'federation_recent_instances';
constant MAX_RECENT_INSTANCES (line 33) | const MAX_RECENT_INSTANCES = 5;
type InstanceDiscoveryStatus (line 35) | type InstanceDiscoveryStatus = 'idle' | 'discovering' | 'success' | 'err...
type InstanceInfo (line 37) | interface InstanceInfo {
type InstanceSelectorProps (line 43) | interface InstanceSelectorProps {
function loadRecentInstances (line 52) | function loadRecentInstances(): Array<InstanceInfo> {
function saveRecentInstance (line 60) | function saveRecentInstance(domain: string, name?: string): void {
function removeRecentInstance (line 78) | function removeRecentInstance(domain: string): void {
function handleClickOutside (line 190) | function handleClickOutside(event: MouseEvent) {
FILE: fluxer_app/src/components/auth/InviteHeader.tsx
type InviteHeaderProps (line 35) | interface InviteHeaderProps {
type GuildInviteHeaderProps (line 39) | interface GuildInviteHeaderProps {
type GroupDMInviteHeaderProps (line 43) | interface GroupDMInviteHeaderProps {
type PackInviteHeaderProps (line 47) | interface PackInviteHeaderProps {
type PreviewGuildInviteHeaderProps (line 51) | interface PreviewGuildInviteHeaderProps {
function formatInviteCount (line 62) | function formatInviteCount(value: number): string {
function InviteHeader (line 169) | function InviteHeader({invite}: InviteHeaderProps) {
FILE: fluxer_app/src/components/auth/IpAuthorizationScreen.tsx
type PollingState (line 29) | type PollingState = 'polling' | 'error';
type IpAuthorizationScreenProps (line 31) | interface IpAuthorizationScreenProps {
constant POLL_INTERVAL_MS (line 37) | const POLL_INTERVAL_MS = 2000;
constant MAX_POLL_ERRORS (line 38) | const MAX_POLL_ERRORS = 3;
FILE: fluxer_app/src/components/auth/MfaScreen.tsx
type MfaScreenProps (line 28) | interface MfaScreenProps {
FILE: fluxer_app/src/components/auth/MockMinimalRegisterForm.tsx
type DateFieldType (line 33) | type DateFieldType = 'month' | 'day' | 'year';
type MockMinimalRegisterFormProps (line 35) | interface MockMinimalRegisterFormProps {
function MockMinimalRegisterForm (line 39) | function MockMinimalRegisterForm({submitLabel}: MockMinimalRegisterFormP...
FILE: fluxer_app/src/components/auth/SubmitTooltip.tsx
type MissingField (line 27) | interface MissingField {
type SubmitTooltipProps (line 32) | interface SubmitTooltipProps {
constant CONSENT_REQUIRED_DESCRIPTOR (line 38) | const CONSENT_REQUIRED_DESCRIPTOR = msg`You must agree to the Terms of S...
function getTooltipContentDescriptor (line 42) | function getTooltipContentDescriptor(consent: boolean, missingFields: Ar...
function shouldDisableSubmit (line 55) | function shouldDisableSubmit(consent: boolean, missingFields: Array<Miss...
function SubmitTooltip (line 59) | function SubmitTooltip({children, consent, missingFields = []}: SubmitTo...
FILE: fluxer_app/src/components/auth/auth_login_core/AuthLoginEmailPasswordForm.tsx
type FieldErrors (line 26) | type FieldErrors = Record<string, string | undefined> | null | undefined;
type AuthFormControllerLike (line 28) | interface AuthFormControllerLike {
type AuthEmailPasswordFormClasses (line 36) | interface AuthEmailPasswordFormClasses {
type Props (line 40) | interface Props {
function AuthLoginEmailPasswordForm (line 52) | function AuthLoginEmailPasswordForm({
FILE: fluxer_app/src/components/auth/auth_login_core/AuthLoginPasskeyActions.tsx
type AuthLoginDividerClasses (line 24) | interface AuthLoginDividerClasses {
function AuthLoginDivider (line 30) | function AuthLoginDivider({
type AuthPasskeyClasses (line 46) | interface AuthPasskeyClasses {
type Props (line 50) | interface Props {
function AuthLoginPasskeyActions (line 63) | function AuthLoginPasskeyActions({
FILE: fluxer_app/src/components/auth/auth_login_core/useDesktopHandoffFlow.tsx
type DesktopHandoffMode (line 23) | type DesktopHandoffMode = 'idle' | 'selecting' | 'login' | 'generating' ...
type Options (line 25) | interface Options {
function useDesktopHandoffFlow (line 32) | function useDesktopHandoffFlow({enabled, hasStoredAccounts, initialMode}...
FILE: fluxer_app/src/components/bottomsheets/CategoryBottomSheet.tsx
type CategoryBottomSheetProps (line 30) | interface CategoryBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/ChannelBottomSheet.tsx
type ChannelBottomSheetProps (line 30) | interface ChannelBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/ChannelDetailsBottomSheet.tsx
constant MEMBER_ITEM_HEIGHT (line 135) | const MEMBER_ITEM_HEIGHT = 56;
constant INITIAL_MEMBER_RANGE (line 136) | const INITIAL_MEMBER_RANGE: [number, number] = [0, 99];
constant SCROLL_BUFFER (line 137) | const SCROLL_BUFFER = 50;
function isScrollableOverflow (line 139) | function isScrollableOverflow(value: string): boolean {
function findScrollableParent (line 143) | function findScrollableParent(node: HTMLElement | null): HTMLElement | n...
type ChannelDetailsTab (line 165) | type ChannelDetailsTab = 'members' | 'pins';
type ChannelDetailsBottomSheetProps (line 167) | interface ChannelDetailsBottomSheetProps {
type QuickActionButtonProps (line 175) | interface QuickActionButtonProps {
type LazyMemberListGroupProps (line 294) | interface LazyMemberListGroupProps {
FILE: fluxer_app/src/components/bottomsheets/ChannelSearchBottomSheet.tsx
type ChannelSearchBottomSheetProps (line 62) | interface ChannelSearchBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/CreateDMBottomSheet.tsx
type CreateDMBottomSheetProps (line 34) | interface CreateDMBottomSheetProps {
type ScrollContentStyle (line 39) | type ScrollContentStyle = React.CSSProperties & {
FILE: fluxer_app/src/components/bottomsheets/DMBottomSheet.tsx
type DMBottomSheetProps (line 30) | interface DMBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/DirectCallLobbyBottomSheet.tsx
type DirectCallLobbyBottomSheetProps (line 59) | interface DirectCallLobbyBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/EmojiInfoBottomSheet.tsx
type EmojiInfoData (line 34) | interface EmojiInfoData {
type EmojiInfoBottomSheetProps (line 40) | interface EmojiInfoBottomSheetProps {
constant EMOJI_SHEET_SNAP_POINTS (line 46) | const EMOJI_SHEET_SNAP_POINTS: Array<number> = [0, 0.4, 0.5];
type EmojiInfoBottomSheetContentProps (line 56) | interface EmojiInfoBottomSheetContentProps {
FILE: fluxer_app/src/components/bottomsheets/FavoritesGuildHeaderBottomSheet.tsx
type FavoritesGuildHeaderBottomSheetProps (line 42) | interface FavoritesGuildHeaderBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/GuildHeaderBottomSheet.tsx
type GuildHeaderBottomSheetProps (line 35) | interface GuildHeaderBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/MuteDurationSheet.tsx
type MuteDurationSheetProps (line 29) | interface MuteDurationSheetProps {
FILE: fluxer_app/src/components/bottomsheets/QuickSwitcherBottomSheet.tsx
type QuickSwitcherContainerStyle (line 53) | type QuickSwitcherContainerStyle = React.CSSProperties & {
constant QUICK_SWITCHER_SCROLL_PADDING_BOTTOM (line 57) | const QUICK_SWITCHER_SCROLL_PADDING_BOTTOM = 'calc(env(safe-area-inset-b...
type QuickSwitcherBottomSheetProps (line 140) | interface QuickSwitcherBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/VoiceLobbyBottomSheet.tsx
type VoiceLobbyBottomSheetProps (line 56) | interface VoiceLobbyBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/VoiceParticipantBottomSheet.tsx
type VoiceParticipantBottomSheetProps (line 27) | interface VoiceParticipantBottomSheetProps {
FILE: fluxer_app/src/components/bottomsheets/VoiceSettingsBottomSheets.tsx
type VoiceAudioSettingsBottomSheetProps (line 47) | interface VoiceAudioSettingsBottomSheetProps {
type VoiceCameraSettingsBottomSheetProps (line 175) | interface VoiceCameraSettingsBottomSheetProps {
type VoiceMoreOptionsBottomSheetProps (line 237) | interface VoiceMoreOptionsBottomSheetProps {
FILE: fluxer_app/src/components/captcha/TurnstileWidget.tsx
type TurnstileWidgetProps (line 23) | interface TurnstileWidgetProps {
FILE: fluxer_app/src/components/channel/Autocomplete.tsx
type ScrollerWithScrollableElement (line 44) | type ScrollerWithScrollableElement = ScrollerHandle & {
type AutocompleteOption (line 48) | type AutocompleteOption =
type AutocompleteType (line 60) | type AutocompleteType = 'mention' | 'channel' | 'emoji' | 'command' | 'm...
method apply (line 131) | apply({rects, elements}) {
function scrollChildIntoView (line 202) | function scrollChildIntoView(node: HTMLElement | null, margin = 32) {
FILE: fluxer_app/src/components/channel/AutocompleteCommand.tsx
type Props (line 25) | interface Props {
FILE: fluxer_app/src/components/channel/BlockedMessageGroups.tsx
type BlockedMessageGroupsProps (line 29) | interface BlockedMessageGroupsProps {
FILE: fluxer_app/src/components/channel/CallMessage.tsx
type DurationUnit (line 42) | type DurationUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute';
constant DURATION_UNITS (line 44) | const DURATION_UNITS: Array<{unit: DurationUnit; minutes: number}> = [
constant DURATION_UNIT_LABELS (line 65) | const DURATION_UNIT_LABELS: Record<DurationUnit, {singular: MessageDescr...
constant FEW_SECONDS_DESCRIPTOR (line 80) | const FEW_SECONDS_DESCRIPTOR = msg`a few seconds`;
FILE: fluxer_app/src/components/channel/ChannelChatLayout.tsx
type ChannelChatLayoutProps (line 33) | interface ChannelChatLayoutProps {
FILE: fluxer_app/src/components/channel/ChannelHeader.tsx
type ChannelHeaderProps (line 100) | interface ChannelHeaderProps {
FILE: fluxer_app/src/components/channel/ChannelIconChangeMessage.tsx
type ChannelIconChangeMessageProps (line 28) | interface ChannelIconChangeMessageProps {
FILE: fluxer_app/src/components/channel/ChannelLayout.tsx
type ChannelLayoutProps (line 29) | interface ChannelLayoutProps {
FILE: fluxer_app/src/components/channel/ChannelMembers.tsx
constant MEMBER_ITEM_HEIGHT (line 46) | const MEMBER_ITEM_HEIGHT = 44;
constant INITIAL_MEMBER_RANGE (line 47) | const INITIAL_MEMBER_RANGE: [number, number] = [0, 99];
constant SCROLL_BUFFER (line 48) | const SCROLL_BUFFER = 50;
function getSeededRandom (line 50) | function getSeededRandom(seed: number): number {
function SkeletonMemberItem (line 55) | function SkeletonMemberItem({index}: {index: number}) {
type GroupDMMemberListGroupProps (line 73) | interface GroupDMMemberListGroupProps {
type LazyMemberListGroupProps (line 99) | interface LazyMemberListGroupProps {
type LazyMemberListProps (line 150) | interface LazyMemberListProps {
type ChannelMembersProps (line 322) | interface ChannelMembersProps {
FILE: fluxer_app/src/components/channel/ChannelMessageStream.tsx
type MessageGroupKind (line 40) | type MessageGroupKind = 'system' | 'regular';
type RenderChannelStreamProps (line 46) | interface RenderChannelStreamProps {
function renderChannelStream (line 64) | function renderChannelStream(props: RenderChannelStreamProps): Array<Rea...
FILE: fluxer_app/src/components/channel/ChannelNameChangeMessage.tsx
type ChannelNameChangeMessageProps (line 29) | interface ChannelNameChangeMessageProps {
FILE: fluxer_app/src/components/channel/ChannelSearchResults.tsx
type ChannelSearchResultsProps (line 85) | interface ChannelSearchResultsProps {
type PaginationItem (line 93) | type PaginationItem = number | 'ellipsis-left' | 'ellipsis-right';
constant INITIAL_POLL_INTERVAL (line 95) | const INITIAL_POLL_INTERVAL = 5000;
constant MAX_POLL_INTERVAL (line 96) | const MAX_POLL_INTERVAL = 30000;
constant POLL_BACKOFF_MULTIPLIER (line 97) | const POLL_BACKOFF_MULTIPLIER = 1.5;
constant DEFAULT_MAX_VISIBLE_PAGES (line 98) | const DEFAULT_MAX_VISIBLE_PAGES = 7;
constant RESULTS_PER_PAGE (line 99) | const RESULTS_PER_PAGE = 25;
constant DETACHED_MESSAGE_BEHAVIOR (line 160) | const DETACHED_MESSAGE_BEHAVIOR: MessageBehaviorOverrides = {
type ChannelSearchSortMode (line 168) | type ChannelSearchSortMode = 'newest' | 'oldest' | 'relevant';
constant SCOPE_ICON_COMPONENTS (line 176) | const SCOPE_ICON_COMPONENTS: Record<MessageSearchScope, React.ComponentT...
constant SORT_ICON_COMPONENTS (line 185) | const SORT_ICON_COMPONENTS: Record<ChannelSearchSortMode, React.Componen...
FILE: fluxer_app/src/components/channel/ChannelSourcePreview.tsx
type SubtextTone (line 43) | type SubtextTone = 'muted' | 'primary';
type ChannelSourcePreviewProps (line 45) | interface ChannelSourcePreviewProps {
function getChannelDisplayName (line 57) | function getChannelDisplayName(channel: ChannelRecord): string {
function getGroupDmMemberCount (line 64) | function getGroupDmMemberCount(channel: ChannelRecord): number {
function renderAvatarImage (line 72) | function renderAvatarImage(props: {url: string; label: string; size: num...
function renderAvatarFallback (line 84) | function renderAvatarFallback(props: {
function renderChannelAvatar (line 105) | function renderChannelAvatar(channel: ChannelRecord, size: MediaProxyIma...
FILE: fluxer_app/src/components/channel/ChannelStickersArea.tsx
type ChannelStickersAreaProps (line 35) | interface ChannelStickersAreaProps {
FILE: fluxer_app/src/components/channel/ChannelTextarea.tsx
function readBorderBoxBlockSize (line 110) | function readBorderBoxBlockSize(entry: ResizeObserverEntry): number {
FILE: fluxer_app/src/components/channel/ChannelWelcomeSection.tsx
type ChannelWelcomeSectionProps (line 32) | interface ChannelWelcomeSectionProps {
FILE: fluxer_app/src/components/channel/EditBar.tsx
type EditBarProps (line 29) | interface EditBarProps {
FILE: fluxer_app/src/components/channel/GifVideoPool.tsx
class ElementPool (line 22) | class ElementPool<T> {
method constructor (line 27) | constructor(createElement: () => T, cleanElement: (element: T) => void) {
method getElement (line 33) | getElement(): T {
method poolElement (line 37) | poolElement(element: T): void {
method clearPool (line 42) | clearPool(): void {
type PooledVideo (line 47) | interface PooledVideo {
method getElement (line 135) | getElement(src?: string): HTMLVideoElement {
method poolElement (line 143) | poolElement(element: HTMLVideoElement, src?: string): void {
method clearPool (line 171) | clearPool(): void {
method registerActive (line 183) | registerActive(element: HTMLVideoElement) {
method unregisterActive (line 186) | unregisterActive(element: HTMLVideoElement) {
method pauseAll (line 189) | pauseAll() {
method resumeAll (line 196) | resumeAll() {
method clearBlobCache (line 205) | clearBlobCache(): void {
FILE: fluxer_app/src/components/channel/GiftEmbed.tsx
type GiftEmbedProps (line 46) | interface GiftEmbedProps {
FILE: fluxer_app/src/components/channel/GuildJoinMessage.tsx
type GuildJoinMessageProps (line 30) | interface GuildJoinMessageProps {
FILE: fluxer_app/src/components/channel/GuildMembersPage.tsx
constant SEARCH_DEBOUNCE_MS (line 74) | const SEARCH_DEBOUNCE_MS = 300;
constant DEFAULT_PAGE_SIZE (line 75) | const DEFAULT_PAGE_SIZE = 25;
constant INDEXING_POLL_INTERVAL_MS (line 76) | const INDEXING_POLL_INTERVAL_MS = 5000;
constant HOUR_MS (line 78) | const HOUR_MS = 3_600_000;
constant DAY_MS (line 79) | const DAY_MS = 86_400_000;
type SearchableGuildMemberSupplemental (line 81) | interface SearchableGuildMemberSupplemental {
type SearchableGuildMember (line 87) | interface SearchableGuildMember {
type GuildMemberSearchResponse (line 101) | interface GuildMemberSearchResponse {
type SearchParams (line 109) | interface SearchParams {
function searchGuildMembers (line 124) | async function searchGuildMembers(guildId: string, params: SearchParams)...
type MemberDisplayData (line 129) | interface MemberDisplayData {
function toMemberDisplayData (line 147) | function toMemberDisplayData(searchMember: SearchableGuildMember, guildI...
type SortMode (line 173) | type SortMode = 'newest' | 'oldest';
type DateRangeFilter (line 175) | interface DateRangeFilter {
type JoinMethodFilter (line 180) | interface JoinMethodFilter {
type MemberTableRowProps (line 185) | interface MemberTableRowProps {
constant PAGE_SIZE_OPTIONS (line 430) | const PAGE_SIZE_OPTIONS: Array<SelectOption<number>> = [
type RolesFilterMenuContentProps (line 437) | interface RolesFilterMenuContentProps {
function RolesFilterMenuContent (line 444) | function RolesFilterMenuContent({roles, initialRoleFilter, setRoleFilter...
function isPresetMatch (line 494) | function isPresetMatch(filter: DateRangeFilter, durationMs: number): boo...
type GuildMembersPageProps (line 1102) | interface GuildMembersPageProps {
FILE: fluxer_app/src/components/channel/InviteEmbed.tsx
function formatInviteCount (line 78) | function formatInviteCount(value: number): string {
type InviteEmbedProps (line 82) | interface InviteEmbedProps {
type GuildInviteEmbedPreviewProps (line 397) | interface GuildInviteEmbedPreviewProps {
FILE: fluxer_app/src/components/channel/MasonryListComputer.tsx
type VisibleSection (line 20) | type VisibleSection = Array<[string, number, number]>;
type GridCoordinates (line 22) | interface GridCoordinates {
type GridData (line 28) | interface GridData {
type CoordsStyle (line 33) | interface CoordsStyle {
type Padding (line 42) | type Padding = number | {top?: number; bottom?: number; left?: number; r...
function defaultGetSectionHeight (line 44) | function defaultGetSectionHeight(_section: number): number {
function findMinColumnIndex (line 48) | function findMinColumnIndex(columnHeights: Array<number>): [number, numb...
function getSectionHeaderKey (line 60) | function getSectionHeaderKey(sectionIndex: number): string {
function getSectionKey (line 64) | function getSectionKey(sectionIndex: number): string {
class MasonryListComputer (line 68) | class MasonryListComputer {
method getPadding (line 101) | private getPadding(key: 'top' | 'bottom' | 'left' | 'right'): number {
method getPaddingLeft (line 111) | private getPaddingLeft(): number {
method getPaddingRight (line 115) | private getPaddingRight(): number {
method getPaddingTop (line 119) | private getPaddingTop(): number {
method getPaddingBottom (line 123) | private getPaddingBottom(): number {
method getSectionGutter (line 127) | private getSectionGutter(): number {
method mergeProps (line 131) | mergeProps(props: {
method computeFullCoords (line 202) | private computeFullCoords(): void {
method computeVisibleSections (line 332) | computeVisibleSections(start: number, end: number): void {
method getMaxColumnHeight (line 397) | private getMaxColumnHeight(columnHeights: Array<number> = this.columnH...
method getState (line 401) | getState(): {
FILE: fluxer_app/src/components/channel/MediaActionBottomSheet.tsx
type MediaActionBottomSheetProps (line 30) | interface MediaActionBottomSheetProps {
FILE: fluxer_app/src/components/channel/MemberListContainer.tsx
type ScrollerResizeType (line 26) | type ScrollerResizeType = 'container' | 'content';
type MemberListContainerProps (line 28) | interface MemberListContainerProps {
FILE: fluxer_app/src/components/channel/MemberListItem.tsx
type MemberListItemProps (line 46) | interface MemberListItemProps {
FILE: fluxer_app/src/components/channel/MentionEveryonePopout.tsx
type MentionEveryonePopoutProps (line 29) | interface MentionEveryonePopoutProps {
FILE: fluxer_app/src/components/channel/Message.tsx
type MessageBehaviorOverrides (line 107) | type MessageBehaviorOverrides = Partial<{
type MessageProps (line 121) | interface MessageProps {
FILE: fluxer_app/src/components/channel/MessageActionBar.tsx
method subscribe (line 151) | subscribe(listener: () => void) {
method getSnapshot (line 155) | getSnapshot(): Array<FlatEmoji> {
method getServerSnapshot (line 161) | getServerSnapshot(): Array<FlatEmoji> {
type MessageActionBarButtonProps (line 185) | interface MessageActionBarButtonProps {
type QuickReactionButtonProps (line 233) | interface QuickReactionButtonProps {
type MessageActionBarCoreProps (line 308) | interface MessageActionBarCoreProps {
FILE: fluxer_app/src/components/channel/MessageActionBottomSheet.tsx
type MessageActionBottomSheetProps (line 35) | interface MessageActionBottomSheetProps {
FILE: fluxer_app/src/components/channel/MessageActionMenu.tsx
type MessageActionMenuOptions (line 72) | interface MessageActionMenuOptions {
type MessageActionMenuData (line 90) | interface MessageActionMenuData {
FILE: fluxer_app/src/components/channel/MessageActionUtils.tsx
function isEmbedsSuppressed (line 63) | function isEmbedsSuppressed(message: MessageRecord): boolean {
function isClientSystemMessage (line 67) | function isClientSystemMessage(message: MessageRecord): boolean {
function canReportMessage (line 71) | function canReportMessage(message: MessageRecord): boolean {
function canDeleteAttachmentUtil (line 84) | function canDeleteAttachmentUtil(message: MessageRecord | undefined): bo...
function requestOpenReactionPicker (line 92) | function requestOpenReactionPicker(messageId: string): void {
function triggerAddReaction (line 96) | function triggerAddReaction(message: MessageRecord): boolean {
type MessagePermissions (line 119) | interface MessagePermissions {
function getMessagePermissionsFromStores (line 132) | function getMessagePermissionsFromStores(message: MessageRecord): Messag...
function useMessagePermissions (line 207) | function useMessagePermissions(message: MessageRecord): MessagePermissio...
type MessageActionHandlersOptions (line 220) | interface MessageActionHandlersOptions {
type MessageActionHandlers (line 225) | interface MessageActionHandlers {
function createMessageActionHandlers (line 242) | function createMessageActionHandlers(
function startMessageEdit (line 381) | function startMessageEdit(message: MessageRecord): void {
function requestDeleteMessage (line 392) | function requestDeleteMessage(message: MessageRecord, i18n: I18n, bypass...
function requestMessagePin (line 401) | function requestMessagePin(message: MessageRecord, i18n: I18n, options: ...
function requestMessageReply (line 438) | function requestMessageReply(message: MessageRecord, options?: {mention?...
function requestMessageForward (line 449) | function requestMessageForward(message: MessageRecord): void {
function requestCopyMessageText (line 462) | function requestCopyMessageText(message: MessageRecord, i18n: I18n): void {
function requestMarkMessageUnread (line 467) | function requestMarkMessageUnread(message: MessageRecord): void {
function requestCopyMessageLink (line 471) | function requestCopyMessageLink(message: MessageRecord, i18n: I18n): void {
function requestCopyMessageId (line 486) | function requestCopyMessageId(message: MessageRecord, i18n: I18n): void {
function requestToggleBookmark (line 490) | function requestToggleBookmark(message: MessageRecord, i18n: I18n): void {
function requestToggleSuppressEmbeds (line 502) | function requestToggleSuppressEmbeds(message: MessageRecord, i18n: I18n)...
function requestSpeakMessage (line 531) | function requestSpeakMessage(message: MessageRecord): void {
FILE: fluxer_app/src/components/channel/MessageAttachmentStateUtils.tsx
type AttachmentRenderingState (line 26) | interface AttachmentRenderingState {
FILE: fluxer_app/src/components/channel/MessageAttachmentUtils.tsx
constant IMAGE_TYPES (line 22) | const IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'...
constant VIDEO_TYPES (line 23) | const VIDEO_TYPES = ['video/mp4', 'video/webm', 'video/ogg', 'video/quic...
constant AUDIO_TYPES (line 24) | const AUDIO_TYPES = ['audio/mpeg', 'audio/mp3', 'audio/ogg', 'audio/wav'...
function isImageType (line 26) | function isImageType(contentType?: string): boolean {
function isVideoType (line 30) | function isVideoType(contentType?: string): boolean {
function isAudioType (line 34) | function isAudioType(contentType?: string): boolean {
function splitMediaAndFileAttachments (line 47) | function splitMediaAndFileAttachments(attachments: ReadonlyArray<Message...
FILE: fluxer_app/src/components/channel/MessageAttachments.tsx
type ForwardedMessageContentProps (line 151) | interface ForwardedMessageContentProps {
FILE: fluxer_app/src/components/channel/MessageAuthorInfo.tsx
type MessageAuthorInfoProps (line 38) | interface MessageAuthorInfoProps {
FILE: fluxer_app/src/components/channel/MessageCharacterCounter.tsx
type MessageCharacterCounterProps (line 25) | interface MessageCharacterCounterProps {
FILE: fluxer_app/src/components/channel/MessageGroup.tsx
type MessageGroupProps (line 29) | interface MessageGroupProps {
FILE: fluxer_app/src/components/channel/MessageReactions.tsx
type EmojiInfoData (line 51) | interface EmojiInfoData {
FILE: fluxer_app/src/components/channel/MessageReactionsSheet.tsx
type MessageReactionsSheetProps (line 42) | interface MessageReactionsSheetProps {
FILE: fluxer_app/src/components/channel/MessageUploadProgress.tsx
type MessageUploadProgressProps (line 36) | interface MessageUploadProgressProps {
FILE: fluxer_app/src/components/channel/MessageViewContext.tsx
type MessagePreviewOverrides (line 25) | interface MessagePreviewOverrides {
type MessagePreviewPermissions (line 30) | interface MessagePreviewPermissions {
type MessageViewContextValue (line 42) | interface MessageViewContextValue {
FILE: fluxer_app/src/components/channel/Messages.tsx
constant MESSAGE_COPY_PARSER_FLAGS (line 65) | const MESSAGE_COPY_PARSER_FLAGS = getParserFlagsForContext(MarkdownConte...
function checkPermissions (line 67) | function checkPermissions(channel: ChannelRecord) {
type MessagesStoreSnapshot (line 78) | interface MessagesStoreSnapshot {
type MessagesProps (line 97) | interface MessagesProps {
function shallowEqual (line 125) | function shallowEqual<T extends object>(a: T, b: T): boolean {
type MessageState (line 141) | interface MessageState extends MessagesStoreSnapshot {
function LoadErrorBar (line 692) | function LoadErrorBar({loading, onRetry}: {loading: boolean; onRetry: ()...
FILE: fluxer_app/src/components/channel/MobileMemesPicker.tsx
type ContentType (line 53) | type ContentType = 'all' | 'image' | 'video' | 'audio' | 'gif';
type FilterOption (line 55) | interface FilterOption {
type MemesPickerState (line 81) | interface MemesPickerState {
type MobileMemesPickerProps (line 91) | interface MobileMemesPickerProps {
type GridItemProps (line 295) | interface GridItemProps {
type MemeActionBottomSheetProps (line 524) | interface MemeActionBottomSheetProps {
FILE: fluxer_app/src/components/channel/MuteOptions.tsx
type MuteDurationOption (line 30) | interface MuteDurationOption {
type MuteDurationOptionDescriptor (line 35) | interface MuteDurationOptionDescriptor {
constant FINITE_MUTE_DURATION_DESCRIPTORS (line 40) | const FINITE_MUTE_DURATION_DESCRIPTORS: ReadonlyArray<MuteDurationOption...
constant INDEFINITE_MUTE_DURATION_DESCRIPTOR (line 50) | const INDEFINITE_MUTE_DURATION_DESCRIPTOR: MuteDurationOptionDescriptor = {
constant MUTE_DURATION_OPTION_DESCRIPTORS (line 55) | const MUTE_DURATION_OPTION_DESCRIPTORS: ReadonlyArray<MuteDurationOption...
FILE: fluxer_app/src/components/channel/NSFWChannelGate.tsx
type Props (line 33) | interface Props {
FILE: fluxer_app/src/components/channel/PinSystemMessage.tsx
type PinSystemMessageProps (line 33) | interface PinSystemMessageProps {
FILE: fluxer_app/src/components/channel/PreloadableUserPopout.tsx
type PreloadableChildProps (line 35) | type PreloadableChildProps = React.HTMLAttributes<HTMLElement> & React.R...
FILE: fluxer_app/src/components/channel/PremiumUpsellBanner.tsx
type PremiumUpsellBannerProps (line 30) | interface PremiumUpsellBannerProps {
constant COMMUNITY_ICON_LIMIT (line 38) | const COMMUNITY_ICON_LIMIT = 4;
FILE: fluxer_app/src/components/channel/QuickReactionsRow.tsx
function renderQuickReactionEmoji (line 27) | function renderQuickReactionEmoji(emoji: FlatEmoji): React.ReactNode {
FILE: fluxer_app/src/components/channel/RecipientAddMessage.tsx
type RecipientAddMessageProps (line 30) | interface RecipientAddMessageProps {
FILE: fluxer_app/src/components/channel/RecipientRemoveMessage.tsx
type RecipientRemoveMessageProps (line 30) | interface RecipientRemoveMessageProps {
FILE: fluxer_app/src/components/channel/ReplyBar.tsx
type ReplyBarProps (line 35) | interface ReplyBarProps {
FILE: fluxer_app/src/components/channel/ScheduledMessageEditBar.tsx
type ScheduledMessageEditBarProps (line 30) | interface ScheduledMessageEditBarProps {
FILE: fluxer_app/src/components/channel/ScrollFillerSkeleton.tsx
type Props (line 24) | interface Props {
FILE: fluxer_app/src/components/channel/SearchResultsUtils.tsx
type SearchMachineStateIdle (line 23) | interface SearchMachineStateIdle {
type SearchMachineStateLoading (line 27) | interface SearchMachineStateLoading {
type SearchMachineStateIndexing (line 31) | interface SearchMachineStateIndexing {
type SearchMachineStateSuccess (line 36) | interface SearchMachineStateSuccess {
type SearchMachineStateError (line 44) | interface SearchMachineStateError {
type SearchMachineState (line 49) | type SearchMachineState =
FILE: fluxer_app/src/components/channel/SearchScopeOptions.tsx
type ScopeValueOption (line 26) | interface ScopeValueOption extends SearchValueOption {
constant DEFAULT_SCOPE_VALUE (line 30) | const DEFAULT_SCOPE_VALUE: MessageSearchScope = 'current';
FILE: fluxer_app/src/components/channel/SlowmodeIndicator.tsx
type SlowmodeIndicatorProps (line 27) | interface SlowmodeIndicatorProps {
FILE: fluxer_app/src/components/channel/ThemeEmbed.tsx
type ThemeEmbedProps (line 37) | interface ThemeEmbedProps {
FILE: fluxer_app/src/components/channel/TimestampWithTooltip.tsx
type TimestampWithTooltipProps (line 28) | interface TimestampWithTooltipProps {
FILE: fluxer_app/src/components/channel/Typing.tsx
type TypingProps (line 26) | interface TypingProps {
FILE: fluxer_app/src/components/channel/TypingUsers.tsx
constant SEVERAL_PEOPLE_DESCRIPTOR (line 40) | const SEVERAL_PEOPLE_DESCRIPTOR = msg`Several people are typing...`;
constant HANDFUL_DESCRIPTOR (line 41) | const HANDFUL_DESCRIPTOR = msg`A handful of keyboard warriors are assemb...
constant SYMPHONY_DESCRIPTOR (line 42) | const SYMPHONY_DESCRIPTOR = msg`A symphony of clacking keys is underway....
constant FIESTA_DESCRIPTOR (line 43) | const FIESTA_DESCRIPTOR = msg`It's a full-blown typing fiesta in here`;
constant APOCALYPSE_DESCRIPTOR (line 44) | const APOCALYPSE_DESCRIPTOR = msg`Whoa, it's a typing apocalypse`;
constant AVATAR_THRESHOLD (line 110) | const AVATAR_THRESHOLD = 5;
FILE: fluxer_app/src/components/channel/UnreadDividerSlot.tsx
type UnreadDividerSlotProps (line 25) | type UnreadDividerSlotProps =
FILE: fluxer_app/src/components/channel/UploadManager.tsx
constant UPLOAD_DROP_MODAL_KEY (line 38) | const UPLOAD_DROP_MODAL_KEY = 'upload-drop-modal';
FILE: fluxer_app/src/components/channel/UserMessage.tsx
constant CUSTOM_EMOJI_MARKDOWN_PATTERN (line 64) | const CUSTOM_EMOJI_MARKDOWN_PATTERN = /<a?:[a-zA-Z0-9_+-]{2,}:([0-9]+)>/g;
FILE: fluxer_app/src/components/channel/UserTag.tsx
type UserTagProps (line 25) | interface UserTagProps extends React.ComponentPropsWithoutRef<'span'> {
FILE: fluxer_app/src/components/channel/VerificationBarrier.tsx
type Props (line 34) | interface Props {
FILE: fluxer_app/src/components/channel/VoiceMessageRecorder.tsx
type StopAction (line 55) | type StopAction = 'send' | 'discard';
type VoiceMessageRecorderProps (line 73) | interface VoiceMessageRecorderProps {
function VoiceMessageRecorder (line 79) | function VoiceMessageRecorder({channelId, disabled, tooltipAnchorRef}: V...
FILE: fluxer_app/src/components/channel/active_now/useActiveFriendVoiceStates.tsx
function useActiveFriendVoiceStates (line 31) | function useActiveFriendVoiceStates(): ReadonlyArray<UserVoiceActivity> {
FILE: fluxer_app/src/components/channel/barriers/BarrierComponents.tsx
type BarrierProps (line 45) | interface BarrierProps {
type TimedBarrierProps (line 49) | interface TimedBarrierProps extends BarrierProps {
type BarrierBaseProps (line 53) | interface BarrierBaseProps {
type BlockedUserBarrierProps (line 260) | interface BlockedUserBarrierProps extends BarrierProps {
FILE: fluxer_app/src/components/channel/channel_header/useChannelHeaderData.tsx
type ChannelHeaderData (line 28) | interface ChannelHeaderData {
FILE: fluxer_app/src/components/channel/channel_header_components/ChannelHeaderIcon.tsx
type ChannelHeaderIconProps (line 29) | interface ChannelHeaderIconProps {
FILE: fluxer_app/src/components/channel/channel_header_components/ChannelNotificationSettingsButton.tsx
type ChannelNotificationSettingsButtonProps (line 31) | interface ChannelNotificationSettingsButtonProps {
FILE: fluxer_app/src/components/channel/channel_header_components/ChannelNotificationSettingsDropdown.tsx
type Props (line 39) | interface Props {
FILE: fluxer_app/src/components/channel/channel_header_components/ChannelPinsButton.tsx
type ChannelPinsButtonProps (line 34) | interface ChannelPinsButtonProps {
FILE: fluxer_app/src/components/channel/channel_view/ChannelViewScaffold.tsx
type ChannelViewScaffoldProps (line 24) | interface ChannelViewScaffoldProps {
FILE: fluxer_app/src/components/channel/channel_view/DMChannelView.tsx
type DMChannelViewProps (line 87) | interface DMChannelViewProps {
constant CALL_AVATAR_DEFAULT_SIZE (line 92) | const CALL_AVATAR_DEFAULT_SIZE = 64;
constant CALL_AVATAR_MAX_SIZE (line 93) | const CALL_AVATAR_MAX_SIZE = 72;
constant CALL_AVATAR_PADDING (line 94) | const CALL_AVATAR_PADDING = 12;
constant CALL_AVATAR_LAYOUT_OFFSET (line 95) | const CALL_AVATAR_LAYOUT_OFFSET = 240;
constant CALL_RINGING_AVATAR_ANIMATION (line 96) | const CALL_RINGING_AVATAR_ANIMATION = {
constant CALL_RINGING_RIPPLE_ANIMATION (line 99) | const CALL_RINGING_RIPPLE_ANIMATION = {
constant CALL_RINGING_BREATH_TIMES (line 103) | const CALL_RINGING_BREATH_TIMES = [0, 0.16, 0.34, 0.52, 0.7, 0.86, 1];
constant CALL_RINGING_DURATION_SECONDS (line 104) | const CALL_RINGING_DURATION_SECONDS = 3.2;
constant CALL_AVATAR_SPRING (line 105) | const CALL_AVATAR_SPRING = {stiffness: 520, damping: 34, mass: 0.6} as c...
constant COMPACT_CALL_RESIZE_DRAG_THRESHOLD_SQ (line 106) | const COMPACT_CALL_RESIZE_DRAG_THRESHOLD_SQ = 9;
constant COMPACT_CALL_RESIZE_VIEWPORT_MARGIN (line 107) | const COMPACT_CALL_RESIZE_VIEWPORT_MARGIN = 32;
constant COMPACT_CALL_RESIZE_STEP (line 108) | const COMPACT_CALL_RESIZE_STEP = 16;
function getFullscreenElement (line 110) | function getFullscreenElement(): Element | null {
function getCompactCallHeightKey (line 121) | function getCompactCallHeightKey(channelId: string, callMessageId: strin...
function getCompactCallHeightMax (line 125) | function getCompactCallHeightMax(compactHeightMin: number): number {
type CallParticipant (line 130) | interface CallParticipant {
type CallParticipantsRowProps (line 135) | interface CallParticipantsRowProps {
type CompactCallResizeListeners (line 142) | interface CompactCallResizeListeners {
type CompactCallResizeState (line 147) | interface CompactCallResizeState {
type CallControlRenderMode (line 155) | type CallControlRenderMode = 'mobile' | 'voiceControlBar';
type CallControlTone (line 156) | type CallControlTone = 'primary' | 'secondary' | 'danger';
FILE: fluxer_app/src/components/channel/channel_view/GuildChannelView.tsx
type GuildChannelViewProps (line 57) | interface GuildChannelViewProps {
FILE: fluxer_app/src/components/channel/channel_view/useCallHeaderState.tsx
type CallHeaderControlsVariant (line 26) | type CallHeaderControlsVariant = 'hidden' | 'inCall' | 'incoming' | 'con...
type CallHeaderState (line 28) | interface CallHeaderState {
function useCallHeaderState (line 37) | function useCallHeaderState(channel?: ChannelRecord | null): CallHeaderS...
FILE: fluxer_app/src/components/channel/channel_view/useChannelSearchState.tsx
type UseChannelSearchStateReturn (line 26) | interface UseChannelSearchStateReturn {
FILE: fluxer_app/src/components/channel/direct_message/AddFriendForm.tsx
type AddFriendFormProps (line 38) | interface AddFriendFormProps {
FILE: fluxer_app/src/components/channel/direct_message/DMFriendsView.tsx
type TabButtonProps (line 44) | interface TabButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLBut...
FILE: fluxer_app/src/components/channel/direct_message/DMLayout.tsx
type DMLayoutProps (line 32) | interface DMLayoutProps {
FILE: fluxer_app/src/components/channel/direct_message/DMList.tsx
type InviteCandidate (line 149) | interface InviteCandidate {
FILE: fluxer_app/src/components/channel/direct_message/DMWelcomeSection.tsx
type DMWelcomeSectionProps (line 48) | interface DMWelcomeSectionProps {
FILE: fluxer_app/src/components/channel/direct_message/GroupDMWelcomeSection.tsx
type GroupDMWelcomeSectionProps (line 38) | interface GroupDMWelcomeSectionProps {
FILE: fluxer_app/src/components/channel/direct_message/PersonalNotesWelcomeSection.tsx
type PersonalNotesWelcomeSectionProps (line 27) | interface PersonalNotesWelcomeSectionProps {
FILE: fluxer_app/src/components/channel/embeds/AltTextBadge.tsx
type AltTextBadgeProps (line 25) | interface AltTextBadgeProps {
FILE: fluxer_app/src/components/channel/embeds/Embed.tsx
constant THUMBNAIL_SIZE (line 71) | const THUMBNAIL_SIZE = 80;
constant MAX_GALLERY_MEDIA (line 72) | const MAX_GALLERY_MEDIA = 10;
constant EMBED_PADDING_X (line 73) | const EMBED_PADDING_X = 12;
constant EMBED_LEFT_BORDER_WIDTH (line 74) | const EMBED_LEFT_BORDER_WIDTH = 4;
constant EMBED_RIGHT_BORDER_WIDTH (line 75) | const EMBED_RIGHT_BORDER_WIDTH = 1;
constant EMBED_MEDIA_CHROME_WIDTH (line 76) | const EMBED_MEDIA_CHROME_WIDTH = EMBED_PADDING_X * 2 + EMBED_LEFT_BORDER...
type EmbedProps (line 78) | interface EmbedProps {
type LinkComponentProps (line 87) | interface LinkComponentProps {
type MediaDimensions (line 93) | interface MediaDimensions {
type BlueskyEmbedProps (line 810) | interface BlueskyEmbedProps extends EmbedProps {
FILE: fluxer_app/src/components/channel/embeds/EmbedUtils.tsx
function deriveDefaultNameFromMessage (line 25) | function deriveDefaultNameFromMessage({
FILE: fluxer_app/src/components/channel/embeds/NSFWBlurOverlay.tsx
type NSFWBlurOverlayProps (line 32) | interface NSFWBlurOverlayProps {
FILE: fluxer_app/src/components/channel/embeds/attachments/Attachment.tsx
type AttachmentProps (line 48) | interface AttachmentProps {
type AttachmentMediaProps (line 57) | interface AttachmentMediaProps {
FILE: fluxer_app/src/components/channel/embeds/attachments/AttachmentFile.tsx
type AttachmentFileProps (line 55) | interface AttachmentFileProps {
FILE: fluxer_app/src/components/channel/embeds/attachments/AttachmentGridItem.tsx
type LayoutType (line 61) | type LayoutType =
type AttachmentGridItemProps (line 75) | interface AttachmentGridItemProps {
type MediaLoadingState (line 84) | interface MediaLoadingState {
FILE: fluxer_app/src/components/channel/embeds/attachments/AttachmentLayoutGrid.tsx
type AttachmentLayoutGridProps (line 27) | interface AttachmentLayoutGridProps {
type LayoutConfig (line 33) | interface LayoutConfig {
function getLayoutConfig (line 39) | function getLayoutConfig(count: number): LayoutConfig {
FILE: fluxer_app/src/components/channel/embeds/attachments/AttachmentMosaic.tsx
type AttachmentMosaicProps (line 34) | interface AttachmentMosaicProps {
type AttachmentMosaicStyle (line 42) | interface AttachmentMosaicStyle extends CSSProperties {
FILE: fluxer_app/src/components/channel/embeds/attachments/AttachmentSingleMedia.tsx
type AttachmentSingleMediaProps (line 37) | interface AttachmentSingleMediaProps {
type AttachmentMediaConstraintStyle (line 45) | interface AttachmentMediaConstraintStyle extends CSSProperties {
FILE: fluxer_app/src/components/channel/embeds/attachments/TextualAttachmentCodePanel.tsx
function TextualAttachmentCodePanel (line 33) | function TextualAttachmentCodePanel({
FILE: fluxer_app/src/components/channel/embeds/attachments/TextualAttachmentPreviewFooter.tsx
function TextualAttachmentPreviewFooter (line 35) | function TextualAttachmentPreviewFooter({
FILE: fluxer_app/src/components/channel/embeds/attachments/TextualAttachmentPreviewUtils.tsx
constant PREVIEW_LIMIT_KB (line 28) | const PREVIEW_LIMIT_KB = TEXT_PREVIEW_MAX_BYTES / 1024;
constant DEFAULT_PREVIEW_LINES (line 29) | const DEFAULT_PREVIEW_LINES = 6;
constant MAX_EXPANDED_PREVIEW_LINES (line 30) | const MAX_EXPANDED_PREVIEW_LINES = 100;
type HighlightLanguageOption (line 34) | interface HighlightLanguageOption {
type PreviewError (line 39) | type PreviewError = {type: 'size'; message?: string} | {type: 'network';...
type PreviewStatus (line 40) | type PreviewStatus = 'idle' | 'loading' | 'loaded' | 'error';
type TextualAttachmentPreviewProps (line 42) | interface TextualAttachmentPreviewProps {
type TextualPreviewContextMenuProps (line 46) | interface TextualPreviewContextMenuProps {
type TextualAttachmentLanguagePopoutProps (line 52) | interface TextualAttachmentLanguagePopoutProps {
type TextualAttachmentCodePanelProps (line 59) | interface TextualAttachmentCodePanelProps {
type PreviewViewportStyle (line 72) | interface PreviewViewportStyle extends CSSProperties {
type TextualAttachmentPreviewFooterProps (line 77) | interface TextualAttachmentPreviewFooterProps {
type TextualAttachmentPreviewModalProps (line 91) | interface TextualAttachmentPreviewModalProps {
function buildHighlightLanguageOptions (line 105) | function buildHighlightLanguageOptions(): Array<HighlightLanguageOption> {
constant HIGHLIGHT_LANGUAGE_OPTIONS (line 136) | const HIGHLIGHT_LANGUAGE_OPTIONS = buildHighlightLanguageOptions();
constant AUTO_HIGHLIGHT_LANGUAGES (line 137) | const AUTO_HIGHLIGHT_LANGUAGES = highlight.listLanguages();
function escapeHtml (line 139) | function escapeHtml(value: string): string {
function getAttachmentFileName (line 143) | function getAttachmentFileName(attachment: MessageAttachment): string {
function getFileExtension (line 147) | function getFileExtension(fileName: string): string | null {
function inferLanguageCodeFromAttachment (line 155) | function inferLanguageCodeFromAttachment(attachment: MessageAttachment):...
function getInitialSelectedLanguage (line 170) | function getInitialSelectedLanguage(attachment: MessageAttachment, infer...
function getLineCount (line 183) | function getLineCount(textContent: string | null): number {
function getVisibleLineCount (line 190) | function getVisibleLineCount(lineCount: number, isExpanded: boolean): nu...
function highlightTextContent (line 202) | function highlightTextContent(selectedLanguage: string, textContent: str...
FILE: fluxer_app/src/components/channel/embeds/media/EmbedAudio.tsx
type EmbedAudioProps (line 41) | type EmbedAudioProps = BaseMediaProps & {
FILE: fluxer_app/src/components/channel/embeds/media/EmbedGifv.tsx
type GifvEmbedProps (line 52) | type GifvEmbedProps = BaseMediaProps & {
type VideoConfig (line 60) | interface VideoConfig {
function useEmbedMediaCalculator (line 69) | function useEmbedMediaCalculator() {
type ImagePreviewHandlerProps (line 157) | interface ImagePreviewHandlerProps {
FILE: fluxer_app/src/components/channel/embeds/media/EmbedImage.tsx
constant IMAGE_CONFIG (line 46) | const IMAGE_CONFIG = {
type ImagePreviewHandlerProps (line 55) | interface ImagePreviewHandlerProps {
type EmbedImageProps (line 72) | type EmbedImageProps = React.ImgHTMLAttributes<HTMLImageElement> &
FILE: fluxer_app/src/components/channel/embeds/media/EmbedVideo.tsx
constant VIDEO_CONFIG (line 54) | const VIDEO_CONFIG = {
type EmbedVideoProps (line 63) | type EmbedVideoProps = BaseMediaProps & {
FILE: fluxer_app/src/components/channel/embeds/media/EmbedYouTube.tsx
constant YOUTUBE_CONFIG (line 34) | const YOUTUBE_CONFIG = {
type EmbedYouTubeProps (line 45) | interface EmbedYouTubeProps {
type ThumbnailProps (line 50) | interface ThumbnailProps {
FILE: fluxer_app/src/components/channel/embeds/media/MediaButtonUtils.tsx
type MediaButtonVisibilityOptions (line 24) | interface MediaButtonVisibilityOptions {
type MediaButtonVisibility (line 28) | interface MediaButtonVisibility {
function getMediaButtonVisibility (line 34) | function getMediaButtonVisibility(
FILE: fluxer_app/src/components/channel/embeds/media/MediaButtons.tsx
type OverlayPlayButtonProps (line 24) | interface OverlayPlayButtonProps {
type OverlayActionButtonProps (line 36) | interface OverlayActionButtonProps {
FILE: fluxer_app/src/components/channel/embeds/media/MediaContainer.tsx
constant MIN_SIZE_FOR_OVERLAYS (line 30) | const MIN_SIZE_FOR_OVERLAYS = 120;
type LongPressEvent (line 39) | type LongPressEvent = React.PointerEvent<HTMLDivElement> | React.TouchEv...
type MediaContainerProps (line 41) | interface MediaContainerProps {
FILE: fluxer_app/src/components/channel/embeds/media/MediaTypes.tsx
type BaseMediaProps (line 22) | interface BaseMediaProps {
type MediaContext (line 33) | interface MediaContext {
FILE: fluxer_app/src/components/channel/embeds/media/VoiceMessagePlayer.tsx
type VoiceMessagePlayerProps (line 45) | interface VoiceMessagePlayerProps extends BaseMediaProps {
function decodeWaveform (line 55) | function decodeWaveform(waveform: string): Array<number> {
function normaliseWaveform (line 69) | function normaliseWaveform(values: Array<number>): Array<number> {
function formatTime (line 81) | function formatTime(time: number): string {
FILE: fluxer_app/src/components/channel/emoji_picker/EmojiPickerCategoryList.tsx
type EmojiPickerCategoryListProps (line 32) | interface EmojiPickerCategoryListProps {
FILE: fluxer_app/src/components/channel/emoji_picker/EmojiPickerConstants.tsx
constant EMOJI_CLAP (line 22) | const EMOJI_CLAP = '\u{1F44F}';
constant EMOJI_SPRITE_SIZE (line 23) | const EMOJI_SPRITE_SIZE = 32;
constant EMOJI_ROW_HEIGHT (line 24) | const EMOJI_ROW_HEIGHT = 48;
constant EMOJI_PICKER_CUSTOM_EMOJI_SIZE (line 25) | const EMOJI_PICKER_CUSTOM_EMOJI_SIZE = 48;
constant CATEGORY_HEADER_HEIGHT (line 26) | const CATEGORY_HEADER_HEIGHT = 32;
constant EMOJIS_PER_ROW (line 27) | const EMOJIS_PER_ROW = 9;
constant OVERSCAN_ROWS (line 28) | const OVERSCAN_ROWS = 5;
type SpriteSheetOptions (line 30) | interface SpriteSheetOptions {
type SpriteSheetVariant (line 34) | interface SpriteSheetVariant {
constant SPRITE_BASE (line 39) | const SPRITE_BASE = 'https://fluxerstatic.com/emoji';
constant SPRITE_VERSION (line 40) | const SPRITE_VERSION = '2';
constant SPRITE_SHEET_RESOURCES (line 53) | const SPRITE_SHEET_RESOURCES: Record<string, SpriteSheetVariant> = {
FILE: fluxer_app/src/components/channel/emoji_picker/EmojiPickerInspector.tsx
type EmojiPickerInspectorProps (line 28) | interface EmojiPickerInspectorProps {
FILE: fluxer_app/src/components/channel/emoji_picker/EmojiPickerSearchBar.tsx
type EmojiPickerSearchBarProps (line 29) | interface EmojiPickerSearchBarProps {
FILE: fluxer_app/src/components/channel/emoji_picker/EmojiRenderer.tsx
type EmojiRendererProps (line 45) | interface EmojiRendererProps {
FILE: fluxer_app/src/components/channel/emoji_picker/SkinToneSelector.tsx
type SkinTonePickerProps (line 33) | interface SkinTonePickerProps {
type SkinTonePickerButtonProps (line 90) | interface SkinTonePickerButtonProps {
FILE: fluxer_app/src/components/channel/emoji_picker/VirtualRow.tsx
type VirtualRow (line 37) | type VirtualRow =
type VirtualRowRendererProps (line 41) | interface VirtualRowRendererProps {
type VirtualizedRowProps (line 192) | interface VirtualizedRowProps {
FILE: fluxer_app/src/components/channel/emoji_picker/hooks/useEmojiCategories.tsx
function useEmojiCategories (line 26) | function useEmojiCategories(
FILE: fluxer_app/src/components/channel/emoji_picker/hooks/useVirtualRows.tsx
function useVirtualRows (line 29) | function useVirtualRows(
FILE: fluxer_app/src/components/channel/friends/FriendListItem.tsx
type FriendAction (line 56) | interface FriendAction {
type FriendListItemProps (line 64) | interface FriendListItemProps {
FILE: fluxer_app/src/components/channel/friends/FriendsTypes.tsx
type FriendsTab (line 20) | type FriendsTab = 'online' | 'all' | 'pending' | 'add';
FILE: fluxer_app/src/components/channel/friends/MobileFriendRequestItem.tsx
type MobileFriendRequestItemProps (line 40) | interface MobileFriendRequestItemProps {
FILE: fluxer_app/src/components/channel/friends/views/FriendsList.tsx
type FriendsListProps (line 35) | interface FriendsListProps {
FILE: fluxer_app/src/components/channel/friends/views/PendingFriendsView.tsx
type PendingFriendsViewProps (line 33) | interface PendingFriendsViewProps {
FILE: fluxer_app/src/components/channel/invite_embed/InviteEmbedUtils.tsx
function getGroupDMTitle (line 24) | function getGroupDMTitle(channel: Channel, unnamedGroupLabel: string): s...
function getChannelDisplayName (line 28) | function getChannelDisplayName(channel: Channel, unnamedGroupLabel: stri...
type InviteGuild (line 46) | type InviteGuild = Guild | GuildRecord;
FILE: fluxer_app/src/components/channel/message_search_bar/AutocompleteOption.tsx
type AutocompleteOptionProps (line 26) | interface AutocompleteOptionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/ChannelsSection.tsx
type ChannelsSectionProps (line 29) | interface ChannelsSectionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/DateSection.tsx
type DateSectionProps (line 28) | interface DateSectionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/FilterOption.tsx
type FilterOptionProps (line 28) | interface FilterOptionProps {
type FiltersSectionProps (line 86) | interface FiltersSectionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/HistorySection.tsx
type HistorySectionProps (line 31) | interface HistorySectionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/MessageSearchBar.tsx
constant SCOPE_ICON_COMPONENTS (line 73) | const SCOPE_ICON_COMPONENTS: Record<MessageSearchScope, React.ComponentT...
type SearchBarProps (line 82) | interface SearchBarProps {
type AutocompleteType (line 94) | type AutocompleteType = 'filters' | 'users' | 'channels' | 'values' | 'd...
type SearchHints (line 96) | interface SearchHints {
type AutocompleteOption (line 101) | type AutocompleteOption =
function deduplicateMembers (line 113) | function deduplicateMembers(members: Array<GuildMemberRecord>): Array<Gu...
function assignRef (line 125) | function assignRef<T>(ref: React.Ref<T> | undefined, value: T | null): v...
function normalizeFilterKey (line 138) | function normalizeFilterKey(filterKey: string): string {
function isDateFilterKey (line 142) | function isDateFilterKey(filterKey: string): boolean {
function isUserFilterKey (line 154) | function isUserFilterKey(filterKey: string): boolean {
type GuildSearchMode (line 164) | type GuildSearchMode = 'none' | 'current_guild' | 'all_guilds';
type UserGuildSearchPlan (line 166) | interface UserGuildSearchPlan {
function getUserGuildSearchPlan (line 173) | function getUserGuildSearchPlan(scope: MessageSearchScope, currentGuildI...
type MemberSearchBoosters (line 222) | type MemberSearchBoosters = Record<string, number>;
function buildUserSearchBoosters (line 224) | function buildUserSearchBoosters(
method apply (line 552) | apply({rects, elements}) {
FILE: fluxer_app/src/components/channel/message_search_bar/UsersSection.tsx
type UsersSectionProps (line 31) | interface UsersSectionProps {
FILE: fluxer_app/src/components/channel/message_search_bar/ValuesSection.tsx
type ValuesSectionProps (line 28) | interface ValuesSectionProps {
FILE: fluxer_app/src/components/channel/pickers/gif/GifPicker.tsx
type GifPickerProps (line 23) | interface GifPickerProps {
FILE: fluxer_app/src/components/channel/pickers/gif/GifPickerGrid.tsx
constant CATEGORY_TILE_WIDTH (line 36) | const CATEGORY_TILE_WIDTH = 200;
constant CATEGORY_TILE_HEIGHT (line 37) | const CATEGORY_TILE_HEIGHT = 96;
function buildSkeletonItems (line 39) | function buildSkeletonItems(count: number): Array<GifPickerGridItemData> {
FILE: fluxer_app/src/components/channel/pickers/gif/GifPickerGridItem.tsx
constant VIDEO_FILE_EXTENSION_REGEX (line 41) | const VIDEO_FILE_EXTENSION_REGEX = /\.(mp4|webm|mov|m4v)(?:$|\?)/iu;
function isVideoSourceUrl (line 43) | function isVideoSourceUrl(value: string): boolean {
function GifPickerGridItem (line 52) | function GifPickerGridItem({
FILE: fluxer_app/src/components/channel/pickers/gif/GifPickerStore.tsx
class GifPickerStore (line 26) | class GifPickerStore {
method constructor (line 47) | constructor() {
method dispose (line 62) | dispose() {
method isLandingPage (line 68) | get isLandingPage(): boolean {
method isShowingFeatured (line 72) | get isShowingFeatured(): boolean {
method gifsToRender (line 76) | get gifsToRender(): Array<Gif> {
method shouldShowNoResults (line 80) | get shouldShowNoResults(): boolean {
method goToDefaultView (line 93) | goToDefaultView() {
method goToTrending (line 104) | goToTrending() {
method ensureFeaturedLoaded (line 123) | async ensureFeaturedLoaded() {
method loadTrending (line 149) | private async loadTrending() {
method setSearchTerm (line 172) | setSearchTerm(term: string) {
method resetSearch (line 192) | resetSearch() {
method triggerSuggestions (line 205) | triggerSuggestions() {
method flushSearch (line 216) | flushSearch() {
method performSearch (line 226) | private async performSearch(term: string) {
method performSuggest (line 252) | private async performSuggest(term: string) {
FILE: fluxer_app/src/components/channel/pickers/gif/GifPickerTypes.tsx
type View (line 22) | type View = 'default' | 'trending';
type GifPickerGridItemData (line 23) | type GifPickerGridItemData =
FILE: fluxer_app/src/components/channel/pickers/memes/MemesPicker.tsx
type MemesPickerProps (line 23) | interface MemesPickerProps {
FILE: fluxer_app/src/components/channel/pickers/memes/MemesPickerHeader.tsx
type ContentType (line 27) | type ContentType = 'all' | 'image' | 'video' | 'audio' | 'gif';
type FilterOption (line 29) | interface FilterOption {
function MemesPickerHeader (line 35) | function MemesPickerHeader({
FILE: fluxer_app/src/components/channel/pickers/memes/MemesPickerView.tsx
type MemesPickerState (line 40) | interface MemesPickerState {
FILE: fluxer_app/src/components/channel/pickers/shared/ComputeColumns.tsx
type ComputeColumnsOptions (line 20) | interface ComputeColumnsOptions {
function computeMasonryColumns (line 26) | function computeMasonryColumns(
FILE: fluxer_app/src/components/channel/pickers/shared/MasonryVirtualGrid.tsx
type VisibleItemTuple (line 26) | type VisibleItemTuple = [itemKey: string, sectionIndex: number, itemInde...
type Coords (line 28) | interface Coords {
type CoordsMap (line 37) | type CoordsMap = Record<string, Coords>;
type VisibleSections (line 38) | type VisibleSections = Record<string, Array<VisibleItemTuple>>;
type GridCoordinates (line 40) | interface GridCoordinates {
type GridData (line 46) | interface GridData {
type MasonryExtraSection (line 51) | interface MasonryExtraSection {
constant EMPTY_EXTRA_SECTIONS (line 57) | const EMPTY_EXTRA_SECTIONS: ReadonlyArray<MasonryExtraSection> = [];
function MasonryVirtualGrid (line 59) | function MasonryVirtualGrid<T>({
FILE: fluxer_app/src/components/channel/pickers/shared/PickerConstants.tsx
constant MASONRY_OVERSCAN_PX (line 20) | const MASONRY_OVERSCAN_PX = 480;
constant MASONRY_PADDING_PX (line 21) | const MASONRY_PADDING_PX = 12;
FILE: fluxer_app/src/components/channel/pickers/shared/usePooledVideo.tsx
type GifVideoPoolLike (line 22) | interface GifVideoPoolLike {
function usePooledVideo (line 30) | function usePooledVideo({
FILE: fluxer_app/src/components/channel/pickers/shared/useScrollerViewport.tsx
type ResizeType (line 23) | type ResizeType = 'container' | 'content';
function useScrollerViewport (line 25) | function useScrollerViewport(scrollerRef: React.RefObject<ScrollerHandle...
FILE: fluxer_app/src/components/channel/shared/MemberListUnavailableFallback.tsx
type MemberListUnavailableFallbackProps (line 24) | interface MemberListUnavailableFallbackProps {
function MemberListUnavailableFallback (line 28) | function MemberListUnavailableFallback({className}: MemberListUnavailabl...
FILE: fluxer_app/src/components/channel/shared/PickerEmptyState.tsx
type PickerEmptyStateProps (line 23) | interface PickerEmptyStateProps {
FILE: fluxer_app/src/components/channel/shared/PickerSearchInput.tsx
constant MODAL_KEYBOARD_SELECTOR (line 35) | const MODAL_KEYBOARD_SELECTOR = '[role="dialog"], .modal-backdrop';
type PickerSearchInputProps (line 58) | interface PickerSearchInputProps {
FILE: fluxer_app/src/components/channel/sticker_picker/StickerPickerCategoryList.tsx
type StickerPickerCategoryListProps (line 29) | interface StickerPickerCategoryListProps {
FILE: fluxer_app/src/components/channel/sticker_picker/StickerPickerConstants.tsx
constant STICKERS_PER_ROW (line 20) | const STICKERS_PER_ROW = 4;
constant STICKERS_PER_ROW_MOBILE (line 21) | const STICKERS_PER_ROW_MOBILE = 3;
FILE: fluxer_app/src/components/channel/sticker_picker/StickerPickerInspector.tsx
type StickerPickerInspectorProps (line 24) | interface StickerPickerInspectorProps {
FILE: fluxer_app/src/components/channel/sticker_picker/StickerPickerSearchBar.tsx
type StickerPickerSearchBarProps (line 27) | interface StickerPickerSearchBarProps {
FILE: fluxer_app/src/components/channel/sticker_picker/VirtualRow.tsx
constant STICKER_ROW_HEIGHT (line 42) | const STICKER_ROW_HEIGHT = 92;
constant CATEGORY_HEADER_HEIGHT (line 43) | const CATEGORY_HEADER_HEIGHT = 32;
constant OVERSCAN_ROWS (line 44) | const OVERSCAN_ROWS = 5;
type VirtualRowRendererProps (line 46) | interface VirtualRowRendererProps {
type StickerButtonProps (line 60) | interface StickerButtonProps {
type VirtualRowWrapperProps (line 314) | interface VirtualRowWrapperProps {
FILE: fluxer_app/src/components/channel/sticker_picker/hooks/useStickerCategories.tsx
function useStickerCategories (line 25) | function useStickerCategories(
FILE: fluxer_app/src/components/channel/sticker_picker/hooks/useVirtualRows.tsx
type VirtualRow (line 26) | type VirtualRow =
FILE: fluxer_app/src/components/channel/textarea/HoldToRecordButton.tsx
type HoldToRecordButtonProps (line 56) | interface HoldToRecordButtonProps {
FILE: fluxer_app/src/components/channel/textarea/MobileTextareaLayout.tsx
type MobileTextareaLayoutProps (line 36) | interface MobileTextareaLayoutProps {
function MobileTextareaLayout (line 68) | function MobileTextareaLayout({
FILE: fluxer_app/src/components/channel/textarea/MobileTextareaPlusBottomSheet.tsx
type MobileTextareaPlusBottomSheetProps (line 28) | interface MobileTextareaPlusBottomSheetProps {
FILE: fluxer_app/src/components/channel/textarea/TextareaButton.tsx
type TextareaButtonProps (line 29) | interface TextareaButtonProps extends React.ButtonHTMLAttributes<HTMLBut...
FILE: fluxer_app/src/components/channel/textarea/TextareaButtons.tsx
type TextareaButtonsProps (line 40) | interface TextareaButtonsProps {
FILE: fluxer_app/src/components/channel/textarea/TextareaContextMenu.tsx
type TextareaContextMenuEditFlags (line 36) | interface TextareaContextMenuEditFlags {
type TextareaContextMenuProps (line 45) | interface TextareaContextMenuProps {
FILE: fluxer_app/src/components/channel/textarea/TextareaInputField.tsx
type TextareaInputFieldProps (line 29) | interface TextareaInputFieldProps {
FILE: fluxer_app/src/components/channel/textarea/TextareaPlusMenu.tsx
type TextareaPlusMenuProps (line 32) | interface TextareaPlusMenuProps {
FILE: fluxer_app/src/components/common/ExpiryFootnote.tsx
type ExpiryFootnoteProps (line 30) | interface ExpiryFootnoteProps {
FILE: fluxer_app/src/components/common/ExternalLink.tsx
type ExternalLinkProps (line 28) | type ExternalLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
FILE: fluxer_app/src/components/common/FriendSelector.tsx
type FriendSelectorProps (line 39) | interface FriendSelectorProps {
type FriendGroup (line 50) | interface FriendGroup {
FILE: fluxer_app/src/components/common/GroupDMAvatar.tsx
function computeGroupStatus (line 43) | function computeGroupStatus(channel: ChannelRecord): string | null {
function renderGroupStatusDot (line 56) | function renderGroupStatusDot(status: string | null, size: number, isTyp...
function renderTypingCutouts (line 138) | function renderTypingCutouts(layout: AvatarStatusLayout): Array<React.Re...
type GroupDMAvatarProps (line 161) | interface GroupDMAvatarProps {
type AvatarPosition (line 169) | interface AvatarPosition {
function getAvatarPosition (line 175) | function getAvatarPosition(count: number, index: number, size: number): ...
FILE: fluxer_app/src/components/common/InstanceBadge.tsx
type InstanceBadgeProps (line 27) | interface InstanceBadgeProps {
type FaviconLoadState (line 34) | type FaviconLoadState = 'loading' | 'loaded' | 'error';
function getFaviconUrl (line 38) | function getFaviconUrl(instanceDomain: string): string {
FILE: fluxer_app/src/components/common/SpoilerOverlay.tsx
type SpoilerOverlayProps (line 26) | interface SpoilerOverlayProps {
FILE: fluxer_app/src/components/common/custom_status_display/CustomStatusDisplay.tsx
type EmojiPressData (line 88) | interface EmojiPressData {
type CustomStatusDisplayProps (line 94) | interface CustomStatusDisplayProps {
type ClampedStyle (line 112) | interface ClampedStyle extends React.CSSProperties {
type StatusEmojiWithTooltipProps (line 135) | interface StatusEmojiWithTooltipProps {
type EmojiRenderResult (line 232) | interface EmojiRenderResult {
FILE: fluxer_app/src/components/debug/ChannelDebugModal.tsx
type ChannelDebugModalProps (line 27) | interface ChannelDebugModalProps {
FILE: fluxer_app/src/components/debug/DebugModal.tsx
type DebugTab (line 35) | interface DebugTab {
type DebugModalProps (line 44) | interface DebugModalProps {
type SummaryItemProps (line 142) | interface SummaryItemProps {
FILE: fluxer_app/src/components/debug/GuildDebugModal.tsx
type GuildDebugModalProps (line 27) | interface GuildDebugModalProps {
FILE: fluxer_app/src/components/debug/GuildMemberDebugModal.tsx
type GuildMemberDebugModalProps (line 27) | interface GuildMemberDebugModalProps {
FILE: fluxer_app/src/components/debug/MessageDebugModal.tsx
type MessageDebugModalProps (line 29) | interface MessageDebugModalProps {
FILE: fluxer_app/src/components/debug/UserDebugModal.tsx
type UserDebugModalProps (line 27) | interface UserDebugModalProps {
FILE: fluxer_app/src/components/embeds/embed_card/EmbedCard.tsx
type EmbedCardProps (line 24) | interface EmbedCardProps {
type SkeletonProps (line 84) | interface SkeletonProps {
FILE: fluxer_app/src/components/embeds/embed_card/useEmbedSkeletonOverride.tsx
function useEmbedSkeletonOverride (line 23) | function useEmbedSkeletonOverride(): boolean {
FILE: fluxer_app/src/components/emojis/EmojiAttributionSubtext.tsx
type EmojiAttributionType (line 30) | type EmojiAttributionType = 'default' | 'custom_invite_required' | 'cust...
type EmojiGuild (line 31) | type EmojiGuild = Guild | GuildRecord;
type EmojiAttribution (line 33) | interface EmojiAttribution {
type EmojiAttributionSource (line 39) | interface EmojiAttributionSource {
type EmojiAttributionSubtextProps (line 80) | interface EmojiAttributionSubtextProps {
FILE: fluxer_app/src/components/emojis/EmojiInfoContent.tsx
type EmojiInfoContentProps (line 26) | interface EmojiInfoContentProps {
FILE: fluxer_app/src/components/emojis/EmojiListItem.tsx
type EmojiRenamePopoutContentProps (line 48) | interface EmojiRenamePopoutContentProps {
FILE: fluxer_app/src/components/form/ColorPickerField.tsx
function clampByte (line 34) | function clampByte(n: number) {
function rgbToHex (line 38) | function rgbToHex(r: number, g: number, b: number) {
function hexToNumber (line 42) | function hexToNumber(hex: string): number {
function numberToHex (line 47) | function numberToHex(n: number): string {
function expandShortHex (line 51) | function expandShortHex(h: string) {
function parseColor (line 60) | function parseColor(input: string): {hex: string; num: number} | null {
function bestIconColorFor (line 103) | function bestIconColorFor(bgColorCss: string): 'black' | 'white' {
type ColorPickerFieldProps (line 118) | interface ColorPickerFieldProps {
FILE: fluxer_app/src/components/form/DateTimePickerField.tsx
type DateTimePickerFieldProps (line 33) | interface DateTimePickerFieldProps {
function formatDisplayDate (line 45) | function formatDisplayDate(date: Date | null): string {
function toTimeString (line 53) | function toTimeString(date: Date): string {
FILE: fluxer_app/src/components/form/Form.tsx
type FormProps (line 23) | type FormProps<T extends FieldValues> = Omit<React.HTMLAttributes<HTMLFo...
FILE: fluxer_app/src/components/form/FormErrorText.tsx
type FormErrorTextProps (line 23) | interface FormErrorTextProps {
function FormErrorText (line 28) | function FormErrorText({message, className}: FormErrorTextProps) {
FILE: fluxer_app/src/components/form/Input.tsx
type FieldSetProps (line 39) | type FieldSetProps = React.HTMLProps<HTMLFieldSetElement> & {
type RenderInputArgs (line 78) | interface RenderInputArgs {
type InputProps (line 85) | type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
type TextareaProps (line 282) | type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
FILE: fluxer_app/src/components/form/Select.tsx
type Primitive (line 44) | type Primitive = string | number | null;
type SelectOption (line 46) | interface SelectOption<V extends Primitive = string> {
type SelectGroup (line 52) | type SelectGroup<V extends Primitive, O extends SelectOption<V>> = Group...
type ReactSelectProps (line 53) | type ReactSelectProps<V extends Primitive, IsMulti extends boolean, O ex...
type SelectProps (line 59) | interface SelectProps<
FILE: fluxer_app/src/components/form/SelectBottomSheet.tsx
type Primitive (line 29) | type Primitive = string | number | null;
type SelectBottomSheetProps (line 31) | interface SelectBottomSheetProps<
type OptionItemProps (line 51) | interface OptionItemProps<V extends Primitive, O extends SelectOption<V>...
FILE: fluxer_app/src/components/form/Switch.tsx
type SwitchProps (line 28) | interface SwitchProps {
FILE: fluxer_app/src/components/form/UsernameValidationRules.tsx
constant FLUXER_TAG_REGEX (line 27) | const FLUXER_TAG_REGEX = /^[a-zA-Z0-9_]+$/;
type UsernameValidationResult (line 29) | interface UsernameValidationResult {
function validateUsername (line 35) | function validateUsername(username: string): UsernameValidationResult {
type UsernameValidationRulesProps (line 49) | interface UsernameValidationRulesProps {
FILE: fluxer_app/src/components/guild/GuildBadge.tsx
type GuildBadgeProps (line 26) | interface GuildBadgeProps {
function hasFeature (line 33) | function hasFeature(features: ReadonlySet<string> | ReadonlyArray<string...
function GuildBadge (line 40) | function GuildBadge({
FILE: fluxer_app/src/components/guild/RoleManagement.tsx
type ManageRolesMenuContentProps (line 120) | interface ManageRolesMenuContentProps {
type ManageRolesBottomSheetProps (line 199) | interface ManageRolesBottomSheetProps {
function openNoRolesModal (line 279) | function openNoRolesModal(guildId: string) {
FILE: fluxer_app/src/components/guild/UploadDropZone.tsx
type UploadDropZoneProps (line 27) | interface UploadDropZoneProps {
FILE: fluxer_app/src/components/guild/UploadSlotInfo.tsx
type UploadSlotInfoProps (line 27) | interface UploadSlotInfoProps {
FILE: fluxer_app/src/components/icons/BlueskyIcon.tsx
type BlueskyIconProps (line 20) | interface BlueskyIconProps {
function BlueskyIcon (line 25) | function BlueskyIcon({size = 16, className}: BlueskyIconProps) {
FILE: fluxer_app/src/components/icons/UnverifiedConnectionIcon.tsx
type UnverifiedConnectionIconProps (line 20) | interface UnverifiedConnectionIconProps {
function UnverifiedConnectionIcon (line 25) | function UnverifiedConnectionIcon({size = 16, className}: UnverifiedConn...
FILE: fluxer_app/src/components/icons/VerifiedConnectionIcon.tsx
type VerifiedConnectionIconProps (line 20) | interface VerifiedConnectionIconProps {
function VerifiedConnectionIcon (line 25) | function VerifiedConnectionIcon({size = 16, className}: VerifiedConnecti...
FILE: fluxer_app/src/components/invites/InviteDateToggle.tsx
type InviteDateToggleProps (line 27) | interface InviteDateToggleProps {
FILE: fluxer_app/src/components/keybinds/KeybindRecorder.tsx
type KeybindRecorderProps (line 32) | interface KeybindRecorderProps {
type KeybindEditorPopoutProps (line 76) | interface KeybindEditorPopoutProps {
FILE: fluxer_app/src/components/layout/ChannelItem.tsx
type ChannelItemCoreProps (line 92) | interface ChannelItemCoreProps {
FILE: fluxer_app/src/components/layout/ChannelItemContent.tsx
type ChannelItemContentProps (line 28) | interface ChannelItemContentProps {
FILE: fluxer_app/src/components/layout/ChannelItemIcon.tsx
type ChannelItemIconProps (line 28) | interface ChannelItemIconProps {
FILE: fluxer_app/src/components/layout/DndContext.tsx
constant DND_OPTIONS (line 32) | const DND_OPTIONS = {
type DndContextProps (line 49) | interface DndContextProps {
FILE: fluxer_app/src/components/layout/FavoritesChannelListContent.tsx
constant DND_TYPES (line 76) | const DND_TYPES = {
type DragItem (line 81) | interface DragItem {
type FavoriteChannelGroup (line 87) | interface FavoriteChannelGroup {
FILE: fluxer_app/src/components/layout/FrameContext.tsx
type FrameSides (line 22) | interface FrameSides {
FILE: fluxer_app/src/components/layout/GenericChannelItem.tsx
type GenericChannelItemProps (line 30) | interface GenericChannelItemProps {
FILE: fluxer_app/src/components/layout/GroupedVoiceParticipant.tsx
function useOpenProfileAriaLabel (line 47) | function useOpenProfileAriaLabel(user: UserRecord) {
type GroupedVoiceParticipantProps (line 53) | interface GroupedVoiceParticipantProps {
FILE: fluxer_app/src/components/layout/GuildDetachedBanner.tsx
constant MAX_VIEWPORT_HEIGHT_FRACTION (line 26) | const MAX_VIEWPORT_HEIGHT_FRACTION = 0.3;
constant DEFAULT_BANNER_HEIGHT (line 27) | const DEFAULT_BANNER_HEIGHT = 240;
function GuildDetachedBanner (line 29) | function GuildDetachedBanner({guild}: {guild: GuildRecord}) {
FILE: fluxer_app/src/components/layout/GuildHeader.tsx
constant HEADER_MIN_HEIGHT (line 40) | const HEADER_MIN_HEIGHT = 56;
constant DEFAULT_BANNER_ASPECT_RATIO (line 41) | const DEFAULT_BANNER_ASPECT_RATIO = 16 / 9;
constant MAX_VIEWPORT_HEIGHT_FRACTION (line 42) | const MAX_VIEWPORT_HEIGHT_FRACTION = 0.3;
FILE: fluxer_app/src/components/layout/GuildHeaderShell.tsx
type GuildHeaderShellProps (line 30) | interface GuildHeaderShellProps {
FILE: fluxer_app/src/components/layout/GuildSidebar.tsx
type GuildSidebarProps (line 28) | interface GuildSidebarProps {
FILE: fluxer_app/src/components/layout/GuildsLayout.tsx
constant DM_LIST_REMOVAL_DELAY_MS (line 77) | const DM_LIST_REMOVAL_DELAY_MS = 750;
constant UNAVAILABLE_INDICATOR_DEBOUNCE_MS (line 78) | const UNAVAILABLE_INDICATOR_DEBOUNCE_MS = 1500;
constant GUILD_LIST_FOCUSABLE_SELECTOR (line 79) | const GUILD_LIST_FOCUSABLE_SELECTOR = '[data-guild-list-focus-item="true...
function getOrganizedItemKey (line 86) | function getOrganizedItemKey(item: OrganizedItem): string {
type TopLevelGuildItem (line 93) | interface TopLevelGuildItem {
type TopLevelGuildFolderItem (line 98) | interface TopLevelGuildFolderItem {
type TopLevelItem (line 103) | type TopLevelItem = TopLevelGuildItem | TopLevelGuildFolderItem;
function cloneGuildFolder (line 105) | function cloneGuildFolder(folder: GuildFolder): GuildFolder {
function getFolderIdFromKey (line 116) | function getFolderIdFromKey(itemKey: string): number | null {
function getNextFolderId (line 125) | function getNextFolderId(guildFolders: ReadonlyArray<GuildFolder>): numb...
function buildTopLevelItems (line 135) | function buildTopLevelItems(guildFolders: ReadonlyArray<GuildFolder>): A...
function buildGuildFoldersFromTopLevelItems (line 162) | function buildGuildFoldersFromTopLevelItems(topLevelItems: ReadonlyArray...
function removeGuildIdsFromGuildFolders (line 196) | function removeGuildIdsFromGuildFolders(
type BottomDropZoneProps (line 215) | interface BottomDropZoneProps {
function BottomDropZone (line 222) | function BottomDropZone({onGuildDrop, lastItemKey, lastItemIsFolder, isD...
FILE: fluxer_app/src/components/layout/MobileBottomNav.tsx
type MobileBottomNavProps (line 38) | interface MobileBottomNavProps {
FILE: fluxer_app/src/components/layout/Nagbar.tsx
type NagbarProps (line 29) | interface NagbarProps {
FILE: fluxer_app/src/components/layout/NagbarButton.tsx
type NagbarButtonProps (line 25) | interface NagbarButtonProps {
FILE: fluxer_app/src/components/layout/NagbarContent.tsx
type NagbarContentProps (line 25) | interface NagbarContentProps {
FILE: fluxer_app/src/components/layout/NativeDragRegion.tsx
type ElementType (line 25) | type ElementType = React.ElementType;
type NativeDragRegionProps (line 27) | type NativeDragRegionProps = Omit<React.HTMLAttributes<HTMLElement>, 'st...
FILE: fluxer_app/src/components/layout/NativeTitlebar.tsx
type NativeTitlebarProps (line 30) | interface NativeTitlebarProps {
FILE: fluxer_app/src/components/layout/NativeTrafficLightsBackdrop.tsx
type NativeTrafficLightsBackdropProps (line 25) | interface NativeTrafficLightsBackdropProps {
FILE: fluxer_app/src/components/layout/NullSpaceDropIndicator.tsx
type NullSpaceDropIndicatorProps (line 28) | interface NullSpaceDropIndicatorProps {
FILE: fluxer_app/src/components/layout/OutlineFrame.tsx
type OutlineFrameProps (line 26) | interface OutlineFrameProps {
FILE: fluxer_app/src/components/layout/ScrollIndicatorOverlay.tsx
type ScrollIndicatorSeverity (line 28) | type ScrollIndicatorSeverity = 'mention' | 'unread';
type ScrollEdgeIndicator (line 30) | interface ScrollEdgeIndicator {
type ScrollIndicatorDirection (line 37) | type ScrollIndicatorDirection = 'top' | 'bottom';
type ActiveScrollIndicator (line 39) | interface ActiveScrollIndicator {
function pickActiveIndicator (line 49) | function pickActiveIndicator(
type FloatingScrollIndicatorProps (line 210) | interface FloatingScrollIndicatorProps {
type ScrollIndicatorOverlayProps (line 259) | interface ScrollIndicatorOverlayProps {
FILE: fluxer_app/src/components/layout/SplashScreen.tsx
constant SPLASH_SCREEN_DELAY (line 32) | const SPLASH_SCREEN_DELAY = 10000;
constant SPLASH_MOTION (line 54) | const SPLASH_MOTION = {
FILE: fluxer_app/src/components/layout/UserArea.tsx
constant VOICE_CONNECTION_HEIGHT_VARIABLE (line 56) | const VOICE_CONNECTION_HEIGHT_VARIABLE = '--layout-voice-connection-heig...
type UserAreaInnerProps (line 58) | interface UserAreaInnerProps {
FILE: fluxer_app/src/components/layout/VoiceChannelUserCount.tsx
type VoiceChannelUserCountProps (line 23) | interface VoiceChannelUserCountProps {
FILE: fluxer_app/src/components/layout/VoiceStateIcons.tsx
type Props (line 28) | interface Props {
FILE: fluxer_app/src/components/layout/app_layout/AppLayoutTypes.tsx
type NagbarType (line 37) | type NagbarType = ValueOf<typeof NagbarType>;
type NagbarState (line 39) | interface NagbarState {
type AppLayoutState (line 45) | interface AppLayoutState {
type NagbarConditions (line 49) | interface NagbarConditions {
constant UPDATE_DISMISS_KEY (line 64) | const UPDATE_DISMISS_KEY = 'fluxer_update_dismissed_until';
FILE: fluxer_app/src/components/layout/app_layout/NagbarContainer.tsx
type NagbarContainerProps (line 38) | interface NagbarContainerProps {
FILE: fluxer_app/src/components/layout/app_layout/nagbars/GuildMembershipCtaNagbar.tsx
constant FLUXER_HQ_INVITE_CODE (line 38) | const FLUXER_HQ_INVITE_CODE = 'fluxer-hq';
FILE: fluxer_app/src/components/layout/dnd/DndDropPosition.tsx
function computeVerticalDropPosition (line 22) | function computeVerticalDropPosition(
function computeHorizontalDropPosition (line 40) | function computeHorizontalDropPosition(clientOffset: XYCoord, boundingRe...
FILE: fluxer_app/src/components/layout/guild_list/FavoritesButton.tsx
type FavoritesButtonProps (line 43) | interface FavoritesButtonProps {
FILE: fluxer_app/src/components/layout/guild_list/GuildFolderItem.tsx
type GuildFolder (line 69) | interface GuildFolder {
type GuildFolderItemProps (line 78) | interface GuildFolderItemProps {
function getFolderColor (line 86) | function getFolderColor(color: number | null, isLightTheme: boolean): st...
function shouldShowCollapsedFolderIcon (line 93) | function shouldShowCollapsedFolderIcon(flags: number): boolean {
function renderCollapsedFolderIcon (line 97) | function renderCollapsedFolderIcon(icon: GuildFolderIcon) {
type MiniGuildIconProps (line 483) | interface MiniGuildIconProps {
FILE: fluxer_app/src/components/layout/guild_list/GuildListDMItem.tsx
type DMListItemProps (line 64) | interface DMListItemProps {
type VoiceRow (line 71) | interface VoiceRow {
type DMVoiceSummary (line 76) | interface DMVoiceSummary {
FILE: fluxer_app/src/components/layout/guild_list/GuildListItem.tsx
type GuildListItemProps (line 74) | interface GuildListItemProps {
type VoiceRow (line 86) | interface VoiceRow {
type GuildVoiceSummary (line 91) | interface GuildVoiceSummary {
type CombinePreviewProps (line 98) | interface CombinePreviewProps {
function CombinePreview (line 103) | function CombinePreview({targetGuild, sourceGuildId}: CombinePreviewProp...
FILE: fluxer_app/src/components/layout/guild_list/VoiceBadge.tsx
type VoiceBadgeProps (line 25) | interface VoiceBadgeProps {
type VoiceBadgeActivity (line 30) | type VoiceBadgeActivity = 'voice' | 'screenshare' | 'video';
function getVoiceBadgeIcon (line 32) | function getVoiceBadgeIcon(activity: VoiceBadgeActivity): React.JSX.Elem...
function VoiceBadge (line 43) | function VoiceBadge({className, activity = 'voice'}: VoiceBadgeProps): R...
FILE: fluxer_app/src/components/layout/types/DndTypes.tsx
constant DND_TYPES (line 20) | const DND_TYPES = {
type DragItem (line 30) | interface DragItem {
type DropResult (line 40) | interface DropResult {
type GuildDragItem (line 46) | interface GuildDragItem {
type GuildDropPosition (line 53) | type GuildDropPosition = 'before' | 'after' | 'inside' | 'combine';
type GuildDropResult (line 55) | interface GuildDropResult {
type AttachmentDragItem (line 62) | interface AttachmentDragItem {
type AttachmentDropResult (line 68) | interface AttachmentDropResult {
type ConnectionDragItem (line 73) | interface ConnectionDragItem {
FILE: fluxer_app/src/components/layout/utils/ChannelMoveOperation.test.tsx
constant TEST_GUILD_ID (line 26) | const TEST_GUILD_ID = 'guild';
function createChannel (line 28) | function createChannel(params: {id: string; type: number; position: numb...
function createDragItem (line 39) | function createDragItem(channel: ChannelRecord): DragItem {
FILE: fluxer_app/src/components/layout/utils/ChannelMoveOperation.tsx
type ChannelMoveOperation (line 66) | interface ChannelMoveOperation {
FILE: fluxer_app/src/components/layout/utils/ChannelOrganization.tsx
type ChannelGroup (line 31) | interface ChannelGroup {
FILE: fluxer_app/src/components/layout/utils/ChannelUnreadState.tsx
type ChannelUnreadStateInput (line 20) | interface ChannelUnreadStateInput {
type ChannelUnreadState (line 27) | interface ChannelUnreadState {
function getChannelUnreadState (line 35) | function getChannelUnreadState({
FILE: fluxer_app/src/components/media_player/components/AudioPlayer.tsx
type AudioPlayerProps (line 37) | interface AudioPlayerProps {
function AudioPlayer (line 46) | function AudioPlayer({
FILE: fluxer_app/src/components/media_player/components/InlineAudioPlayer.tsx
type InlineAudioPlayerProps (line 39) | interface InlineAudioPlayerProps {
function formatFileSize (line 54) | function formatFileSize(bytes: number): string {
function formatTime (line 60) | function formatTime(time: number): string {
function splitFilename (line 67) | function splitFilename(filename: string): {name: string; extension: stri...
function InlineAudioPlayer (line 78) | function InlineAudioPlayer({
FILE: fluxer_app/src/components/media_player/components/MediaFullscreenButton.tsx
type MediaFullscreenButtonProps (line 29) | interface MediaFullscreenButtonProps {
function MediaFullscreenButton (line 39) | function MediaFullscreenButton({
FILE: fluxer_app/src/components/media_player/components/MediaPipButton.tsx
type MediaPipButtonProps (line 29) | interface MediaPipButtonProps {
function MediaPipButton (line 39) | function MediaPipButton({
FILE: fluxer_app/src/components/media_player/components/MediaPlayButton.tsx
type MediaPlayButtonProps (line 29) | interface MediaPlayButtonProps {
constant SIZE_MAP (line 40) | const SIZE_MAP = {
function MediaPlayButton (line 47) | function MediaPlayButton({
FILE: fluxer_app/src/components/media_player/components/MediaPlaybackRate.tsx
type MediaPlaybackRateProps (line 29) | interface MediaPlaybackRateProps {
function formatRate (line 39) | function formatRate(rate: number): string {
function MediaPlaybackRate (line 45) | function MediaPlaybackRate({
FILE: fluxer_app/src/components/media_player/components/MediaProgressBar.tsx
type MediaProgressBarProps (line 35) | interface MediaProgressBarProps {
function MediaProgressBar (line 50) | function MediaProgressBar({
FILE: fluxer_app/src/components/media_player/components/MediaTimeDisplay.tsx
type MediaTimeDisplayProps (line 25) | interface MediaTimeDisplayProps {
function MediaTimeDisplay (line 33) | function MediaTimeDisplay({
FILE: fluxer_app/src/components/media_player/components/MediaVerticalVolumeControl.tsx
type MediaVerticalVolumeControlProps (line 29) | interface MediaVerticalVolumeControlProps {
function getVolumeIcon (line 38) | function getVolumeIcon(volume: number, isMuted: boolean) {
constant POPOUT_GAP (line 51) | const POPOUT_GAP = 8;
function MediaVerticalVolumeControl (line 53) | function MediaVerticalVolumeControl({
FILE: fluxer_app/src/components/media_player/components/MediaVolumeControl.tsx
type MediaVolumeControlProps (line 33) | interface MediaVolumeControlProps {
function getVolumeIcon (line 44) | function getVolumeIcon(volume: number, isMuted: boolean) {
FILE: fluxer_app/src/components/media_player/components/VideoPlayer.tsx
type VideoPlayerProps (line 48) | interface VideoPlayerProps {
FILE: fluxer_app/src/components/media_player/hooks/useControlsVisibility.tsx
type UseControlsVisibilityOptions (line 22) | interface UseControlsVisibilityOptions {
type UseControlsVisibilityReturn (line 29) | interface UseControlsVisibilityReturn {
function useControlsVisibility (line 41) | function useControlsVisibility(options: UseControlsVisibilityOptions = {...
FILE: fluxer_app/src/components/media_player/hooks/useMediaFullscreen.tsx
type UseMediaFullscreenOptions (line 32) | interface UseMediaFullscreenOptions {
type UseMediaFullscreenReturn (line 38) | interface UseMediaFullscreenReturn {
function getFullscreenElement (line 46) | function getFullscreenElement(): Element | null {
function supportsContainerFullscreenAPI (line 57) | function supportsContainerFullscreenAPI(): boolean {
function supportsIOSVideoFullscreen (line 67) | function supportsIOSVideoFullscreen(videoElement: HTMLVideoElement | nul...
function requestFullscreen (line 73) | async function requestFullscreen(element: HTMLElement): Promise<void> {
function exitFullscreenAPI (line 88) | async function exitFullscreenAPI(): Promise<void> {
function useMediaFullscreen (line 101) | function useMediaFullscreen(options: UseMediaFullscreenOptions): UseMedi...
FILE: fluxer_app/src/components/media_player/hooks/useMediaKeyboard.tsx
type UseMediaKeyboardOptions (line 23) | interface UseMediaKeyboardOptions {
type UseMediaKeyboardReturn (line 38) | interface UseMediaKeyboardReturn {
function keyMatches (line 42) | function keyMatches(key: string, keys: ReadonlyArray<string>): boolean {
constant PLAY_PAUSE_KEYS (line 46) | const PLAY_PAUSE_KEYS = ['Space', 'k', 'K'] as const;
constant SEEK_BACKWARD_KEYS (line 47) | const SEEK_BACKWARD_KEYS = ['ArrowLeft', 'j', 'J'] as const;
constant SEEK_FORWARD_KEYS (line 48) | const SEEK_FORWARD_KEYS = ['ArrowRight', 'l', 'L'] as const;
constant VOLUME_UP_KEYS (line 49) | const VOLUME_UP_KEYS = ['ArrowUp'] as const;
constant VOLUME_DOWN_KEYS (line 50) | const VOLUME_DOWN_KEYS = ['ArrowDown'] as const;
constant MUTE_KEYS (line 51) | const MUTE_KEYS = ['m', 'M'] as const;
constant FULLSCREEN_KEYS (line 52) | const FULLSCREEN_KEYS = ['f', 'F'] as const;
constant SEEK_PERCENTAGE_KEYS (line 53) | const SEEK_PERCENTAGE_KEYS = ['0', '1', '2', '3', '4', '5', '6', '7', '8...
function useMediaKeyboard (line 55) | function useMediaKeyboard(options: UseMediaKeyboardOptions): UseMediaKey...
FILE: fluxer_app/src/components/media_player/hooks/useMediaPiP.tsx
type UseMediaPiPOptions (line 26) | interface UseMediaPiPOptions {
type UseMediaPiPReturn (line 31) | interface UseMediaPiPReturn {
function useMediaPiP (line 39) | function useMediaPiP(options: UseMediaPiPOptions): UseMediaPiPReturn {
FILE: fluxer_app/src/components/media_player/hooks/useMediaPlayer.tsx
constant VOLUME_STORAGE_KEY (line 24) | const VOLUME_STORAGE_KEY = 'fluxer:media:volume';
constant MUTE_STORAGE_KEY (line 25) | const MUTE_STORAGE_KEY = 'fluxer:media:muted';
constant PLAYBACK_RATE_STORAGE_KEY (line 26) | const PLAYBACK_RATE_STORAGE_KEY = 'fluxer:media:playbackRate';
type MediaPlayerState (line 30) | interface MediaPlayerState {
type UseMediaPlayerOptions (line 45) | interface UseMediaPlayerOptions {
type UseMediaPlayerReturn (line 61) | interface UseMediaPlayerReturn {
function getStoredVolume (line 75) | function getStoredVolume(): number {
function getStoredMuted (line 88) | function getStoredMuted(): boolean {
function getStoredPlaybackRate (line 96) | function getStoredPlaybackRate(): number {
function storeVolume (line 109) | function storeVolume(volume: number): void {
function storeMuted (line 115) | function storeMuted(muted: boolean): void {
function storePlaybackRate (line 121) | function storePlaybackRate(rate: number): void {
function useMediaPlayer (line 138) | function useMediaPlayer(options: UseMediaPlayerOptions = {}): UseMediaPl...
FILE: fluxer_app/src/components/media_player/hooks/useMediaProgress.tsx
type UseMediaProgressOptions (line 22) | interface UseMediaProgressOptions {
type UseMediaProgressReturn (line 29) | interface UseMediaProgressReturn {
function getBufferedPercentage (line 41) | function getBufferedPercentage(media: HTMLMediaElement): number {
function useMediaProgress (line 66) | function useMediaProgress(options: UseMediaProgressOptions): UseMediaPro...
FILE: fluxer_app/src/components/media_player/hooks/useMediaVolume.tsx
type UseMediaVolumeOptions (line 23) | interface UseMediaVolumeOptions {
type UseMediaVolumeReturn (line 32) | interface UseMediaVolumeReturn {
function getStoredVolume (line 43) | function getStoredVolume(): number {
function getStoredMuted (line 56) | function getStoredMuted(): boolean {
function storeVolume (line 64) | function storeVolume(volume: number): void {
function storeMuted (line 70) | function storeMuted(muted: boolean): void {
function useMediaVolume (line 76) | function useMediaVolume(options: UseMediaVolumeOptions): UseMediaVolumeR...
FILE: fluxer_app/src/components/media_player/utils/MediaConstants.tsx
constant AUDIO_PLAYBACK_RATES (line 20) | const AUDIO_PLAYBACK_RATES = [1, 1.5, 2, 0.75] as const;
constant DEFAULT_SEEK_AMOUNT (line 21) | const DEFAULT_SEEK_AMOUNT = 10;
constant DEFAULT_VOLUME (line 22) | const DEFAULT_VOLUME = 1;
constant PLAYBACK_RATES (line 23) | const PLAYBACK_RATES = [1, 1.5, 2, 0.75] as const;
constant VIDEO_PLAYBACK_RATES (line 24) | const VIDEO_PLAYBACK_RATES = [1, 1.5, 2, 0.75] as const;
constant VIDEO_BREAKPOINTS (line 25) | const VIDEO_BREAKPOINTS = {
constant VOLUME_STEP (line 31) | const VOLUME_STEP = 0.1;
constant SEEK_STEP (line 33) | const SEEK_STEP = 10;
constant VOLUME_STORAGE_KEY (line 35) | const VOLUME_STORAGE_KEY = 'fluxer:media_player:volume';
constant MUTE_STORAGE_KEY (line 37) | const MUTE_STORAGE_KEY = 'fluxer:media_player:muted';
constant PLAYBACK_RATE_STORAGE_KEY (line 39) | const PLAYBACK_RATE_STORAGE_KEY = 'fluxer:media_player:playback-rate';
FILE: fluxer_app/src/components/modals/AccountDeleteModal.tsx
type FormInputs (line 33) | interface FormInputs {
FILE: fluxer_app/src/components/modals/AccountDisableModal.tsx
type FormInputs (line 34) | interface FormInputs {
FILE: fluxer_app/src/components/modals/AddConnectionModal.tsx
constant COPY_RESET_DELAY_MS (line 40) | const COPY_RESET_DELAY_MS = 2000;
type CopyButtonProps (line 42) | interface CopyButtonProps {
type InitiateFormInputs (line 61) | interface InitiateFormInputs {
type VerifyFormInputs (line 65) | interface VerifyFormInputs {
type AddConnectionModalProps (line 69) | interface AddConnectionModalProps {
FILE: fluxer_app/src/components/modals/AddFavoriteChannelModal.tsx
type ChannelWithCategory (line 41) | interface ChannelWithCategory {
FILE: fluxer_app/src/components/modals/AddFavoriteMemeModal.tsx
type AddFavoriteMemeModalProps (line 32) | interface AddFavoriteMemeModalProps {
type FormInputs (line 41) | interface FormInputs {
FILE: fluxer_app/src/components/modals/AddFriendSheet.tsx
type AddFriendSheetProps (line 31) | interface AddFriendSheetProps {
FILE: fluxer_app/src/components/modals/AddFriendsToGroupModal.tsx
type AddFriendsToGroupModalProps (line 32) | interface AddFriendsToGroupModalProps {
FILE: fluxer_app/src/components/modals/AddGuildModal.tsx
type GuildCreateFormInputs (line 48) | interface GuildCreateFormInputs {
type GuildJoinFormInputs (line 53) | interface GuildJoinFormInputs {
type ModalFooterContextValue (line 57) | interface ModalFooterContextValue {
type AddGuildModalView (line 61) | type AddGuildModalView = 'landing' | 'create_guild' | 'join_guild';
FILE: fluxer_app/src/components/modals/AddGuildStickerModal.tsx
type AddGuildStickerModalProps (line 39) | interface AddGuildStickerModalProps {
type FormInputs (line 45) | interface FormInputs {
FILE: fluxer_app/src/components/modals/AssetCropModal.tsx
type AssetType (line 36) | type AssetType = ValueOf<typeof AssetType>;
type AssetConfig (line 38) | interface AssetConfig {
constant ASSET_CONFIGS (line 48) | const ASSET_CONFIGS: Record<AssetType, AssetConfig> = {
type AssetCropModalProps (line 224) | interface AssetCropModalProps {
FILE: fluxer_app/src/components/modals/AttachmentEditModal.tsx
type FormInputs (line 36) | interface FormInputs {
FILE: fluxer_app/src/components/modals/AudioPlaybackPermissionModal.tsx
type AudioPlaybackPermissionModalProps (line 24) | interface AudioPlaybackPermissionModalProps {
FILE: fluxer_app/src/components/modals/BackgroundImageGalleryModal.tsx
type BackgroundImage (line 56) | interface BackgroundImage {
type BuiltInBackground (line 61) | interface BuiltInBackground {
type BackgroundItemType (line 69) | type BackgroundItemType = BuiltInBackground | BackgroundImage;
constant MAX_FILE_SIZE (line 71) | const MAX_FILE_SIZE = 10 * 1024 * 1024;
constant ALLOWED_MIME_TYPES (line 72) | const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'ima...
type BackgroundItemProps (line 74) | interface BackgroundItemProps {
FILE: fluxer_app/src/components/modals/BackupCodesModal.tsx
type BackupCodesModalProps (line 33) | interface BackupCodesModalProps {
FILE: fluxer_app/src/components/modals/BackupCodesRegenerateModal.tsx
type FormInputs (line 35) | interface FormInputs {
type BackupCodesRegenerateModalProps (line 39) | interface BackupCodesRegenerateModalProps {
FILE: fluxer_app/src/components/modals/BackupCodesViewModal.tsx
type FormInputs (line 34) | interface FormInputs {
type BackupCodesViewModalProps (line 38) | interface BackupCodesViewModalProps {
FILE: fluxer_app/src/components/modals/BanDetailsModal.tsx
type BanDetailsModalProps (line 34) | interface BanDetailsModalProps {
FILE: fluxer_app/src/components/modals/BanMemberModal.tsx
type SelectOption (line 41) | interface SelectOption {
FILE: fluxer_app/src/components/modals/BaseChangeNicknameModal.tsx
type FormInputs (line 37) | interface FormInputs {
type BaseChangeNicknameModalProps (line 41) | interface BaseChangeNicknameModalProps {
FILE: fluxer_app/src/components/modals/BookmarksBottomSheet.tsx
type BookmarksBottomSheetProps (line 40) | interface BookmarksBottomSheetProps {
type MessageWithLongPressProps (line 154) | interface MessageWithLongPressProps {
FILE: fluxer_app/src/components/modals/CameraPreviewModal.tsx
type CameraPreviewModalProps (line 48) | interface CameraPreviewModalProps {
type VideoResolutionPreset (line 56) | interface VideoResolutionPreset {
constant TARGET_ASPECT_RATIO (line 62) | const TARGET_ASPECT_RATIO = 16 / 9;
constant ASPECT_RATIO_TOLERANCE (line 63) | const ASPECT_RATIO_TOLERANCE = 0.1;
constant RESOLUTION_WAIT_TIMEOUT (line 64) | const RESOLUTION_WAIT_TIMEOUT = 2000;
constant RESOLUTION_CHECK_INTERVAL (line 65) | const RESOLUTION_CHECK_INTERVAL = 100;
constant VIDEO_ELEMENT_WAIT_TIMEOUT (line 66) | const VIDEO_ELEMENT_WAIT_TIMEOUT = 5000;
constant VIDEO_ELEMENT_CHECK_INTERVAL (line 67) | const VIDEO_ELEMENT_CHECK_INTERVAL = 10;
constant CAMERA_RESOLUTION_PRESETS (line 69) | const CAMERA_RESOLUTION_PRESETS: Record<'low' | 'medium' | 'high', Video...
FILE: fluxer_app/src/components/modals/CaptchaModal.tsx
type CaptchaType (line 34) | type CaptchaType = 'turnstile' | 'hcaptcha';
type HCaptchaComponentProps (line 36) | interface HCaptchaComponentProps {
type CaptchaModalProps (line 47) | interface CaptchaModalProps {
FILE: fluxer_app/src/components/modals/CategoryCreateModal.tsx
type FormInputs (line 32) | interface FormInputs {
FILE: fluxer_app/src/components/modals/ChangeFriendNicknameModal.tsx
type ChangeFriendNicknameModalProps (line 28) | interface ChangeFriendNicknameModalProps {
FILE: fluxer_app/src/components/modals/ChangeGroupDMNicknameModal.tsx
type ChangeGroupDMNicknameModalProps (line 28) | interface ChangeGroupDMNicknameModalProps {
FILE: fluxer_app/src/components/modals/ChangeNicknameModal.tsx
type ChangeNicknameModalProps (line 29) | interface ChangeNicknameModalProps {
FILE: fluxer_app/src/components/modals/ClaimAccountModal.tsx
type FormInputs (line 38) | interface FormInputs {
type Stage (line 44) | type Stage = 'collect' | 'verify';
constant CLAIM_ACCOUNT_MODAL_KEY (line 234) | const CLAIM_ACCOUNT_MODAL_KEY = 'claim-account-modal';
FILE: fluxer_app/src/components/modals/ConfirmModal.tsx
type ConfirmModalCheckboxProps (line 33) | interface ConfirmModalCheckboxProps {
type ConfirmModalPrimaryVariant (line 38) | type ConfirmModalPrimaryVariant = 'primary' | 'danger-primary';
type ConfirmModalProps (line 40) | type ConfirmModalProps =
FILE: fluxer_app/src/components/modals/CreateFavoriteCategoryModal.tsx
type FormInputs (line 31) | interface FormInputs {
FILE: fluxer_app/src/components/modals/CreatePackModal.tsx
type FormInputs (line 33) | interface FormInputs {
type CreatePackModalProps (line 38) | interface CreatePackModalProps {
FILE: fluxer_app/src/components/modals/CustomStatusBottomSheet.tsx
constant CUSTOM_STATUS_SNAP_POINTS (line 49) | const CUSTOM_STATUS_SNAP_POINTS: Array<number> = [0, 1];
type ExpiryOption (line 51) | interface ExpiryOption {
type CustomStatusBottomSheetProps (line 57) | interface CustomStatusBottomSheetProps {
FILE: fluxer_app/src/components/modals/CustomStatusModal.tsx
constant MS_PER_MINUTE (line 58) | const MS_PER_MINUTE = 60 * 1000;
type TimeLabel (line 60) | interface TimeLabel {
type ExpirationPreset (line 65) | interface ExpirationPreset {
type ExpirationOption (line 71) | interface ExpirationOption {
constant DEFAULT_EXPIRATION_KEY (line 79) | const DEFAULT_EXPIRATION_KEY: TimeWindowKey = DEFAULT_TIME_WINDOW_KEY;
FILE: fluxer_app/src/components/modals/DeviceRevokeModal.tsx
type DeviceRevokeModalProps (line 32) | interface DeviceRevokeModalProps {
type FormInputs (line 36) | interface FormInputs {
FILE: fluxer_app/src/components/modals/DuplicateGroupConfirmModal.tsx
type DuplicateGroupConfirmModalProps (line 34) | interface DuplicateGroupConfirmModalProps {
FILE: fluxer_app/src/components/modals/EditAltTextModal.tsx
type FormInputs (line 40) | interface FormInputs {
type EditAltTextModalProps (line 44) | interface EditAltTextModalProps {
function handleKeyDown (line 108) | function handleKeyDown(event: KeyboardEvent) {
FILE: fluxer_app/src/components/modals/EditConnectionModal.tsx
type Props (line 31) | interface Props {
FILE: fluxer_app/src/components/modals/EditFavoriteMemeModal.tsx
type EditFavoriteMemeModalProps (line 34) | interface EditFavoriteMemeModalProps {
type FormInputs (line 38) | interface FormInputs {
FILE: fluxer_app/src/components/modals/EditGroupBottomSheet.tsx
type FormInputs (line 43) | interface FormInputs {
type EditGroupBottomSheetProps (line 48) | interface EditGroupBottomSheetProps {
FILE: fluxer_app/src/components/modals/EditGroupModal.tsx
type FormInputs (line 42) | interface FormInputs {
FILE: fluxer_app/src/components/modals/EditGuildStickerModal.tsx
type EditGuildStickerModalProps (line 40) | interface EditGuildStickerModalProps {
type FormInputs (line 46) | interface FormInputs {
FILE: fluxer_app/src/components/modals/EditPackModal.tsx
type FormInputs (line 34) | interface FormInputs {
type EditPackModalProps (line 39) | interface EditPackModalProps {
FILE: fluxer_app/src/components/modals/EmailChangeModal.tsx
type Stage (line 35) | type Stage = 'intro' | 'verifyOriginal' | 'newEmail' | 'verifyNew';
type NewEmailForm (line 37) | interface NewEmailForm {
type EmailChangeModalProps (line 41) | interface EmailChangeModalProps {
FILE: fluxer_app/src/components/modals/EmojiUploadModal.tsx
type EmojiUploadModalProps (line 27) | interface EmojiUploadModalProps {
FILE: fluxer_app/src/components/modals/ExpressionPickerSheet.tsx
type ExpressionPickerCategoryDescriptor (line 43) | interface ExpressionPickerCategoryDescriptor {
constant EXPRESSION_PICKER_CATEGORY_DESCRIPTORS (line 56) | const EXPRESSION_PICKER_CATEGORY_DESCRIPTORS: Array<ExpressionPickerCate...
type ExpressionPickerSheetProps (line 111) | interface ExpressionPickerSheetProps {
FILE: fluxer_app/src/components/modals/FluxerTagChangeModal.tsx
type FormInputs (line 46) | interface FormInputs {
type FluxerTagChangeModalProps (line 51) | interface FluxerTagChangeModalProps {
FILE: fluxer_app/src/components/modals/ForwardModal.tsx
type ForwardModalProps (line 70) | interface ForwardModalProps {
FILE: fluxer_app/src/components/modals/GiftAcceptModal.tsx
type GiftAcceptModalProps (line 40) | interface GiftAcceptModalProps {
FILE: fluxer_app/src/components/modals/GroupInvitesBottomSheet.tsx
type GroupInvitesBottomSheetProps (line 44) | interface GroupInvitesBottomSheetProps {
FILE: fluxer_app/src/components/modals/GuildDeleteModal.tsx
type FormInputs (line 32) | interface FormInputs {
FILE: fluxer_app/src/components/modals/GuildFolderSettingsModal.tsx
constant FOLDER_ICON_MAP (line 51) | const FOLDER_ICON_MAP: Record<GuildFolderIcon, ReactNode> = {
type GuildFolderSettingsModalProps (line 61) | interface GuildFolderSettingsModalProps {
function openGuildFolderSettingsModal (line 209) | function openGuildFolderSettingsModal(folderId: number): void {
FILE: fluxer_app/src/components/modals/GuildNotificationSettingsModal.tsx
type ChannelOption (line 41) | interface ChannelOption {
FILE: fluxer_app/src/components/modals/GuildOwnershipWarningModal.tsx
type GuildOwnershipWarningModalProps (line 29) | interface GuildOwnershipWarningModalProps {
FILE: fluxer_app/src/components/modals/GuildSettingsModal.tsx
type GuildSettingsModalProps (line 42) | interface GuildSettingsModalProps {
FILE: fluxer_app/src/components/modals/IARModal.tsx
type ViolationSelectOption (line 45) | interface ViolationSelectOption extends SelectOption<string> {
type IARContext (line 51) | type IARContext =
type IARModalProps (line 66) | interface IARModalProps {
FILE: fluxer_app/src/components/modals/ImageCropModal.tsx
type Point (line 37) | interface Point {
type Size (line 41) | interface Size {
type DragBoundaries (line 45) | interface DragBoundaries {
type AnimatedImageCropOptions (line 52) | interface AnimatedImageCropOptions {
function cropAnimatedImageWithWorker (line 62) | async function cropAnimatedImageWithWorker(
function clamp (line 70) | function clamp(value: number, min: number, max: number): number {
function inRange (line 76) | function inRange(value: number, start: number, end?: number): boolean {
function computeCropRect (line 89) | function computeCropRect(containerWidth: number, containerHeight: number...
function computeDragBoundaries (line 105) | function computeDragBoundaries(imageWidth: number, imageHeight: number, ...
function clampTransformToBounds (line 117) | function clampTransformToBounds(x: number, y: number, bounds: DragBounda...
function rotatePoint (line 124) | function rotatePoint({x, y}: Point, rotationDeg: number): Point {
function computeDestinationOffset (line 138) | function computeDestinationOffset(cropWidthNatural: number, cropHeightNa...
type ComputeCropGeometryInput (line 154) | interface ComputeCropGeometryInput {
type ComputeCropGeometryOutput (line 163) | interface ComputeCropGeometryOutput {
function computeCropGeometry (line 176) | function computeCropGeometry(input: ComputeCropGeometryInput): ComputeCr...
function containSize (line 227) | function containSize(srcW: number, srcH: number, boxW: number, boxH: num...
function exportStaticImage (line 237) | async function exportStaticImage(
function exportAnimatedImage (line 323) | async function exportAnimatedImage(
function snapCropOptionsToImageBounds (line 392) | function snapCropOptionsToImageBounds(options: AnimatedImageCropOptions,...
function hasEditsFrom (line 429) | function hasEditsFrom(zoomRatio: number, rotation: number, transform: Po...
type ImageCropModalProps (line 433) | interface ImageCropModalProps {
FILE: fluxer_app/src/components/modals/InputMonitoringCTAModal.tsx
type InputMonitoringCTAModalProps (line 32) | interface InputMonitoringCTAModalProps {
FILE: fluxer_app/src/components/modals/InviteAcceptModal.tsx
type InviteAcceptModalProps (line 46) | interface InviteAcceptModalProps {
FILE: fluxer_app/src/components/modals/InviteAcceptModalPreview.tsx
type InviteAcceptModalPreviewProps (line 34) | interface InviteAcceptModalPreviewProps {
FILE: fluxer_app/src/components/modals/InvitePagePreviewModal.tsx
type InvitePagePreviewModalProps (line 47) | interface InvitePagePreviewModalProps {
constant ALIGNMENT_MIN_WIDTH (line 56) | const ALIGNMENT_MIN_WIDTH = 1600;
FILE: fluxer_app/src/components/modals/KeyboardModeIntroModal.tsx
function KeyboardModeIntroModal (line 30) | function KeyboardModeIntroModal() {
FILE: fluxer_app/src/components/modals/MediaModal.tsx
type MediaModalProps (line 62) | interface MediaModalProps {
type MediaThumbnail (line 92) | interface MediaThumbnail {
type ControlButtonProps (line 98) | interface ControlButtonProps {
type FileInfoProps (line 142) | interface FileInfoProps {
type ControlsProps (line 204) | interface ControlsProps {
type CompactMobileControlsProps (line 338) | interface CompactMobileControlsProps {
type ZoomState (line 362) | type ZoomState = 'fit' | 'zoomed';
type DesktopMediaViewerProps (line 364) | interface DesktopMediaViewerProps {
type MobileMediaViewerProps (line 581) | interface MobileMediaViewerProps {
FILE: fluxer_app/src/components/modals/MediaViewerModal.tsx
type MobileMediaOptionsSheetProps (line 50) | interface MobileMediaOptionsSheetProps {
function getBaseProxyURL (line 59) | function getBaseProxyURL(src: string): string {
FILE: fluxer_app/src/components/modals/MessageHistoryThresholdModal.tsx
type MessageHistoryThresholdModalProps (line 42) | interface MessageHistoryThresholdModalProps {
FILE: fluxer_app/src/components/modals/MfaTotpDisableModal.tsx
type FormInputs (line 32) | interface FormInputs {
FILE: fluxer_app/src/components/modals/MfaTotpEnableModal.tsx
type FormInputs (line 39) | interface FormInputs {
type MfaTotpEnableModalProps (line 43) | interface MfaTotpEnableModalProps {
FILE: fluxer_app/src/components/modals/MobileVideoViewer.tsx
type MobileVideoViewerProps (line 31) | interface MobileVideoViewerProps {
function formatTime (line 39) | function formatTime(time: number): string {
FILE: fluxer_app/src/components/modals/Modal.tsx
type ContentProps (line 396) | type ContentProps = React.ComponentPropsWithoutRef<typeof Scroller> & {
type FooterProps (line 417) | interface FooterProps {
type InsetCloseButtonProps (line 447) | type InsetCloseButtonProps = Omit<React.ButtonHTMLAttributes<HTMLButtonE...
type ContentLayoutProps (line 474) | interface ContentLayoutProps {
type DescriptionProps (line 489) | interface DescriptionProps {
type InputGroupProps (line 504) | interface InputGroupProps {
type FormFooterProps (line 517) | interface FormFooterProps {
FILE: fluxer_app/src/components/modals/NoteEditSheet.tsx
type NoteEditSheetProps (line 31) | interface NoteEditSheetProps {
FILE: fluxer_app/src/components/modals/PackInviteModal.tsx
type PackInviteModalProps (line 35) | interface PackInviteModalProps {
FILE: fluxer_app/src/components/modals/PasskeyNameModal.tsx
type FormInputs (line 29) | interface FormInputs {
FILE: fluxer_app/src/components/modals/PasswordChangeModal.tsx
type Stage (line 34) | type Stage = 'intro' | 'verifyEmail' | 'changePassword';
type PasswordForm (line 36) | interface PasswordForm {
FILE: fluxer_app/src/components/modals/PhoneAddModal.tsx
type PhoneFormInputs (line 46) | interface PhoneFormInputs {
type CodeFormInputs (line 50) | interface CodeFormInputs {
type CountrySelectOption (line 54) | interface CountrySelectOption {
FILE: fluxer_app/src/components/modals/RemoveTimeoutModal.tsx
type RemoveTimeoutModalProps (line 35) | interface RemoveTimeoutModalProps {
FILE: fluxer_app/src/components/modals/RenameChannelModal.tsx
type FormInputs (line 31) | interface FormInputs {
FILE: fluxer_app/src/components/modals/RequiredActionModal.tsx
type PhoneFormInputs (line 58) | interface PhoneFormInputs {
type CodeFormInputs (line 61) | interface CodeFormInputs {
type BouncedEmailFormInputs (line 65) | interface BouncedEmailFormInputs {
type CountrySelectOption (line 69) | interface CountrySelectOption {
type VerificationMode (line 111) | type VerificationMode = 'email' | 'phone' | 'email_or_phone';
type PhoneVerificationStep (line 112) | type PhoneVerificationStep = 'phone' | 'code';
type VerificationTab (line 113) | interface VerificationTab {
FILE: fluxer_app/src/components/modals/ScheduleMessageModal.tsx
type ScheduleMessageModalProps (line 30) | interface ScheduleMessageModalProps {
FILE: fluxer_app/src/components/modals/ScreenShareSettingsModal.tsx
type ScreenShareSettingsModalProps (line 33) | interface ScreenShareSettingsModalProps {
FILE: fluxer_app/src/components/modals/ScreenShareSourceModal.tsx
type ScreenShareSourceModalProps (line 27) | interface ScreenShareSourceModalProps {
FILE: fluxer_app/src/components/modals/StatusChangeBottomSheet.tsx
constant STATUS_ORDER (line 49) | const STATUS_ORDER = [StatusTypes.ONLINE, StatusTypes.IDLE, StatusTypes....
constant STATUS_DESCRIPTIONS (line 51) | const STATUS_DESCRIPTIONS: Record<(typeof STATUS_ORDER)[number], React.R...
constant STATUS_EXPIRY_LABEL_MESSAGES (line 58) | const STATUS_EXPIRY_LABEL_MESSAGES: Record<TimeWindowKey, MessageDescrip...
type StatusExpiryOption (line 63) | interface StatusExpiryOption {
constant STATUS_SHEET_SNAP_POINTS (line 78) | const STATUS_SHEET_SNAP_POINTS: Array<number> = [0, 0.75, 1];
type StatusChangeBottomSheetProps (line 80) | interface StatusChangeBottomSheetProps {
type StatusItemProps (line 85) | interface StatusItemProps {
type CustomStatusSectionProps (line 154) | interface CustomStatusSectionProps {
FILE: fluxer_app/src/components/modals/SudoVerificationModal.tsx
type FormInputs (line 41) | interface FormInputs {
type SmsStatus (line 47) | enum SmsStatus {
FILE: fluxer_app/src/components/modals/ThemeAcceptModal.tsx
type ThemeAcceptModalProps (line 39) | interface ThemeAcceptModalProps {
FILE: fluxer_app/src/components/modals/TimeoutMemberModal.tsx
type SelectOption (line 44) | interface SelectOption<V extends string | number = number> {
type TimeoutMemberModalProps (line 49) | interface TimeoutMemberModalProps {
constant MAX_TIMEOUT_SECONDS (line 54) | const MAX_TIMEOUT_SECONDS = DAYS_PER_YEAR * SECONDS_PER_DAY;
type CustomDurationUnit (line 56) | type CustomDurationUnit = 'seconds' | 'minutes' | 'hours' | 'days';
constant CUSTOM_DURATION_MULTIPLIERS (line 58) | const CUSTOM_DURATION_MULTIPLIERS: Record<CustomDurationUnit, number> = {
FILE: fluxer_app/src/components/modals/TimeoutMemberOptions.tsx
type TimeoutDurationOption (line 23) | interface TimeoutDurationOption {
type TimeoutDurationOptionDescriptor (line 28) | interface TimeoutDurationOptionDescriptor {
constant TIMEOUT_DURATION_OPTIONS_DESCRIPTORS (line 33) | const TIMEOUT_DURATION_OPTIONS_DESCRIPTORS: ReadonlyArray<TimeoutDuratio...
FILE: fluxer_app/src/components/modals/TimeoutMemberSheet.tsx
type TimeoutMemberSheetProps (line 44) | interface TimeoutMemberSheetProps {
FILE: fluxer_app/src/components/modals/UploadDropModal.tsx
type UploadDropModalProps (line 27) | interface UploadDropModalProps {
FILE: fluxer_app/src/components/modals/UserProfileActionsSheet.tsx
type UserProfileActionsSheetProps (line 56) | interface UserProfileActionsSheetProps {
FILE: fluxer_app/src/components/modals/UserProfileMobileSheet.tsx
type UserProfileMobileSheetContentProps (line 220) | interface UserProfileMobileSheetContentProps {
type EmojiInfoState (line 230) | interface EmojiInfoState {
FILE: fluxer_app/src/components/modals/UserProfileModal.tsx
type UserProfileModalProps (line 125) | interface UserProfileModalProps {
type UserInfoProps (line 134) | interface UserInfoProps {
type UserNoteEditorProps (line 141) | interface UserNoteEditorProps {
type ProfileContentProps (line 148) | interface ProfileContentProps {
type UserProfileModalComponent (line 156) | type UserProfileModalComponent = React.FC<UserProfileModalProps>;
type ProfileModalContentProps (line 158) | interface ProfileModalCon
Copy disabled (too large)
Download .json
Condensed preview — 5720 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (71,107K chars).
[
{
"path": ".devcontainer/Caddyfile.dev",
"chars": 1073,
"preview": "# Like dev/Caddyfile.dev, but LiveKit and Mailpit are referenced by their\n# Docker Compose hostnames instead of 127.0.0."
},
{
"path": ".devcontainer/Dockerfile",
"chars": 1616,
"preview": "# Language runtimes (Node.js, Go, Rust, Python) are installed via devcontainer\n# features. This Dockerfile handles Erlan"
},
{
"path": ".devcontainer/devcontainer.json",
"chars": 1570,
"preview": "{\n\t\"name\": \"Fluxer\",\n\t\"dockerComposeFile\": \"docker-compose.yml\",\n\t\"service\": \"app\",\n\t\"workspaceFolder\": \"/workspace\",\n\n\t"
},
{
"path": ".devcontainer/docker-compose.yml",
"chars": 1527,
"preview": "services:\n app:\n build:\n context: .\n dockerfile: Dockerfile\n volumes:\n - ..:/workspace:cached\n "
},
{
"path": ".devcontainer/livekit.yaml",
"chars": 530,
"preview": "# Credentials here must match the values on-create.sh writes to config.json.\n\nport: 7880\n\nkeys:\n fluxer-devcontainer-ke"
},
{
"path": ".devcontainer/on-create.sh",
"chars": 2494,
"preview": "#!/usr/bin/env bash\n\n# Runs once when the container is first created.\n\nset -euo pipefail\n\nREPO_ROOT=\"$(cd \"$(dirname \"$0"
},
{
"path": ".devcontainer/process-compose.yml",
"chars": 1429,
"preview": "# Application processes only — backing services (Valkey, Meilisearch, LiveKit,\n# Mailpit, NATS) run via Docker Compose.\n"
},
{
"path": ".dockerignore",
"chars": 618,
"preview": "**/*.dump\n**/*.lock\n**/*.log\n**/*.swo\n**/*.swp\n**/*.tmp\n**/*~\n**/.cache\n**/.dev.vars\n**/.DS_Store\n**/.env\n**/.env.*.loca"
},
{
"path": ".editorconfig",
"chars": 280,
"preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nmax_line_l"
},
{
"path": ".envrc",
"chars": 58,
"preview": "#!/usr/bin/env bash\n\neval \"$(devenv direnvrc)\"\nuse devenv\n"
},
{
"path": ".gitattributes",
"chars": 12,
"preview": "* text=auto\n"
},
{
"path": ".github/DISCUSSION_TEMPLATE/ideas.yaml",
"chars": 1146,
"preview": "body:\n - type: markdown\n attributes:\n value: |\n Thanks for the suggestion.\n\n For larger changes, "
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 1655,
"preview": "name: Bug report\ndescription: Report a reproducible problem in Fluxer\nlabels: ['bug']\nbody:\n - type: markdown\n attri"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 333,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Feature requests\n url: https://github.com/orgs/fluxerapp/discuss"
},
{
"path": ".github/ISSUE_TEMPLATE/docs.yml",
"chars": 1272,
"preview": "name: Documentation\ndescription: Report a docs issue or suggest an improvement\nlabels: ['docs']\nbody:\n - type: markdown"
},
{
"path": ".github/pull_request_template.md",
"chars": 724,
"preview": "## Summary\n\n<!-- A few bullets is perfect: what changed, why it changed, and anything reviewers should pay attention to."
},
{
"path": ".github/workflows/build-desktop.yaml",
"chars": 13765,
"preview": "name: build desktop\n\non:\n workflow_dispatch:\n inputs:\n channel:\n description: Channel to build (stable o"
},
{
"path": ".github/workflows/channel-vars.yaml",
"chars": 1424,
"preview": "name: channel vars\n\non:\n workflow_call:\n inputs:\n github_event_name:\n type: string\n github_ref_name"
},
{
"path": ".github/workflows/ci.yaml",
"chars": 3648,
"preview": "name: CI\n\non:\n pull_request:\n types: [opened, reopened, synchronize]\n\njobs:\n typecheck:\n runs-on: blacksmith-8vc"
},
{
"path": ".github/workflows/deploy-admin.yaml",
"chars": 3937,
"preview": "name: deploy admin\n\non:\n push:\n branches:\n - main\n - canary\n paths:\n - fluxer_admin/**\n - .gi"
},
{
"path": ".github/workflows/deploy-api.yaml",
"chars": 4215,
"preview": "name: deploy api\n\non:\n push:\n branches:\n - main\n - canary\n paths:\n - fluxer_api/**\n - .github"
},
{
"path": ".github/workflows/deploy-app.yaml",
"chars": 6505,
"preview": "name: deploy app\n\non:\n push:\n branches:\n - main\n - canary\n paths:\n - fluxer_app/**\n - fluxer_"
},
{
"path": ".github/workflows/deploy-gateway.yaml",
"chars": 1588,
"preview": "name: deploy gateway\n\non:\n workflow_dispatch:\n inputs:\n ref:\n type: string\n required: false\n "
},
{
"path": ".github/workflows/deploy-marketing.yaml",
"chars": 4193,
"preview": "name: deploy marketing\n\non:\n push:\n branches:\n - main\n - canary\n paths:\n - fluxer_marketing/**\n "
},
{
"path": ".github/workflows/deploy-media-proxy.yaml",
"chars": 2805,
"preview": "name: deploy media-proxy\n\non:\n push:\n branches:\n - main\n paths:\n - fluxer_media_proxy/**\n - .githu"
},
{
"path": ".github/workflows/deploy-relay-directory.yaml",
"chars": 2788,
"preview": "name: deploy relay directory\n\non:\n push:\n branches:\n - canary\n paths:\n - fluxer_relay_directory/**\n "
},
{
"path": ".github/workflows/deploy-relay.yaml",
"chars": 1568,
"preview": "name: deploy relay\n\non:\n workflow_dispatch:\n inputs:\n ref:\n type: string\n required: false\n "
},
{
"path": ".github/workflows/deploy-static-proxy.yaml",
"chars": 2817,
"preview": "name: deploy static-proxy\n\non:\n push:\n branches:\n - main\n paths:\n - fluxer_media_proxy/**\n - .gith"
},
{
"path": ".github/workflows/migrate-cassandra.yaml",
"chars": 2094,
"preview": "name: migrate cassandra\n\non:\n push:\n branches:\n - canary\n paths:\n - fluxer_devops/cassandra/migrations/"
},
{
"path": ".github/workflows/promote-canary-to-main.yaml",
"chars": 1809,
"preview": "name: promote canary -> main\n\non:\n workflow_dispatch:\n inputs:\n dry_run:\n type: boolean\n default:"
},
{
"path": ".github/workflows/release-livekitctl.yaml",
"chars": 4274,
"preview": "name: release livekitctl\n\non:\n push:\n tags:\n - 'livekitctl-v*'\n workflow_dispatch:\n inputs:\n version:\n"
},
{
"path": ".github/workflows/release-relay-directory.yaml",
"chars": 9515,
"preview": "name: release relay directory\n\non:\n push:\n branches: [canary]\n paths:\n - fluxer_relay_directory/**\n - ."
},
{
"path": ".github/workflows/release-relay.yaml",
"chars": 9356,
"preview": "name: release relay\n\non:\n push:\n branches: [canary]\n paths:\n - fluxer_relay/**\n - .github/workflows/rel"
},
{
"path": ".github/workflows/release-server.yaml",
"chars": 10123,
"preview": "name: release server\n\non:\n push:\n branches: [canary]\n paths:\n - packages/**\n - fluxer_server/**\n -"
},
{
"path": ".github/workflows/restart-gateway.yaml",
"chars": 2555,
"preview": "name: restart gateway\n\non:\n workflow_dispatch:\n inputs:\n confirmation:\n description: this will cause ser"
},
{
"path": ".github/workflows/sync-desktop.yaml",
"chars": 2827,
"preview": "name: sync desktop\n\non:\n push:\n branches:\n - main\n - canary\n paths:\n - 'fluxer_desktop/**'\n workf"
},
{
"path": ".github/workflows/sync-static.yaml",
"chars": 1037,
"preview": "name: sync static-bucket\n\non:\n push:\n branches:\n - main\n paths:\n - 'fluxer_static/**'\n workflow_dispat"
},
{
"path": ".github/workflows/test-cassandra-backup.yaml",
"chars": 2618,
"preview": "name: test cassandra-backup\n\non:\n workflow_dispatch:\n schedule:\n - cron: '0 */2 * * *'\n\nconcurrency:\n group: test-"
},
{
"path": ".github/workflows/update-word-lists.yaml",
"chars": 1950,
"preview": "name: update word-lists\n\non:\n schedule:\n - cron: '0 3 1 * *'\n workflow_dispatch:\n\njobs:\n update-word-lists:\n ru"
},
{
"path": ".gitignore",
"chars": 1632,
"preview": "*.tsbuildinfo\n**/*.beam\n**/*.css.d.ts\n**/*.dump\n**/dump.rdb\n**/*.iml\n**/*.log\n**/*.o\n**/*.plt\n**/*.source\n**/*.swo\n**/*."
},
{
"path": ".gitmodules",
"chars": 97,
"preview": "[submodule \"fluxer_static\"]\n\tpath = fluxer_static\n\turl = https://github.com/fluxerapp/static.git\n"
},
{
"path": ".ignore",
"chars": 1035,
"preview": "!fluxer_app/scripts/build\n*.tsbuildinfo\n**/*.beam\n**/*.css.d.ts\n**/*.dump\n**/dump.rdb\n**/*.iml\n**/*.lock\n**/*.log\n**/*.o"
},
{
"path": ".npmrc",
"chars": 22,
"preview": "update-notifier=false\n"
},
{
"path": ".nvmrc",
"chars": 3,
"preview": "24\n"
},
{
"path": ".prettierignore",
"chars": 407,
"preview": "*.log\n**/*.css.d.ts\n**/.cache\n**/.pnpm-store\n**/.swc\n**/.turbo\n**/node_modules\n**/package-lock.json\n**/pnpm-lock.yaml\n.f"
},
{
"path": ".tool-versions",
"chars": 0,
"preview": ""
},
{
"path": ".vscode/extensions.json",
"chars": 181,
"preview": "{\n\t\"recommendations\": [\n\t\t\"TypeScriptTeam.native-preview\",\n\t\t\"biomejs.biome\",\n\t\t\"clinyong.vscode-css-modules\",\n\t\t\"pgourl"
},
{
"path": ".vscode/launch.json",
"chars": 2480,
"preview": "{\n\t\"version\": \"0.2.0\",\n\t\"configurations\": [\n\t\t{\n\t\t\t\"type\": \"node\",\n\t\t\t\"request\": \"launch\",\n\t\t\t\"name\": \"Debug: fluxer_ser"
},
{
"path": ".vscode/settings.json",
"chars": 151,
"preview": "{\n\t\"typescript.preferences.includePackageJsonAutoImports\": \"auto\",\n\t\"typescript.suggest.autoImports\": true,\n\t\"typescript"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5188,
"preview": "# Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our community"
},
{
"path": "CONTRIBUTING.md",
"chars": 6234,
"preview": "# Contributing to Fluxer\n\nThanks for contributing. This document explains how we work so your changes can land smoothly "
},
{
"path": "LICENSE",
"chars": 34523,
"preview": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C)"
},
{
"path": "LICENSING.md",
"chars": 3284,
"preview": "# Licensing\n\nFluxer is licensed under the **GNU Affero General Public License v3.0 (AGPLv3)**. See [`LICENSE`](./LICENSE"
},
{
"path": "README.md",
"chars": 9204,
"preview": "> [!CAUTION]\n> I'm repeating it again: Holy smokes, what a ride. Fluxer is taking off much earlier than I'd expected.\n>\n"
},
{
"path": "SECURITY.md",
"chars": 153,
"preview": "# Security Policy\n\nPlease **do not** report security vulnerabilities via public GitHub issues.\n\nReport security issues h"
},
{
"path": "biome.json",
"chars": 3469,
"preview": "{\n\t\"$schema\": \"./node_modules/@biomejs/biome/configuration_schema.json\",\n\t\"formatter\": {\n\t\t\"enabled\": true,\n\t\t\"formatWit"
},
{
"path": "compose.yaml",
"chars": 3064,
"preview": "x-logging: &default-logging\n driver: json-file\n options:\n max-size: '10m'\n max-file: '5'\n\nservices:\n valkey:\n "
},
{
"path": "config/config.dev.template.json",
"chars": 2104,
"preview": "{\n\t\"$schema\": \"../packages/config/src/ConfigSchema.json\",\n\t\"env\": \"development\",\n\t\"domain\": {\n\t\t\"base_domain\": \"localhos"
},
{
"path": "config/config.production.template.json",
"chars": 1532,
"preview": "{\n\t\"$schema\": \"../packages/config/src/ConfigSchema.json\",\n\t\"env\": \"production\",\n\t\"domain\": {\n\t\t\"base_domain\": \"chat.exam"
},
{
"path": "config/config.schema.json",
"chars": 116,
"preview": "{\n\t\"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n\t\"$ref\": \"../packages/config/src/ConfigSchema.json\"\n}\n"
},
{
"path": "config/config.test.json",
"chars": 1788,
"preview": "{\n\t\"env\": \"test\",\n\t\"instance\": {\n\t\t\"self_hosted\": false\n\t},\n\t\"domain\": {\n\t\t\"base_domain\": \"localhost\"\n\t},\n\t\"database\": {"
},
{
"path": "config/livekit.example.yaml",
"chars": 209,
"preview": "port: 7880\n\nkeys:\n '<replace-with-api-key>': '<replace-with-api-secret>'\n\nrtc:\n tcp_port: 7881\n\nturn:\n enabled: true\n"
},
{
"path": "dev/Caddyfile.dev",
"chars": 954,
"preview": "{\n\tauto_https off\n\tadmin off\n}\n\n:48763 {\n\thandle /_caddy_health {\n\t\trespond \"OK\" 200\n\t}\n\n\t@gateway path /gateway /gatewa"
},
{
"path": "dev/livekit.template.yaml",
"chars": 397,
"preview": "port: 7880\n\nkeys:\n '{{API_KEY}}': '{{API_SECRET}}'\n\nrtc:\n tcp_port: 7881\n port_range_start: 50000\n port_range_end: 5"
},
{
"path": "devenv.nix",
"chars": 8265,
"preview": "{ pkgs, config, lib, ... }:\n{\n\timports = lib.optional (builtins.pathExists ./devenv.local.nix) ./devenv.local.nix;\n\n\tenv"
},
{
"path": "devenv.yaml",
"chars": 265,
"preview": "# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json\ninputs:\n devenv:\n url: github:cachix/devenv/v1."
},
{
"path": "fluxer_admin/Dockerfile",
"chars": 2459,
"preview": "ARG BUILD_SHA\nARG BUILD_NUMBER\nARG BUILD_TIMESTAMP\nARG RELEASE_CHANNEL=nightly\n\nFROM node:24-bookworm-slim AS base\n\nWORK"
},
{
"path": "fluxer_admin/package.json",
"chars": 750,
"preview": "{\n\t\"name\": \"fluxer_admin\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"build:css\": \"pnpm --filter @fluxer/admi"
},
{
"path": "fluxer_admin/public/static/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "fluxer_admin/src/Config.tsx",
"chars": 1905,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_admin/src/Instrument.tsx",
"chars": 996,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_admin/src/Logger.tsx",
"chars": 909,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_admin/src/index.tsx",
"chars": 1758,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_admin/tsconfig.json",
"chars": 213,
"preview": "{\n\t\"extends\": \"../tsconfigs/hono-service.json\",\n\t\"compilerOptions\": {\n\t\t\"paths\": {\n\t\t\t\"@app/*\": [\"./src/*\"],\n\t\t\t\"@fluxer"
},
{
"path": "fluxer_api/Dockerfile",
"chars": 2427,
"preview": "ARG BUILD_SHA\nARG BUILD_NUMBER\nARG BUILD_TIMESTAMP\nARG RELEASE_CHANNEL=nightly\n\nFROM node:24-bookworm-slim AS base\n\nWORK"
},
{
"path": "fluxer_api/package.json",
"chars": 690,
"preview": "{\n\t\"name\": \"fluxer_api\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"dev\": \"tsx watch --clear-screen=false src"
},
{
"path": "fluxer_api/scripts/CassandraMigrate.tsx",
"chars": 18025,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/scripts/Dockerfile.cassandra-migrate",
"chars": 381,
"preview": "FROM node:24-bookworm-slim\n\nWORKDIR /app\n\nRUN corepack enable && corepack prepare pnpm@10.26.0 --activate\n\nRUN echo '{\"t"
},
{
"path": "fluxer_api/scripts/LicenseEnforcer.tsx",
"chars": 11184,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/App.tsx",
"chars": 2197,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/AppEntrypoint.tsx",
"chars": 781,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/Config.tsx",
"chars": 1397,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/Instrument.tsx",
"chars": 1160,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/Logger.tsx",
"chars": 907,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/src/WorkerEntrypoint.tsx",
"chars": 1189,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_api/tsconfig.json",
"chars": 229,
"preview": "{\n\t\"extends\": \"../tsconfigs/hono-service.json\",\n\t\"compilerOptions\": {\n\t\t\"paths\": {\n\t\t\t\"@app/*\": [\"./src/*\"],\n\t\t\t\"@fluxer"
},
{
"path": "fluxer_api/tsconfig.worker.json",
"chars": 144,
"preview": "{\n\t\"extends\": \"./tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"noEmit\": false\n\t},\n\t\"i"
},
{
"path": "fluxer_app/crates/libfluxcore/Cargo.toml",
"chars": 421,
"preview": "[package]\nname = \"libfluxcore\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\ngif = \""
},
{
"path": "fluxer_app/crates/libfluxcore/src/animation.rs",
"chars": 4254,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/crates/libfluxcore/src/apng.rs",
"chars": 12384,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/crates/libfluxcore/src/gateway.rs",
"chars": 1250,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/crates/libfluxcore/src/gif.rs",
"chars": 16648,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/crates/libfluxcore/src/lib.rs",
"chars": 1015,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/crates/libfluxcore/src/static_image.rs",
"chars": 3375,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/index.html",
"chars": 1898,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Fluxer</title>\n<meta name=\"viewport\" content=\"widt"
},
{
"path": "fluxer_app/lingui.config.js",
"chars": 1273,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/package.json",
"chars": 5276,
"preview": "{\n\t\"name\": \"fluxer_app\",\n\t\"version\": \"0.0.0\",\n\t\"private\": true,\n\t\"description\": \"Fluxer is a free and open source instan"
},
{
"path": "fluxer_app/postcss.config.js",
"chars": 1253,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/rspack.config.mjs",
"chars": 19082,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/rust-toolchain.toml",
"chars": 31,
"preview": "[toolchain]\nchannel = \"1.93.0\"\n"
},
{
"path": "fluxer_app/scripts/DevServer.tsx",
"chars": 9330,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/GenerateAvatarMasks.tsx",
"chars": 22156,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/GenerateColorSystem.tsx",
"chars": 30019,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/GenerateEmojiSprites.tsx",
"chars": 8412,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/auto-i18n.mjs",
"chars": 2666,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/Config.tsx",
"chars": 1905,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/rspack/externals.mjs",
"chars": 1522,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/rspack/lingui.mjs",
"chars": 1343,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/rspack/po-loader.mjs",
"chars": 4376,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/rspack/static-files.mjs",
"chars": 3448,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/rspack/wasm.mjs",
"chars": 1684,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/tsconfig.json",
"chars": 580,
"preview": "{\n\t\"$schema\": \"https://json.schemastore.org/tsconfig\",\n\t\"compilerOptions\": {\n\t\t\"target\": \"ES2023\",\n\t\t\"module\": \"ESNext\","
},
{
"path": "fluxer_app/scripts/build/types.d.ts",
"chars": 2854,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/Assets.tsx",
"chars": 2368,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/CssDts.tsx",
"chars": 3902,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/Html.tsx",
"chars": 3243,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/Resolve.tsx",
"chars": 1420,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/ServiceWorker.tsx",
"chars": 1224,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build/utils/Sourcemaps.tsx",
"chars": 2336,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/build-sw.mjs",
"chars": 991,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/scripts/translate-i18n.mjs",
"chars": 10744,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/App.module.css",
"chars": 1569,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/App.tsx",
"chars": 16750,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/AppConstants.tsx",
"chars": 2822,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/Config.tsx",
"chars": 2336,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/Endpoints.tsx",
"chars": 14240,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/I18n.tsx",
"chars": 7884,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/Router.tsx",
"chars": 1305,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/Routes.tsx",
"chars": 3621,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/AccessibilityActionCreators.tsx",
"chars": 953,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/AuthSessionActionCreators.tsx",
"chars": 2290,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/AuthenticationActionCreators.tsx",
"chars": 17387,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/CallActionCreators.tsx",
"chars": 6904,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ChannelActionCreators.tsx",
"chars": 4789,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ChannelPinsActionCreators.tsx",
"chars": 5250,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ChannelStickerActionCreators.tsx",
"chars": 1150,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ConnectionActionCreators.tsx",
"chars": 6316,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ContextMenuActionCreators.tsx",
"chars": 5547,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/DeveloperOptionsActionCreators.tsx",
"chars": 3266,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/DimensionActionCreators.tsx",
"chars": 1528,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/DiscoveryActionCreators.tsx",
"chars": 2300,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/DraftActionCreators.tsx",
"chars": 1192,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/EmojiActionCreators.tsx",
"chars": 1009,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/EmojiPickerActionCreators.tsx",
"chars": 1344,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ExpressionPickerActionCreators.tsx",
"chars": 1680,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/FavoriteMemeActionCreators.tsx",
"chars": 4680,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/FavoritesActionCreators.tsx",
"chars": 1873,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GifActionCreators.tsx",
"chars": 4804,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GiftActionCreators.tsx",
"chars": 6888,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GuildActionCreators.tsx",
"chars": 14456,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GuildEmojiActionCreators.tsx",
"chars": 3143,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GuildMemberActionCreators.tsx",
"chars": 3854,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GuildNSFWActionCreators.tsx",
"chars": 1013,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/GuildStickerActionCreators.tsx",
"chars": 2949,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/HighlightActionCreators.tsx",
"chars": 1005,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/IARActionCreators.tsx",
"chars": 2511,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/InboxActionCreators.tsx",
"chars": 913,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/InviteActionCreators.tsx",
"chars": 14803,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/KlipyActionCreators.tsx",
"chars": 3922,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/LayoutActionCreators.tsx",
"chars": 1275,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/MediaViewerActionCreators.tsx",
"chars": 1354,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/MessageActionCreators.tsx",
"chars": 19933,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/MfaActionCreators.tsx",
"chars": 2507,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ModalActionCreators.tsx",
"chars": 4038,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ModalRender.tsx",
"chars": 821,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/NagbarActionCreators.tsx",
"chars": 1606,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/NavigationActionCreators.tsx",
"chars": 2970,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/NotificationActionCreators.tsx",
"chars": 2155,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/OAuth2AuthorizationActionCreators.tsx",
"chars": 1714,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PackActionCreators.tsx",
"chars": 3014,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PackInviteActionCreators.tsx",
"chars": 1670,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PiPActionCreators.tsx",
"chars": 1193,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PopoutActionCreators.tsx",
"chars": 1064,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PremiumActionCreators.tsx",
"chars": 3408,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PremiumModalActionCreators.tsx",
"chars": 1474,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/PrivateChannelActionCreators.tsx",
"chars": 3709,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/QuickSwitcherActionCreators.tsx",
"chars": 5096,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ReactionActionCreators.tsx",
"chars": 9676,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ReadStateActionCreators.tsx",
"chars": 5025,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/RecentMentionActionCreators.tsx",
"chars": 3602,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/RelationshipActionCreators.tsx",
"chars": 2479,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/SavedMessageActionCreators.tsx",
"chars": 3598,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ScheduledMessageActionCreators.tsx",
"chars": 13929,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/SlowmodeActionCreators.tsx",
"chars": 1184,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/SoundActionCreators.tsx",
"chars": 1192,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/StickerPickerActionCreators.tsx",
"chars": 1357,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/TextCopyActionCreators.tsx",
"chars": 2589,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ThemeActionCreators.tsx",
"chars": 1940,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ThemePreferenceActionCreators.tsx",
"chars": 1496,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/ToastActionCreators.tsx",
"chars": 1203,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/TrustedDomainActionCreators.tsx",
"chars": 1718,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/TypingActionCreators.tsx",
"chars": 1750,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UnsavedChangesActionCreators.tsx",
"chars": 1336,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UserActionCreators.tsx",
"chars": 17948,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UserGuildSettingsActionCreators.tsx",
"chars": 8213,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UserNoteActionCreators.tsx",
"chars": 1246,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UserProfileActionCreators.tsx",
"chars": 4991,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/UserSettingsActionCreators.tsx",
"chars": 995,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/VoiceCallLayoutActionCreators.tsx",
"chars": 1255,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
},
{
"path": "fluxer_app/src/actions/VoiceSettingsActionCreators.tsx",
"chars": 1978,
"preview": "/*\n * Copyright (C) 2026 Fluxer Contributors\n *\n * This file is part of Fluxer.\n *\n * Fluxer is free software: you can r"
}
]
// ... and 5520 more files (download for full content)
About this extraction
This page contains the full source code of the fluxerapp/fluxer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5720 files (79.8 MB), approximately 16.9M tokens, and a symbol index with 23025 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.