From ddef59d1bcf7759a5091c106e1638511c1df134c Mon Sep 17 00:00:00 2001
From: DIYgod
Date: Mon, 22 Jun 2026 14:57:04 +0800
Subject: [PATCH 01/22] release(desktop): release v1.10.0
---
apps/desktop/changelog/1.10.0.md | 16 ++++++++++++++++
apps/desktop/changelog/next.md | 15 +++++----------
apps/desktop/package.json | 4 ++--
apps/desktop/release-plan.json | 6 +++---
apps/desktop/release.json | 8 ++++----
5 files changed, 30 insertions(+), 19 deletions(-)
create mode 100644 apps/desktop/changelog/1.10.0.md
diff --git a/apps/desktop/changelog/1.10.0.md b/apps/desktop/changelog/1.10.0.md
new file mode 100644
index 000000000..8795f8f75
--- /dev/null
+++ b/apps/desktop/changelog/1.10.0.md
@@ -0,0 +1,16 @@
+# What's new in v1.10.0
+
+## No longer broken
+
+- Fixed duplicated lines in code blocks from feeds that wrap each line in nested divs (e.g., Cloudflare's changelog)
+- Fixed social timeline scroll reset on view changes
+- Fixed timeline refreshes returning to the top before new content is rendered
+- Fixed mark-read state changes while the timeline is being reset
+- Fixed the recent reader spacer appearing when there are no recent entries
+- Fixed reading mode content disappearing after translation updates
+- Fixed streaming TTS scheduling stability
+- Fixed the Spline AI indicator rendering while idle
+
+## Thanks
+
+Special thanks to volunteer contributor @TonyRL for the nested code block fix
diff --git a/apps/desktop/changelog/next.md b/apps/desktop/changelog/next.md
index 743f6b5f0..8f5eac449 100644
--- a/apps/desktop/changelog/next.md
+++ b/apps/desktop/changelog/next.md
@@ -1,16 +1,11 @@
# What's new in vNEXT_VERSION
+## Shiny new things
+
+## Improvements
+
## No longer broken
-- Fixed duplicated lines in code blocks from feeds that wrap each line in nested divs (e.g., Cloudflare's changelog)
-- Fixed social timeline scroll reset on view changes
-- Fixed timeline refreshes returning to the top before new content is rendered
-- Fixed mark-read state changes while the timeline is being reset
-- Fixed the recent reader spacer appearing when there are no recent entries
-- Fixed reading mode content disappearing after translation updates
-- Fixed streaming TTS scheduling stability
-- Fixed the Spline AI indicator rendering while idle
-
## 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/desktop/package.json b/apps/desktop/package.json
index 6244d99f6..90bb61445 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -1,7 +1,7 @@
{
"name": "Folo",
"type": "module",
- "version": "1.9.0",
+ "version": "1.10.0",
"private": true,
"description": "Follow everything in one place",
"author": "Folo Team",
@@ -98,5 +98,5 @@
},
"runtimeVersion": "1.9.0",
"productName": "Folo",
- "mainHash": "0ccdf61724c1dac73e38b9267958138671911ef8cf87830abb9451c2729b9211"
+ "mainHash": "79b9a1c73ebea4fc92b28cc4952a2fe92557557141b1de0c81074622d8a1f404"
}
diff --git a/apps/desktop/release-plan.json b/apps/desktop/release-plan.json
index e340e3bfd..da0a2c1c6 100644
--- a/apps/desktop/release-plan.json
+++ b/apps/desktop/release-plan.json
@@ -1,5 +1,5 @@
{
- "mode": "ota",
- "runtimeVersion": "1.9.0",
- "channel": "stable"
+ "mode": "build",
+ "runtimeVersion": null,
+ "channel": null
}
diff --git a/apps/desktop/release.json b/apps/desktop/release.json
index fcc73b649..53251c263 100644
--- a/apps/desktop/release.json
+++ b/apps/desktop/release.json
@@ -1,6 +1,6 @@
{
- "version": "1.9.0",
- "mode": "build",
- "runtimeVersion": null,
- "channel": null
+ "version": "1.10.0",
+ "mode": "ota",
+ "runtimeVersion": "1.9.0",
+ "channel": "stable"
}
From 195a2a71f4548b07a2af12596f6d4e177ae3c250 Mon Sep 17 00:00:00 2001
From: DIYgod
Date: Mon, 22 Jun 2026 14:57:45 +0800
Subject: [PATCH 02/22] docs(desktop): restore mobile release inputs
---
apps/mobile/changelog/next.md | 11 +++++------
apps/mobile/release-plan.json | 6 +++---
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/apps/mobile/changelog/next.md b/apps/mobile/changelog/next.md
index 4165126b6..000f858e3 100644
--- a/apps/mobile/changelog/next.md
+++ b/apps/mobile/changelog/next.md
@@ -1,12 +1,11 @@
# What's New in vNEXT_VERSION
+## Shiny new things
+
+## Improvements
+
## 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
+Special thanks to volunteer contributors @ for their valuable contributions
diff --git a/apps/mobile/release-plan.json b/apps/mobile/release-plan.json
index 74637e871..0a4e0fb6f 100644
--- a/apps/mobile/release-plan.json
+++ b/apps/mobile/release-plan.json
@@ -1,5 +1,5 @@
{
- "mode": "ota",
- "runtimeVersion": "0.5.0",
- "channel": "production"
+ "mode": "store",
+ "runtimeVersion": null,
+ "channel": null
}
From c782efa65e15601a762daf30b4430a34dfe62602 Mon Sep 17 00:00:00 2001
From: DIYgod
Date: Mon, 22 Jun 2026 20:57:58 +0800
Subject: [PATCH 03/22] fix(landing): bundle legal markdown content
---
apps/landing/global.d.ts | 2 ++
.../src/app/[locale]/privacy-policy/page.tsx | 3 +-
.../app/[locale]/terms-of-service/page.tsx | 3 +-
.../ui/markdown/get-markdown-content.ts | 35 +++++++++++++++++++
.../src/components/ui/markdown/index.tsx | 32 -----------------
.../components/ui/markdown/markdown.test.ts | 19 ++++++++++
6 files changed, 60 insertions(+), 34 deletions(-)
create mode 100644 apps/landing/src/components/ui/markdown/get-markdown-content.ts
create mode 100644 apps/landing/src/components/ui/markdown/markdown.test.ts
diff --git a/apps/landing/global.d.ts b/apps/landing/global.d.ts
index bc4a25e68..2378c3a15 100644
--- a/apps/landing/global.d.ts
+++ b/apps/landing/global.d.ts
@@ -1,3 +1,5 @@
+///
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 31275a8dc..470109544 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 000000000..2783e4c86 --- /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 6645dcf21..85be7322e 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 6e27ac51f..9cd236eac 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 36153c110..406ea2ca0 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 (