9dc11757e2
Entfernt tatsächlich toten Code, den flutter analyze als Warning markiert hatte: unbenutzte Felder/Parameter (_saved, _hovered wird jetzt für Hover- Feedback genutzt, destructive-Flag ohne Aufrufer, size-Parameter ohne Override), unerreichbaren dead_code (Room.topic/Space.topic sind laut SDK nie null, client.database ist nie null) sowie Legacy-Funktionen aus der alten Push-Architektur (_showNotif/_fetchTitle, ersetzt durch natives PushService.kt) und einen leeren Noise-Suppression-Stub ohne Aufrufer. Keine funktionale Verhaltensänderung an aktiven Code-Pfaden. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
166 lines
4.8 KiB
Dart
166 lines
4.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:matrix/matrix.dart';
|
|
import 'package:pyramid/core/app_state.dart';
|
|
import 'package:pyramid/core/matrix_client.dart';
|
|
import 'package:pyramid/core/theme.dart';
|
|
import 'package:pyramid/widgets/hover_region.dart';
|
|
import 'package:pyramid/widgets/mxc_image.dart';
|
|
import 'package:pyramid/widgets/pyramid_logo.dart';
|
|
|
|
final _ownProfileProvider = FutureProvider.autoDispose<Profile?>((ref) async {
|
|
final client = await ref.watch(matrixClientProvider.future);
|
|
final userId = client.userID;
|
|
if (userId == null) return null;
|
|
try {
|
|
return await client.getProfileFromUserId(userId);
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
});
|
|
|
|
class UserPanel extends ConsumerWidget {
|
|
const UserPanel({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final pt = PyramidTheme.of(context);
|
|
final clientAsync = ref.watch(matrixClientProvider);
|
|
final profile = ref.watch(_ownProfileProvider).valueOrNull;
|
|
|
|
final client = clientAsync.valueOrNull;
|
|
final fallbackName = client?.userID?.split(':').first.replaceFirst('@', '') ?? '...';
|
|
final displayName = profile?.displayName ?? fallbackName;
|
|
final avatarUri = profile?.avatarUrl;
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: pt.bg2,
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(color: pt.border),
|
|
),
|
|
child: _ProfileRow(
|
|
pt: pt,
|
|
client: client,
|
|
avatarUri: avatarUri,
|
|
displayName: displayName,
|
|
ref: ref,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ProfileRow extends StatelessWidget {
|
|
final PyramidTheme pt;
|
|
final Client? client;
|
|
final Uri? avatarUri;
|
|
final String displayName;
|
|
final WidgetRef ref;
|
|
|
|
const _ProfileRow({
|
|
required this.pt,
|
|
required this.client,
|
|
required this.avatarUri,
|
|
required this.displayName,
|
|
required this.ref,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
|
|
child: Row(
|
|
children: [
|
|
Stack(
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
if (client != null && avatarUri != null)
|
|
MxcAvatar(
|
|
mxcUri: avatarUri!,
|
|
client: client!,
|
|
size: 32,
|
|
borderRadius: BorderRadius.circular(4),
|
|
placeholder: (_) => _InitialAvatar(name: displayName, radius: 4),
|
|
)
|
|
else
|
|
_InitialAvatar(name: displayName, radius: 4),
|
|
Positioned(
|
|
bottom: -2,
|
|
right: -2,
|
|
child: PresenceDot(status: 'online', size: 10, borderColor: pt.bg2),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
displayName,
|
|
style: TextStyle(
|
|
color: pt.fg,
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
Text(
|
|
'online',
|
|
style: TextStyle(color: pt.fgMuted, fontSize: 11),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
PyrIconBtn(
|
|
size: 28,
|
|
icon: const Icon(Icons.settings_rounded),
|
|
tooltip: 'Einstellungen',
|
|
onPressed: () => ref.read(activeModalProvider.notifier).state = ModalKind.settings,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _InitialAvatar extends StatelessWidget {
|
|
static const double _size = 32;
|
|
final String name;
|
|
final double radius;
|
|
const _InitialAvatar({required this.name, required this.radius});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
width: _size,
|
|
height: _size,
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [Color(0xFFFF6B9D), Color(0xFFC471F5)],
|
|
),
|
|
borderRadius: BorderRadius.circular(radius),
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
name.isNotEmpty ? name[0].toUpperCase() : '?',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: _size * 0.44,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|