Got it working + New component

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
rapterjet2004 2025-02-18 11:37:47 -06:00
parent 33fd163ee6
commit a294c4845f
No known key found for this signature in database
GPG Key ID: 3AA5FDFED7944099
3 changed files with 220 additions and 67 deletions

View File

@ -0,0 +1,142 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Julius Linus <juliuslinus1@gmail.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.ui
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.graphics.Bitmap
import android.os.Build
import android.provider.MediaStore
import android.util.Log
import android.util.Size
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import autodagger.AutoInjector
import com.nextcloud.talk.application.NextcloudTalkApplication
@AutoInjector(NextcloudTalkApplication::class)
class LastImagesCompose {
companion object {
private const val LIMIT = 10
private const val IMAGE_HEIGHT = 50
private const val IMAGE_WIDTH = 50
}
init {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
}
@Composable
fun GetView(context: Context) {
val thumbnails = getLast10Images(context)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
items(thumbnails) { bitmap ->
LastImageItem(bitmap)
}
item {
ShowGalleryButton()
}
}
}
// FIXME check if this works on my physical device
private fun getLast10Images(context: Context): List<Bitmap> {
val thumbnails = mutableListOf<Bitmap>()
val projection = arrayOf(
MediaStore.Images.Media._ID,
)
val queryArgs = bundleOf()
queryArgs.putInt(ContentResolver.QUERY_ARG_SORT_DIRECTION, ContentResolver.QUERY_SORT_DIRECTION_DESCENDING)
queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, LIMIT)
context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
queryArgs,
null
)?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val contentUri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
id
)
val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
context.contentResolver.loadThumbnail(
contentUri, Size(IMAGE_WIDTH, IMAGE_HEIGHT), null)
} else {
val kind = MediaStore.Images.Thumbnails.MINI_KIND
MediaStore.Images.Thumbnails.getThumbnail(context.contentResolver, id, kind, null)
}
thumbnails.add(bitmap)
}
}
Log.d("Julius", "Size: ${thumbnails.size}")
return thumbnails
}
@Composable
private fun LastImageItem(bitmap: Bitmap) {
Image(
bitmap = bitmap.asImageBitmap(),
modifier = Modifier.size(IMAGE_HEIGHT.dp),
contentDescription = "Image from Gallery" // TODO make this more accessible
)
}
@Composable
private fun ShowGalleryButton() {
val pickMedia = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
Log.d("Julius", "Selected URI: $uri") // TODO add to chat
} else {
Log.d("Julius", "No media selected")
}
}
IconButton(onClick = {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}) {
Icon(
imageVector = Icons.Filled.AddCircle,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
}
}
}

View File

@ -19,9 +19,10 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.databinding.DialogAttachmentBinding
import com.nextcloud.talk.ui.LastImagesCompose
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.SpreedFeatures
import com.nextcloud.talk.utils.CapabilitiesUtil
import com.nextcloud.talk.utils.SpreedFeatures
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -45,6 +46,10 @@ class AttachmentDialog(val activity: Activity, var chatActivity: ChatActivity) :
initItemsStrings()
initItemsVisibility()
initItemsClickListeners()
dialogAttachmentBinding.lastImagesCompose.setContent {
LastImagesCompose().GetView(context)
}
}
private fun initItemsStrings() {

View File

@ -31,6 +31,78 @@
android:textColor="@color/medium_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/last_images_compose"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- TODO combine both photo/video into 1 option called Open Camera -->
<LinearLayout
android:id="@+id/menu_attach_picture_from_cam"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/standard_padding"
android:paddingEnd="@dimen/standard_padding"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/menu_icon_attach_picture_from_cam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_baseline_photo_camera_24"
app:tint="@color/high_emphasis_menu_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/txt_attach_picture_from_cam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/zero"
android:text="@string/nc_upload_picture_from_cam"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/menu_attach_video_from_cam"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/standard_padding"
android:paddingEnd="@dimen/standard_padding"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/menu_icon_attach_video_from_cam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_baseline_videocam_24"
app:tint="@color/high_emphasis_menu_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/txt_attach_video_from_cam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/zero"
android:text="@string/nc_upload_video_from_cam"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/menu_attach_poll"
android:layout_width="match_parent"
@ -130,72 +202,6 @@
</LinearLayout>
<LinearLayout
android:id="@+id/menu_attach_picture_from_cam"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/standard_padding"
android:paddingEnd="@dimen/standard_padding"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/menu_icon_attach_picture_from_cam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_baseline_photo_camera_24"
app:tint="@color/high_emphasis_menu_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/txt_attach_picture_from_cam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/zero"
android:text="@string/nc_upload_picture_from_cam"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/menu_attach_video_from_cam"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_item_height"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/standard_padding"
android:paddingEnd="@dimen/standard_padding"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/menu_icon_attach_video_from_cam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_baseline_videocam_24"
app:tint="@color/high_emphasis_menu_icon" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/txt_attach_video_from_cam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:paddingStart="@dimen/standard_double_padding"
android:paddingEnd="@dimen/zero"
android:text="@string/nc_upload_video_from_cam"
android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textSize="@dimen/bottom_sheet_text_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/menu_attach_file_from_local"
android:layout_width="match_parent"