diff --git a/CHANGES.md b/CHANGES.md index 73d02f2..30af5da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1078,3 +1078,18 @@ 2026-06-12 00:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart 2026-06-12 00:35 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md 2026-06-12 00:36 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-07-03 06:20 [Edit] /home/steggi/pyramid/lib/features/call/mini_call_widget.dart +2026-07-03 06:20 [Edit] /home/steggi/pyramid/lib/features/call/mini_call_widget.dart +2026-07-03 06:20 [Edit] /home/steggi/pyramid/lib/features/rooms/user_panel.dart +2026-07-03 06:20 [Edit] /home/steggi/pyramid/lib/widgets/pyramid_loader.dart +2026-07-03 06:21 [Edit] /home/steggi/pyramid/lib/widgets/screen_share_picker.dart +2026-07-03 06:21 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart +2026-07-03 06:22 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart +2026-07-03 06:22 [Edit] /home/steggi/pyramid/lib/widgets/create_join_dialog.dart +2026-07-03 06:22 [Edit] /home/steggi/pyramid/lib/widgets/create_join_dialog.dart +2026-07-03 06:22 [Edit] /home/steggi/pyramid/lib/widgets/create_join_dialog.dart +2026-07-03 06:23 [Edit] /home/steggi/pyramid/lib/core/background_push.dart +2026-07-03 06:24 [Edit] /home/steggi/pyramid/lib/core/background_push.dart +2026-07-03 06:24 [Edit] /home/steggi/pyramid/lib/core/background_push.dart +2026-07-03 06:24 [Edit] /home/steggi/pyramid/lib/core/background_push.dart +2026-07-03 06:24 [Edit] /home/steggi/pyramid/lib/core/livekit_call_manager.dart diff --git a/lib/core/background_push.dart b/lib/core/background_push.dart index 1965283..452ac29 100644 --- a/lib/core/background_push.dart +++ b/lib/core/background_push.dart @@ -1,6 +1,4 @@ -import 'dart:convert'; import 'dart:io'; -import 'dart:isolate'; import 'dart:ui'; import 'package:firebase_messaging/firebase_messaging.dart'; @@ -14,8 +12,6 @@ import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite/sqflite.dart' as sqflite_native; -const _kChannel = 'pyramid_messages'; - /// Port name used to locate the main isolate from background isolates. /// Registered by notification_service.dart when the app starts. const kMainIsolateName = 'pyramid_main'; @@ -304,99 +300,3 @@ Future handleBackgroundNotificationResponse( print('[NOTIF-BG] background reply sent=$sent room=$roomId'); } -// ── Notification builder ────────────────────────────────────────────────────── - -Future _showNotif({ - required String title, - required String body, - required String? roomId, - required int notifId, -}) async { - final plugin = FlutterLocalNotificationsPlugin(); - await plugin.initialize( - const InitializationSettings( - android: AndroidInitializationSettings('@drawable/ic_notification')), - onDidReceiveBackgroundNotificationResponse: handleBackgroundNotificationResponse, - ); - - await plugin.show( - notifId, title, body, - NotificationDetails( - android: AndroidNotificationDetails( - _kChannel, 'Nachrichten', - channelDescription: 'Neue Nachrichten', - importance: Importance.high, - priority: Priority.high, - icon: '@drawable/ic_notification', - color: const Color(0xFF7B61FF), - groupKey: 'pyramid_messages', - actions: roomId != null - ? const [ - AndroidNotificationAction( - 'reply', 'Antworten', - inputs: [AndroidNotificationActionInput(label: 'Antworten…')], - allowGeneratedReplies: true, - showsUserInterface: false, // BroadcastReceiver path — app never opens - ), - AndroidNotificationAction( - 'read', 'Gelesen', - showsUserInterface: false, - ), - ] - : const [], - ), - ), - payload: roomId, - ); -} - -// ── HTTP fallback — fetch sender / room name without the SDK ────────────────── - -Future _fetchTitle( - String hs, String token, String roomId, String eventId) async { - try { - final encRoom = Uri.encodeComponent(roomId); - final encEvent = Uri.encodeComponent(eventId); - - final rawEvent = await _get( - '$hs/_matrix/client/v3/rooms/$encRoom/event/$encEvent', token); - if (rawEvent == null) return null; - - final senderId = rawEvent['sender'] as String? ?? ''; - String senderName = senderId.split(':').first.replaceFirst('@', ''); - - if (senderId.isNotEmpty) { - final encSender = Uri.encodeComponent(senderId); - final memberState = await _get( - '$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.member/$encSender', - token); - final name = memberState?['displayname'] as String?; - if (name != null && name.isNotEmpty) senderName = name; - } - - final nameState = - await _get('$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.name', token); - final roomName = nameState?['name'] as String?; - - return roomName?.isNotEmpty == true - ? '$senderName · $roomName' - : senderName; - } catch (_) { - return null; - } -} - -Future?> _get(String url, String token) async { - try { - final req = await HttpClient() - .getUrl(Uri.parse(url)) - .timeout(const Duration(seconds: 8)); - req.headers.add('Authorization', 'Bearer $token'); - final res = await req.close(); - if (res.statusCode != 200) return null; - final raw = await res.transform(utf8.decoder).join(); - return jsonDecode(raw) as Map; - } catch (_) { - return null; - } -} diff --git a/lib/core/livekit_call_manager.dart b/lib/core/livekit_call_manager.dart index 29e1119..67f88e0 100644 --- a/lib/core/livekit_call_manager.dart +++ b/lib/core/livekit_call_manager.dart @@ -586,8 +586,6 @@ class LiveKitCallManager with ChangeNotifier { } } - void _applyNoiseSuppression(bool enabled) {} - void _startStatsLogging() { _stopStatsLogging(); _statsTimer = Timer.periodic(const Duration(seconds: 5), (_) => _logStats()); diff --git a/lib/features/call/mini_call_widget.dart b/lib/features/call/mini_call_widget.dart index a3e5114..4aa872f 100644 --- a/lib/features/call/mini_call_widget.dart +++ b/lib/features/call/mini_call_widget.dart @@ -333,7 +333,9 @@ class _ControlBtnState extends State<_ControlBtn> { duration: pt.durationFast, height: 32, decoration: BoxDecoration( - color: widget.active ? (widget.danger ? pt.danger : pt.accent) : pt.bg3, + color: widget.active + ? (widget.danger ? pt.danger : pt.accent) + : (_hovered ? pt.bgHover : pt.bg3), borderRadius: BorderRadius.circular(pt.rSm), ), child: Icon( diff --git a/lib/features/rooms/user_panel.dart b/lib/features/rooms/user_panel.dart index a616184..22bd7ae 100644 --- a/lib/features/rooms/user_panel.dart +++ b/lib/features/rooms/user_panel.dart @@ -132,16 +132,16 @@ class _ProfileRow extends StatelessWidget { } class _InitialAvatar extends StatelessWidget { + static const double _size = 32; final String name; final double radius; - final double size; - const _InitialAvatar({required this.name, required this.radius, this.size = 32}); + const _InitialAvatar({required this.name, required this.radius}); @override Widget build(BuildContext context) { return Container( - width: size, - height: size, + width: _size, + height: _size, decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, @@ -155,7 +155,7 @@ class _InitialAvatar extends StatelessWidget { name.isNotEmpty ? name[0].toUpperCase() : '?', style: TextStyle( color: Colors.white, - fontSize: size * 0.44, + fontSize: _size * 0.44, fontWeight: FontWeight.w600, ), ), diff --git a/lib/widgets/create_join_dialog.dart b/lib/widgets/create_join_dialog.dart index 87c88fa..b13f4a8 100644 --- a/lib/widgets/create_join_dialog.dart +++ b/lib/widgets/create_join_dialog.dart @@ -518,13 +518,12 @@ class _SpaceEditDialogState extends ConsumerState { late TextEditingController _topicCtrl; bool _saving = false; String? _error; - bool _saved = false; @override void initState() { super.initState(); _nameCtrl = TextEditingController(text: widget.space.getLocalizedDisplayname()); - _topicCtrl = TextEditingController(text: widget.space.topic ?? ''); + _topicCtrl = TextEditingController(text: widget.space.topic); } @override @@ -535,17 +534,17 @@ class _SpaceEditDialogState extends ConsumerState { } Future _save() async { - setState(() { _saving = true; _error = null; _saved = false; }); + setState(() { _saving = true; _error = null; }); try { final name = _nameCtrl.text.trim(); final topic = _topicCtrl.text.trim(); if (name.isNotEmpty && name != widget.space.getLocalizedDisplayname()) { await widget.space.setName(name); } - if (topic != (widget.space.topic ?? '')) { + if (topic != widget.space.topic) { await widget.space.setDescription(topic); } - if (mounted) setState(() { _saving = false; _saved = true; }); + if (mounted) setState(() { _saving = false; }); await Future.delayed(const Duration(seconds: 1)); if (mounted) Navigator.of(context).pop(true); } catch (e) { @@ -674,7 +673,7 @@ class _RoomSettingsDialogState extends ConsumerState { void initState() { super.initState(); _nameCtrl = TextEditingController(text: widget.room.getLocalizedDisplayname()); - _topicCtrl = TextEditingController(text: widget.room.topic ?? ''); + _topicCtrl = TextEditingController(text: widget.room.topic); } @override @@ -691,7 +690,7 @@ class _RoomSettingsDialogState extends ConsumerState { await widget.room.setName(_nameCtrl.text.trim()); } final newTopic = _topicCtrl.text.trim(); - if (newTopic != (widget.room.topic ?? '')) { + if (newTopic != widget.room.topic) { await widget.room.setDescription(newTopic); } if (mounted) Navigator.of(context).pop(); diff --git a/lib/widgets/pyramid_loader.dart b/lib/widgets/pyramid_loader.dart index e78431e..22643b1 100644 --- a/lib/widgets/pyramid_loader.dart +++ b/lib/widgets/pyramid_loader.dart @@ -127,17 +127,6 @@ class _PyramidPainter extends CustomPainter { Offset _proj(List v, double sc, double cx, double cy, double tr) => Offset(cx + v[0] * sc, cy + (v[1] * cos(tr) + v[2] * sin(tr)) * sc); - double _frontness(List> verts) { - final a = verts[0], b = verts[1], c = verts[2]; - final ux = b[0]-a[0], uy = b[1]-a[1], uz = b[2]-a[2]; - final vx = c[0]-a[0], vy = c[1]-a[1], vz = c[2]-a[2]; - final nz = ux * vy - uy * vx; - final nLen = sqrt( - pow(uy * vz - uz * vy, 2) + pow(uz * vx - ux * vz, 2) + nz * nz, - ); - return nLen == 0 ? 0 : max(0.0, -nz / nLen); - } - Color _darken(Color c, double amount) => Color.fromARGB( c.alpha, max(0, (c.red * (1 - amount)).round()), diff --git a/lib/widgets/screen_share_picker.dart b/lib/widgets/screen_share_picker.dart index 03704f4..3df258e 100644 --- a/lib/widgets/screen_share_picker.dart +++ b/lib/widgets/screen_share_picker.dart @@ -1,4 +1,3 @@ -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:pyramid/core/theme.dart'; diff --git a/lib/widgets/settings_modal.dart b/lib/widgets/settings_modal.dart index 031ea3d..08c12cb 100644 --- a/lib/widgets/settings_modal.dart +++ b/lib/widgets/settings_modal.dart @@ -859,7 +859,6 @@ class _PrimaryBtn extends StatelessWidget { final VoidCallback? onPressed; final PyramidTheme pt; final bool loading; - final bool destructive; const _PrimaryBtn({ required this.label, @@ -867,13 +866,12 @@ class _PrimaryBtn extends StatelessWidget { this.icon, this.onPressed, this.loading = false, - this.destructive = false, }); @override Widget build(BuildContext context) { - final bg = destructive ? pt.danger : pt.accent; - final fg = destructive ? Colors.white : pt.accentFg; + final bg = pt.accent; + final fg = pt.accentFg; return ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: bg, @@ -3626,7 +3624,6 @@ class _EncryptionSectionState extends ConsumerState<_EncryptionSection> { try { final client = await ref.read(matrixClientProvider.future); final db = client.database; - if (db == null) throw Exception('Datenbank nicht verfügbar.'); final stored = await db.getAllInboundGroupSessions(); final sessions = >[];