tabcss
This commit is contained in:
parent
32ff57f523
commit
f5c3639a0b
|
|
@ -18,6 +18,8 @@ import { useLikesTemplates } from '@/hooks/data/use-likes-templates'
|
|||
import { userBalanceStore, userStore } from '@/stores'
|
||||
import { screenWidth, storage } from '@/utils'
|
||||
import { cn } from '@/utils/cn'
|
||||
import ParallelogramButton from '@/components/ParallelogramButton'
|
||||
import ParallelogramShape from '@/components/ParallelogramShape'
|
||||
|
||||
const CATEGORY_ID = process.env.EXPO_PUBLIC_INDEX_GROUP_ID
|
||||
const ITEM_WIDTH = Math.floor((screenWidth - 24 - 12 * 2) / 3)
|
||||
|
|
@ -38,8 +40,7 @@ type MediaItem = {
|
|||
authorName?: string
|
||||
isLiked?: boolean
|
||||
}
|
||||
type ActiveTab = 'gen' | '' | 'new' | 'like'
|
||||
|
||||
type ActiveTab = 'gen' | 'HOT' | 'NEW' | 'LIKE'
|
||||
/** =========================
|
||||
* Entry page
|
||||
* ========================= */
|
||||
|
|
@ -53,7 +54,7 @@ const Index = observer(function Index() {
|
|||
|
||||
/** ================= 状态 ================= */
|
||||
|
||||
const [activeTab, setActiveTab] = useState<ActiveTab>('')
|
||||
const [activeTab, setActiveTab] = useState<ActiveTab>('HOT')
|
||||
const [isSearchOpen, setIsSearchOpen] = useState(false)
|
||||
|
||||
const [allItems, setAllItems] = useState<MediaItem[]>([])
|
||||
|
|
@ -142,7 +143,7 @@ const Index = observer(function Index() {
|
|||
const { page, pageSize, search, tab } = queryRef.current
|
||||
let newItems: MediaItem[] = []
|
||||
|
||||
if (tab === 'like') {
|
||||
if (tab === 'LIKE') {
|
||||
console.log('加载收藏列表,isAuthenticated=', isLogin)
|
||||
if (!isLogin) {
|
||||
setHasMore(false)
|
||||
|
|
@ -155,7 +156,7 @@ const Index = observer(function Index() {
|
|||
.map((f) => transformTemplateToMediaItem(f.template as TemplateData)) || []
|
||||
}
|
||||
} else {
|
||||
const sortBy = tab === 'new' ? 'createdAt' : 'likeCount'
|
||||
const sortBy = tab === 'NEW' ? 'createdAt' : 'likeCount'
|
||||
const { data } = await loadTemplates({
|
||||
page,
|
||||
limit: pageSize,
|
||||
|
|
@ -357,7 +358,7 @@ const Index = observer(function Index() {
|
|||
}
|
||||
|
||||
const renderListEmpty = () => {
|
||||
if (activeTab === 'like' && !isLogin) {
|
||||
if (activeTab === 'LIKE' && !isLogin) {
|
||||
return (
|
||||
<Block className="mt-[40px] items-center justify-center gap-[16px] py-[60px]">
|
||||
<Block className="size-[80px] items-center justify-center rounded-full border-4 border-white/20 bg-white/10">
|
||||
|
|
@ -526,35 +527,54 @@ const SearchOverlay = memo<SearchOverlayProps>(function SearchOverlay({ isOpen,
|
|||
onSearch('')
|
||||
onClose?.()
|
||||
}, [onClose, onSearch])
|
||||
|
||||
const searchHeight = 48
|
||||
const closeSize = 48
|
||||
const skewOffset = 8 // 统一所有平行四边形的倾斜角度
|
||||
const padding = 2
|
||||
const searchWidth = screenWidth - 40 - 8 - closeSize
|
||||
if (!isOpen) return null
|
||||
return (
|
||||
<Block className="absolute inset-x-0 top-0 z-50 mt-[24px] flex-row items-center gap-[8px] px-[20px]">
|
||||
<Block
|
||||
className="flex-1 flex-row items-center border-[3px] border-black bg-white px-[12px] shadow-[4px_4px_0px_#000]"
|
||||
style={{ height: 48, transform: [{ skewX: '-6deg' }] }}
|
||||
>
|
||||
<Ionicons color="black" name="search" size={20} style={{ marginRight: 8 }} />
|
||||
<TextInput
|
||||
autoFocus
|
||||
onChangeText={handleTextChange}
|
||||
placeholder="搜索作品 / 用户..."
|
||||
placeholderTextColor="#9CA3AF"
|
||||
style={{
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
}}
|
||||
value={searchText}
|
||||
/>
|
||||
<Block className="relative flex-1" style={{ height: searchHeight }}>
|
||||
<ParallelogramShape
|
||||
width={searchWidth}
|
||||
height={searchHeight}
|
||||
fillColor="#FFFFFF"
|
||||
padding={padding}
|
||||
skewOffset={skewOffset}
|
||||
>
|
||||
<Block className="absolute inset-0 flex-row items-center px-[18px]">
|
||||
<Ionicons color="black" name="search" size={20} style={{ marginRight: 8 }} />
|
||||
<TextInput
|
||||
autoFocus
|
||||
onChangeText={handleTextChange}
|
||||
placeholder="搜索作品 / 用户..."
|
||||
placeholderTextColor="#9CA3AF"
|
||||
style={{
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
}}
|
||||
value={searchText}
|
||||
/>
|
||||
</Block>
|
||||
</ParallelogramShape>
|
||||
</Block>
|
||||
<Block
|
||||
className="items-center justify-center border-[3px] border-black bg-accent shadow-[4px_4px_0px_#000]"
|
||||
onClick={handleClose}
|
||||
style={{ width: 48, height: 48, transform: [{ skewX: '-6deg' }] }}
|
||||
>
|
||||
<Ionicons color="black" name="close" size={24} style={{ transform: [{ skewX: '6deg' }] }} />
|
||||
|
||||
{/* 关闭按钮平行四边形 */}
|
||||
<Block className="relative" style={{ width: closeSize, height: closeSize }} onClick={handleClose}>
|
||||
<ParallelogramShape
|
||||
width={closeSize}
|
||||
height={closeSize}
|
||||
fillColor="#FFE500"
|
||||
padding={padding}
|
||||
skewOffset={skewOffset}
|
||||
>
|
||||
<Block className="absolute inset-0 items-center justify-center">
|
||||
<Ionicons color="black" name="close" size={24} />
|
||||
</Block>
|
||||
</ParallelogramShape>
|
||||
</Block>
|
||||
</Block>
|
||||
)
|
||||
|
|
@ -569,26 +589,63 @@ const GooActions = observer<GooActionsProps>(function GooActions({ gooPoints, on
|
|||
const { isPolling } = userBalanceStore
|
||||
const isDev = __DEV__
|
||||
const isLogin = userStore.isLogin
|
||||
|
||||
const width = 100
|
||||
const height = 32
|
||||
const skewOffset = 8 // 统一所有平行四边形的倾斜角度
|
||||
const padding = 2
|
||||
|
||||
const addWidth = 40
|
||||
const addHeight = height
|
||||
const addSkewOffset = 8 // 统一所有平行四边形的倾斜角度
|
||||
|
||||
return (
|
||||
<Block>
|
||||
<Block className="mt-[12px] flex-row items-center gap-[8px]">
|
||||
{!!isLogin && (
|
||||
<Block
|
||||
className="flex-row items-center gap-[4px] rounded-full border-[3px] border-white bg-black px-[12px] py-[8px] shadow-[3px_3px_0px_rgba(0,0,0,0.5)]"
|
||||
onClick={onAddGoo}
|
||||
>
|
||||
<Text className="text-[12px] font-black text-accent">{gooPoints}</Text>
|
||||
<Ionicons color="#FFE500" name="add" size={12} style={{ fontWeight: 'bold' }} />
|
||||
{isDev && isPolling && <Block className="ml-[4px] size-[6px] rounded-full bg-green-500" />}
|
||||
</Block>
|
||||
)}
|
||||
<Block
|
||||
className="relative"
|
||||
style={{ width, height }}
|
||||
onClick={onAddGoo}
|
||||
>
|
||||
<ParallelogramShape
|
||||
width={width}
|
||||
height={height}
|
||||
fillColor="#FFFFFF"
|
||||
strokeWidth={2}
|
||||
padding={padding}
|
||||
skewOffset={skewOffset}
|
||||
>
|
||||
<Block className="absolute inset-0 flex-row items-center gap-[4px] pl-[12px]">
|
||||
{isDev && isPolling && <Block className="ml-[4px] size-[6px] rounded-full bg-green-500" />}
|
||||
<Text className="text-[12px] font-black text-accent">{gooPoints}</Text>
|
||||
<Block className="ml-auto h-full relative" style={{ width: addWidth }}>
|
||||
<ParallelogramShape
|
||||
width={addWidth}
|
||||
height={addHeight}
|
||||
fillColor="#FAE307"
|
||||
strokeWidth={1}
|
||||
padding={padding}
|
||||
skewOffset={addSkewOffset}
|
||||
showShadow={false}
|
||||
>
|
||||
<Block className="absolute inset-0 items-center justify-center">
|
||||
<Ionicons color="#323232" name="add" size={12} style={{ fontWeight: 'bold' }} />
|
||||
</Block>
|
||||
</ParallelogramShape>
|
||||
</Block>
|
||||
</Block>
|
||||
</ParallelogramShape>
|
||||
|
||||
</Block>
|
||||
)}
|
||||
<Block
|
||||
className="size-[48px] items-center justify-center rounded-full border-[3px] border-black bg-white shadow-[4px_4px_0px_#000]"
|
||||
className="size-[40px] items-center justify-center rounded-full border-[2px] border-black bg-white shadow-[4px_4px_0px_#000]"
|
||||
onClick={onOpenSearch}
|
||||
>
|
||||
<Ionicons color="black" name="search" size={22} />
|
||||
<Ionicons color="black" name="search" size={20} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
)
|
||||
})
|
||||
|
|
@ -656,29 +713,30 @@ type FilterSectionProps = {
|
|||
const FilterSection = memo<FilterSectionProps>(function FilterSection({ activeTab, onChange }) {
|
||||
const tabs = useMemo(
|
||||
() => [
|
||||
{ label: '最热', state: '' as const },
|
||||
{ label: '最新', state: 'new' as const },
|
||||
{ label: '喜欢', state: 'like' as const },
|
||||
{ label: '最热', state: 'HOT' as const },
|
||||
{ label: '最新', state: 'NEW' as const },
|
||||
{ label: '喜欢', state: 'LIKE' as const },
|
||||
],
|
||||
[],
|
||||
)
|
||||
|
||||
return (
|
||||
<Block className="mt-[12px] flex-row items-end justify-between">
|
||||
<Block className="flex-row gap-[8px]">
|
||||
<Block className="flex-row gap-[4px]">
|
||||
{tabs.map(({ label, state }) => {
|
||||
const isActive = activeTab === state
|
||||
const buttonWidth = Math.max(label.length * 13 + 12, 66) // 最小宽度 70,适应13px字体
|
||||
const buttonHeight = 30 // 稍微增加高度以适应13px字体
|
||||
return (
|
||||
<Block
|
||||
className={`border-2 border-black px-[16px] py-[4px] ${isActive ? 'bg-accent' : 'bg-white'}`}
|
||||
<ParallelogramButton
|
||||
key={state}
|
||||
onClick={() => onChange(state)}
|
||||
style={{
|
||||
transform: [{ skewX: '-6deg' }],
|
||||
}}
|
||||
>
|
||||
<Text className={`text-[10px] font-[900] ${isActive ? 'text-black' : 'text-gray-500'}`}>{label}</Text>
|
||||
</Block>
|
||||
label={label}
|
||||
state={state}
|
||||
isActive={isActive}
|
||||
onPress={() => onChange(state)}
|
||||
width={buttonWidth}
|
||||
height={buttonHeight}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Block>
|
||||
|
|
|
|||
Loading…
Reference in New Issue