Skip to content

Commit

Permalink
Merge branch 'dev' into feat/rn-mirco-app
Browse files Browse the repository at this point in the history
  • Loading branch information
Innei authored Feb 6, 2025
2 parents a2d5c18 + 631b240 commit 0a4c989
Show file tree
Hide file tree
Showing 41 changed files with 584 additions and 446 deletions.
1 change: 0 additions & 1 deletion apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
"react-native": "npm:[email protected]",
"react-native-bouncy-checkbox": "4.1.2",
"react-native-color-matrix-image-filters": "^7.0.2",
"react-native-context-menu-view": "1.16.0",
"react-native-gesture-handler": "~2.22.0",
"react-native-image-colors": "2.4.0",
"react-native-ios-context-menu": "3.1.0",
Expand Down
54 changes: 0 additions & 54 deletions apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx

This file was deleted.

72 changes: 40 additions & 32 deletions apps/mobile/src/components/ui/form/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { cn } from "@follow/utils"
import { useEffect, useMemo, useState } from "react"
import type { StyleProp, ViewStyle } from "react-native"
import { Text, View } from "react-native"
import { useEventCallback } from "usehooks-ts"
import * as DropdownMenu from "zeego/dropdown-menu"

import { MingcuteDownLineIcon } from "@/src/icons/mingcute_down_line"
import { accentColor } from "@/src/theme/colors"

import { DropdownMenu } from "../dropdown/DropdownMenu"
import { FormLabel } from "./Label"

interface SelectProps<T> {
Expand Down Expand Up @@ -43,44 +42,53 @@ export function Select<T>({
}, new Map<T, string>())
}, [options])

const handleChangeValue = useEventCallback((value: T) => {
setCurrentValue(value)
onValueChange(value)
})

useEffect(() => {
onValueChange(currentValue)
}, [])

const Trigger = (
<DropdownMenu<T>
options={options.map((option) => ({
label: option.label,
value: option.value,
}))}
currentValue={currentValue}
handleChangeValue={handleChangeValue}
>
<View
className={cn(
"flex-1 shrink flex-row items-center rounded-lg pl-3",
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<View
className={cn(
"min-w-24 flex-1 shrink flex-row items-center rounded-lg pl-3",

wrapperClassName,
)}
style={wrapperStyle}
>
<Text
className="min-w-0 flex-1 text-right font-semibold text-accent"
ellipsizeMode="middle"
numberOfLines={1}
wrapperClassName,
)}
style={wrapperStyle}
>
{valueToLabelMap.get(currentValue)}
</Text>
<View className="ml-auto shrink-0 pl-1">
<MingcuteDownLineIcon color={accentColor} height={18} width={18} />
<Text
className="flex-1 text-right font-semibold text-accent"
ellipsizeMode="middle"
numberOfLines={1}
>
{valueToLabelMap.get(currentValue)}
</Text>
<View className="ml-auto shrink-0 pl-1">
<MingcuteDownLineIcon color={accentColor} height={18} width={18} />
</View>
</View>
</View>
</DropdownMenu>
</DropdownMenu.Trigger>

<DropdownMenu.Content>
{options.map((option) => {
const isSelected = currentValue === option.value
const handleSelect = () => {
setCurrentValue(option.value)
onValueChange(option.value)
}
return (
<DropdownMenu.CheckboxItem
key={option.label}
value={isSelected}
onSelect={handleSelect}
>
<DropdownMenu.ItemTitle>{option.label}</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
)
})}
</DropdownMenu.Content>
</DropdownMenu.Root>
)

