# 09 — Profil, Präsenz & Account-Daten

---

## Inhaltsverzeichnis
- [Eigenes Profil lesen](#eigenes-profil-lesen)
- [Profil aktualisieren](#profil-aktualisieren)
- [Profil anderer User](#profil-anderer-user)
- [Präsenz (Presence)](#präsenz-presence)
- [Account-Daten (Account Data)](#account-daten-account-data)
- [Ignorierte User](#ignorierte-user)
- [Tags / Favoriten](#tags--favoriten)
- [Account löschen / deaktivieren](#account-löschen--deaktivieren)

---

## Eigenes Profil lesen

```dart
// Aus dem Client (gecacht)
print(client.userID);             // '@alice:server'
print(client.displayName);        // 'Alice'
print(client.avatarUrl);          // mxc://...

// Frisch vom Server
final profile = await client.fetchOwnProfile();
print(profile.displayname);
print(profile.avatarUrl);

// Avatar als HTTP-URL
final avatarHttp = client.avatarUrl?.getThumbnail(
  client,
  width: 128,
  height: 128,
  method: ThumbnailMethod.crop,
);
```

---

## Profil aktualisieren

```dart
// Displayname setzen
await client.setDisplayName(client.userID!, 'Neuer Name');

// Avatar hochladen und setzen
final avatarBytes = await File('avatar.png').readAsBytes();
final mxcUri = await client.uploadContent(
  avatarBytes,
  filename: 'avatar.png',
  contentType: 'image/png',
);
await client.setAvatarUrl(client.userID!, mxcUri);

// Avatar entfernen
await client.setAvatarUrl(client.userID!, null);
```

---

## Profil anderer User

```dart
// Profil via API
final profile = await client.getProfileFromUserId('@bob:server');
print(profile.displayname);
print(profile.avatarUrl);

// Spezifisches Feld (Matrix 1.16+ API)
final displayname = await client.getProfileField(
  '@bob:server',
  'displayname',
);
final avatar = await client.getProfileField(
  '@bob:server',
  'avatar_url',
);

// User in einem Raum (schneller, gecacht)
final user = room.unsafeGetUserFromMemoryOrFallback('@bob:server');
print(user.displayName);
print(user.avatarUrl);
print(user.id);

// User-Suche
final results = await client.searchUserDirectory(
  'alice',
  limit: 20,
);
for (final user in results.results) {
  print(user.userId);
  print(user.displayName);
  print(user.avatarUrl);
}
```

---

## Präsenz (Presence)

```dart
// Eigene Präsenz setzen
await client.setPresence(
  client.userID!,
  PresenceType.online,           // .online | .unavailable | .offline
  statusMsg: 'Im Meeting',       // Optionaler Status-Text
);

// Präsenz anderer User abrufen
final presence = await client.fetchCurrentPresence('@bob:server');
print(presence.presence);        // PresenceType
print(presence.currentlyActive); // bool?
print(presence.statusMsg);       // String?
print(presence.lastActiveAgo);   // int? (Millisekunden seit letzter Aktivität)

// Präsenz aus Raum-Mitglieder
final user = room.unsafeGetUserFromMemoryOrFallback('@bob:server');
// Präsenz wird nicht direkt im User gecacht — fetchCurrentPresence nötig

// Präsenz-Anzeige im UI
String getPresenceText(PresenceType? type, int? lastActiveAgo) {
  switch (type) {
    case PresenceType.online:    return 'Online';
    case PresenceType.unavailable:
      return 'Abwesend';
    case PresenceType.offline:
      if (lastActiveAgo != null) {
        final mins = lastActiveAgo ~/ 60000;
        if (mins < 60) return 'Vor $mins Min. aktiv';
        final hours = mins ~/ 60;
        if (hours < 24) return 'Vor $hours Std. aktiv';
        return 'Vor ${hours ~/ 24} Tagen aktiv';
      }
      return 'Offline';
    default: return '';
  }
}
```

---

## Account-Daten (Account Data)

```dart
// Account-Daten sind private, servergespeicherte Einstellungen.
// Bleiben über Geräte hinweg synchron.

// Lesen
final data = client.accountData['com.example.my_setting']?.content;

// Schreiben
await client.setAccountData(
  client.userID!,
  'com.example.my_setting',
  {'key': 'value', 'enabled': true},
);

// Wichtige Standard-Account-Daten:
// 'm.direct'              → DM-Raumliste
// 'm.push_rules'          → Push-Regel-Overrides
// 'm.ignored_user_list'   → Ignorierte User
// 'm.identity_server'     → Identity-Server-URL
// 'im.vector.setting.breadcrumbs' → FluffyChat letzte Räume

// Raumspezifische Account-Daten
await client.setRoomAccountData(
  client.userID!,
  '!roomId:server',
  'm.fully_read',
  {'event_id': eventId},
);

// Tag für Raum setzen (Favorit, Low-Priority)
await client.setRoomTag(
  client.userID!,
  '!roomId:server',
  'm.favourite',
  TagContent(order: 0.5),
);
await client.setRoomTag(client.userID!, '!roomId:server', 'm.lowpriority', TagContent());
await client.deleteRoomTag(client.userID!, '!roomId:server', 'm.favourite');
```

---

## Ignorierte User

```dart
// User ignorieren
final ignoredList = client.ignoredUsers; // List<String>
final updated = [...ignoredList, '@spammer:server'];
await client.setAccountData(
  client.userID!,
  'm.ignored_user_list',
  {'ignored_users': Map.fromIterable(updated, value: (_) => {})},
);

// User entblockieren
final filtered = ignoredList.where((id) => id != '@spammer:server').toList();
await client.setAccountData(
  client.userID!,
  'm.ignored_user_list',
  {'ignored_users': Map.fromIterable(filtered, value: (_) => {})},
);

// Ignorierte User abrufen
final ignored = client.ignoredUsers; // automatisch aus Account-Data
```

---

## Tags / Favoriten

```dart
// Raum als Favorit markieren
await room.addTag('m.favourite', order: 0.1);

// Raum als Low-Priority markieren
await room.addTag('m.lowpriority');

// Alle Tags eines Raums
final tags = room.tags; // Map<String, Tag>
final isFavourite = tags.containsKey('m.favourite');
final isLowPriority = tags.containsKey('m.lowpriority');

// Tag entfernen
await room.removeTag('m.favourite');

// Eigene Tags
await room.addTag('com.example.myapp.tag', order: 0.5);

// Räume nach Tag filtern
final favourites = client.rooms
    .where((r) => r.tags.containsKey('m.favourite'))
    .toList();
```

---

## Account löschen / deaktivieren

```dart
// Account deaktivieren (PERMANENT, nicht rückgängig!)
await client.uiaRequestBackground(
  (auth) => client.deactivateAccount(
    auth: auth,
    eraseData: true,     // true: alle Nachrichten löschen (soweit möglich)
  ),
);

// Passwort ändern (braucht Re-Auth via UIAA)
await client.uiaRequestBackground(
  (auth) => client.changePassword(
    'neuesPasswort',
    auth: auth,
    oldPassword: 'altesPasswort',
  ),
);

// E-Mail-Adresse hinzufügen (über Identity-Server)
// Dies ist ein mehrstufiger UIAA-Flow und erfordert E-Mail-Bestätigung.
// Normalerweise über den Homeserver-spezifischen Registration-Flow.
```
