fix: flutter analyze Warnings beheben (totes/unerreichbares Code)
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>
This commit is contained in:
@@ -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<void> handleBackgroundNotificationResponse(
|
||||
print('[NOTIF-BG] background reply sent=$sent room=$roomId');
|
||||
}
|
||||
|
||||
// ── Notification builder ──────────────────────────────────────────────────────
|
||||
|
||||
Future<void> _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<String?> _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<Map<String, dynamic>?> _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<String, dynamic>;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,8 +586,6 @@ class LiveKitCallManager with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
void _applyNoiseSuppression(bool enabled) {}
|
||||
|
||||
void _startStatsLogging() {
|
||||
_stopStatsLogging();
|
||||
_statsTimer = Timer.periodic(const Duration(seconds: 5), (_) => _logStats());
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -518,13 +518,12 @@ class _SpaceEditDialogState extends ConsumerState<SpaceEditDialog> {
|
||||
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<SpaceEditDialog> {
|
||||
}
|
||||
|
||||
Future<void> _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<RoomSettingsDialog> {
|
||||
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<RoomSettingsDialog> {
|
||||
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();
|
||||
|
||||
@@ -127,17 +127,6 @@ class _PyramidPainter extends CustomPainter {
|
||||
Offset _proj(List<double> 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<List<double>> 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()),
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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 = <Map<String, dynamic>>[];
|
||||
|
||||
Reference in New Issue
Block a user