filepick

A WhatsApp & Telegram style media picker, attachment selector, image cropper, and upload progress ring for Flutter apps.

Features

  • 📸 In-App Media Picker Sheet: Displays live camera tile first, recent photos/videos, album selection dropdown, limited media access management banner, and graceful system picker fallbacks.
  • 📎 Attachment Selector: Clean sheet for picking photos, videos, and documents with file type enforcement.
  • ✂️ Interactive Image Cropper: Pinch-to-zoom crop screen supporting 1:1 round avatars, 3:1 cover banners, or custom aspect ratios with automatic EXIF orientation fixing.
  • ⭕ Upload Ring: Non-covering animated progress arc around circular avatars while media uploads are in progress.
  • 🎨 Fully Themeable & Localizable: Adaptable colors via FilePickTheme, custom text translations with FilePickStrings, and security guard hooks with FilePick.guard.

Installation

Add filepick to your pubspec.yaml:

dependencies:
  filepick: ^1.0.0

Platform Setup

Android (android/app/src/main/AndroidManifest.xml)

Add permissions depending on your app's requirements:

<!-- Camera Access -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Media Access for Android 13+ (API 33+) -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<!-- Media Access for Android 12 and below -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

iOS (ios/Runner/Info.plist)

Add description keys for permissions required by photo picker and camera:

<key>NSCameraUsageDescription</key>
<string>Allow access to take photos and videos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Allow access to select photos from your library.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow access to record video with audio.</string>

Usage Examples

1. Pick and Crop Profile Photo / Avatar

final CroppedImage? cropped = await pickAndCropImage(
  context,
  title: 'Crop Profile Photo',
  aspectRatio: 1.0,
  circle: true,
  fileName: 'avatar.jpg',
);

if (cropped != null) {
  // Access cropped.bytes (Uint8List) and cropped.fileName
}

2. Attach File / Photo / Video

final PlatformFile? file = await pickAttachment(
  context,
  extensions: ['jpg', 'png', 'pdf', 'mp4'],
  title: 'Attach File',
);

if (file != null) {
  // Access file.path, file.bytes, file.name, file.size
}

3. Display Upload Ring around Avatar

UploadRing(
  active: isUploading,
  strokeWidth: 4,
  child: CircleAvatar(
    radius: 40,
    backgroundImage: NetworkImage(avatarUrl),
  ),
)

4. Customizing Theme & App Lock Guard

void main() {
  // Guard against App Lock / lifecycle background re-locking during camera/gallery pick
  FilePick.guard = <T>(action) => AppLockProvider.keepUnlockedDuring(action);

  runApp(const MyApp());
}

// Custom Theme Extension
MaterialApp(
  theme: ThemeData(
    extensions: const [
      FilePickTheme(
        accentColor: Colors.deepOrange,
        surfaceColor: Colors.white,
      ),
    ],
  ),
);

License

MIT License. See LICENSE for details.

Libraries

filepick