# 05 — Medien & Dateien

---

## Inhaltsverzeichnis
- [Datei hochladen](#datei-hochladen)
- [Bild senden](#bild-senden)
- [Video senden](#video-senden)
- [Audio / Sprachnachricht senden](#audio--sprachnachricht-senden)
- [Datei senden](#datei-senden)
- [Sticker senden](#sticker-senden)
- [Medien herunterladen & entschlüsseln](#medien-herunterladen--entschlüsseln)
- [Thumbnails & Vorschaubilder](#thumbnails--vorschaubilder)
- [MXC-URL zu HTTP-URL](#mxc-url-zu-http-url)
- [Verschlüsselte Medien](#verschlüsselte-medien)
- [Avatar hochladen](#avatar-hochladen)
- [MatrixFile-Objekte](#matrixfile-objekte)

---

## Datei hochladen

```dart
// Bytes hochladen → mxc:// URI zurück
final mxcUri = await client.uploadContent(
  fileBytes,                              // Uint8List
  filename: 'datei.pdf',
  contentType: 'application/pdf',         // optional, SDK erkennt es
);
print(mxcUri); // mxc://example.org/AbCdEf...
```

---

## Bild senden

```dart
import 'package:matrix/matrix.dart';

// MatrixImageFile erstellen
final imageFile = MatrixImageFile(
  bytes: imageBytes,                      // Uint8List
  name: 'foto.jpg',
  mimeType: 'image/jpeg',
  width: 1920,                            // optional, für Info
  height: 1080,
);

// Mit Thumbnail
final thumbnail = MatrixImageFile(
  bytes: thumbnailBytes,
  name: 'foto_thumb.jpg',
  mimeType: 'image/jpeg',
  width: 320,
  height: 180,
);

// Senden (lädt automatisch hoch + sendet m.image Event)
await room.sendFileEvent(
  imageFile,
  thumbnail: thumbnail,                   // optional
);

// Alternativ mit sendImageEvent
await room.sendImageEvent(
  imageFile,
  thumbnail: thumbnail,
);
```

---

## Video senden

```dart
final videoFile = MatrixVideoFile(
  bytes: videoBytes,
  name: 'video.mp4',
  mimeType: 'video/mp4',
  duration: 45000,                        // Millisekunden
  width: 1920,
  height: 1080,
);

final thumbFile = MatrixImageFile(
  bytes: thumbnailBytes,
  name: 'thumb.jpg',
  mimeType: 'image/jpeg',
  width: 320,
  height: 180,
);

await room.sendVideoEvent(
  videoFile,
  thumbnail: thumbFile,
);
```

---

## Audio / Sprachnachricht senden

```dart
// Audio-Datei
final audioFile = MatrixAudioFile(
  bytes: audioBytes,
  name: 'aufnahme.ogg',
  mimeType: 'audio/ogg',
  duration: 12000,                        // Millisekunden
);

await room.sendAudioEvent(audioFile);

// Sprachnachricht (Voice Message MSC3245)
await room.sendFileEvent(
  audioFile,
  extraContent: {
    'org.matrix.msc3245.voice': {},       // markiert als Sprachnachricht
    'org.matrix.msc1767.audio': {
      'duration': 12000,
      'waveform': [0, 50, 100, 75, ...],  // Amplituden (0-1024)
    },
  },
);
```

---

## Datei senden

```dart
final file = MatrixFile(
  bytes: fileBytes,
  name: 'dokument.pdf',
  mimeType: 'application/pdf',
);

await room.sendFileEvent(file);

// Mit Extra-Metadaten
await room.sendFileEvent(
  file,
  extraContent: {
    'org.matrix.msc3554.caption': {
      'msgtype': 'm.text',
      'body': 'Hier das Dokument',
    },
  },
);
```

---

## Sticker senden

```dart
// Sticker sind ein eigener Event-Typ (m.sticker)
await room.sendEvent(
  {
    'body': 'Ein Sticker',
    'url': 'mxc://example.org/stickerId',
    'info': {
      'mimetype': 'image/png',
      'w': 256,
      'h': 256,
    },
  },
  EventTypes.Sticker,                     // 'm.sticker'
);
```

---

## Medien herunterladen & entschlüsseln

```dart
// Aus Event-Attachment herunterladen (+ automatisch entschlüsseln bei E2EE)
final data = await event.downloadAndDecryptAttachment(
  getThumbnail: false,                    // true für Thumbnail statt Original
);
// data ist MatrixFile mit .bytes: Uint8List

// Direkte MXC-URL herunterladen
final bytes = await client.database.getFile(mxcUri);
// oder über HTTP:
final httpUri = mxcUri.getDownloadUri(client);
// → https://homeserver/_matrix/media/v3/download/server/mediaId
```

---

## Thumbnails & Vorschaubilder

```dart
// Thumbnail-URL für Widget
final thumbnailUri = event.thumbnailUrl;  // mxc:// URI

// HTTP-URL für Thumbnail (mit Größe)
final httpUrl = thumbnailUri?.getThumbnail(
  client,
  width: 800,
  height: 600,
  method: ThumbnailMethod.scale,          // oder .crop
);

// Avatar-Thumbnail
final avatarUrl = user.avatarUrl?.getThumbnail(
  client,
  width: 56,
  height: 56,
  method: ThumbnailMethod.crop,
);

// Im Flutter Widget (CachedNetworkImage o.ä.):
Image.network(httpUrl.toString());
```

---

## MXC-URL zu HTTP-URL

```dart
// Download-URL
final downloadUrl = Uri.parse(mxcUriString).getDownloadUri(client);
// → https://homeserver/_matrix/media/v3/download/server/mediaId

// Thumbnail-URL
final thumbUrl = Uri.parse(mxcUriString).getThumbnail(
  client,
  width: 300,
  height: 300,
  method: ThumbnailMethod.crop,
);

// Direkt als String
final urlString = downloadUrl.toString();
```

---

## Verschlüsselte Medien

```dart
// In verschlüsselten Räumen werden Medien automatisch verschlüsselt.
// Das SDK übernimmt Ver- und Entschlüsselung transparent.

// Verschlüsselter Download (automatisch):
final file = await event.downloadAndDecryptAttachment();
// file.bytes enthält die entschlüsselten Rohdaten

// Manuell ver-/entschlüsseln (selten nötig):
// Nutze EncryptedFile aus dem matrix-package
final encryptedFile = EncryptedFile(
  url: 'mxc://...',
  key: {/* JWK */},
  iv: 'base64...',
  hashes: {'sha256': 'base64...'},
  v: 'v2',
);
```

---

## Avatar hochladen

```dart
// Eigener Avatar
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);

// Raum-Avatar
final roomAvatarMxc = await client.uploadContent(imageBytes, filename: 'room.png');
await room.setAvatar(roomAvatarMxc);
```

---

## MatrixFile-Objekte

```dart
// Basis-Klasse
MatrixFile({
  required Uint8List bytes,
  required String name,
  String? mimeType,
})

// Spezialisierte Unterklassen:
MatrixImageFile({
  required Uint8List bytes,
  required String name,
  String? mimeType,       // z.B. 'image/jpeg'
  int? width,
  int? height,
  bool? animated,         // für GIFs
})

MatrixVideoFile({
  required Uint8List bytes,
  required String name,
  String? mimeType,       // 'video/mp4'
  int? duration,          // ms
  int? width,
  int? height,
  MatrixImageFile? thumbnail,
})

MatrixAudioFile({
  required Uint8List bytes,
  required String name,
  String? mimeType,       // 'audio/ogg'
  int? duration,          // ms
})

// Eigenschaften
file.bytes              // Uint8List
file.name               // Dateiname
file.mimeType           // MIME-Typ
file.sizeString         // '1.4 MB' (formatiert)
file.size               // Bytes als int
```

---

## Medien-Events lesen

```dart
// Attachment-Info aus Event
if (event.messageType == 'm.image') {
  final url = event.attachmentMxcUrl;     // mxc:// URI
  final mime = event.attachmentMimetype;  // 'image/jpeg'
  final size = event.attachmentSize;      // Bytes
  final width = event.infoMap['w'] as int?;
  final height = event.infoMap['h'] as int?;
}

if (event.messageType == 'm.video') {
  final duration = event.infoMap['duration'] as int?; // ms
}

if (event.messageType == 'm.audio') {
  final duration = event.infoMap['duration'] as int?;
  final waveform = event.content
      .tryGetMap('org.matrix.msc1767.audio')
      ?.tryGetList<int>('waveform');
}

// Datei-Größe als lesbarer String
print(event.sizeString); // '2.3 MB'
```
