From 5d6b5ed40fa059bf42d41ac7340f45e61d42a9e5 Mon Sep 17 00:00:00 2001
From: DIYgod
Date: Mon, 22 Jun 2026 14:58:32 +0800
Subject: [PATCH 01/24] release(mobile): release v0.5.5
---
apps/mobile/changelog/0.5.5.md | 12 ++++++++++++
apps/mobile/changelog/next.md | 11 +++++------
apps/mobile/ios/Folo/Info.plist | 4 ++--
apps/mobile/package.json | 2 +-
apps/mobile/release-plan.json | 6 +++---
apps/mobile/release.json | 4 ++--
6 files changed, 25 insertions(+), 14 deletions(-)
create mode 100644 apps/mobile/changelog/0.5.5.md
diff --git a/apps/mobile/changelog/0.5.5.md b/apps/mobile/changelog/0.5.5.md
new file mode 100644
index 00000000000..3c99ff2ec25
--- /dev/null
+++ b/apps/mobile/changelog/0.5.5.md
@@ -0,0 +1,12 @@
+# What's New in v0.5.5
+
+## No longer broken
+
+- Fixed duplicated lines in code blocks from feeds that wrap each line in nested divs (e.g., Cloudflare's changelog)
+- Fixed timeline refreshes returning to the top before new content is rendered
+- Fixed mark-read state changes while the timeline is being reset
+- Fixed social timeline scroll reset preservation across mobile list layouts
+
+## Thanks
+
+Special thanks to volunteer contributor @TonyRL for the nested code block fix
diff --git a/apps/mobile/changelog/next.md b/apps/mobile/changelog/next.md
index 4165126b6db..000f858e3d2 100644
--- a/apps/mobile/changelog/next.md
+++ b/apps/mobile/changelog/next.md
@@ -1,12 +1,11 @@
# What's New in vNEXT_VERSION
-## No longer broken
+## Shiny new things
+
+## Improvements
-- Fixed duplicated lines in code blocks from feeds that wrap each line in nested divs (e.g., Cloudflare's changelog)
-- Fixed timeline refreshes returning to the top before new content is rendered
-- Fixed mark-read state changes while the timeline is being reset
-- Fixed social timeline scroll reset preservation across mobile list layouts
+## No longer broken
## Thanks
-Special thanks to volunteer contributor @TonyRL for the nested code block fix
+Special thanks to volunteer contributors @ for their valuable contributions
diff --git a/apps/mobile/ios/Folo/Info.plist b/apps/mobile/ios/Folo/Info.plist
index 7afb39911d9..6680d0043cb 100644
--- a/apps/mobile/ios/Folo/Info.plist
+++ b/apps/mobile/ios/Folo/Info.plist
@@ -33,7 +33,7 @@
Error loading content. Please try again later.
', + } + } +} diff --git a/apps/landing/src/components/ui/markdown/index.tsx b/apps/landing/src/components/ui/markdown/index.tsx index 31275a8dc1a..4701095443c 100644 --- a/apps/landing/src/components/ui/markdown/index.tsx +++ b/apps/landing/src/components/ui/markdown/index.tsx @@ -1,11 +1,3 @@ -import fs from 'node:fs' - -import { join } from 'pathe' -import rehypeStringify from 'rehype-stringify' -import remarkParse from 'remark-parse' -import remarkRehype from 'remark-rehype' -import { unified } from 'unified' - interface MarkdownContentProps { content: string } @@ -25,27 +17,3 @@ export function MarkdownContent({ content }: MarkdownContentProps) { ) } - -// Utility function to read and process markdown files -export async function getMarkdownContent(filePath: string) { - try { - const fullPath = join(process.cwd(), 'src', filePath) - const fileContents = fs.readFileSync(fullPath, 'utf8') - - // Process markdown to HTML using unified - const processedContent = await unified() - .use(remarkParse) - .use(remarkRehype, { allowDangerousHtml: true }) - .use(rehypeStringify, { allowDangerousHtml: true }) - .process(fileContents) - - return { - content: processedContent.toString(), - } - } catch (error) { - console.error('Error reading markdown file:', error) - return { - content: 'Error loading content. Please try again later.
', - } - } -} diff --git a/apps/landing/src/components/ui/markdown/markdown.test.ts b/apps/landing/src/components/ui/markdown/markdown.test.ts new file mode 100644 index 00000000000..2783e4c86aa --- /dev/null +++ b/apps/landing/src/components/ui/markdown/markdown.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest' + +import { getMarkdownContent } from './get-markdown-content' + +describe('getMarkdownContent', () => { + it('renders the privacy policy markdown content', async () => { + const { content } = await getMarkdownContent('legal/privacy.md') + + expect(content).toContain('= FC
& NavigationControllerViewExtraProps
export type NavigationControllerViewType = StackPresentationTypes
diff --git a/apps/mobile/src/modules/discover/search-tabs/SearchFeed.tsx b/apps/mobile/src/modules/discover/search-tabs/SearchFeed.tsx
index 6645dcf2181..85be7322e00 100644
--- a/apps/mobile/src/modules/discover/search-tabs/SearchFeed.tsx
+++ b/apps/mobile/src/modules/discover/search-tabs/SearchFeed.tsx
@@ -9,18 +9,9 @@ import { followClient } from "@/src/lib/api-client"
import { useSearchPageContext } from "../ctx"
import { ItemSeparator } from "./__base"
import { useDataSkeleton } from "./hooks"
-import type { SearchFeedCardItem } from "./SearchFeedCard"
+import { resolveSearchFeedItems } from "./search-feed-items"
import { SearchFeedCard } from "./SearchFeedCard"
-const isDirectFeedInput = (value: string) => value.includes("://")
-
-const createDirectFeedItem = (value: string): SearchFeedCardItem => ({
- feed: {
- title: value,
- url: value,
- },
-})
-
export const SearchFeed = () => {
const { t } = useTranslation("common")
const { searchValueAtom } = useSearchPageContext()
@@ -33,18 +24,12 @@ export const SearchFeed = () => {
},
enabled: !!searchValue,
})
- const skeleton = useDataSkeleton(isLoading, data)
+ const discoveredItems = data?.data ?? []
+ const items = resolveSearchFeedItems(discoveredItems, searchValue)
+ const skeleton = useDataSkeleton(isLoading, data === undefined ? undefined : items.length)
if (skeleton) return skeleton
if (data === undefined) return null
- const discoveredItems = data.data ?? []
- const items =
- discoveredItems.length > 0
- ? discoveredItems
- : searchValue && isDirectFeedInput(searchValue)
- ? [createDirectFeedItem(searchValue)]
- : []
-
const resultCount = items.length
const resultLabel =
resultCount === 0
diff --git a/apps/mobile/src/modules/discover/search-tabs/SearchList.tsx b/apps/mobile/src/modules/discover/search-tabs/SearchList.tsx
index 6e27ac51f9d..9cd236eac9c 100644
--- a/apps/mobile/src/modules/discover/search-tabs/SearchList.tsx
+++ b/apps/mobile/src/modules/discover/search-tabs/SearchList.tsx
@@ -36,7 +36,7 @@ export const SearchList = () => {
queryFn: () => followClient.api.discover.discover({ keyword: searchValue, target: "lists" }),
enabled: !!searchValue,
})
- const skeleton = useDataSkeleton(isLoading, data)
+ const skeleton = useDataSkeleton(isLoading, data?.data.length)
if (skeleton) return skeleton
if (data === undefined) return null
const resultCount = data.data?.length ?? 0
diff --git a/apps/mobile/src/modules/discover/search-tabs/hooks.tsx b/apps/mobile/src/modules/discover/search-tabs/hooks.tsx
index 36153c11087..406ea2ca088 100644
--- a/apps/mobile/src/modules/discover/search-tabs/hooks.tsx
+++ b/apps/mobile/src/modules/discover/search-tabs/hooks.tsx
@@ -9,7 +9,7 @@ import { useColor } from "@/src/theme/colors"
import { BaseSearchPageRootView } from "./__base"
-export const useDataSkeleton = (isLoading: boolean, data: any) => {
+export const useDataSkeleton = (isLoading: boolean, itemCount: number | undefined) => {
const { t } = useTranslation("common")
const textColor = useColor("text")
return useMemo(() => {
@@ -20,7 +20,7 @@ export const useDataSkeleton = (isLoading: boolean, data: any) => {
)
}
- if (data?.data.length === 0) {
+ if (itemCount === 0) {
return (