Files
pyramid/lib/features/chat/view/chat_misc.dart
T
Bernd SteckmeisterandClaude Opus 5.5 c38e9c18b0 feat: Handy-Chatliste als Messenger-Kachel (Vorschau, Uhrzeit, Ungelesen) + deutsche Beschriftungen
- rooms_mobile_tile.dart: auf dem Handy grosser Avatar, Name + Uhrzeit der
  letzten Nachricht, Vorschau (gleiche Texte wie Push: Medien-Labels,
  Antwort-Zitat entfernt; "Du:" bzw. Absender in Gruppen), Ungelesen-Zaehler.
  PC behaelt die kompakte Liste, Voice-Kanaele ihre Darstellung.
- utils/date_labels.dart: chatListTime (heute Uhrzeit, Gestern, Wochentag,
  Datum; sicher an Zeitumstellungs-Tagen) + 5 Tests.
- Sichtbare englische Texte eingedeutscht (Chats durchsuchen,
  Direktnachrichten, Raeume, Nachricht..., Mitglieder, Suchen, ...).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 17:21:33 +02:00

132 lines
3.7 KiB
Dart

part of '../chat_view.dart';
class _DragOverlay extends StatefulWidget {
final PyramidTheme pt;
final bool active;
const _DragOverlay({required this.pt, required this.active});
@override
State<_DragOverlay> createState() => _DragOverlayState();
}
class _DragOverlayState extends State<_DragOverlay>
with SingleTickerProviderStateMixin {
// Sanftes Auf-und-ab des Icons, solange das Overlay aktiv ist.
late final AnimationController _bob = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 900),
);
@override
void initState() {
super.initState();
if (widget.active) _bob.repeat(reverse: true);
}
@override
void didUpdateWidget(_DragOverlay old) {
super.didUpdateWidget(old);
if (widget.active && !old.active) {
_bob.repeat(reverse: true);
} else if (!widget.active && old.active) {
_bob.stop();
}
}
@override
void dispose() {
_bob.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final pt = widget.pt;
return Container(
color: pt.bg0.withAlpha(200),
child: Center(
child: AnimatedScale(
scale: widget.active ? 1.0 : 0.88,
duration: const Duration(milliseconds: 220),
curve: Curves.easeOutBack,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 32),
decoration: BoxDecoration(
color: pt.bg2,
borderRadius: BorderRadius.circular(20),
border: Border.all(color: pt.accent, width: 2),
boxShadow: [
BoxShadow(
color: pt.accent.withAlpha(60),
blurRadius: 32,
spreadRadius: 4,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedBuilder(
animation: _bob,
builder: (_, child) => Transform.translate(
offset: Offset(
0, -7 * Curves.easeInOut.transform(_bob.value)),
child: child,
),
child:
Icon(Icons.upload_file_rounded, size: 56, color: pt.accent),
),
const SizedBox(height: 16),
Text(
'Datei hier ablegen',
style: TextStyle(
color: pt.fg,
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
Text(
'Loslassen zum Hochladen',
style: TextStyle(color: pt.fgMuted, fontSize: 14),
),
],
),
),
),
),
);
}
}
// Placeholder shown when no room is selected
class NoChatSelected extends StatelessWidget {
const NoChatSelected({super.key});
@override
Widget build(BuildContext context) {
final pt = PyramidTheme.of(context);
return Container(
color: pt.bg1,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.forum_outlined, size: 64, color: pt.fgDim),
const SizedBox(height: 16),
Text(
'Wähle einen Chat aus',
style: TextStyle(color: pt.fgMuted, fontSize: 16),
),
const SizedBox(height: 8),
Text(
'Choose from the sidebar on the left',
style: TextStyle(color: pt.fgDim, fontSize: 13),
),
],
),
),
);
}
}