From 42be2402f304e5ccd90008340f72f73cf6411110 Mon Sep 17 00:00:00 2001 From: Prateek batra Date: Mon, 16 Mar 2026 10:56:08 +0530 Subject: [PATCH 1/2] feat/add-drag-drop : Add Drag & Drop Functionality --- .../java/com/example/cahier/MainActivity.kt | 5 +- .../cahier/core/utils/DragAndDropUtils.kt | 69 +++++++++++++++++++ .../features/home/HomeScreenComponents.kt | 3 + 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/example/cahier/MainActivity.kt b/app/src/main/java/com/example/cahier/MainActivity.kt index 4a8428e..3d36169 100644 --- a/app/src/main/java/com/example/cahier/MainActivity.kt +++ b/app/src/main/java/com/example/cahier/MainActivity.kt @@ -30,6 +30,7 @@ import androidx.core.content.IntentCompat import com.example.cahier.core.data.NoteType import com.example.cahier.features.home.CahierApp import com.example.cahier.core.ui.theme.CahierAppTheme +import com.example.cahier.core.utils.createDragAndDropTarget import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -48,7 +49,9 @@ class MainActivity : ComponentActivity() { setContent { CahierAppTheme { Surface( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .createDragAndDropTarget(this), color = MaterialTheme.colorScheme.background ) { CahierApp(noteId = noteId, noteType = noteType) diff --git a/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt b/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt index 36d5ae3..e9fd013 100644 --- a/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt +++ b/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt @@ -18,13 +18,27 @@ package com.example.cahier.core.utils +import android.app.Activity +import android.app.PendingIntent +import android.content.ClipData +import android.content.ClipDescription +import android.content.Intent import android.net.Uri +import android.os.Build import android.view.DragAndDropPermissions +import android.view.View import androidx.activity.ComponentActivity +import androidx.annotation.RequiresApi import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.draganddrop.dragAndDropSource +import androidx.compose.foundation.draganddrop.dragAndDropTarget +import androidx.compose.ui.Modifier import androidx.compose.ui.draganddrop.DragAndDropEvent import androidx.compose.ui.draganddrop.DragAndDropTarget +import androidx.compose.ui.draganddrop.DragAndDropTransferData import androidx.compose.ui.draganddrop.toAndroidDragEvent +import com.example.cahier.AppArgs +import com.example.cahier.core.data.Note @OptIn(ExperimentalFoundationApi::class) fun createDropTarget( @@ -43,3 +57,58 @@ fun createDropTarget( } } } + +fun Modifier.createDragAndDropSource( + activity: Activity?, + note: Note +): Modifier = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + dragAndDropSource { _ -> + activity?.let { + DragAndDropTransferData( + clipData = getClipData(it, note), + flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION or View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG, + ) + } + } +} else { + this +} + +fun Modifier.createDragAndDropTarget( + activity: Activity +): Modifier = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + dragAndDropTarget( + shouldStartDragAndDrop = { event -> + event.toAndroidDragEvent().clipDescription?.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT) ?: false + }, + target = object : DragAndDropTarget { + override fun onDrop(event: DragAndDropEvent): Boolean = + event.toAndroidDragEvent().clipData?.getItemAt(0)?.intent?.let { + activity.startActivity(it) + true + } ?: false + } + ) +} else { + this +} + + +@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) +fun getClipData(activity: Activity, note: Note): ClipData { + val componentName = activity.componentName + val intent = Intent.makeMainActivity(componentName).apply { + putExtra(AppArgs.NOTE_ID_KEY, note.id) + putExtra(AppArgs.NOTE_TYPE_KEY, note.type) + flags = Intent.FLAG_ACTIVITY_NEW_TASK or + Intent.FLAG_ACTIVITY_MULTIPLE_TASK or + Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT + } + val pendingIntent = PendingIntent.getActivity( + activity, 0, intent, PendingIntent.FLAG_IMMUTABLE + ) + return ClipData( + AppArgs.NOTE_ID_KEY, arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT), + ClipData.Item.Builder().setIntentSender(pendingIntent.intentSender).build() + ) +} diff --git a/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt b/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt index a71ab20..9f3c918 100644 --- a/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt +++ b/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt @@ -18,6 +18,7 @@ package com.example.cahier.features.home +import androidx.activity.compose.LocalActivity import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -75,6 +76,7 @@ import com.example.cahier.R import com.example.cahier.core.data.Note import com.example.cahier.core.data.NoteType import com.example.cahier.core.ui.theme.CahierAppTheme +import com.example.cahier.core.utils.createDragAndDropSource import com.example.cahier.features.drawing.DrawingDetailThumbnail @Composable @@ -212,6 +214,7 @@ fun NoteItem( .fillMaxWidth() .clip(CardDefaults.outlinedShape) .clickable { onClick() } + .createDragAndDropSource(LocalActivity.current, note) ) { NoteItemContent(note) NoteItemActions(onToggleFavorite, note, onDelete, onNewWindow, isCompact) From 02b02eb27540dbc9989180084c7bdf5b951dcda6 Mon Sep 17 00:00:00 2001 From: Prateek batra Date: Tue, 24 Mar 2026 09:22:24 +0530 Subject: [PATCH 2/2] feat/add-drag-drop : Fix Click & Drag Handling to Outline Card --- .../java/com/example/cahier/MainActivity.kt | 4 +--- .../cahier/core/utils/DragAndDropUtils.kt | 21 ------------------- .../features/home/HomeScreenComponents.kt | 14 +++++++------ 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/example/cahier/MainActivity.kt b/app/src/main/java/com/example/cahier/MainActivity.kt index 3d36169..4c43978 100644 --- a/app/src/main/java/com/example/cahier/MainActivity.kt +++ b/app/src/main/java/com/example/cahier/MainActivity.kt @@ -30,7 +30,6 @@ import androidx.core.content.IntentCompat import com.example.cahier.core.data.NoteType import com.example.cahier.features.home.CahierApp import com.example.cahier.core.ui.theme.CahierAppTheme -import com.example.cahier.core.utils.createDragAndDropTarget import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -50,8 +49,7 @@ class MainActivity : ComponentActivity() { CahierAppTheme { Surface( modifier = Modifier - .fillMaxSize() - .createDragAndDropTarget(this), + .fillMaxSize(), color = MaterialTheme.colorScheme.background ) { CahierApp(noteId = noteId, noteType = noteType) diff --git a/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt b/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt index e9fd013..18af930 100644 --- a/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt +++ b/app/src/main/java/com/example/cahier/core/utils/DragAndDropUtils.kt @@ -31,7 +31,6 @@ import androidx.activity.ComponentActivity import androidx.annotation.RequiresApi import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.draganddrop.dragAndDropSource -import androidx.compose.foundation.draganddrop.dragAndDropTarget import androidx.compose.ui.Modifier import androidx.compose.ui.draganddrop.DragAndDropEvent import androidx.compose.ui.draganddrop.DragAndDropTarget @@ -74,26 +73,6 @@ fun Modifier.createDragAndDropSource( this } -fun Modifier.createDragAndDropTarget( - activity: Activity -): Modifier = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { - dragAndDropTarget( - shouldStartDragAndDrop = { event -> - event.toAndroidDragEvent().clipDescription?.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT) ?: false - }, - target = object : DragAndDropTarget { - override fun onDrop(event: DragAndDropEvent): Boolean = - event.toAndroidDragEvent().clipData?.getItemAt(0)?.intent?.let { - activity.startActivity(it) - true - } ?: false - } - ) -} else { - this -} - - @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) fun getClipData(activity: Activity, note: Note): ClipData { val componentName = activity.componentName diff --git a/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt b/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt index 9f3c918..723e19e 100644 --- a/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt +++ b/app/src/main/java/com/example/cahier/features/home/HomeScreenComponents.kt @@ -205,18 +205,20 @@ fun NoteItem( modifier: Modifier = Modifier ) { OutlinedCard( + onClick = onClick, elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), colors = CardDefaults.cardColors( containerColor = if (isSelected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceContainerLow ), - modifier = modifier - .fillMaxWidth() - .clip(CardDefaults.outlinedShape) - .clickable { onClick() } - .createDragAndDropSource(LocalActivity.current, note) + modifier = modifier.fillMaxWidth() ) { - NoteItemContent(note) + NoteItemContent( + note = note, + modifier = Modifier + .fillMaxWidth() + .createDragAndDropSource(LocalActivity.current, note) + ) NoteItemActions(onToggleFavorite, note, onDelete, onNewWindow, isCompact) } }