import React, { useState, useRef } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, PanResponder, Alert } from 'react-native'; import { Canvas, Path, Skia } from '@shopify/react-native-skia'; export default function WhiteboardScreen() { const [paths, setPaths] = useState>([]); const [color, setColor] = useState('#00A0C8'); const [strokeWidth, setStrokeWidth] = useState(3); const currentPath = useRef(''); const drawing = useRef(false); const COLORS = ['#00A0C8', '#ff4444', '#44bb44', '#ffbb00', '#bb44bb', '#fff']; const panResponder = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderGrant: (e) => { const { locationX, locationY } = e.nativeEvent; currentPath.current = `M${locationX} ${locationY}`; drawing.current = true; }, onPanResponderMove: (e) => { if (!drawing.current) return; const { locationX, locationY } = e.nativeEvent; currentPath.current += ` L${locationX} ${locationY}`; setPaths(prev => { const next = [...prev]; if (next.length && next[next.length - 1].d === 'drawing') { next[next.length - 1] = { d: currentPath.current, color, width: strokeWidth }; } else { next.push({ d: currentPath.current, color, width: strokeWidth }); } return next; }); }, onPanResponderRelease: () => { drawing.current = false; }, }); const clear = () => { setPaths([]); currentPath.current = ''; }; const undo = () => setPaths(prev => prev.slice(0, -1)); const share = () => Alert.alert('공유', 'SR 채팅방으로 화이트보드를 공유합니다'); return ( 화이트보드 실행취소 지우기 공유 {paths.map((p, i) => { const skiaPath = Skia.Path.MakeFromSVGString(p.d); if (!skiaPath) return null; const paint = Skia.Paint(); paint.setColor(Skia.Color(p.color)); paint.setStrokeWidth(p.width); paint.setStyle(1); return ; })} {COLORS.map(c => ( setColor(c)} /> ))} {[2, 4, 8].map(w => ( setStrokeWidth(w)}> ))} ); } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0A0E1A' }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 12, borderBottomWidth: 1, borderBottomColor: '#333' }, title: { color: '#fff', fontSize: 18, fontWeight: '700' }, headerActions: { flexDirection: 'row', gap: 8 }, headerBtn: { paddingHorizontal: 12, paddingVertical: 6, backgroundColor: '#1A1F2E', borderRadius: 8 }, headerBtnText: { color: '#aaa', fontSize: 13 }, shareBtn: { backgroundColor: '#003366' }, shareBtnText: { color: '#fff', fontWeight: '700', fontSize: 13 }, canvas: { flex: 1 }, toolbar: { padding: 12, borderTopWidth: 1, borderTopColor: '#333', backgroundColor: '#0A0E1A' }, colorRow: { flexDirection: 'row', gap: 10, marginBottom: 10, justifyContent: 'center' }, colorBtn: { width: 28, height: 28, borderRadius: 14 }, widthRow: { flexDirection: 'row', gap: 16, justifyContent: 'center', alignItems: 'center' }, widthBtn: { padding: 8, borderRadius: 8 }, widthBtnActive: { backgroundColor: '#1A1F2E' }, widthDot: { backgroundColor: '#fff' }, });