chore(mobile): update dependencies and refactor UI components

- Upgrade react-native-uikit-colors to v0.2.0
- Enhance CustomURLSchemeHandler with improved task management
- Update RecommendationListItem and EntryListItem with context menu improvements
- Refactor entry list item styling using system colors and context menu preview
- Add context menu preview to login and entry list modules

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-02-08 22:24:17 +08:00
parent e03f38a7fd
commit 17c7f9d3e9
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
6 changed files with 118 additions and 70 deletions

View File

@ -10,8 +10,8 @@ import WebKit
class CustomURLSchemeHandler: NSObject, WKURLSchemeHandler {
static let rewriteScheme = "follow-xhr"
private let queue = DispatchQueue(label: "com.follow.urlschemehandler")
private var activeTasks: [String: URLSessionDataTask] = [:]
private var stoppedTasks: Set<String> = []
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
guard let url = urlSchemeTask.request.url,
@ -47,43 +47,38 @@ class CustomURLSchemeHandler: NSObject, WKURLSchemeHandler {
let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
guard let self = self else { return }
// Check if task is still active
guard self.activeTasks[taskID] != nil else { return }
DispatchQueue.main.async {
if let error = error {
urlSchemeTask.didFailWithError(error)
self.queue.sync {
guard !self.stoppedTasks.contains(taskID) else { return }
if let error = error {
urlSchemeTask.didFailWithError(error)
self.activeTasks.removeValue(forKey: taskID)
return
}
return
}
if let response = response as? HTTPURLResponse, let data = data {
do {
if let response = response as? HTTPURLResponse, let data = data {
guard !self.stoppedTasks.contains(taskID) else { return }
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
} catch {
// Ignore errors that might occur if task was stopped
print("Error completing URL scheme task: \(error)")
self.activeTasks.removeValue(forKey: taskID)
}
}
self.activeTasks.removeValue(forKey: taskID)
}
queue.sync {
activeTasks[taskID] = task
}
activeTasks[taskID] = task
task.resume()
}
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
let taskID = urlSchemeTask.description
queue.sync {
if let task = activeTasks[taskID] {
task.cancel()
activeTasks.removeValue(forKey: taskID)
}
if let task = activeTasks[taskID] {
stoppedTasks.insert(taskID)
task.cancel()
activeTasks.removeValue(forKey: taskID)
}
}
}

View File

@ -86,7 +86,7 @@
"react-native-safe-area-context": "5.1.0",
"react-native-screens": "~4.5.0",
"react-native-svg": "15.8.0",
"react-native-uikit-colors": "0.1.2",
"react-native-uikit-colors": "0.2.0",
"react-native-web": "~0.19.13",
"react-native-webview": "13.13.1",
"shiki": "2.2.0",

View File

@ -45,7 +45,7 @@ export const RecommendationListItem: FC<{
<View className="ml-2 flex-1">
<Text className="text-text text-base font-medium">{data.name}</Text>
{/* Maintainers */}
<View className="flex-row flex-wrap items-center">
<View className="mb-1 flex-row flex-wrap items-center">
{maintainers.map((m) => (
<ContextMenu.Root key={m}>
<ContextMenu.Trigger asChild>
@ -55,7 +55,7 @@ export const RecommendationListItem: FC<{
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Preview>
<ContextMenu.Preview size="STRETCH">
{() => <WebView source={{ uri: `https://github.com/${m}` }} />}
</ContextMenu.Preview>

View File

@ -7,12 +7,16 @@ import { router } from "expo-router"
import { useCallback, useContext, useMemo } from "react"
import { StyleSheet, Text, useAnimatedValue, View } from "react-native"
import { useSafeAreaInsets } from "react-native-safe-area-context"
import * as ContextMenu from "zeego/context-menu"
import {
NavigationBlurEffectHeader,
NavigationContext,
} from "@/src/components/common/SafeNavigationScrollView"
import { setWebViewEntry } from "@/src/components/native/webview/EntryContentWebView"
import {
EntryContentWebView,
setWebViewEntry,
} from "@/src/components/native/webview/EntryContentWebView"
import { ItemPressable } from "@/src/components/ui/pressable/item-pressable"
import { useDefaultHeaderHeight } from "@/src/hooks/useDefaultHeaderHeight"
import { useSelectedFeed, useSelectedFeedTitle } from "@/src/modules/feed-drawer/atoms"
@ -109,7 +113,6 @@ const ItemSeparator = () => {
/>
)
}
function EntryItem({ entryId }: { entryId: string }) {
const entry = useEntry(entryId)
@ -125,25 +128,39 @@ function EntryItem({ entryId }: { entryId: string }) {
const blurhash = media?.[0]?.blurhash
return (
<ItemPressable className="flex flex-row items-center p-4" onPress={handlePress}>
<View className="flex-1 space-y-2">
<Text numberOfLines={2} className="text-lg font-semibold text-zinc-900 dark:text-zinc-100">
{title}
</Text>
<Text className="line-clamp-2 text-sm text-zinc-600 dark:text-zinc-400">{description}</Text>
<Text className="text-xs text-zinc-500 dark:text-zinc-500">
{publishedAt.toLocaleString()}
</Text>
</View>
{image && (
<Image
source={{ uri: image }}
placeholder={{ blurhash }}
className="ml-2 size-20 rounded-md bg-zinc-200 dark:bg-zinc-800"
contentFit="cover"
/>
)}
</ItemPressable>
<ContextMenu.Root>
<ContextMenu.Trigger>
<ItemPressable className="flex flex-row items-center p-4" onPress={handlePress}>
<View className="flex-1 space-y-2">
<Text numberOfLines={2} className="text-label text-lg font-semibold">
{title}
</Text>
<Text className="text-secondary-label line-clamp-2 text-sm">{description}</Text>
<Text className="text-tertiary-label text-xs">{publishedAt.toLocaleString()}</Text>
</View>
{image && (
<Image
source={{ uri: image }}
placeholder={{ blurhash }}
className="bg-system-fill ml-2 size-20 rounded-md"
contentFit="cover"
/>
)}
</ItemPressable>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Preview size="STRETCH" onPress={handlePress}>
{() => (
<View className="bg-system-background flex-1">
<Text className="text-label -mb-3 mt-5 p-4 text-2xl font-semibold" numberOfLines={2}>
{title}
</Text>
<EntryContentWebView entry={entry} />
</View>
)}
</ContextMenu.Preview>
</ContextMenu.Content>
</ContextMenu.Root>
)
}

View File

@ -133,6 +133,7 @@ const TeamsText = () => {
<ContextMenu.Content>
<ContextMenu.Preview
size="STRETCH"
onPress={useCallback(() => {
router.push("/terms")
}, [])}

View File

@ -4,6 +4,59 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
'@types/react': npm:@types/react@^18.3.12
'@types/react-dom': npm:@types/react-dom@^18.3.1
app-builder-lib: npm:app-builder-lib@^25.1.8
electron: 33.2.0
esbuild: npm:esbuild@^0.24.2
expo-modules-core: npm:expo-modules-core@2.2.0
is-core-module: npm:@nolyfill/is-core-module@^1
isarray: npm:@nolyfill/isarray@^1
lightningcss: npm:lightningcss@^1.29.1
react-native: npm:react-native@0.77.0
typescript: 5.7.3
unist-util-visit-parents: 5.1.3
vfile: 5.3.7
patchedDependencies:
'@microflash/remark-callout-directives':
hash: bl6uhe4vs4xm3d2jmecdpzbh2m
path: patches/@microflash__remark-callout-directives.patch
'@mozilla/readability':
hash: 43niildbdafdxi7qfcwhpkkxwa
path: patches/@mozilla__readability.patch
'@pengx17/electron-forge-maker-appimage':
hash: vov3v67fgv3lrfz3n24bnubw4m
path: patches/@pengx17__electron-forge-maker-appimage.patch
'@tanstack/react-virtual':
hash: 44veyovhgqddxy4cx3biv6jmoa
path: patches/@tanstack__react-virtual.patch
daisyui:
hash: igsntdatmoaxzwxof4bkkh35fy
path: patches/daisyui.patch
devlop:
hash: xzgzapu45daboiid4fiusduvwa
path: patches/devlop.patch
electron-context-menu:
hash: c53at4t5fflixuwjz35hmcqdu4
path: patches/electron-context-menu.patch
hono:
hash: qptujxncoai6tukc4qaqsrqk24
path: patches/hono.patch
immer@10.1.1:
hash: og7mbnoo5vh43tjlw5rbmrdbvu
path: patches/immer@10.1.1.patch
jsonpointer:
hash: prxuhlhyjugus5tiew4vc3pahu
path: patches/jsonpointer.patch
re-resizable:
hash: yitcmpfwcomg2fky72uc3lhk2i
path: patches/re-resizable@6.9.17.patch
workbox-precaching:
hash: frtipzgil4wle57aliuhcr746e
path: patches/workbox-precaching.patch
importers:
.:
@ -574,8 +627,8 @@ importers:
specifier: 15.8.0
version: 15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)
react-native-uikit-colors:
specifier: 0.1.2
version: 0.1.2(nativewind@4.1.23(react-native-reanimated@3.16.7(@babel/core@7.26.7)(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@5.1.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3)))
specifier: 0.2.0
version: 0.2.0(nativewind@4.1.23(react-native-reanimated@3.16.7(@babel/core@7.26.7)(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@5.1.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3)))
react-native-web:
specifier: ~0.19.13
version: 0.19.13(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -648,24 +701,6 @@ importers:
specifier: ^4.0.3
version: 4.0.3(3g6n6qn7ir7dwkefeyw6r7oy24)
apps/mobile/web-app/html-renderer:
dependencies:
'@follow/components':
specifier: workspace:*
version: link:../../../../packages/components
'@follow/types':
specifier: workspace:*
version: link:../../../../packages/types
clsx:
specifier: 2.1.1
version: 2.1.1
jotai:
specifier: 2.11.3
version: 2.11.3(@types/react@18.3.18)(react@18.3.1)
react-blurhash:
specifier: ^0.3.0
version: 0.3.0(blurhash@2.0.5)(react@18.3.1)
apps/renderer:
dependencies:
'@dnd-kit/core':
@ -10068,7 +10103,7 @@ packages:
resolution: {integrity: sha512-B/PsewAQ0UOS5e2+TTWegUPQ3SCLPCjPY24LYUjfn2EorGlluTA2dFjVLgF1+xHLjK9Jit3y5mKHyMG3Xq/GZg==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=17.0.0'
'@types/react': npm:@types/react@^18.3.12
react: '>=17.0.0'
peerDependenciesMeta:
'@types/react':
@ -12505,8 +12540,8 @@ packages:
react: '*'
react-native: npm:react-native@0.77.0
react-native-uikit-colors@0.1.2:
resolution: {integrity: sha512-dmlQAxfb3FHGpDQhB399/5gs0vE/6M4lV4rKBiCMmH6BB+w1PCNOIKOHtgX2YW0xEuoHJfS2mwoGjvyT/15wXg==}
react-native-uikit-colors@0.2.0:
resolution: {integrity: sha512-YYJHejX3JgmfGceo058fC8iFVhXdZtWjjqcb9lfSYVjYX29DnkcHmdjUGNLAK6M5R0/IFv9v7N2V2drpRKRVvA==}
peerDependencies:
nativewind: '>=4.1.0'
react: '>=18.0.0'
@ -29398,7 +29433,7 @@ snapshots:
react-native: 0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1)
warn-once: 0.1.1
react-native-uikit-colors@0.1.2(nativewind@4.1.23(react-native-reanimated@3.16.7(@babel/core@7.26.7)(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@5.1.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))):
react-native-uikit-colors@0.2.0(nativewind@4.1.23(react-native-reanimated@3.16.7(@babel/core@7.26.7)(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@5.1.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3))):
dependencies:
nativewind: 4.1.23(react-native-reanimated@3.16.7(@babel/core@7.26.7)(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@5.1.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.26.7(@babel/core@7.26.7))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3)))
react: 18.3.1