mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 18:26:41 +02:00
feat(chat): integrate chat project into monorepo with full app structure
- Restructure chat as apps/mobile, apps/web, apps/landing, backend - Add NestJS backend for secure Azure OpenAI API calls - Remove exposed API key from mobile app (security fix) - Add shared chat-types package - Create SvelteKit web app scaffold - Create Astro landing page scaffold - Update pnpm workspace configuration - Add project-level CLAUDE.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fcf3a344b1
commit
c638a7ffee
155 changed files with 22622 additions and 348 deletions
81
chat/apps/mobile/components/SkeletonLoader.tsx
Normal file
81
chat/apps/mobile/components/SkeletonLoader.tsx
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { View, Animated, Easing, StyleSheet } from 'react-native';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
type SkeletonLoaderProps = {
|
||||
lines?: number;
|
||||
animated?: boolean;
|
||||
style?: any;
|
||||
};
|
||||
|
||||
export default function SkeletonLoader({
|
||||
lines = 3,
|
||||
animated = true,
|
||||
style
|
||||
}: SkeletonLoaderProps) {
|
||||
const { colors } = useTheme();
|
||||
const [fadeAnim] = useState(new Animated.Value(0.3));
|
||||
|
||||
useEffect(() => {
|
||||
if (animated) {
|
||||
Animated.loop(
|
||||
Animated.sequence([
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 0.8,
|
||||
duration: 800,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 0.3,
|
||||
duration: 800,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
])
|
||||
).start();
|
||||
}
|
||||
}, [fadeAnim, animated]);
|
||||
|
||||
// Erstelle verschiedene Längen für die Zeilen
|
||||
const getRandomWidth = (index: number) => {
|
||||
// Erste und letzte Zeile sind kürzer
|
||||
if (index === 0) return { width: '70%' };
|
||||
if (index === lines - 1) return { width: '40%' };
|
||||
|
||||
// Zufällige Breite für die Zeilen dazwischen
|
||||
const widths = ['85%', '90%', '75%', '95%'];
|
||||
return { width: widths[index % widths.length] };
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
{Array.from({ length: lines }).map((_, index) => (
|
||||
<Animated.View
|
||||
key={index}
|
||||
style={[
|
||||
styles.line,
|
||||
getRandomWidth(index),
|
||||
{
|
||||
backgroundColor: colors.text + '20',
|
||||
opacity: fadeAnim,
|
||||
marginBottom: index === lines - 1 ? 0 : 8
|
||||
},
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
padding: 16,
|
||||
maxWidth: '80%',
|
||||
alignSelf: 'flex-start',
|
||||
},
|
||||
line: {
|
||||
height: 15,
|
||||
borderRadius: 4,
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue