Files
pyramid/lib/features/rooms/panel/rooms_voice.dart
T
Bernd Steckmeister a863fa3b9a refactor: Gott-Datei rooms_panel.dart in 8 Dateien aufgeteilt
Gleiche Technik wie bei settings_modal.dart/message_group.dart: reine
Verschiebung per Dart part/part-of, keine Logikänderung. rooms_panel.dart
schrumpft von 2555 auf 31 Zeilen (nur noch Bibliothekskopf). Verifiziert
per automatisiertem Blockvergleich gegen das Original und flutter analyze.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 11:00:22 +02:00

133 lines
3.9 KiB
Dart

part of '../rooms_panel.dart';
class _VoiceParticipantList extends StatelessWidget {
final List<Map<String, dynamic>> participants;
final Client? client;
final PyramidTheme pt;
const _VoiceParticipantList(
{required this.participants, required this.client, required this.pt});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: participants.map((p) {
final avatarUrl = p['avatarUrl'] as String?;
final name = (p['displayName'] as String? ?? '?');
final letter = name.isNotEmpty ? name[0].toUpperCase() : '?';
return Padding(
padding: const EdgeInsets.only(top: 3),
child: Row(
children: [
SizedBox(
width: 16,
height: 16,
child: client != null && avatarUrl != null
? MxcAvatar(
mxcUri: Uri.tryParse(avatarUrl),
client: client!,
size: 16,
borderRadius: BorderRadius.circular(8),
placeholder: (_) => _Initials(letter: letter, pt: pt, size: 16),
)
: _Initials(letter: letter, pt: pt, size: 16),
),
const SizedBox(width: 6),
Expanded(
child: Text(
name,
style: TextStyle(
color: const Color(0xFF57F287).withAlpha(200),
fontSize: 12,
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
),
),
Icon(Icons.mic_rounded,
size: 11,
color: const Color(0xFF57F287).withAlpha(140)),
],
),
);
}).toList(),
);
}
}
class _Initials extends StatelessWidget {
final String letter;
final PyramidTheme pt;
final double size;
const _Initials({required this.letter, required this.pt, this.size = 18});
@override
Widget build(BuildContext context) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
color: pt.bg3,
borderRadius: BorderRadius.circular(size / 2),
),
child: Center(
child: Text(letter,
style: TextStyle(
color: pt.fg,
fontSize: size * 0.5,
fontWeight: FontWeight.w700)),
),
);
}
}
class _VoiceBarBtn extends StatefulWidget {
final IconData icon;
final bool active;
final Color activeColor;
final Color inactiveColor;
final PyramidTheme pt;
final VoidCallback onTap;
const _VoiceBarBtn({
required this.icon,
required this.active,
required this.activeColor,
required this.inactiveColor,
required this.pt,
required this.onTap,
});
@override
State<_VoiceBarBtn> createState() => _VoiceBarBtnState();
}
class _VoiceBarBtnState extends State<_VoiceBarBtn> {
bool _hovered = false;
@override
Widget build(BuildContext context) {
final pt = widget.pt;
final color = widget.active ? widget.activeColor : widget.inactiveColor;
return MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (_) => setState(() => _hovered = true),
onExit: (_) => setState(() => _hovered = false),
child: GestureDetector(
onTap: widget.onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 120),
width: 28,
height: 28,
decoration: BoxDecoration(
color: _hovered ? pt.bg3 : Colors.transparent,
borderRadius: BorderRadius.circular(6),
),
child: Center(child: Icon(widget.icon, size: 16, color: color)),
),
),
);
}
}