Skip to content

Conversation

@prathieshna
Copy link

feat: Implement content picker and grid layout for media

Replaced the generic file picker with a new content picker sheet that allows users to add media from the camera, gallery, or files.

  • Content Picker: Added a bottom sheet (ContentPickerFragment) to choose between Camera, Gallery, and Files.
  • Modern Media Pickers: Implemented modern ActivityResultContracts for picking visual media, taking pictures, and opening documents.
  • Camera Integration: Added logic to handle camera permissions and launch either the native camera or a custom camera activity.
  • Grid Layout: Changed the file list from a LinearLayoutManager to a GridLayoutManager for a visual, grid-based display.
  • File Type Filtering: The file picker now filters for supported media types (image, video, audio) and shows a warning for invalid files.
  • Open Downloaded Files: Implemented functionality to open downloaded files using an ACTION_VIEW intent.
  • UI Enhancements:
    • A new snowbird_media_grid_item.xml layout was created for grid items.
    • The adapter now displays appropriate icons based on file type (image, video, audio).

Elelan and others added 3 commits December 4, 2025 19:29
feat: add DWeb server control to SnowbirdFragment and update service …
Replaced the generic file picker with a new content picker sheet that allows users to add media from the camera, gallery, or files.

- **Content Picker:** Added a bottom sheet (`ContentPickerFragment`) to choose between Camera, Gallery, and Files.
- **Modern Media Pickers:** Implemented modern `ActivityResultContracts` for picking visual media, taking pictures, and opening documents.
- **Camera Integration:** Added logic to handle camera permissions and launch either the native camera or a custom camera activity.
- **Grid Layout:** Changed the file list from a `LinearLayoutManager` to a `GridLayoutManager` for a visual, grid-based display.
- **File Type Filtering:** The file picker now filters for supported media types (image, video, audio) and shows a warning for invalid files.
- **Open Downloaded Files:** Implemented functionality to open downloaded files using an `ACTION_VIEW` intent.
- **UI Enhancements:**
    - A new `snowbird_media_grid_item.xml` layout was created for grid items.
    - The adapter now displays appropriate icons based on file type (image, video, audio).
@prathieshna prathieshna requested a review from Elelan December 5, 2025 16:40
@prathieshna prathieshna self-assigned this Dec 5, 2025
import java.lang.ref.WeakReference

class SnowbirdFileViewHolder(val binding: OneLineRowBinding) : RecyclerView.ViewHolder(binding.root)
class SnowbirdFileViewHolder(val binding: SnowbirdMediaGridItemBinding) : RecyclerView.ViewHolder(binding.root)

Check warning

Code scanning / detekt

Library classes should not be public. Warning

Class SnowbirdFileViewHolder should not be public

// Modern visual media picker for gallery (supports up to 10 items)
private val galleryLauncher =
registerForActivityResult(ActivityResultContracts.PickMultipleVisualMedia(10)) { uris: List<Uri>? ->

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
val filteredUris = uris.filter { uri ->
val mimeType = requireContext().contentResolver.getType(uri)
mimeType?.startsWith("image/") == true ||
mimeType?.startsWith("video/") == true ||

Check warning

Code scanning / detekt

Reports mis-indented code Warning

Unexpected indentation (20) (should be 24)
val mimeType = requireContext().contentResolver.getType(uri)
mimeType?.startsWith("image/") == true ||
mimeType?.startsWith("video/") == true ||
mimeType?.startsWith("audio/") == true

Check warning

Code scanning / detekt

Reports mis-indented code Warning

Unexpected indentation (20) (should be 24)
dialogManager.showDialog(dialogManager.requireResourceProvider()) {
type = DialogType.Warning
title = UiText.DynamicString("Invalid File Type")
message = UiText.DynamicString("Please select only image, video, or audio files. Other file types are not supported.")

Check warning

Code scanning / detekt

Reports lines with exceeded length Warning

Exceeded max line length (120)
// Only allow media file types (images, videos, audio)
try {
filePickerLauncher.launch(arrayOf("image/*", "video/*", "audio/*"))
} catch (e: Exception) {

Check warning

Code scanning / detekt

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. Warning

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.
val request = PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo)
try {
galleryLauncher.launch(request)
} catch (e: Exception) {

Check warning

Code scanning / detekt

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. Warning

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.
viewBinding.snowbirdMediaRecyclerView.setEmptyView(R.layout.view_empty_state)
// viewBinding.snowbirdMediaRecyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
viewBinding.snowbirdMediaRecyclerView.layoutManager = LinearLayoutManager(requireContext())
viewBinding.snowbirdMediaRecyclerView.layoutManager = GridLayoutManager(requireContext(), 3)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
}
}
}
} catch (e: Exception) {

Check warning

Code scanning / detekt

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. Warning

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.
}
}

private fun getMimeType(fileName: String): String? {

Check warning

Code scanning / detekt

Prefer splitting up complex methods into smaller, easier to test methods. Warning

The function getMimeType appears to be too complex based on Cyclomatic Complexity (complexity: 27). Defined complexity threshold for methods is set to '15'
Copy link

@Elelan Elelan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Elelan Elelan merged commit 3b99596 into feature/dweb-next Dec 5, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants