Add Sign in with Apple sorta

This commit is contained in:
2025-03-05 12:58:18 -06:00
parent 06471f688a
commit c62926b8f2
35 changed files with 1458 additions and 620 deletions

View File

@@ -0,0 +1,84 @@
import React from 'react';
import { StyleSheet, Image, ImageProps, View } from 'react-native';
import ThemedText from '@/components/theme/default/ThemedText';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
type ThemedAvatarProps = Omit<ImageProps, 'source'> & {
size?: number;
source?: ImageProps['source'];
name?: string;
borderWidth?: number;
borderColor?: string;
};
const ThemedAvatar: React.FC<ThemedAvatarProps> = ({
size = 50,
source,
name,
borderWidth = 0,
borderColor,
style,
...restProps
}) => {
const scheme = useColorScheme() ?? 'dark';
const border = borderColor || Colors[scheme].tint;
// Get initials from name
const getInitials = (name?: string) => {
if (!name) return '';
return name
.split(' ')
.map((part) => part[0])
.join('')
.toUpperCase()
.substring(0, 2);
};
const initials = getInitials(name);
return (
<View
style={[
styles.container,
{
width: size,
height: size,
borderRadius: size / 2,
borderWidth,
borderColor: border,
backgroundColor: source ? 'transparent' : Colors[scheme].tint,
},
]}
>
{source ? (
<Image
source={source}
style={[
{
width: size - 2 * borderWidth,
height: size - 2 * borderWidth,
borderRadius: (size - 2 * borderWidth) / 2,
},
style,
]}
{...restProps}
/>
) : (
<ThemedText style={{ color: Colors[scheme].background, fontSize: size * 0.4 }}>
{initials}
</ThemedText>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
},
});
export default ThemedAvatar;

View File

@@ -0,0 +1,58 @@
import React from 'react';
import { StyleSheet, ViewProps } from 'react-native';
import ThemedText from '@/components/theme/default/ThemedText';
import ThemedView from '@/components/theme/default/ThemedView';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
type ThemedBadgeProps = ViewProps & {
value: number | string;
size?: number;
color?: string;
textColor?: string;
};
const ThemedBadge: React.FC<ThemedBadgeProps> = ({
value,
size = 24,
color,
textColor,
style,
...restProps
}) => {
const scheme = useColorScheme() ?? 'dark';
const badgeColor = color || Colors[scheme].tint;
const badgeTextColor = textColor || Colors[scheme].background;
return (
<ThemedView
style={[
styles.badge,
{
width: size,
height: size,
borderRadius: size / 2,
backgroundColor: badgeColor,
},
style,
]}
{...restProps}
>
<ThemedText style={[styles.text, { color: badgeTextColor, fontSize: size * 0.5 }]}>
{value}
</ThemedText>
</ThemedView>
);
};
const styles = StyleSheet.create({
badge: {
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontWeight: 'bold',
},
});
export default ThemedBadge;

View File

@@ -0,0 +1,64 @@
import React from 'react';
import { StyleSheet, ViewProps, Platform, DimensionValue } from 'react-native';
import ThemedView from '@/components/theme/default/ThemedView';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
type ThemedCardProps = ViewProps & {
width?: DimensionValue;
height?: DimensionValue;
padding?: number;
elevation?: number;
borderRadius?: number;
};
const ThemedCard: React.FC<ThemedCardProps> = ({
width = '100%',
height,
padding = 16,
elevation = 3,
borderRadius = 12,
style,
children,
...restProps
}) => {
const scheme = useColorScheme() ?? 'dark';
return (
<ThemedView
style={[
styles.card,
{
width,
height,
padding,
borderRadius,
backgroundColor: Colors[scheme].card,
...Platform.select({
ios: {
shadowColor: Colors[scheme].text,
shadowOffset: { width: 0, height: elevation / 2 },
shadowOpacity: 0.1,
shadowRadius: elevation,
},
android: {
elevation,
},
}),
},
style,
]}
{...restProps}
>
{children}
</ThemedView>
);
};
const styles = StyleSheet.create({
card: {
overflow: 'hidden',
},
});
export default ThemedCard;

View File

@@ -0,0 +1,37 @@
import React from 'react';
import { StyleSheet, ViewProps, View, DimensionValue } from 'react-native';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
type ThemedDividerProps = ViewProps & {
orientation?: 'horizontal' | 'vertical';
thickness?: DimensionValue;
length?: DimensionValue;
color?: string;
};
const ThemedDivider: React.FC<ThemedDividerProps> = ({
orientation = 'horizontal',
thickness = 1,
length = '100%',
style,
...restProps
}) => {
const scheme = useColorScheme() ?? 'dark';
const color = restProps.color || Colors[scheme].border;
return (
<View
style={[
orientation === 'horizontal'
? { height: thickness, width: length }
: { width: thickness, height: length },
{ backgroundColor: color },
style,
]}
{...restProps}
/>
);
};
export default ThemedDivider;

View File

@@ -0,0 +1,20 @@
import React from 'react';
import { StyleSheet, ViewProps } from 'react-native';
import { Ionicons } from '@expo/vector-icons'; // Or your preferred icon library
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
type ThemedIconProps = ViewProps & {
name: string;
size?: number;
color?: string;
};
const ThemedIcon: React.FC<ThemedIconProps> = ({ name, size = 24, color, style, ...restProps }) => {
const scheme = useColorScheme() ?? 'dark';
const iconColor = color || Colors[scheme].text;
return <Ionicons name={name} size={size} color={iconColor} style={style} {...restProps} />;
};
export default ThemedIcon;