Keyboard Shortcuts

j / kScroll down / up
ggScroll to top
GScroll to bottom
K / /Open search
?Show this help
EscClose search / help
n / NNext / previous section
hGo to landing
dGo to docs
:Command mode — type section name

Press ? or Esc to close

Systems

Media Upload

Uploads are tracked globally by MediaUploadCubit, a singleton registered at bootstrap. Any screen can start an upload and observe its progress by id.

Starting an upload

lib/features/media_upload/logic/media_upload_cubit.dart
final id = const Uuid().v4();
await sl<MediaUploadCubit>().upload(
  filePath: picked.path,
  folder: MediaFolder.avatars,
  onSendProgress: (sent, total) {
    // progress is already emitted into state by the cubit
  },
);

Observing progress

The cubit keeps a map of UploadItem keyed by id. Each item carries progress (0–1) and a status: uploading, success, or failure.

lib/features/media_upload/logic/media_upload_cubit.dart
BlocBuilder<MediaUploadCubit, MediaUploadState>(
  builder: (context, state) {
    final item = state.items[id];
    if (item == null) return const SizedBox.shrink();
    if (item.isUploading) return AppCircularIndicator(value: item.progress);
    if (item.isSuccess) return AppImage(src: item.url!);
    return const AppEmptyState.error();
  },
)

Store

Under the hood, MediaUploadStore calls ApiClient.postMultipart with a FormData body and forwards Dio's onSendProgress into the cubit.

lib/features/media_upload/data/store/media_upload_store.dart
Future<ApiResponse<String, void>> upload(String path, MediaFolder folder) =>
    execute(
      request: () => _client.postMultipart(
        '/upload',
        FormData.fromMap({'file': await MultipartFile.fromFile(path), 'folder': folder.name}),
        onSendProgress: (sent, total) => _onProgress(sent / total),
      ),
      parser: (d) => d['url'] as String,
      empty: '',
    );
Why global: uploads survive screen pops. A user can start an avatar upload and leave the screen — progress and the resulting URL are still observable from anywhere.
sam's arch — A Pragmatic Flutter Architecture