import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/msn_api.dart'; import '../../core/session_controller.dart'; import '../../models/context_model.dart'; import '../../models/profile_model.dart'; import '../../theme/toss_theme.dart'; import 'home_providers.dart'; final myProfileForContextProvider = FutureProvider.autoDispose.family((ref, contextId) async { return ref.watch(msnApiProvider).getMyProfile(contextId); }); /// Edit display name and status per messenger space, with 일상 / 직장 segment synced to top chips. class MyProfileTab extends ConsumerStatefulWidget { const MyProfileTab({super.key}); @override ConsumerState createState() => _MyProfileTabState(); } class _MyProfileTabState extends ConsumerState { final _nameCtrl = TextEditingController(); final _statusCtrl = TextEditingController(); bool _dirty = false; bool _saving = false; @override void dispose() { _nameCtrl.dispose(); _statusCtrl.dispose(); super.dispose(); } Future _save(String contextId) async { setState(() => _saving = true); try { await ref.read(msnApiProvider).updateMyProfile( contextId, displayName: _nameCtrl.text.trim(), statusMessage: _statusCtrl.text.trim(), ); ref.invalidate(myProfileForContextProvider(contextId)); ref.invalidate(membersForContextProvider(contextId)); if (!mounted) return; setState(() { _dirty = false; _saving = false; }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('저장했습니다')), ); } catch (e) { if (!mounted) return; setState(() => _saving = false); ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('$e'))); } } Future _onSegmentChanged(String contextId) async { await ref.read(sessionProvider.notifier).setSelectedContext(contextId); setState(() => _dirty = false); } @override Widget build(BuildContext context) { final session = ref.watch(sessionProvider).value; final cid = session?.effectiveContextId; final contextsAsync = ref.watch(contextsListProvider); return contextsAsync.when( loading: () => const Center(child: CircularProgressIndicator(color: TossColors.blue)), error: (e, _) => Center(child: Text('$e')), data: (contexts) { final personal = _firstOfKind(contexts, 'personal'); final work = _firstOfKind(contexts, 'work'); if (cid == null) { return const Center(child: Text('맥락이 없습니다')); } final async = ref.watch(myProfileForContextProvider(cid)); ref.listen>(myProfileForContextProvider(cid), (prev, next) { next.whenData((p) { if (!_dirty && mounted) { _nameCtrl.text = p.displayName; _statusCtrl.text = p.statusMessage ?? ''; } }); }); return async.when( loading: () => const Center(child: CircularProgressIndicator(color: TossColors.blue)), error: (e, _) => Center(child: Text('$e')), data: (_) => RefreshIndicator( color: TossColors.blue, onRefresh: () async { ref.invalidate(myProfileForContextProvider(cid)); await ref.read(myProfileForContextProvider(cid).future); }, child: ListView( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.fromLTRB(16, 8, 16, 100), children: [ if (personal != null && work != null) ...[ SegmentedButton( segments: [ ButtonSegment( value: personal.id, label: Text(personal.name), icon: const Icon(Icons.home_outlined, size: 18), ), ButtonSegment( value: work.id, label: Text(work.name), icon: const Icon(Icons.business_outlined, size: 18), ), ], selected: {cid}, onSelectionChanged: (s) { if (s.isEmpty) return; _onSegmentChanged(s.first); }, ), const SizedBox(height: 12), ], Text( '지금 편집: ${_contextName(contexts, cid)}', style: Theme.of(context).textTheme.titleSmall, ), const SizedBox(height: 8), Text( '이 맥락에서만 보이는 이름과 상태입니다.', style: Theme.of(context).textTheme.bodySmall, ), const SizedBox(height: 20), TextField( controller: _nameCtrl, decoration: const InputDecoration( labelText: '표시 이름', border: OutlineInputBorder(), ), onChanged: (_) => setState(() => _dirty = true), ), const SizedBox(height: 16), TextField( controller: _statusCtrl, decoration: const InputDecoration( labelText: '상태 메시지', border: OutlineInputBorder(), ), maxLines: 3, onChanged: (_) => setState(() => _dirty = true), ), const SizedBox(height: 24), FilledButton( onPressed: _saving ? null : () => _save(cid), child: _saving ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), ) : const Text('저장'), ), ], ), ), ); }, ); } ContextModel? _firstOfKind(List list, String kind) { for (final c in list) { if (c.kind == kind) return c; } return null; } String _contextName(List list, String id) { for (final c in list) { if (c.id == id) return c.name; } return id; } }