gitextract_2f1tk_0x/ ├── .codex/ │ └── skills/ │ ├── screen2navkey/ │ │ └── SKILL.md │ └── voyager2nav3/ │ └── SKILL.md ├── .editorconfig ├── .github/ │ ├── FUNDING.yml │ ├── ci-gradle.properties │ └── workflows/ │ ├── build_apk.yml │ └── check.yml ├── .gitignore ├── Agents.md ├── LICENSE ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ ├── FreadAndroidApplication.kt │ │ └── screen/ │ │ └── FreadActivity.kt │ └── res/ │ ├── drawable/ │ │ ├── ic_launcher_foreground.xml │ │ └── shape_alert_dialog_background.xml │ ├── mipmap-anydpi-v26/ │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ ├── values/ │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── values-zh/ │ └── strings.xml ├── app-hosting/ │ ├── build.gradle.kts │ └── src/ │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ ├── HostingApplication.kt │ │ ├── composable/ │ │ │ └── LoadingPage.android.kt │ │ ├── di/ │ │ │ ├── HostingModule.android.kt │ │ │ └── PlatformedFreadApplication.android.kt │ │ ├── screen/ │ │ │ └── DeviceCornerRadius.android.kt │ │ └── utils/ │ │ └── ActivityHelper.android.kt │ ├── commonMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ ├── CommonNavEntryProvider.kt │ │ ├── auth/ │ │ │ └── AuthenticationPage.kt │ │ ├── composable/ │ │ │ └── LoadingPage.kt │ │ ├── di/ │ │ │ ├── FreadApplication.kt │ │ │ └── HostingModule.kt │ │ ├── screen/ │ │ │ ├── DeviceCornerRadius.kt │ │ │ ├── FreadApp.kt │ │ │ ├── FreadScreen.kt │ │ │ ├── NavDisplayTransitions.kt │ │ │ ├── PredictiveBackEntryDecorator.kt │ │ │ └── main/ │ │ │ ├── MainPageUiState.kt │ │ │ ├── MainViewModel.kt │ │ │ └── drawer/ │ │ │ ├── MainDrawer.kt │ │ │ ├── MainDrawerUiState.kt │ │ │ └── MainDrawerViewModel.kt │ │ └── utils/ │ │ └── ActivityHelper.kt │ └── iosMain/ │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ ├── di/ │ │ ├── HostingModule.ios.kt │ │ └── PlatformedFreadApplication.ios.kt │ ├── screen/ │ │ ├── DeviceCornerRadius.ios.kt │ │ ├── FreadViewController.kt │ │ └── IosFreadApp.kt │ ├── startup/ │ │ └── KRouterStartup.kt │ └── utils/ │ └── ActivityHelper.ios.kt ├── appprivacy.html ├── bizframework/ │ └── status-provider/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── status/ │ │ ├── richtext/ │ │ │ └── RichTextBuilder.android.kt │ │ └── utils/ │ │ └── ImplementerFinder.kt │ ├── commonMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── status/ │ │ ├── StatusProvider.kt │ │ ├── StatusProviderModel.kt │ │ ├── account/ │ │ │ ├── AccountManager.kt │ │ │ ├── AuthenticationFailureException.kt │ │ │ └── LoggedAccount.kt │ │ ├── author/ │ │ │ └── BlogAuthor.kt │ │ ├── blog/ │ │ │ ├── Blog.kt │ │ │ ├── BlogEmbed.kt │ │ │ ├── BlogMedia.kt │ │ │ ├── BlogMediaMeta.kt │ │ │ ├── BlogMediaType.kt │ │ │ ├── BlogPoll.kt │ │ │ ├── BlogServer.kt │ │ │ ├── BlogTranslation.kt │ │ │ ├── CurrentUserQuoteApproval.kt │ │ │ └── PostingApplication.kt │ │ ├── content/ │ │ │ ├── ContentManager.kt │ │ │ └── MixedContent.kt │ │ ├── model/ │ │ │ ├── BlogFiltered.kt │ │ │ ├── ContentConfig.kt │ │ │ ├── ContentType.kt │ │ │ ├── Emoji.kt │ │ │ ├── FacetFeatureUnion.kt │ │ │ ├── FormattingTime.kt │ │ │ ├── FreadContent.kt │ │ │ ├── Hashtag.kt │ │ │ ├── HashtagInStatus.kt │ │ │ ├── LoggedAccountDetail.kt │ │ │ ├── Mention.kt │ │ │ ├── PagedData.kt │ │ │ ├── PlatformLocator.kt │ │ │ ├── PostInteractionSetting.kt │ │ │ ├── PublishBlogRules.kt │ │ │ ├── QuoteApprovalPolicy.kt │ │ │ ├── Relationships.kt │ │ │ ├── StatusActionType.kt │ │ │ ├── StatusList.kt │ │ │ ├── StatusProviderProtocol.kt │ │ │ ├── StatusUiState.kt │ │ │ └── StatusVisibility.kt │ │ ├── notification/ │ │ │ ├── NotificationResolver.kt │ │ │ └── StatusNotification.kt │ │ ├── platform/ │ │ │ ├── BlogPlatform.kt │ │ │ ├── PlatformResolver.kt │ │ │ └── PlatformSnapshot.kt │ │ ├── publish/ │ │ │ ├── PublishBlogManager.kt │ │ │ └── PublishingPost.kt │ │ ├── richtext/ │ │ │ ├── OnLinkTargetClick.kt │ │ │ ├── RichText.kt │ │ │ ├── RichTextBuilder.kt │ │ │ ├── model/ │ │ │ │ └── RichLinkTarget.kt │ │ │ └── parser/ │ │ │ ├── HtmlParser.kt │ │ │ └── PlaintextParser.kt │ │ ├── screen/ │ │ │ └── StatusScreenProvider.kt │ │ ├── search/ │ │ │ ├── SearchContentResult.kt │ │ │ ├── SearchEngine.kt │ │ │ └── SearchResult.kt │ │ ├── source/ │ │ │ ├── StatusSource.kt │ │ │ └── StatusSourceResolver.kt │ │ ├── status/ │ │ │ ├── StatusResolver.kt │ │ │ └── model/ │ │ │ ├── Status.kt │ │ │ └── StatusContext.kt │ │ ├── uri/ │ │ │ ├── FormalUri.kt │ │ │ └── FormalUriParser.kt │ │ └── utils/ │ │ ├── DateTimeFormatter.kt │ │ └── ResultKtx.kt │ └── commonTest/ │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ └── status/ │ ├── richtext/ │ │ └── parser/ │ │ └── HtmlParserTest.kt │ └── uri/ │ └── FormalUriTest.kt ├── build-logic/ │ ├── README.md │ ├── convention/ │ │ ├── build.gradle.kts │ │ └── src/ │ │ └── main/ │ │ └── kotlin/ │ │ ├── AndroidApplicationConventionPlugin.kt │ │ ├── AndroidLibraryConventionPlugin.kt │ │ ├── ComposeMultiPlatformConventionPlugin.kt │ │ ├── KotlinMultiplatformLibraryConventionPlugin.kt │ │ ├── Project.kt │ │ ├── ProjectFeatureKmpConventionPlugin.kt │ │ ├── ProjectFrameworkKmpConventionPlugin.kt │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ ├── KotlinAndroid.kt │ │ ├── PrintTestApks.kt │ │ └── ProjectExt.kt │ ├── gradle.properties │ └── settings.gradle.kts ├── build.gradle.kts ├── commonbiz/ │ ├── analytics/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── commonMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── analytics/ │ │ ├── Analytics.kt │ │ ├── EventNames.kt │ │ └── TrackingEventDataBuilder.kt │ ├── common/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ └── src/ │ │ ├── androidMain/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin/ │ │ │ │ └── com/ │ │ │ │ └── zhangke/ │ │ │ │ └── fread/ │ │ │ │ └── common/ │ │ │ │ ├── AndroidCommonModule.kt │ │ │ │ ├── browser/ │ │ │ │ │ ├── AndroidSystemBrowserLauncher.kt │ │ │ │ │ └── OAuthLauncher.android.kt │ │ │ │ ├── daynight/ │ │ │ │ │ └── DayNightPlatformHelper.android.kt │ │ │ │ ├── di/ │ │ │ │ │ └── ApplicationContext.kt │ │ │ │ ├── handler/ │ │ │ │ │ └── TextHandler.android.kt │ │ │ │ ├── language/ │ │ │ │ │ ├── ActivityLanguageHelper.android.kt │ │ │ │ │ └── LanguageHelper.android.kt │ │ │ │ ├── page/ │ │ │ │ │ └── BasePagerTabHookManager.android.kt │ │ │ │ ├── startup/ │ │ │ │ │ └── LanguageModuleStartup.kt │ │ │ │ ├── update/ │ │ │ │ │ └── AppPlatformUpdater.android.kt │ │ │ │ └── utils/ │ │ │ │ ├── ActivityResultUtils.kt │ │ │ │ ├── MediaFileHelper.android.kt │ │ │ │ ├── PlatformUriHelper.android.kt │ │ │ │ ├── RandomIdGenerator.android.kt │ │ │ │ ├── ShareHelper.kt │ │ │ │ ├── StorageHelper.android.kt │ │ │ │ └── ToastHelper.android.kt │ │ │ └── res/ │ │ │ ├── anim/ │ │ │ │ ├── fade_in.xml │ │ │ │ └── fade_out.xml │ │ │ ├── drawable/ │ │ │ │ └── ic_logo_skeleton.xml │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ └── theme.xml │ │ ├── commonMain/ │ │ │ ├── composeResources/ │ │ │ │ └── drawable/ │ │ │ │ ├── bluesky_logo.xml │ │ │ │ ├── ic_explorer.xml │ │ │ │ ├── ic_not_found_404.xml │ │ │ │ ├── mastodon_black_text.xml │ │ │ │ ├── mastodon_logo.xml │ │ │ │ └── mastodon_white_text.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── common/ │ │ │ ├── CommonModule.kt │ │ │ ├── CommonNavEntryProvider.kt │ │ │ ├── CommonStartup.kt │ │ │ ├── MixedContentJsonBuilder.kt │ │ │ ├── account/ │ │ │ │ └── ActiveAccountsSynchronizer.kt │ │ │ ├── action/ │ │ │ │ ├── ComposableActions.kt │ │ │ │ ├── RouteAction.kt │ │ │ │ └── RouteActions.kt │ │ │ ├── adapter/ │ │ │ │ └── StatusUiStateAdapter.kt │ │ │ ├── browser/ │ │ │ │ ├── BrowserInterceptor.kt │ │ │ │ ├── BrowserLauncher.kt │ │ │ │ ├── OAuthHandler.kt │ │ │ │ ├── SystemBrowserLauncher.kt │ │ │ │ └── UrlRedirectScreen.kt │ │ │ ├── bubble/ │ │ │ │ ├── Bubble.kt │ │ │ │ └── BubbleManager.kt │ │ │ ├── composable/ │ │ │ │ ├── EmptyContent.kt │ │ │ │ ├── ErrorContent.kt │ │ │ │ └── SelectableAccount.kt │ │ │ ├── config/ │ │ │ │ ├── AppCommonConfig.kt │ │ │ │ ├── FreadConfigManager.kt │ │ │ │ ├── LocalConfigManager.kt │ │ │ │ ├── StatusConfig.kt │ │ │ │ ├── StatusContentSize.kt │ │ │ │ └── TimelineDefaultPosition.kt │ │ │ ├── content/ │ │ │ │ ├── FreadContentDbMigrateManager.kt │ │ │ │ └── FreadContentRepo.kt │ │ │ ├── daynight/ │ │ │ │ ├── DayNightHelper.kt │ │ │ │ └── DayNightMode.kt │ │ │ ├── db/ │ │ │ │ ├── ContentConfigDatabases.kt │ │ │ │ ├── FreadContentDatabase.kt │ │ │ │ ├── MixedStatusDatabases.kt │ │ │ │ ├── converts/ │ │ │ │ │ ├── BlogMediaConverterHelper.kt │ │ │ │ │ ├── BlogMediaListConverter.kt │ │ │ │ │ ├── BlogPollConverter.kt │ │ │ │ │ ├── ContentTabConverter.kt │ │ │ │ │ ├── ContentTypeConverter.kt │ │ │ │ │ ├── FormalBaseUrlConverter.kt │ │ │ │ │ ├── FormalUriConverter.kt │ │ │ │ │ ├── FreadContentConverter.kt │ │ │ │ │ ├── PlatformLocatorConverter.kt │ │ │ │ │ ├── StatusConverter.kt │ │ │ │ │ ├── StatusNotificationConverter.kt │ │ │ │ │ ├── StatusProviderUriListConverter.kt │ │ │ │ │ └── StatusUiStateConverter.kt │ │ │ │ └── old/ │ │ │ │ └── OldFreadContentDatabase.kt │ │ │ ├── deeplink/ │ │ │ │ ├── ExternalInputHandler.kt │ │ │ │ ├── ExternalInputParser.kt │ │ │ │ ├── SelectAccountScreen.kt │ │ │ │ └── SelectedContentSwitcher.kt │ │ │ ├── di/ │ │ │ │ └── ApplicationCoroutineScope.kt │ │ │ ├── feeds/ │ │ │ │ └── model/ │ │ │ │ └── RefreshResult.kt │ │ │ ├── handler/ │ │ │ │ └── TextHandler.kt │ │ │ ├── language/ │ │ │ │ ├── LanguageHelper.kt │ │ │ │ └── LanguageSettingItem.kt │ │ │ ├── mixed/ │ │ │ │ └── MixedStatusRepo.kt │ │ │ ├── onboarding/ │ │ │ │ └── OnboardingComponent.kt │ │ │ ├── page/ │ │ │ │ └── BasePagerTabHookManager.kt │ │ │ ├── publish/ │ │ │ │ └── PublishPostManager.kt │ │ │ ├── push/ │ │ │ │ └── IPushManager.kt │ │ │ ├── repo/ │ │ │ │ └── LinkPreviewCardRepo.kt │ │ │ ├── resources/ │ │ │ │ └── ProtocolsSymbol.kt │ │ │ ├── review/ │ │ │ │ ├── DefaultAppStoreReviewer.kt │ │ │ │ └── FreadReviewManager.kt │ │ │ ├── startup/ │ │ │ │ ├── FeedsRepoModuleStartup.kt │ │ │ │ ├── FreadConfigModuleStartup.kt │ │ │ │ └── StartupManager.kt │ │ │ ├── status/ │ │ │ │ ├── StatusConfiguration.kt │ │ │ │ ├── StatusIdGenerator.kt │ │ │ │ ├── StatusUpdater.kt │ │ │ │ ├── adapter/ │ │ │ │ │ └── ContentConfigAdapter.kt │ │ │ │ ├── model/ │ │ │ │ │ └── SearchResultUiState.kt │ │ │ │ └── usecase/ │ │ │ │ └── FormatStatusDisplayTimeUseCase.kt │ │ │ ├── theme/ │ │ │ │ └── ThemeType.kt │ │ │ ├── update/ │ │ │ │ ├── AppPlatformUpdater.kt │ │ │ │ ├── AppReleaseInfo.kt │ │ │ │ └── AppUpdateManager.kt │ │ │ └── utils/ │ │ │ ├── GlobalScreenNavigation.kt │ │ │ ├── HashtagTextUtils.kt │ │ │ ├── InstantExt.kt │ │ │ ├── LinkTextUtils.kt │ │ │ ├── ListStringConverter.kt │ │ │ ├── MediaFileHelper.kt │ │ │ ├── MentionTextUtil.kt │ │ │ ├── PlatformUriHelper.kt │ │ │ ├── RandomIdGenerator.kt │ │ │ ├── StorageHelper.kt │ │ │ ├── ToastHelper.kt │ │ │ └── WebFingerConverter.kt │ │ ├── commonTest/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── common/ │ │ │ ├── status/ │ │ │ │ └── utils/ │ │ │ │ └── createStatus.kt │ │ │ └── utils/ │ │ │ ├── DateTimeFormatterTest.kt │ │ │ ├── FormalUriTest.kt │ │ │ └── HashtagTextUtilsTest.kt │ │ └── iosMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── common/ │ │ ├── CommonIosModule.kt │ │ ├── browser/ │ │ │ ├── IosSystemBrowserLauncher.kt │ │ │ └── OAuthLauncher.ios.kt │ │ ├── daynight/ │ │ │ └── DayNightPlatformHelper.ios.kt │ │ ├── handler/ │ │ │ └── TextHandler.ios.kt │ │ ├── language/ │ │ │ └── LanguageHelper.ios.kt │ │ ├── page/ │ │ │ └── BasePagerTabHookManager.ios.kt │ │ ├── update/ │ │ │ └── AppPlatformUpdater.ios.kt │ │ └── utils/ │ │ ├── MediaFileHelper.ios.kt │ │ ├── PlatformUriHelper.ios.kt │ │ ├── RandomIdGenerator.ios.kt │ │ ├── StorageHelper.ios.kt │ │ ├── SystemUtils.kt │ │ └── ToastHelper.ios.kt │ ├── sharedscreen/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── commonbiz/ │ │ │ └── shared/ │ │ │ ├── SharedScreenAndroidEntryProvider.kt │ │ │ ├── SharedScreenAndroidModule.kt │ │ │ ├── composable/ │ │ │ │ └── WebViewPreviewer.android.kt │ │ │ └── screen/ │ │ │ └── ImageViewerScreen.android.kt │ │ ├── commonMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── commonbiz/ │ │ │ └── shared/ │ │ │ ├── ModuleScreenVisitor.kt │ │ │ ├── SharedScreenModule.kt │ │ │ ├── SharedScreenNavEntryProvider.kt │ │ │ ├── blog/ │ │ │ │ └── detail/ │ │ │ │ ├── RssBlogDetailScreen.kt │ │ │ │ └── RssBlogDetailViewModel.kt │ │ │ ├── composable/ │ │ │ │ ├── BlogUi.kt │ │ │ │ ├── FeedsContent.kt │ │ │ │ ├── FeedsStatusNode.kt │ │ │ │ ├── ObserveForFeedsConnection.kt │ │ │ │ ├── OnBlogMediaClick.kt │ │ │ │ ├── SearchResultUi.kt │ │ │ │ ├── UserInfoCard.kt │ │ │ │ └── WebViewPreviewer.kt │ │ │ ├── db/ │ │ │ │ └── SelectedAccountPublishingDatabase.kt │ │ │ ├── feeds/ │ │ │ │ ├── CommonFeedsUiState.kt │ │ │ │ ├── FeedsViewModelController.kt │ │ │ │ ├── IFeedsViewModelController.kt │ │ │ │ ├── IInteractiveHandler.kt │ │ │ │ ├── InteractiveHandleResult.kt │ │ │ │ └── InteractiveHandler.kt │ │ │ ├── notification/ │ │ │ │ ├── FollowNotification.kt │ │ │ │ ├── FollowRequestNotification.kt │ │ │ │ ├── NotificationHeadLine.kt │ │ │ │ ├── NotificationWithWholeStatus.kt │ │ │ │ ├── SeveredRelationshipsNotification.kt │ │ │ │ ├── StatusNotificationUi.kt │ │ │ │ └── UnknownNotification.kt │ │ │ ├── repo/ │ │ │ │ └── SelectedAccountPublishingRepo.kt │ │ │ ├── screen/ │ │ │ │ ├── ImageViewerScreen.kt │ │ │ │ ├── SelectLanguageScreen.kt │ │ │ │ ├── publish/ │ │ │ │ │ ├── PublishBlogScreen.kt │ │ │ │ │ ├── PublishBlogUiState.kt │ │ │ │ │ ├── PublishPostBottomPanel.kt │ │ │ │ │ ├── PublishPostMediaAttachment.kt │ │ │ │ │ ├── PublishPostScaffold.kt │ │ │ │ │ ├── PublishSettingLabel.kt │ │ │ │ │ ├── PublishTopBar.kt │ │ │ │ │ ├── composable/ │ │ │ │ │ │ ├── AvatarsHorizontalStack.kt │ │ │ │ │ │ ├── BlogMediaAttachment.kt │ │ │ │ │ │ ├── InputBlogTextField.kt │ │ │ │ │ │ ├── PostInteractionSettingLabel.kt │ │ │ │ │ │ ├── PostStatusVisibilityUi.kt │ │ │ │ │ │ └── PostStatusWarning.kt │ │ │ │ │ ├── model/ │ │ │ │ │ │ └── PublishBlogMediaAttachment.kt │ │ │ │ │ └── multi/ │ │ │ │ │ ├── MultiAccountPublishingScreen.kt │ │ │ │ │ ├── MultiAccountPublishingUiState.kt │ │ │ │ │ ├── MultiAccountPublishingViewModel.kt │ │ │ │ │ └── PublishingAccounts.kt │ │ │ │ ├── search/ │ │ │ │ │ ├── AbstractSearchStatusScreen.kt │ │ │ │ │ ├── AbstractSearchStatusViewModel.kt │ │ │ │ │ └── SearchStatusUiState.kt │ │ │ │ ├── status/ │ │ │ │ │ ├── account/ │ │ │ │ │ │ ├── SelectAccountOpenStatusScreen.kt │ │ │ │ │ │ ├── SelectAccountOpenStatusUiState.kt │ │ │ │ │ │ └── SelectAccountOpenStatusViewModel.kt │ │ │ │ │ └── context/ │ │ │ │ │ ├── StatusContextScreen.kt │ │ │ │ │ ├── StatusContextSubViewModel.kt │ │ │ │ │ ├── StatusContextUiState.kt │ │ │ │ │ └── StatusContextViewModel.kt │ │ │ │ └── video/ │ │ │ │ └── FullVideoScreen.kt │ │ │ ├── usecase/ │ │ │ │ ├── PublishPostOnMultiAccountUseCase.kt │ │ │ │ ├── RefactorToNewBlogUseCase.kt │ │ │ │ └── RefactorToNewStatusUseCase.kt │ │ │ └── utils/ │ │ │ └── LoadableStatusController.kt │ │ └── iosMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── commonbiz/ │ │ └── shared/ │ │ ├── SharedScreenIosModule.kt │ │ ├── composable/ │ │ │ └── WebViewPreviewer.ios.kt │ │ └── screen/ │ │ └── ImageViewerScreen.ios.kt │ └── status-ui/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── status/ │ │ └── ui/ │ │ ├── StatusPlaceHolder.preview.kt │ │ ├── common/ │ │ │ └── FormattingTimeText.kt │ │ ├── poll/ │ │ │ └── BlogPollOption.preview.kt │ │ ├── utils/ │ │ │ └── ScreenSize.android.kt │ │ └── video/ │ │ ├── BlogVideos.kt │ │ ├── LocalInlineVideoPlayer.kt │ │ └── inline/ │ │ └── InlineVideo.kt │ ├── commonMain/ │ │ ├── composeResources/ │ │ │ └── drawable/ │ │ │ ├── ic_drag_indicator.xml │ │ │ ├── ic_format_quote.xml │ │ │ ├── ic_format_quote_in_left.xml │ │ │ ├── ic_mode_edit.xml │ │ │ ├── ic_more.xml │ │ │ ├── ic_post_status_spoiler.xml │ │ │ ├── ic_share.xml │ │ │ ├── ic_status_comment.xml │ │ │ ├── ic_status_forward.xml │ │ │ ├── img_banner_background.xml │ │ │ └── status_ui_baseline_visibility_off_24.xml │ │ └── kotlin/ │ │ ├── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── status/ │ │ │ └── ui/ │ │ │ ├── BlogAuthorAvatar.kt │ │ │ ├── BlogAuthorUi.kt │ │ │ ├── BlogContent.kt │ │ │ ├── BlogDivider.kt │ │ │ ├── BlogUi.kt │ │ │ ├── ComposedStatusInteraction.kt │ │ │ ├── StatusInfoLine.kt │ │ │ ├── StatusPlaceHolder.kt │ │ │ ├── StatusUi.kt │ │ │ ├── action/ │ │ │ │ ├── ModalDropdownMenuItem.kt │ │ │ │ ├── StatusActions.kt │ │ │ │ ├── StatusBottomInteractionPanel.kt │ │ │ │ ├── StatusIconButton.kt │ │ │ │ ├── StatusInteractiveExts.kt │ │ │ │ └── StatusMoreInteractionPanel.kt │ │ │ ├── bar/ │ │ │ │ └── EditContentTopBar.kt │ │ │ ├── common/ │ │ │ │ ├── BlogTranslaction.kt │ │ │ │ ├── ContentToolbar.kt │ │ │ │ ├── DetailHeaderContent.kt │ │ │ │ ├── DetailPageScaffold.kt │ │ │ │ ├── DetailTopBar.kt │ │ │ │ ├── HomeContentTabsTopBar.kt │ │ │ │ ├── LinkPreviewCard.kt │ │ │ │ ├── NestedTabConnection.kt │ │ │ │ ├── NewStatusNotifyBar.kt │ │ │ │ ├── ObserveMaxReadItem.kt │ │ │ │ ├── ObserveScrollStopedPosition.kt │ │ │ │ ├── PostStatusTextVisualTransformation.kt │ │ │ │ ├── ProgressedAvatar.kt │ │ │ │ ├── ProgressedBanner.kt │ │ │ │ ├── PublishingFab.kt │ │ │ │ ├── RelationshipStateButton.kt │ │ │ │ ├── RemainingTextStatus.kt │ │ │ │ ├── SelectAccountDialog.kt │ │ │ │ ├── StatusSharedElementConfig.kt │ │ │ │ └── UserFollowLine.kt │ │ │ ├── embed/ │ │ │ │ ├── BlogEmbedsUi.kt │ │ │ │ ├── BlogInEmbedding.kt │ │ │ │ ├── StatusEmbedLinkUi.kt │ │ │ │ └── UnavailableQuoteInEmbedding.kt │ │ │ ├── hashtag/ │ │ │ │ └── HashtagUi.kt │ │ │ ├── image/ │ │ │ │ ├── BlogImageMedia.kt │ │ │ │ ├── DoubleBlogImageLayout.kt │ │ │ │ ├── FivefoldImageMediaFrameLayout.kt │ │ │ │ ├── HorizontalImageMediaFrameLayout.kt │ │ │ │ ├── HorizontalImageMediaListLayout.kt │ │ │ │ ├── QuadrupleImageMediaLayout.kt │ │ │ │ ├── SingleBlogImageLayout.kt │ │ │ │ ├── SixfoldImageMediaLayout.kt │ │ │ │ ├── TripleImageMediaLayout.kt │ │ │ │ ├── VerticalImageMediaFrameLayout.kt │ │ │ │ └── VerticalImageMediaListLayout.kt │ │ │ ├── label/ │ │ │ │ ├── StatusBottomEditedLabel.kt │ │ │ │ ├── StatusBottomInteractionLabel.kt │ │ │ │ ├── StatusBottomTimeLabel.kt │ │ │ │ └── StatusTopLabel.kt │ │ │ ├── media/ │ │ │ │ └── BlogMedias.kt │ │ │ ├── placeholder/ │ │ │ │ └── ListWithAvatarPlaceholder.kt │ │ │ ├── poll/ │ │ │ │ ├── BlogPoll.kt │ │ │ │ ├── BlogPollOption.kt │ │ │ │ ├── MultipleChoicePoll.kt │ │ │ │ └── SingleChoicePoll.kt │ │ │ ├── publish/ │ │ │ │ ├── BlogInQuoting.kt │ │ │ │ ├── NameAndAccountInfo.kt │ │ │ │ └── PublishBlogStyle.kt │ │ │ ├── richtext/ │ │ │ │ ├── FreadRichText.kt │ │ │ │ └── RichTextWithIcon.kt │ │ │ ├── source/ │ │ │ │ ├── BlogPlatformUi.kt │ │ │ │ ├── SearchPlatformResultUi.kt │ │ │ │ ├── SourceCommonUi.kt │ │ │ │ └── StatusSourceUi.kt │ │ │ ├── style/ │ │ │ │ ├── LocalStatusStyle.kt │ │ │ │ ├── StatusInfoStyle.kt │ │ │ │ ├── StatusStyle.kt │ │ │ │ └── StatusUiConfig.kt │ │ │ ├── threads/ │ │ │ │ ├── Threads.kt │ │ │ │ └── ThreadsType.kt │ │ │ ├── update/ │ │ │ │ └── AppUpdateDialog.kt │ │ │ ├── user/ │ │ │ │ ├── CommonUserUi.kt │ │ │ │ └── UserHandleLine.kt │ │ │ ├── utils/ │ │ │ │ ├── CardInfoSection.kt │ │ │ │ └── ScreenSize.kt │ │ │ └── video/ │ │ │ ├── BlogVideos.kt │ │ │ ├── VideoDurationFormatter.kt │ │ │ └── full/ │ │ │ └── FullScreenVideoPlayer.kt │ │ └── org/ │ │ └── burnoutcrew/ │ │ └── reorderable/ │ │ ├── DetectReorder.kt │ │ ├── DragCancelledAnimation.kt │ │ ├── DragGesture.kt │ │ ├── ItemPosition.kt │ │ ├── Reorderable.kt │ │ ├── ReorderableItem.kt │ │ ├── ReorderableLazyGridState.kt │ │ ├── ReorderableLazyListState.kt │ │ └── ReorderableState.kt │ └── iosMain/ │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ └── status/ │ └── ui/ │ ├── utils/ │ │ └── ScreenSize.ios.kt │ └── video/ │ └── BlogVideos.ios.kt ├── deleteuserdata.html ├── di-dependencis.md ├── documents/ │ ├── UserSource.drawio │ └── architecture.xmind ├── fastlane/ │ ├── Fastfile │ └── metadata/ │ └── android/ │ ├── en-US/ │ │ ├── full_description.txt │ │ └── short_description.txt │ └── zh-CN/ │ ├── full_description.txt │ └── short_description.txt ├── feature/ │ ├── explore/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── commonMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── explore/ │ │ ├── ExploreNavEntryProvider.kt │ │ ├── ExplorerElements.kt │ │ ├── di/ │ │ │ └── ExploreModule.kt │ │ ├── model/ │ │ │ └── ExplorerItem.kt │ │ ├── screens/ │ │ │ ├── home/ │ │ │ │ ├── ExploreTab.kt │ │ │ │ ├── ExplorerHomeUiState.kt │ │ │ │ ├── ExplorerHomeViewModel.kt │ │ │ │ └── ExplorerScreen.kt │ │ │ └── search/ │ │ │ ├── SearchScreen.kt │ │ │ ├── SearchUiState.kt │ │ │ ├── SearchViewModel.kt │ │ │ ├── author/ │ │ │ │ ├── SearchAuthorViewModel.kt │ │ │ │ └── SearchedAuthorTab.kt │ │ │ ├── bar/ │ │ │ │ ├── ExplorerSearchBar.kt │ │ │ │ ├── SearchBarUiState.kt │ │ │ │ └── SearchBarViewModel.kt │ │ │ ├── hashtag/ │ │ │ │ ├── SearchHashtagViewModel.kt │ │ │ │ └── SearchedHashtagTab.kt │ │ │ ├── platform/ │ │ │ │ ├── SearchPlatformViewModel.kt │ │ │ │ ├── SearchedPlatformTab.kt │ │ │ │ └── SearchedPlatformUiState.kt │ │ │ └── status/ │ │ │ ├── SearchStatusViewModel.kt │ │ │ └── SearchedStatusTab.kt │ │ └── usecase/ │ │ └── BuildSearchResultUiStateUseCase.kt │ ├── feeds/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── feeds/ │ │ │ └── pages/ │ │ │ └── manager/ │ │ │ └── importing/ │ │ │ └── OpenDocumentContainer.android.kt │ │ ├── commonMain/ │ │ │ ├── composeResources/ │ │ │ │ └── drawable/ │ │ │ │ ├── ic_home.xml │ │ │ │ └── ic_import.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── feeds/ │ │ │ ├── FeedsNavEntryProvider.kt │ │ │ ├── FeedsScreenVisitor.kt │ │ │ ├── composable/ │ │ │ │ └── StatusSource.kt │ │ │ ├── di/ │ │ │ │ └── FeedsModule.kt │ │ │ └── pages/ │ │ │ ├── home/ │ │ │ │ ├── ContentHomeUiState.kt │ │ │ │ ├── ContentHomeViewModel.kt │ │ │ │ ├── FeedsContentHomeTab.kt │ │ │ │ ├── FeedsHomeTab.kt │ │ │ │ └── feeds/ │ │ │ │ ├── MixedContentSubViewModel.kt │ │ │ │ ├── MixedContentTab.kt │ │ │ │ ├── MixedContentUiState.kt │ │ │ │ └── MixedContentViewModel.kt │ │ │ └── manager/ │ │ │ ├── add/ │ │ │ │ ├── mixed/ │ │ │ │ │ ├── AddMixedFeedsScreen.kt │ │ │ │ │ ├── AddMixedFeedsUiState.kt │ │ │ │ │ └── AddMixedFeedsViewModel.kt │ │ │ │ └── type/ │ │ │ │ ├── SelectContentTypeScreen.kt │ │ │ │ └── SelectContentTypeViewModel.kt │ │ │ ├── edit/ │ │ │ │ ├── EditMixedContentScreen.kt │ │ │ │ ├── EditMixedContentUiState.kt │ │ │ │ └── EditMixedContentViewModel.kt │ │ │ ├── importing/ │ │ │ │ ├── ImportFeedsScreen.kt │ │ │ │ ├── ImportFeedsUiState.kt │ │ │ │ ├── ImportFeedsViewModel.kt │ │ │ │ └── OpenDocumentContainer.kt │ │ │ └── search/ │ │ │ ├── SearchForAddUiState.kt │ │ │ ├── SearchSourceForAddScreen.kt │ │ │ └── SearchSourceForAddViewModel.kt │ │ └── iosMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── feeds/ │ │ └── pages/ │ │ └── manager/ │ │ └── importing/ │ │ └── OpenDocumentContainer.ios.kt │ ├── notifications/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── feature/ │ │ │ └── message/ │ │ │ └── di/ │ │ │ └── NotificationsAndroidModule.kt │ │ ├── commonMain/ │ │ │ ├── composeResources/ │ │ │ │ └── drawable/ │ │ │ │ └── ic_notification_tab.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── feature/ │ │ │ └── message/ │ │ │ ├── NotificationElements.kt │ │ │ ├── NotificationsNavEntryProvider.kt │ │ │ ├── di/ │ │ │ │ └── NotificationsModule.kt │ │ │ ├── repo/ │ │ │ │ └── notification/ │ │ │ │ ├── NotificationsDatabase.kt │ │ │ │ └── NotificationsRepo.kt │ │ │ └── screens/ │ │ │ ├── home/ │ │ │ │ ├── NotificationScreen.kt │ │ │ │ ├── NotificationsHomeUiState.kt │ │ │ │ ├── NotificationsHomeViewModel.kt │ │ │ │ └── NotificationsTab.kt │ │ │ └── notification/ │ │ │ ├── NotificationContainerViewModel.kt │ │ │ ├── NotificationTab.kt │ │ │ ├── NotificationUiState.kt │ │ │ └── NotificationViewModel.kt │ │ └── iosMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── feature/ │ │ └── message/ │ │ └── di/ │ │ └── NotificationsIosModule.kt │ └── profile/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ └── commonMain/ │ ├── composeResources/ │ │ └── drawable/ │ │ ├── ic_code.xml │ │ ├── ic_github_logo.xml │ │ ├── ic_profile_tab.xml │ │ ├── ic_ratting.xml │ │ ├── ic_telegram.xml │ │ └── kofi_symbol.xml │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ └── profile/ │ ├── ProfileNavEntryProvider.kt │ ├── ProfileScreenVisitor.kt │ ├── di/ │ │ └── ProfileModule.kt │ └── screen/ │ ├── donate/ │ │ └── DonateScreen.kt │ ├── home/ │ │ ├── ProfileHomeUiState.kt │ │ ├── ProfileHomeViewModel.kt │ │ ├── ProfileScreen.kt │ │ └── ProfileTab.kt │ ├── opensource/ │ │ └── OpenSourceScreen.kt │ └── setting/ │ ├── FeedbackBottomSheet.kt │ ├── SettingComponents.kt │ ├── SettingItemNames.kt │ ├── SettingScreen.kt │ ├── SettingScreenModel.kt │ ├── SettingUiState.kt │ ├── about/ │ │ ├── AboutScreen.kt │ │ ├── AboutUiState.kt │ │ └── AboutViewModel.kt │ ├── appearance/ │ │ ├── AppearanceSettingsScreen.kt │ │ ├── AppearanceSettingsUiState.kt │ │ └── AppearanceSettingsViewModel.kt │ └── behavior/ │ ├── BehaviorSettingsScreen.kt │ ├── BehaviorSettingsUiState.kt │ └── BehaviorSettingsViewModel.kt ├── framework/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ ├── androidInstrumentedTest/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── framework/ │ │ ├── ExampleInstrumentedTest.kt │ │ └── utils/ │ │ └── UtiUtilsTest.kt │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── framework/ │ │ ├── activity/ │ │ │ └── TopActivityManager.kt │ │ ├── architect/ │ │ │ ├── http/ │ │ │ │ ├── GlobalOkHttpClient.kt │ │ │ │ └── HttpClientEngine.android.kt │ │ │ └── theme/ │ │ │ └── FreadTheme.android.kt │ │ ├── blurhash/ │ │ │ └── BitmapExt.android.kt │ │ ├── composable/ │ │ │ ├── AnimatableExt.kt │ │ │ ├── Loading.android.kt │ │ │ ├── TextString.android.kt │ │ │ └── pick/ │ │ │ └── PickVisualMediaLauncherContainer.android.kt │ │ ├── date/ │ │ │ └── InstantFormater.android.kt │ │ ├── datetime/ │ │ │ └── Instant.android.kt │ │ ├── ktx/ │ │ │ └── SingletonDelegate.kt │ │ ├── media/ │ │ │ └── MediaFileUtil.kt │ │ ├── permission/ │ │ │ ├── PermissionUtils.kt │ │ │ ├── RequireLocalStoragePermission.android.kt │ │ │ └── RequirePermission.kt │ │ ├── serialize/ │ │ │ └── DateSerializer.kt │ │ ├── toast/ │ │ │ └── Toast.android.kt │ │ └── utils/ │ │ ├── ActivityLifecycleCallbacksAdapter.kt │ │ ├── ActivityResultContractsExt.kt │ │ ├── BitmapUtils.kt │ │ ├── ContextUtils.kt │ │ ├── DensityUtils.android.kt │ │ ├── DrawableExt.kt │ │ ├── DrawableWrapper.kt │ │ ├── ExoPlayerUtils.kt │ │ ├── FileUtils.kt │ │ ├── IDNUtils.android.kt │ │ ├── ImageCompressUtils.android.kt │ │ ├── ImageLoaderUtils.kt │ │ ├── LanguageUtils.android.kt │ │ ├── PlatformIgnoredOnParcel.android.kt │ │ ├── PlatformParcelable.android.kt │ │ ├── PlatformTransient.android.kt │ │ ├── PlatformUri.android.kt │ │ ├── Serializable.android.kt │ │ ├── SignatureUtils.kt │ │ ├── SystemPageUtils.kt │ │ ├── SystemUtils.kt │ │ ├── UriUtils.android.kt │ │ └── VideoUtils.android.kt │ ├── androidUnitTest/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── framework/ │ │ ├── ExampleUnitTest.kt │ │ ├── RegexFactoryTest.kt │ │ ├── date/ │ │ │ └── DateParserTest.kt │ │ ├── feeds/ │ │ │ └── fetcher/ │ │ │ ├── FeedsFetcherTest.kt │ │ │ └── FeedsGeneratorTest.kt │ │ └── utils/ │ │ ├── RegexFactoryTest.kt │ │ ├── StorageSizeTest.kt │ │ └── WebFingerTest.kt │ ├── commonMain/ │ │ ├── kotlin/ │ │ │ └── com/ │ │ │ ├── sd/ │ │ │ │ └── lib/ │ │ │ │ └── compose/ │ │ │ │ └── wheel_picker/ │ │ │ │ ├── WheelPicker.kt │ │ │ │ ├── WheelPickerDefault.kt │ │ │ │ └── WheelPickerState.kt │ │ │ └── zhangke/ │ │ │ └── framework/ │ │ │ ├── architect/ │ │ │ │ ├── coroutines/ │ │ │ │ │ ├── ApplicationScope.kt │ │ │ │ │ └── Flows.kt │ │ │ │ ├── http/ │ │ │ │ │ └── HttpClientEngine.kt │ │ │ │ ├── json/ │ │ │ │ │ ├── Json.kt │ │ │ │ │ └── JsonModuleBuilder.kt │ │ │ │ └── theme/ │ │ │ │ ├── Color.kt │ │ │ │ └── FreadTheme.kt │ │ │ ├── blur/ │ │ │ │ ├── BlurController.kt │ │ │ │ └── LocalEnableBlurAppBarStyle.kt │ │ │ ├── blurhash/ │ │ │ │ ├── BitmapExt.kt │ │ │ │ ├── BlurHashDecoder.kt │ │ │ │ └── BlurHashModifier.kt │ │ │ ├── collections/ │ │ │ │ └── Collections.kt │ │ │ ├── composable/ │ │ │ │ ├── AlertConfirmDialog.kt │ │ │ │ ├── AvatarStatck.kt │ │ │ │ ├── BackHandler.kt │ │ │ │ ├── BezierCurve.kt │ │ │ │ ├── BottomSheetState.kt │ │ │ │ ├── Bounds.kt │ │ │ │ ├── CollapsableTopBarScrollConnection.kt │ │ │ │ ├── CompositionLocal.kt │ │ │ │ ├── DatePickerDialog.kt │ │ │ │ ├── DirectionalLazyListState.kt │ │ │ │ ├── DpSaver.kt │ │ │ │ ├── DurationSelector.kt │ │ │ │ ├── FlowUtils.android.kt │ │ │ │ ├── FlowUtils.kt │ │ │ │ ├── FreadDialog.kt │ │ │ │ ├── FreadTabRow.kt │ │ │ │ ├── Grid.kt │ │ │ │ ├── HorizontalPageIndicator.kt │ │ │ │ ├── IconButton.kt │ │ │ │ ├── InsetAwareSearchBar.kt │ │ │ │ ├── Keyboard.kt │ │ │ │ ├── LazyListStateUtils.kt │ │ │ │ ├── LoadableLayout.kt │ │ │ │ ├── Loading.kt │ │ │ │ ├── LoadingDialog.kt │ │ │ │ ├── LocalContentPadding.kt │ │ │ │ ├── LocalSnackMessage.kt │ │ │ │ ├── NavigationBar.kt │ │ │ │ ├── NestedScrollConnection.kt │ │ │ │ ├── NoDoubleClick.kt │ │ │ │ ├── NoRippleClick.kt │ │ │ │ ├── Offset.kt │ │ │ │ ├── PaddingValuesUtils.kt │ │ │ │ ├── Placeholder.kt │ │ │ │ ├── PopupFloatingActionButton.kt │ │ │ │ ├── PopupMenu.kt │ │ │ │ ├── PredictiveBackProgressState.kt │ │ │ │ ├── ScreenUtils.kt │ │ │ │ ├── ScrollTopAppBar.kt │ │ │ │ ├── SearchToolbar.kt │ │ │ │ ├── Size.kt │ │ │ │ ├── SlickRoundCornerShape.kt │ │ │ │ ├── Snackbar.kt │ │ │ │ ├── StateSaver.kt │ │ │ │ ├── StyledIconButton.kt │ │ │ │ ├── StyledTextButton.kt │ │ │ │ ├── SystemUi.kt │ │ │ │ ├── TabIndicator.kt │ │ │ │ ├── TabsTopAppBar.kt │ │ │ │ ├── TextString.kt │ │ │ │ ├── TextWithIcon.kt │ │ │ │ ├── Toolbar.kt │ │ │ │ ├── TopAppBar.kt │ │ │ │ ├── TopBarWithTabLayout.kt │ │ │ │ ├── TwoTextsInRow.kt │ │ │ │ ├── VelocityExt.kt │ │ │ │ ├── VerticalIndentLayout.kt │ │ │ │ ├── collapsable/ │ │ │ │ │ ├── CollapsableTopBarLayout.kt │ │ │ │ │ ├── CollapsableTopBarLayoutConnection.kt │ │ │ │ │ └── ScrollUpTopBarLayout.kt │ │ │ │ ├── icons/ │ │ │ │ │ └── Toufu.kt │ │ │ │ ├── image/ │ │ │ │ │ └── viewer/ │ │ │ │ │ ├── ImageViewer.kt │ │ │ │ │ ├── ImageViewerState.kt │ │ │ │ │ └── TransformGestureDetector.kt │ │ │ │ ├── infinite/ │ │ │ │ │ ├── InfiniteBox.kt │ │ │ │ │ └── InfinityBoxState.kt │ │ │ │ ├── inline/ │ │ │ │ │ ├── InlineVideoLazyColumn.kt │ │ │ │ │ └── PlayableIndexRecorderLocal.kt │ │ │ │ ├── pick/ │ │ │ │ │ └── PickVisualMediaLauncherContainer.kt │ │ │ │ ├── sensitive/ │ │ │ │ │ ├── SensitiveLazyColumn.kt │ │ │ │ │ └── SensitiveLazyColumnState.kt │ │ │ │ ├── topout/ │ │ │ │ │ ├── TopOutTopBarLayout.kt │ │ │ │ │ └── TopOutTopBarLayoutConnection.kt │ │ │ │ └── video/ │ │ │ │ └── VideoPlayer.kt │ │ │ ├── controller/ │ │ │ │ ├── CommonLoadableController.kt │ │ │ │ └── LoadableController.kt │ │ │ ├── coroutines/ │ │ │ │ └── JobExt.kt │ │ │ ├── date/ │ │ │ │ ├── DateParser.kt │ │ │ │ └── InstantFormater.kt │ │ │ ├── datetime/ │ │ │ │ └── Instant.kt │ │ │ ├── imageloader/ │ │ │ │ └── ImageLoaderUtils.kt │ │ │ ├── ktx/ │ │ │ │ ├── CollectionsExt.kt │ │ │ │ ├── FlowExt.kt │ │ │ │ ├── LazyBackingFieldDelegate.kt │ │ │ │ ├── StringExt.kt │ │ │ │ └── ViewModels.kt │ │ │ ├── lifecycle/ │ │ │ │ ├── ContainerViewModel.kt │ │ │ │ └── SubViewModel.kt │ │ │ ├── loadable/ │ │ │ │ ├── lazycolumn/ │ │ │ │ │ ├── LoadMoreUi.kt │ │ │ │ │ ├── LoadableInlineVideoLazyColumn.kt │ │ │ │ │ ├── LoadableLazyColumn.kt │ │ │ │ │ └── PullToRefreshIndicator.kt │ │ │ │ └── previous/ │ │ │ │ └── PreviousPageLoadingState.kt │ │ │ ├── module/ │ │ │ │ └── ModuleStartup.kt │ │ │ ├── nav/ │ │ │ │ ├── DialogNavMetadata.kt │ │ │ │ ├── LocalNavBackStack.kt │ │ │ │ ├── NavBackStackExt.kt │ │ │ │ ├── NavEntryProvider.kt │ │ │ │ ├── ScreenEventFlow.kt │ │ │ │ ├── SharedElementScope.kt │ │ │ │ └── Tab.kt │ │ │ ├── network/ │ │ │ │ ├── FormalBaseUrl.kt │ │ │ │ ├── GlobalRoutes.kt │ │ │ │ ├── HttpScheme.kt │ │ │ │ └── SimpleUri.kt │ │ │ ├── opml/ │ │ │ │ ├── OpmlOutline.kt │ │ │ │ └── OpmlParser.kt │ │ │ ├── permission/ │ │ │ │ └── RequireLocalStoragePermission.kt │ │ │ ├── security/ │ │ │ │ └── Md5.kt │ │ │ ├── serialize/ │ │ │ │ └── TimestampAsInstantSerializer.kt │ │ │ ├── toast/ │ │ │ │ └── Toast.kt │ │ │ └── utils/ │ │ │ ├── AspectRatio.kt │ │ │ ├── BlendColorUtils.kt │ │ │ ├── ContentProviderFile.kt │ │ │ ├── DebugUtils.kt │ │ │ ├── DensityUtils.kt │ │ │ ├── DomainValidator.kt │ │ │ ├── DurationFormatUtils.kt │ │ │ ├── ExtractUrlFromTextUtils.kt │ │ │ ├── FloatExt.kt │ │ │ ├── Handle.kt │ │ │ ├── HighlightTextBuildUtil.kt │ │ │ ├── IDNUtils.kt │ │ │ ├── ImageCompressUtils.kt │ │ │ ├── IntExt.kt │ │ │ ├── LanguageUtils.kt │ │ │ ├── LinkPreviewUtils.kt │ │ │ ├── LoadState.kt │ │ │ ├── Log.kt │ │ │ ├── Parcelize.kt │ │ │ ├── PlatformIgnoredOnParcel.kt │ │ │ ├── PlatformParcelable.kt │ │ │ ├── PlatformSerializable.kt │ │ │ ├── PlatformTransient.kt │ │ │ ├── PlatformUri.kt │ │ │ ├── RegexFactory.kt │ │ │ ├── ResultExt.kt │ │ │ ├── Rfc822InstantParser.kt │ │ │ ├── SizeUtils.kt │ │ │ ├── Standard.kt │ │ │ ├── StorageSize.kt │ │ │ ├── TextFieldUtils.kt │ │ │ ├── ThrowableUtils.kt │ │ │ ├── UriUtils.kt │ │ │ ├── UrlEncoder.kt │ │ │ ├── VideoUtils.kt │ │ │ └── WebFinger.kt │ │ └── res/ │ │ └── values/ │ │ ├── colors.xml │ │ └── ids.xml │ ├── commonTest/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── framework/ │ │ ├── network/ │ │ │ └── SimpleUriTest.kt │ │ ├── opml/ │ │ │ └── OpmlParserTest.kt │ │ ├── security/ │ │ │ └── Md5Test.kt │ │ └── utils/ │ │ ├── ExtractUrlFromTextUtilsTest.kt │ │ ├── IntExtTest.kt │ │ └── WebFingerTest.kt │ └── iosMain/ │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── framework/ │ ├── architect/ │ │ ├── http/ │ │ │ └── HttpClientEngine.ios.kt │ │ └── theme/ │ │ └── FreadTheme.ios.kt │ ├── blurhash/ │ │ └── BitmapExt.ios.kt │ ├── composable/ │ │ ├── TextString.ios.kt │ │ └── pick/ │ │ └── PickVisualMediaLauncherContainer.ios.kt │ ├── date/ │ │ └── InstantFormater.ios.kt │ ├── datetime/ │ │ └── Instant.ios.kt │ ├── permission/ │ │ └── RequireLocalStoragePermission.ios.kt │ ├── toast/ │ │ └── Toast.ios.kt │ └── utils/ │ ├── IDNUtils.ios.kt │ ├── ImageCompressUtils.kt │ ├── LanguageUtils.ios.kt │ ├── PlatformIgnoredOnParcel.ios.kt │ ├── PlatformParcelable.ios.kt │ ├── PlatformTransient.ios.kt │ ├── PlatformUri.ios.kt │ ├── Serializable.ios.kt │ └── VideoUtils.ios.kt ├── gradle/ │ ├── libs.versions.toml │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── iosApp/ │ ├── .gitignore │ ├── Configuration/ │ │ └── Config.xcconfig │ ├── iosApp/ │ │ ├── Assets.xcassets/ │ │ │ ├── AccentColor.colorset/ │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── ContentView.swift │ │ ├── GoogleService-Info.plist │ │ ├── Info.plist │ │ ├── Preview Content/ │ │ │ └── Preview Assets.xcassets/ │ │ │ └── Contents.json │ │ └── iOSApp.swift │ └── iosApp.xcodeproj/ │ └── project.pbxproj ├── kotlin-inject-relative.md ├── localization/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── localization/ │ │ └── LanguageCodeUtils.kt │ └── commonMain/ │ ├── composeResources/ │ │ ├── values/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-de-rDE/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-es-rES/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-fr-rFR/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-ja-rJP/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-pt-rPT/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-ru-rRU/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-zh-rCN/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ ├── values-zh-rHK/ │ │ │ ├── strings.xml │ │ │ ├── strings_mastodon.xml │ │ │ └── strings_status_ui.xml │ │ └── values-zh-rTW/ │ │ ├── strings.xml │ │ ├── strings_mastodon.xml │ │ └── strings_status_ui.xml │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ └── localization/ │ ├── LanguageCode.kt │ ├── LanguageCodeNames.kt │ ├── Localization.kt │ └── LocalizedString.kt ├── plugins/ │ ├── activitypub-app/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidMain/ │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── activitypub/ │ │ │ └── app/ │ │ │ ├── ActivityPubAndroidModule.kt │ │ │ └── internal/ │ │ │ ├── auth/ │ │ │ │ └── ActivityPubOAuthRedirectActivity.kt │ │ │ └── push/ │ │ │ ├── ActivityPubPushManager.android.kt │ │ │ ├── ActivityPubPushMessageReceiverHelper.android.kt │ │ │ ├── CryptoUtil.kt │ │ │ ├── PushInfoRepo.kt │ │ │ └── notification/ │ │ │ ├── ActivityPubPushMessage.kt │ │ │ └── PushNotificationManager.kt │ │ ├── androidUnitTest/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── utopia/ │ │ │ └── activitypubapp/ │ │ │ └── ExampleUnitTest.kt │ │ ├── commonMain/ │ │ │ ├── composeResources/ │ │ │ │ └── drawable/ │ │ │ │ └── detail_page_banner_background.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── activitypub/ │ │ │ └── app/ │ │ │ ├── ActivityPubAccountManager.kt │ │ │ ├── ActivityPubContentManager.kt │ │ │ ├── ActivityPubJsonBuilder.kt │ │ │ ├── ActivityPubModule.kt │ │ │ ├── ActivityPubNavEntryProvider.kt │ │ │ ├── ActivityPubNotificationResolver.kt │ │ │ ├── ActivityPubProvider.kt │ │ │ ├── ActivityPubPublishManager.kt │ │ │ ├── ActivityPubScreenProvider.kt │ │ │ ├── ActivityPubSearchEngine.kt │ │ │ ├── ActivityPubSourceResolver.kt │ │ │ ├── ActivityPubStartup.kt │ │ │ ├── ActivityPubStatusResolver.kt │ │ │ ├── ActivityPubUrlInterceptor.kt │ │ │ └── internal/ │ │ │ ├── DataTrackingElements.kt │ │ │ ├── adapter/ │ │ │ │ ├── ActivityPubAccountEntityAdapter.kt │ │ │ │ ├── ActivityPubApplicationEntityAdapter.kt │ │ │ │ ├── ActivityPubBlogMetaAdapter.kt │ │ │ │ ├── ActivityPubContentAdapter.kt │ │ │ │ ├── ActivityPubCustomEmojiEntityAdapter.kt │ │ │ │ ├── ActivityPubInstanceAdapter.kt │ │ │ │ ├── ActivityPubLoggedAccountAdapter.kt │ │ │ │ ├── ActivityPubPlatformEntityAdapter.kt │ │ │ │ ├── ActivityPubPollAdapter.kt │ │ │ │ ├── ActivityPubSearchAdapter.kt │ │ │ │ ├── ActivityPubStatusAdapter.kt │ │ │ │ ├── ActivityPubTagAdapter.kt │ │ │ │ ├── ActivityPubTranslationEntityAdapter.kt │ │ │ │ ├── PostStatusAttachmentAdapter.kt │ │ │ │ ├── QuoteApprovalPolicyExt.kt │ │ │ │ ├── RegisterApplicationEntryAdapter.kt │ │ │ │ └── StatusVisibilityExt.kt │ │ │ ├── auth/ │ │ │ │ ├── ActivityPubClientManager.kt │ │ │ │ ├── ActivityPubOAuthor.kt │ │ │ │ └── LoggedAccountProvider.kt │ │ │ ├── composable/ │ │ │ │ └── ActivityPubTabNames.kt │ │ │ ├── content/ │ │ │ │ └── ActivityPubContent.kt │ │ │ ├── db/ │ │ │ │ ├── ActivityPubApplicationTable.kt │ │ │ │ ├── ActivityPubDatabases.kt │ │ │ │ ├── ActivityPubLoggedAccountDatabase.kt │ │ │ │ ├── ActivityPubPlatformTable.kt │ │ │ │ ├── UserIdTable.kt │ │ │ │ ├── converter/ │ │ │ │ │ ├── ActivityPubAccountEntityConverter.kt │ │ │ │ │ ├── ActivityPubInstanceEntityConverter.kt │ │ │ │ │ ├── ActivityPubLoggedAccountConverter.kt │ │ │ │ │ ├── ActivityPubStatusEntityConverter.kt │ │ │ │ │ ├── ActivityPubStatusSourceTypeConverter.kt │ │ │ │ │ ├── ActivityPubUserTokenConverter.kt │ │ │ │ │ ├── BlogAuthorConverter.kt │ │ │ │ │ ├── EmojiListConverter.kt │ │ │ │ │ ├── FormalBaseUrlConverter.kt │ │ │ │ │ ├── PlatformEntityTypeConverter.kt │ │ │ │ │ ├── RelationshipSeveranceEventConverter.kt │ │ │ │ │ └── StatusNotificationTypeConverter.kt │ │ │ │ ├── old/ │ │ │ │ │ └── ActivityPubLoggedAccountTable.kt │ │ │ │ └── status/ │ │ │ │ ├── ActivityPubStatusDatabases.kt │ │ │ │ └── ActivityPubStatusReadStateDatabases.kt │ │ │ ├── migrate/ │ │ │ │ └── ActivityPubContentMigrator.kt │ │ │ ├── model/ │ │ │ │ ├── ActivityPubApplication.kt │ │ │ │ ├── ActivityPubInstanceRule.kt │ │ │ │ ├── ActivityPubLoggedAccount.kt │ │ │ │ ├── ActivityPubStatusSourceType.kt │ │ │ │ ├── ActivityPubTimelineType.kt │ │ │ │ ├── CustomEmoji.kt │ │ │ │ ├── PlatformUriInsights.kt │ │ │ │ ├── RelationshipSeveranceEvent.kt │ │ │ │ ├── ServerDetailContract.kt │ │ │ │ ├── StatusNotification.kt │ │ │ │ ├── StatusNotificationType.kt │ │ │ │ ├── UserSource.kt │ │ │ │ └── UserUriInsights.kt │ │ │ ├── platform/ │ │ │ │ └── FreadApplicationRegisterInfo.kt │ │ │ ├── push/ │ │ │ │ ├── ActivityPubPushManager.kt │ │ │ │ └── ActivityPubPushMessageReceiver.kt │ │ │ ├── repo/ │ │ │ │ ├── WebFingerBaseUrlToUserIdRepo.kt │ │ │ │ ├── account/ │ │ │ │ │ ├── ActivityPubLoggedAccountRepo.kt │ │ │ │ │ └── LoggedAccountMigrateUtil.kt │ │ │ │ ├── application/ │ │ │ │ │ └── ActivityPubApplicationRepo.kt │ │ │ │ ├── platform/ │ │ │ │ │ ├── ActivityPubPlatformRepo.kt │ │ │ │ │ ├── BlogPlatformResourceLoader.kt │ │ │ │ │ └── MastodonInstanceRepo.kt │ │ │ │ ├── status/ │ │ │ │ │ ├── ActivityPubStatusReadStateRepo.kt │ │ │ │ │ └── ActivityPubTimelineStatusRepo.kt │ │ │ │ └── user/ │ │ │ │ └── UserRepo.kt │ │ │ ├── route/ │ │ │ │ └── ActivityPubRoutes.kt │ │ │ ├── screen/ │ │ │ │ ├── account/ │ │ │ │ │ ├── EditAccountInfoScreen.kt │ │ │ │ │ ├── EditAccountInfoViewModel.kt │ │ │ │ │ └── EditAccountUiState.kt │ │ │ │ ├── add/ │ │ │ │ │ ├── AddActivityPubContentScreen.kt │ │ │ │ │ ├── AddActivityPubContentViewModel.kt │ │ │ │ │ └── select/ │ │ │ │ │ ├── SelectPlatformScreen.kt │ │ │ │ │ ├── SelectPlatformUiState.kt │ │ │ │ │ └── SelectPlatformViewModel.kt │ │ │ │ ├── content/ │ │ │ │ │ ├── ActivityPubContentSubViewModel.kt │ │ │ │ │ ├── ActivityPubContentTab.kt │ │ │ │ │ ├── ActivityPubContentUiState.kt │ │ │ │ │ ├── ActivityPubContentViewModel.kt │ │ │ │ │ ├── edit/ │ │ │ │ │ │ ├── EditContentConfigScreen.kt │ │ │ │ │ │ ├── EditContentConfigUiState.kt │ │ │ │ │ │ └── EditContentConfigViewModel.kt │ │ │ │ │ └── timeline/ │ │ │ │ │ ├── ActivityPubTimelineContainerViewModel.kt │ │ │ │ │ ├── ActivityPubTimelineTab.kt │ │ │ │ │ ├── ActivityPubTimelineViewModel.kt │ │ │ │ │ └── ActivityPubUiState.kt │ │ │ │ ├── explorer/ │ │ │ │ │ ├── ExplorerContainerTab.kt │ │ │ │ │ ├── ExplorerContainerViewModel.kt │ │ │ │ │ ├── ExplorerFeedsTabType.kt │ │ │ │ │ ├── ExplorerItem.kt │ │ │ │ │ ├── ExplorerTab.kt │ │ │ │ │ ├── ExplorerUiState.kt │ │ │ │ │ └── ExplorerViewModel.kt │ │ │ │ ├── filters/ │ │ │ │ │ ├── edit/ │ │ │ │ │ │ ├── EditFilterScreen.kt │ │ │ │ │ │ ├── EditFilterUiState.kt │ │ │ │ │ │ ├── EditFilterViewModel.kt │ │ │ │ │ │ ├── FilterContext.kt │ │ │ │ │ │ └── HiddenKeywordScreen.kt │ │ │ │ │ └── list/ │ │ │ │ │ ├── FiltersListScreen.kt │ │ │ │ │ ├── FiltersListUiState.kt │ │ │ │ │ └── FiltersListViewModel.kt │ │ │ │ ├── hashtag/ │ │ │ │ │ ├── HashtagTimelineContainerViewModel.kt │ │ │ │ │ ├── HashtagTimelineScreen.kt │ │ │ │ │ ├── HashtagTimelineUiState.kt │ │ │ │ │ └── HashtagTimelineViewModel.kt │ │ │ │ ├── instance/ │ │ │ │ │ ├── InstanceDetailScreen.kt │ │ │ │ │ ├── InstanceDetailUiState.kt │ │ │ │ │ ├── InstanceDetailViewModel.kt │ │ │ │ │ ├── about/ │ │ │ │ │ │ ├── ServerAboutPage.kt │ │ │ │ │ │ ├── ServerAboutUiState.kt │ │ │ │ │ │ └── ServerAboutViewModel.kt │ │ │ │ │ └── tags/ │ │ │ │ │ ├── ServerTrendsTagsPage.kt │ │ │ │ │ ├── ServerTrendsTagsUiState.kt │ │ │ │ │ └── ServerTrendsTagsViewModel.kt │ │ │ │ ├── list/ │ │ │ │ │ ├── CreatedListsScreen.kt │ │ │ │ │ ├── CreatedListsUiState.kt │ │ │ │ │ ├── CreatedListsViewModel.kt │ │ │ │ │ ├── ListDetailPageContent.kt │ │ │ │ │ ├── ListItem.kt │ │ │ │ │ ├── add/ │ │ │ │ │ │ ├── AddListScreen.kt │ │ │ │ │ │ ├── AddListUiState.kt │ │ │ │ │ │ └── AddListViewModel.kt │ │ │ │ │ └── edit/ │ │ │ │ │ ├── EditListScreen.kt │ │ │ │ │ ├── EditListUiState.kt │ │ │ │ │ └── EditListViewModel.kt │ │ │ │ ├── search/ │ │ │ │ │ ├── SearchStatusScreen.kt │ │ │ │ │ └── SearchStatusViewModel.kt │ │ │ │ ├── status/ │ │ │ │ │ └── post/ │ │ │ │ │ ├── PostStatusScreen.kt │ │ │ │ │ ├── PostStatusScreenRoute.kt │ │ │ │ │ ├── PostStatusUiState.kt │ │ │ │ │ ├── PostStatusViewModel.kt │ │ │ │ │ ├── PublishInteractionSettingLabel.kt │ │ │ │ │ ├── adapter/ │ │ │ │ │ │ └── CustomEmojiAdapter.kt │ │ │ │ │ ├── composable/ │ │ │ │ │ │ ├── CustomEmojiPicker.kt │ │ │ │ │ │ ├── PostStatusBottomBar.kt │ │ │ │ │ │ └── PostStatusPoll.kt │ │ │ │ │ └── usecase/ │ │ │ │ │ ├── GenerateInitPostStatusUiStateUseCase.kt │ │ │ │ │ └── PublishPostUseCase.kt │ │ │ │ ├── trending/ │ │ │ │ │ ├── TrendingStatusSubViewModel.kt │ │ │ │ │ ├── TrendingStatusTab.kt │ │ │ │ │ └── TrendingStatusViewModel.kt │ │ │ │ └── user/ │ │ │ │ ├── UserDetailContainerViewModel.kt │ │ │ │ ├── UserDetailScreen.kt │ │ │ │ ├── UserDetailUiState.kt │ │ │ │ ├── UserDetailViewModel.kt │ │ │ │ ├── list/ │ │ │ │ │ ├── UserListScreen.kt │ │ │ │ │ ├── UserListType.kt │ │ │ │ │ ├── UserListUiState.kt │ │ │ │ │ └── UserListViewModel.kt │ │ │ │ ├── search/ │ │ │ │ │ ├── SearchUserScreen.kt │ │ │ │ │ ├── SearchUserUiState.kt │ │ │ │ │ └── SearchUserViewModel.kt │ │ │ │ ├── status/ │ │ │ │ │ ├── StatusListContainerViewModel.kt │ │ │ │ │ ├── StatusListScreen.kt │ │ │ │ │ ├── StatusListTab.kt │ │ │ │ │ ├── StatusListType.kt │ │ │ │ │ └── StatusListViewModel.kt │ │ │ │ ├── tags/ │ │ │ │ │ ├── TagListScreen.kt │ │ │ │ │ ├── TagListUiState.kt │ │ │ │ │ └── TagListViewModel.kt │ │ │ │ └── timeline/ │ │ │ │ ├── UserTimelineContainerViewModel.kt │ │ │ │ ├── UserTimelineTab.kt │ │ │ │ ├── UserTimelineTabType.kt │ │ │ │ ├── UserTimelineUiState.kt │ │ │ │ └── UserTimelineViewModel.kt │ │ │ ├── source/ │ │ │ │ └── UserSourceTransformer.kt │ │ │ ├── uri/ │ │ │ │ ├── ActivityPubUriHost.kt │ │ │ │ ├── ActivityPubUriPath.kt │ │ │ │ ├── PlatformUriTransformer.kt │ │ │ │ ├── StatusProviderUriExts.kt │ │ │ │ └── UserUriTransformer.kt │ │ │ ├── usecase/ │ │ │ │ ├── ActivityPubAccountLogoutUseCase.kt │ │ │ │ ├── GetDefaultBaseUrlUseCase.kt │ │ │ │ ├── GetInstanceAnnouncementUseCase.kt │ │ │ │ ├── GetServerTrendTagsUseCase.kt │ │ │ │ ├── UpdateActivityPubUserListUseCase.kt │ │ │ │ ├── content/ │ │ │ │ │ ├── GetUserCreatedListUseCase.kt │ │ │ │ │ └── ReorderActivityPubTabUseCase.kt │ │ │ │ ├── emoji/ │ │ │ │ │ ├── GetCustomEmojiUseCase.kt │ │ │ │ │ └── MapCustomEmojiUseCase.kt │ │ │ │ ├── media/ │ │ │ │ │ └── UploadMediaAttachmentUseCase.kt │ │ │ │ ├── platform/ │ │ │ │ │ └── GetInstancePostStatusRulesUseCase.kt │ │ │ │ ├── source/ │ │ │ │ │ └── user/ │ │ │ │ │ └── SearchUserSourceNoTokenUseCase.kt │ │ │ │ └── status/ │ │ │ │ ├── GetStatusContextUseCase.kt │ │ │ │ ├── GetTimelineStatusUseCase.kt │ │ │ │ ├── GetUserStatusUseCase.kt │ │ │ │ ├── StatusInteractiveUseCase.kt │ │ │ │ └── VotePollUseCase.kt │ │ │ └── utils/ │ │ │ ├── Base64Utils.kt │ │ │ ├── DeleteTextUtil.kt │ │ │ ├── MastodonHelper.kt │ │ │ └── PlatformLocatorUtils.kt │ │ └── iosMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── activitypub/ │ │ └── app/ │ │ ├── ActivityPubIosModule.kt │ │ └── internal/ │ │ └── push/ │ │ ├── ActivityPubPushManager.ios.kt │ │ └── ActivityPubPushMessageReceiverHelper.ios.kt │ ├── bluesky/ │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── androidMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── bluesky/ │ │ │ └── BlueskyAndroidModule.kt │ │ ├── androidTest/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── bluesky/ │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── commonMain/ │ │ │ ├── composeResources/ │ │ │ │ └── drawable/ │ │ │ │ └── bluesky_logo.xml │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── bluesky/ │ │ │ ├── BlueskyAccountManager.kt │ │ │ ├── BlueskyModule.kt │ │ │ ├── BlueskyNavEntryProvider.kt │ │ │ ├── BlueskyNotificationResolver.kt │ │ │ ├── BlueskyProvider.kt │ │ │ ├── BlueskyPublishManager.kt │ │ │ ├── BlueskyScreenProvider.kt │ │ │ ├── BlueskySearchEngine.kt │ │ │ ├── BlueskyStatusResolver.kt │ │ │ ├── BlueskyStatusSourceResolver.kt │ │ │ ├── BskyStartup.kt │ │ │ ├── BskyUrlInterceptor.kt │ │ │ └── internal/ │ │ │ ├── account/ │ │ │ │ ├── BlueskyLoggedAccount.kt │ │ │ │ └── BlueskyLoggedAccountManager.kt │ │ │ ├── adapter/ │ │ │ │ ├── BlueskyAccountAdapter.kt │ │ │ │ ├── BlueskyFeedsAdapter.kt │ │ │ │ ├── BlueskyNotificationAdapter.kt │ │ │ │ ├── BlueskyProfileAdapter.kt │ │ │ │ └── BlueskyStatusAdapter.kt │ │ │ ├── client/ │ │ │ │ ├── BlueskyClient.kt │ │ │ │ ├── BlueskyClientManager.kt │ │ │ │ ├── BlueskyResponseUtils.kt │ │ │ │ ├── BskyCollections.kt │ │ │ │ ├── BskyHttpPlugin.kt │ │ │ │ ├── records.kt │ │ │ │ └── rkeys.kt │ │ │ ├── composable/ │ │ │ │ ├── BlueskyFeedsUi.kt │ │ │ │ └── DetailTopBar.kt │ │ │ ├── content/ │ │ │ │ ├── BlueskyContent.kt │ │ │ │ └── BlueskyContentManager.kt │ │ │ ├── db/ │ │ │ │ ├── BlueskyLoggedAccountDatabase.kt │ │ │ │ └── converter/ │ │ │ │ ├── BlueskyLoggedAccountConverter.kt │ │ │ │ └── GeneratorViewConverter.kt │ │ │ ├── migrate/ │ │ │ │ └── BlueskyContentMigrator.kt │ │ │ ├── model/ │ │ │ │ ├── BlueskyFeeds.kt │ │ │ │ ├── BlueskyProfile.kt │ │ │ │ ├── BskyPagingFeeds.kt │ │ │ │ └── CompletedBskyNotification.kt │ │ │ ├── repo/ │ │ │ │ ├── BlueskyLoggedAccountRepo.kt │ │ │ │ └── BlueskyPlatformRepo.kt │ │ │ ├── screen/ │ │ │ │ ├── BlueskyRoutes.kt │ │ │ │ ├── add/ │ │ │ │ │ ├── AddBlueskyContentScreen.kt │ │ │ │ │ ├── AddBlueskyContentUiState.kt │ │ │ │ │ └── AddBlueskyContentViewModel.kt │ │ │ │ ├── content/ │ │ │ │ │ ├── BlueskyContentContainerViewModel.kt │ │ │ │ │ ├── BlueskyContentTab.kt │ │ │ │ │ ├── BlueskyContentUiState.kt │ │ │ │ │ └── BlueskyContentViewModel.kt │ │ │ │ ├── explorer/ │ │ │ │ │ └── BlueskyExplorerTab.kt │ │ │ │ ├── feeds/ │ │ │ │ │ ├── detail/ │ │ │ │ │ │ ├── FeedsDetailScreen.kt │ │ │ │ │ │ ├── FeedsDetailUiState.kt │ │ │ │ │ │ └── FeedsDetailViewModel.kt │ │ │ │ │ ├── explorer/ │ │ │ │ │ │ ├── ExplorerFeedsScreen.kt │ │ │ │ │ │ ├── ExplorerFeedsUiState.kt │ │ │ │ │ │ └── ExplorerFeedsViewModel.kt │ │ │ │ │ ├── following/ │ │ │ │ │ │ ├── BskyFollowingFeedsPage.kt │ │ │ │ │ │ ├── BskyFollowingFeedsUiState.kt │ │ │ │ │ │ └── BskyFollowingFeedsViewModel.kt │ │ │ │ │ └── home/ │ │ │ │ │ ├── HomeFeedsContainerViewModel.kt │ │ │ │ │ ├── HomeFeedsScreen.kt │ │ │ │ │ ├── HomeFeedsTab.kt │ │ │ │ │ └── HomeFeedsViewModel.kt │ │ │ │ ├── publish/ │ │ │ │ │ ├── MentionCandidateBar.kt │ │ │ │ │ ├── PublishPostEmbed.kt │ │ │ │ │ ├── PublishPostMediaAttachment.kt │ │ │ │ │ ├── PublishPostScreen.kt │ │ │ │ │ ├── PublishPostUiState.kt │ │ │ │ │ └── PublishPostViewModel.kt │ │ │ │ ├── search/ │ │ │ │ │ ├── SearchStatusScreen.kt │ │ │ │ │ └── SearchStatusViewModel.kt │ │ │ │ └── user/ │ │ │ │ ├── detail/ │ │ │ │ │ ├── BskyUserDetailScreen.kt │ │ │ │ │ ├── BskyUserDetailUiState.kt │ │ │ │ │ └── BskyUserDetailViewModel.kt │ │ │ │ ├── edit/ │ │ │ │ │ ├── EditProfileScreen.kt │ │ │ │ │ ├── EditProfileUiState.kt │ │ │ │ │ └── EditProfileViewModel.kt │ │ │ │ └── list/ │ │ │ │ ├── UserListItemUiState.kt │ │ │ │ ├── UserListScreen.kt │ │ │ │ ├── UserListType.kt │ │ │ │ └── UserListViewModel.kt │ │ │ ├── tracking/ │ │ │ │ └── BskyTrackingElements.kt │ │ │ ├── uri/ │ │ │ │ ├── BlueskyUriHost.kt │ │ │ │ ├── BlueskyUriPath.kt │ │ │ │ ├── platform/ │ │ │ │ │ ├── PlatformUriInsights.kt │ │ │ │ │ └── PlatformUriTransformer.kt │ │ │ │ └── user/ │ │ │ │ ├── UserUriInsights.kt │ │ │ │ └── UserUriTransformer.kt │ │ │ ├── usecase/ │ │ │ │ ├── BskyStatusInteractiveUseCase.kt │ │ │ │ ├── CreateRecordUseCase.kt │ │ │ │ ├── DeleteRecordUseCase.kt │ │ │ │ ├── GetAllListsUseCase.kt │ │ │ │ ├── GetAtIdentifierUseCase.kt │ │ │ │ ├── GetCompletedNotificationUseCase.kt │ │ │ │ ├── GetFeedsStatusUseCase.kt │ │ │ │ ├── GetFollowingFeedsUseCase.kt │ │ │ │ ├── GetStatusContextUseCase.kt │ │ │ │ ├── LoginToBskyUseCase.kt │ │ │ │ ├── PinFeedsUseCase.kt │ │ │ │ ├── PublishingPostUseCase.kt │ │ │ │ ├── RefreshSessionUseCase.kt │ │ │ │ ├── UnblockUserWithoutUriUseCase.kt │ │ │ │ ├── UnpinFeedsUseCase.kt │ │ │ │ ├── UpdateBlockUseCase.kt │ │ │ │ ├── UpdateHomeTabUseCase.kt │ │ │ │ ├── UpdatePinnedFeedsOrderUseCase.kt │ │ │ │ ├── UpdatePreferencesUseCase.kt │ │ │ │ ├── UpdateProfileRecordUseCase.kt │ │ │ │ ├── UpdateRelationshipUseCase.kt │ │ │ │ ├── UploadBlobUseCase.kt │ │ │ │ └── UploadImageByImageUrlUseCase.kt │ │ │ └── utils/ │ │ │ ├── AtResponseUtils.kt │ │ │ ├── PlatformLocatorUtils.kt │ │ │ └── Tid.kt │ │ ├── iosMain/ │ │ │ └── kotlin/ │ │ │ └── com/ │ │ │ └── zhangke/ │ │ │ └── fread/ │ │ │ └── bluesky/ │ │ │ └── BlueskyIosModule.kt │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── bluesky/ │ │ └── ExampleUnitTest.kt │ └── rss/ │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src/ │ ├── androidMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── rss/ │ │ ├── RssAndroidModule.kt │ │ └── internal/ │ │ └── utils/ │ │ └── AvatarUtils.android.kt │ ├── commonMain/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── rss/ │ │ ├── RssAccountManager.kt │ │ ├── RssContentManager.kt │ │ ├── RssModule.kt │ │ ├── RssNavEntryProvider.kt │ │ ├── RssNotificationResolver.kt │ │ ├── RssPublishManager.kt │ │ ├── RssScreenProvider.kt │ │ ├── RssSearchEngine.kt │ │ ├── RssStatusProvider.kt │ │ ├── RssStatusResolver.kt │ │ ├── RssStatusSourceResolver.kt │ │ └── internal/ │ │ ├── adapter/ │ │ │ ├── BlogAuthorAdapter.kt │ │ │ ├── RssBlogMediaExtractor.kt │ │ │ └── RssStatusAdapter.kt │ │ ├── db/ │ │ │ ├── RssChannelTable.kt │ │ │ ├── RssDatabases.kt │ │ │ └── converter/ │ │ │ ├── FormalUriConverter.kt │ │ │ └── InstantConverter.kt │ │ ├── model/ │ │ │ ├── RssChannelItem.kt │ │ │ └── RssSource.kt │ │ ├── platform/ │ │ │ └── RssPlatformTransformer.kt │ │ ├── repo/ │ │ │ ├── RssRepo.kt │ │ │ └── RssStatusRepo.kt │ │ ├── rss/ │ │ │ ├── RssChannel.kt │ │ │ ├── RssFetcher.kt │ │ │ ├── RssImage.kt │ │ │ ├── RssItem.kt │ │ │ ├── RssParserWrapper.kt │ │ │ └── adapter/ │ │ │ ├── RssChannelAdapter.kt │ │ │ ├── RssImageAdapter.kt │ │ │ └── RssItemAdapter.kt │ │ ├── screen/ │ │ │ ├── RssRoutes.kt │ │ │ └── source/ │ │ │ ├── RssSourceScreen.kt │ │ │ ├── RssSourceUiState.kt │ │ │ └── RssSourceViewModel.kt │ │ ├── source/ │ │ │ └── RssSourceTransformer.kt │ │ ├── uri/ │ │ │ ├── RssUri.kt │ │ │ ├── RssUriHost.kt │ │ │ ├── RssUriInsight.kt │ │ │ ├── RssUriPath.kt │ │ │ └── RssUriTransformer.kt │ │ ├── utils/ │ │ │ └── AvatarUtils.kt │ │ └── webfinger/ │ │ └── RssSourceWebFingerTransformer.kt │ ├── commonTest/ │ │ └── kotlin/ │ │ └── com/ │ │ └── zhangke/ │ │ └── fread/ │ │ └── rss/ │ │ └── internal/ │ │ └── adapter/ │ │ └── RssBlogMediaExtractorTest.kt │ └── iosMain/ │ └── kotlin/ │ └── com/ │ └── zhangke/ │ └── fread/ │ └── rss/ │ ├── RssIosModule.kt │ └── internal/ │ └── utils/ │ └── AvatarUtils.ios.kt ├── privacy_cn.md ├── privacy_en.md ├── settings.gradle.kts └── thirds/ ├── halilibo-richtext-material3/ │ ├── build.gradle.kts │ └── src/ │ ├── androidMain/ │ │ └── AndroidManifest.xml │ └── commonMain/ │ └── kotlin/ │ └── com/ │ └── halilibo/ │ └── richtext/ │ └── ui/ │ └── material3/ │ └── RichText.kt └── halilibo-richtext-ui/ ├── build.gradle.kts └── src/ ├── androidMain/ │ ├── AndroidManifest.xml │ └── kotlin/ │ └── com/ │ └── halilibo/ │ └── richtext/ │ └── ui/ │ ├── CodeBlock.android.kt │ └── util/ │ └── UUID.android.kt ├── commonMain/ │ └── kotlin/ │ └── com/ │ └── halilibo/ │ └── richtext/ │ └── ui/ │ ├── BasicRichText.kt │ ├── BlockQuote.kt │ ├── CodeBlock.kt │ ├── FormattedList.kt │ ├── Heading.kt │ ├── HorizontalRule.kt │ ├── InfoPanel.kt │ ├── RichTextLocals.kt │ ├── RichTextScope.kt │ ├── RichTextStyle.kt │ ├── RichTextThemeConfiguration.kt │ ├── RichTextThemeProvider.kt │ ├── SimpleTableLayout.kt │ ├── Table.kt │ ├── string/ │ │ ├── InlineContent.kt │ │ ├── RichTextString.kt │ │ └── Text.kt │ └── util/ │ ├── ConditionalTapGestureDetector.kt │ └── UUID.kt └── iosMain/ └── kotlin/ └── com/ └── halilibo/ └── richtext/ └── ui/ ├── CodeBlock.ios.kt └── util/ └── UUID.ios.kt