mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 13:39:41 +02:00
Move inactive projects out of active workspace: - bauntown (community website) - maerchenzauber (AI story generation) - memoro (voice memo app) - news (news aggregation) - nutriphi (nutrition tracking) - reader (reading app) - uload (URL shortener) - wisekeep (AI wisdom extraction) Update CLAUDE.md documentation: - Add presi to active projects - Document archived projects section - Update workspace configuration Archived apps can be re-activated by moving back to apps/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
257 lines
6.2 KiB
TypeScript
257 lines
6.2 KiB
TypeScript
import React from 'react';
|
|
import { BlurView } from 'expo-blur';
|
|
import { View, StyleSheet, TouchableOpacity, Platform } from 'react-native';
|
|
import { useWindowDimensions } from 'react-native';
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
import { useRouter } from 'expo-router';
|
|
import Text from '../atoms/Text';
|
|
import Icon from '../atoms/Icon';
|
|
import { useDebugBorders } from '../../hooks/useDebugBorders';
|
|
import ManaCounter from './ManaCounter';
|
|
import HeaderMenu from './HeaderMenu';
|
|
|
|
interface CommonHeaderProps {
|
|
title: string;
|
|
showBackButton?: boolean;
|
|
showSettingsButton?: boolean;
|
|
showManaButton?: boolean;
|
|
onBack?: () => void;
|
|
onSettingsPress?: () => void;
|
|
onManaPress?: () => void;
|
|
rightComponent?: React.ReactNode;
|
|
level?: number;
|
|
showAppIcon?: boolean;
|
|
showLogo?: boolean;
|
|
}
|
|
|
|
export default function CommonHeader({
|
|
title,
|
|
showBackButton = true,
|
|
showSettingsButton = false,
|
|
showManaButton = false,
|
|
onBack,
|
|
onSettingsPress,
|
|
onManaPress,
|
|
rightComponent,
|
|
level,
|
|
showAppIcon = false,
|
|
showLogo = false,
|
|
}: CommonHeaderProps) {
|
|
const router = useRouter();
|
|
const { width: windowWidth } = useWindowDimensions();
|
|
const insets = useSafeAreaInsets();
|
|
const isWeb = Platform.OS === 'web';
|
|
const isWideScreen = windowWidth > 1000;
|
|
const isTablet = windowWidth >= 768;
|
|
|
|
// Responsive font size for title
|
|
const titleFontSize = isTablet ? 26 : 18;
|
|
|
|
const handleBack = () => {
|
|
if (onBack) {
|
|
onBack();
|
|
} else {
|
|
router.back();
|
|
}
|
|
};
|
|
|
|
const handleSettings = () => {
|
|
if (onSettingsPress) {
|
|
onSettingsPress();
|
|
} else {
|
|
router.push('/settings');
|
|
}
|
|
};
|
|
|
|
const handleMana = () => {
|
|
if (onManaPress) {
|
|
onManaPress();
|
|
} else {
|
|
router.push('/subscription');
|
|
}
|
|
};
|
|
|
|
// Verschiedene Debug-Borders für unterschiedliche Bereiche
|
|
const containerDebug = useDebugBorders('#00FF00', { borderStyle: 'dashed' });
|
|
const leftSectionDebug = useDebugBorders('#FF0000', { borderStyle: 'dashed' });
|
|
const titleDebug = useDebugBorders('#0000FF', { borderStyle: 'dashed' });
|
|
const blurDebug = useDebugBorders('#FF00FF', { borderStyle: 'dashed' });
|
|
const rightSectionDebug = useDebugBorders('#FF00FF');
|
|
const buttonDebug = useDebugBorders('#FFA500');
|
|
|
|
const headerContent = (
|
|
<>
|
|
<View style={[styles.leftSection, leftSectionDebug]}>
|
|
{showBackButton && (
|
|
<TouchableOpacity
|
|
onPress={handleBack}
|
|
style={[styles.iconButton, buttonDebug]}
|
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
>
|
|
<Icon set="ionicons" name="chevron-back" size={24} color="#ffffff" />
|
|
</TouchableOpacity>
|
|
)}
|
|
{showManaButton && <ManaCounter onPress={handleMana} size="small" />}
|
|
{showLogo && (
|
|
<View style={styles.logoContainer}>
|
|
<ManaCounter onPress={handleMana} size="small" />
|
|
</View>
|
|
)}
|
|
</View>
|
|
<View style={[styles.centerSection, titleDebug]}>
|
|
<View style={styles.titleContainer}>
|
|
<Text
|
|
style={[
|
|
styles.title,
|
|
{ fontSize: titleFontSize },
|
|
!showBackButton && styles.titleWithoutBack,
|
|
]}
|
|
numberOfLines={1}
|
|
ellipsizeMode="tail"
|
|
{...(Platform.OS === 'android' ? { includeFontPadding: false } : {})}
|
|
>
|
|
{title}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
<View style={[styles.rightSection, rightSectionDebug]}>
|
|
{rightComponent}
|
|
{showSettingsButton && (
|
|
<HeaderMenu
|
|
onSettingsPress={handleSettings}
|
|
onArchivePress={() => router.push('/archive')}
|
|
onHelpPress={() => router.push('/help')}
|
|
onManaPress={handleMana}
|
|
onFeedbackPress={() => router.push('/feedback')}
|
|
/>
|
|
)}
|
|
</View>
|
|
</>
|
|
);
|
|
|
|
return (
|
|
<View style={[styles.headerWrapper, containerDebug]}>
|
|
{isWeb && isWideScreen ? (
|
|
<View style={[styles.container, styles.webContainer, containerDebug]}>{headerContent}</View>
|
|
) : Platform.OS === 'android' ? (
|
|
<View
|
|
style={[
|
|
styles.blurContainer,
|
|
styles.androidHeader,
|
|
{ paddingTop: insets.top + 4 },
|
|
blurDebug,
|
|
]}
|
|
>
|
|
<View style={[styles.container, containerDebug]}>{headerContent}</View>
|
|
</View>
|
|
) : (
|
|
<BlurView
|
|
intensity={250}
|
|
tint="dark"
|
|
style={[styles.blurContainer, { paddingTop: insets.top + 8 }, blurDebug]}
|
|
>
|
|
<View style={[styles.container, containerDebug]}>{headerContent}</View>
|
|
</BlurView>
|
|
)}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
debug: {
|
|
borderWidth: 1,
|
|
borderStyle: 'dashed',
|
|
},
|
|
headerWrapper: {
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
zIndex: 1000,
|
|
...(Platform.OS === 'web'
|
|
? {
|
|
paddingTop: 0,
|
|
paddingHorizontal: 16,
|
|
}
|
|
: {}),
|
|
},
|
|
blurContainer: {
|
|
paddingVertical: 16,
|
|
paddingHorizontal: 16,
|
|
// paddingTop wird jetzt dynamisch über useSafeAreaInsets gesetzt
|
|
},
|
|
androidHeader: {
|
|
backgroundColor: 'rgba(24, 24, 24, 0.95)',
|
|
borderBottomWidth: 0.5,
|
|
borderBottomColor: 'rgba(255, 255, 255, 0.1)',
|
|
},
|
|
container: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
backgroundColor: 'transparent',
|
|
marginTop: Platform.OS === 'web' ? 0 : Platform.OS === 'android' ? 4 : 8,
|
|
alignSelf: 'center',
|
|
height: 48,
|
|
width: '100%',
|
|
maxWidth: 900,
|
|
paddingHorizontal: 0,
|
|
},
|
|
webContainer: {
|
|
marginTop: 0,
|
|
paddingTop: 8,
|
|
maxWidth: 1400,
|
|
width: '100%',
|
|
},
|
|
leftSection: {
|
|
flex: 0.8,
|
|
minWidth: 40,
|
|
height: '100%',
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-start',
|
|
flexDirection: 'row',
|
|
gap: 8,
|
|
},
|
|
centerSection: {
|
|
flex: 2,
|
|
height: '100%',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
flexDirection: 'row',
|
|
paddingHorizontal: 8,
|
|
},
|
|
rightSection: {
|
|
flex: 0.8,
|
|
minWidth: 40,
|
|
height: '100%',
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-end',
|
|
flexDirection: 'row',
|
|
gap: 8,
|
|
},
|
|
titleContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
title: {
|
|
...(Platform.OS === 'android'
|
|
? { fontFamily: 'Grandstander_700Bold', paddingTop: 0, lineHeight: 26 }
|
|
: { fontFamily: 'Grandstander_700Bold', fontWeight: '700' as const, paddingTop: 5 }),
|
|
color: '#FFFFFF',
|
|
textAlign: 'center',
|
|
letterSpacing: 0.5,
|
|
},
|
|
iconButton: {
|
|
width: 40,
|
|
height: 40,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
borderRadius: 20,
|
|
backgroundColor: 'rgba(255, 255, 255, 0.00)',
|
|
},
|
|
titleWithoutBack: {},
|
|
logoContainer: {
|
|
marginRight: 0,
|
|
},
|
|
});
|