writeToFile method

Future<void> writeToFile(
  1. String path, {
  2. Uint8List? coverImage,
  3. void onProgress(
    1. String name,
    2. double progress
    )?,
})

Implementation

Future<void> writeToFile(
  String path, {
  Uint8List? coverImage,
  void Function(String name, double progress)? onProgress,
}) async {
  final file = File(path);
  final sink = file.openWrite();

  // --- MAGIC + VERSION + FLAGS ---
  sink.add(utf8.encode(mime)); // magic
  sink.add([version]);

  int flags = 0;
  if (coverImage != null) flags |= 1 << 0;
  sink.add([flags]);

  // --- Optional PNG Cover ---
  if (coverImage != null) {
    final coverSize = ByteData(4)..setUint32(0, coverImage.length);
    sink.add(coverSize.buffer.asUint8List());
    sink.add(coverImage);
  }

  // --- Config JSON ---
  final configJson = utf8.encode(jsonEncode(config));
  final configSize = ByteData(4)..setUint32(0, configJson.length);
  sink.add(configSize.buffer.asUint8List());
  sink.add(configJson);

  // --- File Index Section (names, offsets, lengths) ---
  // final indexStart = await file.length(); // save index start position
  // final fileCount = files.length;

  // placeholder for file index
  final fileIndex = BytesBuilder();
  int currentOffset = 0;

  for (final f in files) {
    final nameBytes = utf8.encode(f.name);
    final nameLen = ByteData(2)..setUint16(0, nameBytes.length);
    final offsetBytes = ByteData(8)..setInt64(0, currentOffset);
    final lengthBytes = ByteData(8)..setInt64(0, f.data.length);

    fileIndex.add(nameLen.buffer.asUint8List());
    fileIndex.add(nameBytes);
    fileIndex.add(offsetBytes.buffer.asUint8List());
    fileIndex.add(lengthBytes.buffer.asUint8List());

    currentOffset += f.data.length;
  }

  final indexBytes = fileIndex.toBytes();
  final indexSize = ByteData(4)..setUint32(0, indexBytes.length);
  sink.add(indexSize.buffer.asUint8List());
  sink.add(indexBytes);

  // --- Write Actual File Data ---
  int writtenSize = 0;
  final totalSize = files.fold<int>(0, (sum, f) => sum + f.data.length);

  for (final f in files) {
    final data = f.data;
    const chunkSize = 1024 * 1024;
    int offset = 0;

    while (offset < data.length) {
      final end = (offset + chunkSize).clamp(0, data.length);
      sink.add(data.sublist(offset, end));
      writtenSize += (end - offset);
      offset = end;

      if (onProgress != null) {
        onProgress(f.name, writtenSize / totalSize);
      }
    }
  }

  await sink.flush();
  await sink.close();
}