Files
frontend/src/screens/create/composers/ChannelPicker.tsx

140 lines
4.1 KiB
TypeScript
Raw Normal View History

/**
* /
* +
*/
import React from 'react';
import { View, TouchableOpacity, StyleSheet } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Text } from '../../../components/common';
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../../theme';
export type ChannelOption = { id: string; name: string };
interface ChannelPickerProps {
channels: ChannelOption[];
selectedId: string | null;
onSelect: (channelId: string) => void;
expanded: boolean;
onToggle: () => void;
}
export function ChannelPicker({
channels,
selectedId,
onSelect,
expanded,
onToggle,
}: ChannelPickerProps) {
const colors = useAppColors();
const styles = React.useMemo(() => createChannelPickerStyles(colors), [colors]);
const selectedName = React.useMemo(() => {
if (!selectedId) return '';
return channels.find(c => c.id === selectedId)?.name || '';
}, [selectedId, channels]);
return (
<>
{/* 入口行 */}
<TouchableOpacity style={styles.channelEntryRow} onPress={onToggle} activeOpacity={0.8}>
<Text variant="body" color={colors.text.secondary} style={styles.channelEntryLabel}>
</Text>
<View style={styles.channelEntryValueWrap}>
<Text
variant="body"
color={selectedName ? colors.text.primary : colors.text.hint}
style={styles.channelEntryValue}
>
{selectedName || '选择频道'}
</Text>
<MaterialCommunityIcons name="chevron-right" size={18} color={colors.text.hint} />
</View>
</TouchableOpacity>
{/* 展开面板 */}
{expanded && (
<View style={styles.tagsSection}>
<View style={styles.tagsContainer}>
{channels.map((channel) => {
const isSelected = selectedId === channel.id;
return (
<TouchableOpacity
key={channel.id}
style={[styles.tag, isSelected && styles.channelSelected]}
onPress={() => onSelect(channel.id)}
>
<Text
variant="caption"
color={isSelected ? colors.primary.contrast : colors.text.secondary}
style={styles.tagText}
>
{channel.name}
</Text>
</TouchableOpacity>
);
})}
</View>
{channels.length === 0 && (
<Text variant="caption" color={colors.text.hint}></Text>
)}
</View>
)}
</>
);
}
function createChannelPickerStyles(colors: AppColors) {
return StyleSheet.create({
channelEntryRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: spacing.lg,
paddingVertical: spacing.sm,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: colors.divider,
backgroundColor: colors.background.paper,
},
channelEntryLabel: {
fontSize: fontSizes.md,
},
channelEntryValueWrap: {
flexDirection: 'row',
alignItems: 'center',
gap: spacing.xs,
},
channelEntryValue: {
fontSize: fontSizes.md,
},
tagsSection: {
paddingHorizontal: spacing.lg,
paddingTop: spacing.md,
paddingBottom: spacing.sm,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: colors.divider,
backgroundColor: colors.background.paper,
},
tagsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: spacing.sm,
},
tag: {
backgroundColor: colors.background.default,
borderRadius: borderRadius.full,
paddingHorizontal: spacing.md,
paddingVertical: spacing.xs,
borderWidth: 1,
borderColor: colors.divider,
},
channelSelected: {
backgroundColor: colors.primary.main,
borderColor: colors.primary.main,
},
tagText: {
fontWeight: '500',
},
});
}