if (!label) {
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/src/modules/entry-list/entry-list-gird.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { NavigationContext } from "@/src/components/common/SafeNavigationScrollV
import { ThemedText } from "@/src/components/common/ThemedText"
import { ItemPressable } from "@/src/components/ui/pressable/item-pressable"
import { useEntry } from "@/src/store/entry/hooks"
import { debouncedFetchEntryContentByStream } from "@/src/store/entry/store"

import { useSelectedFeed } from "../feed-drawer/atoms"

Expand All @@ -33,6 +34,10 @@ export function EntryListContentGrid({
renderItem={useTypeScriptHappyCallback(({ item }) => {
return <RenderEntryItem id={item} />
}, [])}
keyExtractor={(id) => id}
onViewableItemsChanged={({ viewableItems }) => {
debouncedFetchEntryContentByStream(viewableItems.map((item) => item.key))
}}
numColumns={2}
onScroll={useTypeScriptHappyCallback(
(e) => {
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/src/modules/entry-list/entry-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ItemPressable } from "@/src/components/ui/pressable/item-pressable"
import { useDefaultHeaderHeight } from "@/src/hooks/useDefaultHeaderHeight"
import { useSelectedFeed, useSelectedFeedTitle } from "@/src/modules/feed-drawer/atoms"
import { useEntry } from "@/src/store/entry/hooks"
import { debouncedFetchEntryContentByStream } from "@/src/store/entry/store"

import { ViewSelector } from "../feed-drawer/view-selector"
import { LeftAction, RightAction } from "./action"
Expand Down Expand Up @@ -79,6 +80,10 @@ function EntryListContent({ entryIds }: { entryIds: string[] }) {
),
[],
)}
keyExtractor={(id) => id}
onViewableItemsChanged={({ viewableItems }) => {
debouncedFetchEntryContentByStream(viewableItems.map((item) => item.key))
}}
scrollIndicatorInsets={{
top: headerHeight - insets.top,
bottom: tabBarHeight - insets.bottom,
Expand Down
16 changes: 9 additions & 7 deletions apps/mobile/src/modules/settings/routes/General.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export const GeneralScreen = () => {
<GroupedInsetListBaseCell>
<Text className="text-label">Translation Language</Text>

<Select
value={translationLanguage}
onValueChange={(value) => {
setGeneralSetting("translationLanguage", value)
}}
options={Object.values(LanguageMap)}
/>
<View className="w-[150px]">
<Select
value={translationLanguage}
onValueChange={(value) => {
setGeneralSetting("translationLanguage", value)
}}
options={Object.values(LanguageMap)}
/>
</View>
</GroupedInsetListBaseCell>
</GroupedInsetListCard>
</View>
Expand Down
134 changes: 85 additions & 49 deletions apps/mobile/src/modules/subscription/header-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from "react"
import { TouchableOpacity } from "react-native"
import type { ContextMenuAction } from "react-native-context-menu-view"
import * as DropdownMenu from "zeego/dropdown-menu"

import { DropdownMenu } from "@/src/components/ui/dropdown/DropdownMenu"
import { ListExpansionCuteReIcon } from "@/src/icons/list_expansion_cute_re"

import {
Expand All @@ -15,58 +15,94 @@ export const SortActionButton = () => {
const sortMethod = useFeedListSortMethod()
const sortOrder = useFeedListSortOrder()

const alphabetOrderActions: ContextMenuAction[] = [
{ title: "Ascending", selected: sortMethod === "alphabet" && sortOrder === "asc" },
{ title: "Descending", selected: sortMethod === "alphabet" && sortOrder === "desc" },
]
const actions = useMemo(() => {
const alphabetOrderActions = [
{
title: "Ascending",
selected: sortMethod === "alphabet" && sortOrder === "asc",
onSelect: () => {
setFeedListSortMethod("alphabet")
setFeedListSortOrder("asc")
},
},
{
title: "Descending",
selected: sortMethod === "alphabet" && sortOrder === "desc",
onSelect: () => {
setFeedListSortMethod("alphabet")
setFeedListSortOrder("desc")
},
},
]

const countOrderActions: ContextMenuAction[] = [
{ title: "Ascending", selected: sortMethod === "count" && sortOrder === "asc" },
{ title: "Descending", selected: sortMethod === "count" && sortOrder === "desc" },
]
const countOrderActions = [
{
title: "Ascending",
selected: sortMethod === "count" && sortOrder === "asc",
onSelect: () => {
setFeedListSortMethod("count")
setFeedListSortOrder("asc")
},
},
{
title: "Descending",
selected: sortMethod === "count" && sortOrder === "desc",
onSelect: () => {
setFeedListSortMethod("count")
setFeedListSortOrder("desc")
},
},
]

const actions: ContextMenuAction[] = [
{
title: "Sort by Alphabet",
actions: alphabetOrderActions,
selected: sortMethod === "alphabet",
},
{ title: "Sort by Unread Count", actions: countOrderActions, selected: sortMethod === "count" },
]
return [
{
title: "Sort by Alphabet",
actions: alphabetOrderActions,
selected: sortMethod === "alphabet",
},
{
title: "Sort by Unread Count",
actions: countOrderActions,
selected: sortMethod === "count",
},
]
}, [sortMethod, sortOrder])

return (
<TouchableOpacity className="size-5 rounded-full">
<DropdownMenu
options={actions}
currentValue={sortMethod}
handlePress={(e) => {
const [firstArgs, secondary] = e.nativeEvent.indexPath
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<TouchableOpacity className="size-5 rounded-full">
<ListExpansionCuteReIcon width={20} height={20} />
</TouchableOpacity>
</DropdownMenu.Trigger>

switch (firstArgs) {
case 0: {
setFeedListSortMethod("alphabet")
break
}
case 1: {
setFeedListSortMethod("count")
break
}
}
<DropdownMenu.Content>
{actions.map((action) => {
const subActions = action.actions
return (
<DropdownMenu.Sub key={`Sub/${action.title}`}>
<DropdownMenu.SubTrigger key={`SubTrigger/${action.title}`}>
<DropdownMenu.ItemTitle>{action.title}</DropdownMenu.ItemTitle>
</DropdownMenu.SubTrigger>

switch (secondary) {
case 0: {
setFeedListSortOrder("asc")
break
}
case 1: {
setFeedListSortOrder("desc")
break
}
}
}}
>
<ListExpansionCuteReIcon width={20} height={20} />
</DropdownMenu>
</TouchableOpacity>
<DropdownMenu.SubContent>
{subActions.map((subAction) => {
const isSelected = subAction.selected
return (
<DropdownMenu.CheckboxItem
key={`SubContent/${action.title}/${subAction.title}`}
value={isSelected}
onSelect={subAction.onSelect}
>
<DropdownMenu.ItemTitle>{subAction.title}</DropdownMenu.ItemTitle>
</DropdownMenu.CheckboxItem>
)
})}
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
)
})}
</DropdownMenu.Content>
</DropdownMenu.Root>
)
}
6 changes: 5 additions & 1 deletion apps/mobile/src/services/entry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { eq } from "drizzle-orm"
import { eq, inArray } from "drizzle-orm"

import { db } from "../database"
import { entriesTable } from "../database/schemas"
Expand Down Expand Up @@ -28,6 +28,10 @@ class EntryServiceStatic implements Hydratable, Resetable {
await db.update(entriesTable).set(entry).where(eq(entriesTable.id, entry.id))
}

getEntryMany(entryId: string[]) {
return db.query.entriesTable.findMany({ where: inArray(entriesTable.id, entryId) })
}

async hydrate() {
const entries = await db.query.entriesTable.findMany()
entryActions.upsertManyInSession(entries.map((e) => dbStoreMorph.toEntryModel(e)))
Expand Down
Loading

0 comments on commit 0a4c989

Please sign in to comment.