Untitled

 avatar
unknown
plain_text
5 months ago
21 kB
2
Indexable
package com.htd.myapplication.ui.main.components

import android.annotation.SuppressLint
import android.content.Context
import android.util.DisplayMetrics
import android.util.Log
import android.view.ViewGroup
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.pager.PagerState
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.htd.myapplication.MainActivity
import com.htd.myapplication.R
import com.htd.myapplication.data.AppPackage
import com.htd.myapplication.ui.main.MainViewModel
import com.htd.myapplication.ui.theme.dp1
import kotlinx.coroutines.launch
import org.burnoutcrew.reorderable.ReorderableItem
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
import org.burnoutcrew.reorderable.rememberReorderableLazyGridState
import org.burnoutcrew.reorderable.reorderable
import kotlin.math.min

@Composable
fun ListApp(
    numberPages: Int,
    viewModel: MainViewModel,
    appStateList: MutableList<AppPackage>,
    modifier: Modifier
) {
    val context = LocalContext.current
    val openDeleteApp by viewModel.openDeleteApp.collectAsState()
    var size1 by remember { mutableStateOf(IntSize.Zero) }
    val positionDel = remember { mutableStateOf(0) }
    val isNavigateApp by viewModel.isNavigateMode.collectAsState()
    if (appStateList.isEmpty()) {
        val temp = viewModel.listApps.collectAsState();
        appStateList.addAll(temp.value)
    }

    var appAdapter = remember {
        AppAdapter().apply {
            this.appList = appStateList.toList()
            this.viewModel = viewModel
        }
    }

    LaunchedEffect(key1 = appStateList) {
        appAdapter.appList = appStateList.toList()
        appAdapter.notifyDataSetChanged()
    }

    Box(
        modifier = modifier
            .fillMaxSize()
            .onSizeChanged { size1 = it }
    ) {
        var isInUninstallZone by remember { mutableStateOf(false) }

        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            AndroidView(
                modifier = Modifier
                    .fillMaxHeight(0.9f)
                    .padding(vertical = 10.dp)
                    .fillMaxWidth(),
                factory = { context ->
                    RecyclerView(context).apply {
                        layoutManager = GridLayoutManager(context, 5)
                        adapter = appAdapter
                        layoutParams = ViewGroup.LayoutParams(
                            ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT
                        )
                        // Setup ItemTouchHelper for drag and drop
                        val itemTouchHelper = ItemTouchHelper(object :
                            ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, 0) {

                            override fun onMove(
                                recyclerView: RecyclerView,
                                viewHolder: RecyclerView.ViewHolder,
                                target: RecyclerView.ViewHolder
                            ): Boolean {
                                // Regular drag and drop
                                val fromPosition = viewHolder.adapterPosition
                                val toPosition = target.adapterPosition
                                appStateList.add(toPosition, appStateList.removeAt(fromPosition))
                                adapter?.notifyItemMoved(fromPosition, toPosition)
                                return true
                            }

                            override fun onSelectedChanged(
                                viewHolder: RecyclerView.ViewHolder?,
                                actionState: Int
                            ) {
                                super.onSelectedChanged(viewHolder, actionState)
                                if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
                                    viewHolder?.itemView?.alpha = 0.5f
                                    viewModel._openDeleteApp.value = true
                                }
                            }

                            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                                // No swipe action
                            }

                            override fun onChildDraw(
                                c: android.graphics.Canvas,
                                recyclerView: RecyclerView,
                                viewHolder: RecyclerView.ViewHolder,
                                dX: Float,
                                dY: Float,
                                actionState: Int,
                                isCurrentlyActive: Boolean
                            ) {
                                // Check if the view is in the uninstall zone
                                val itemView = viewHolder.itemView
                                val recyclerViewHeight = recyclerView.height
                                val itemBottom = itemView.bottom

                                // Get the screen width and the x position of the dragged item
                                val screenWidth = recyclerView.width
                                val itemLeft = itemView.left
                                val itemRight = itemView.right
                        
                                // Define uninstall zone: bottom 100px and width centered
                                val uninstallZoneWidth = 200 / DisplayMetrics().density
                                val uninstallZoneLeft = (screenWidth - uninstallZoneWidth) / 2
                                val uninstallZoneRight = uninstallZoneLeft + uninstallZoneWidth
                                Log.e("anth", "onChildDraw: ${itemBottom} ${recyclerViewHeight} ${itemLeft} ${uninstallZoneLeft} ")
                                // Check if item is within the bottom and centered uninstall zone
                                val isDraggingIntoUninstallZone = itemBottom > recyclerViewHeight - 300 && // Bottom 100px
                                        itemLeft >= uninstallZoneLeft

                                isInUninstallZone = isDraggingIntoUninstallZone

                                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
                            }

                            override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
                                super.clearView(recyclerView, viewHolder)
                                if (isInUninstallZone) {
                                    isInUninstallZone = false
                                    val position = viewHolder.adapterPosition
                                    if (position != RecyclerView.NO_POSITION) {
                                        val appInfo = appStateList[position]
                                        MainActivity.getInstance()?.uninstallApp(appInfo.pkgId)
                                        positionDel.value = position
                                    }
                                }
                                viewModel._openDeleteApp.value = false
                                viewHolder.itemView.alpha = 1f
                                Log.e("anth", "clearView: check " + isInUninstallZone)
                            }

                            override fun isLongPressDragEnabled(): Boolean {
                                return true
                            }
                        })
                        itemTouchHelper.attachToRecyclerView(this)
                    }
                },
                update = {
                    if (appAdapter.itemCount != appStateList.size) {
                        appStateList.removeAt(positionDel.value)
                        appAdapter.appList = appStateList.toList()
                        Log.e("anth", "ListApp: need update adapter")
                    }
                }
            )

            // Uninstall Zone (Bottom of the Screen with specific width)
            if (openDeleteApp) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(100.dp),
                    contentAlignment = Alignment.Center
                ) {
                    Box(
                        modifier = Modifier
                            .width(200.dp) // Set a specific width for the drop zone
                            .fillMaxHeight()
                            .background(Color.Transparent), // Transparent background for inner box
                        contentAlignment = Alignment.Center
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.image_uninstall_app),
                            contentDescription = "",
                            modifier = Modifier.size(width= 100.dp1, height = 30.dp1)
                        )
                    }
                }
            }
        }
    }
}

@SuppressLint("CoroutineCreationDuringComposition", "StateFlowValueCalledInComposition")
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun HorizontalGrid(
    list: List<AppPackage>,
    context: Context, viewModel: MainViewModel,
    pagerState: Any,
    listApps: List<AppPackage>,
    width: Int,
    height: Int,
    positionDelete: Offset,
    widthDevice: Float,
    tmp: Boolean,
    onChange: (Boolean) -> Unit,
    width1: Dp,
    height1: Dp
) {

    val allowerDeleteApp by viewModel.allowerDeleteApp.collectAsState()
    val widthLeftContent by viewModel.widthLeftContent.collectAsState()

    val check = remember {
        mutableStateOf(0)
    }

    var lists = remember {
        mutableStateOf(list)
    }

    var listAppss = remember {
        mutableStateOf(listApps)
    }

    LaunchedEffect(tmp, listApps) {
        lists.value = list
        listAppss.value = listApps
    }

    val state = rememberReorderableLazyGridState(onMove = {from, to ->
        lists.value = lists.value.toMutableList().apply {
            val itemToMove = removeAt(from.index)
            add(to.index, itemToMove)
        }
        if (pagerState is PagerState) {
            listAppss.value = listAppss.value.toMutableList().apply {
                val itemToMove = removeAt(from.index + (pagerState.currentPage * 9))
                add(to.index + (pagerState.currentPage * 9), itemToMove)
                check.value = check.value ++
            }
            viewModel.setList(listAppss.value)
        }
    })
    var boxPosition by remember { mutableStateOf(IntOffset.Zero) }

    var checkAllowDelete = remember { mutableStateOf(true) }


    LazyVerticalGrid(
        columns = GridCells.Fixed(5),
        state = state.gridState,
        verticalArrangement = Arrangement.spacedBy(50.dp1),
        horizontalArrangement = Arrangement.spacedBy(width1 * 0.12f),
        contentPadding = PaddingValues(horizontal = 30.dp, vertical = 10.dp),
        modifier = Modifier
            .reorderable(state)
            .fillMaxSize()
            .detectReorderAfterLongPress(state)
    ) {
        items(lists.value.size, { if  (lists.value[it].icon == null) lists.value[it].pkgId else lists.value[it].icon!!.toString()}) { item ->
            val coroutineScope = rememberCoroutineScope()
            ReorderableItem(state, lists.value[item].icon.toString()) { isDragging ->
                if (isDragging) {
                    viewModel._itemDelete.value = lists.value.get(item)
                    viewModel._openDeleteApp.value = true
                    viewModel._allowerDeleteApp.value = false
                    if (boxPosition.x > widthDevice - 100) {

                        if (pagerState is PagerState) {
                            if (checkAllowDelete.value) {
                                checkAllowDelete.value = false


                                listAppss.value = listAppss.value.toMutableList().apply {
                                    val itemToMove =
                                        removeAt(item + ((pagerState.currentPage) * 9))
                                    add(min(((pagerState.currentPage + 1) * 9), listAppss.value.size), itemToMove)
                                }
                                viewModel.setList(listAppss.value)
                                coroutineScope.launch {
                                    pagerState.scrollToPage(pagerState.currentPage + 1)
                                    onChange(!tmp)
                                }

                            }
                        }
                    } else if (boxPosition.x < widthLeftContent && boxPosition.x != 0) {
                        if (pagerState is PagerState) {
                            if (pagerState.currentPage > 0) {
                                if (checkAllowDelete.value) {
                                    checkAllowDelete.value = false

                                    listAppss.value = listAppss.value.toMutableList().apply {
                                        val itemToMove =
                                            removeAt(item + ((pagerState.currentPage) * 9))
                                        add(min(0+ ((pagerState.currentPage - 1) * 9), listAppss.value.size), itemToMove)
                                    }
                                    viewModel.setList(listAppss.value)
                                    coroutineScope.launch {
                                        pagerState.scrollToPage(pagerState.currentPage - 1)
                                        onChange(!tmp)
                                    }
                                }
                            }
                        }
                    } else if (boxPosition.x < (positionDelete.x + width) && boxPosition.x > (positionDelete.x - width) && boxPosition.y < (positionDelete.y + height) && boxPosition.y > (positionDelete.y - height)) {
                        viewModel._allowerDeleteApp.value = true
                    } else {
                        viewModel._allowerDeleteApp.value = false
                    }
                } else {
                    if (lists.value.get(item) == viewModel.itemDelete.value) {
                        viewModel._openDeleteApp.value = false
                        if (allowerDeleteApp) {
                            viewModel._allowerDeleteApp.value = false
                            viewModel.uninstallApp(context = context, packageName = lists.value.get(item).pkgId)
                        }
                    }
                }
                if (lists.value[item].icon == null) {
                    Box(modifier = Modifier.fillMaxSize()) {

                    }
                } else {
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .clickable {
                                kotlin.runCatching {
                                    viewModel.startActivity(context, list[item])
                                }
                            }) {
                        Column(
                            modifier = Modifier.fillMaxSize(),
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {
                            Box(contentAlignment = Alignment.Center) {
                                Image(
                                    painter = painterResource(id = R.drawable.ic_bg_app),
                                    contentDescription = "",
                                    modifier = Modifier.size(width1 * 0.1f)
                                )
                                Image(
                                    painter = rememberDrawablePainter(drawable = lists.value[item].icon),
                                    contentDescription = "",
                                    modifier = Modifier
                                        .size(width1 * 0.065f)
                                        .padding(5.dp1)
                                        .onGloballyPositioned { coordinates ->
                                            if (isDragging == true) {
                                                boxPosition = IntOffset(
                                                    x = coordinates.positionInWindow().x.toInt(),
                                                    y = coordinates.positionInWindow().y.toInt()
                                                )
                                            }
                                        }
                                )
                            }
                            Text(
                                text = lists.value[item].title,
                                modifier = Modifier.padding(top = 10.dp1, bottom = 10.dp1),
                                maxLines = 1,
                                overflow = TextOverflow.Ellipsis,
                                style = TextStyle(
                                    color = Color.White,
                                    fontWeight = FontWeight.Bold,
                                    fontSize = 12.sp
                                )
                            )
                        }
                    }
                }

            }
        }
    }
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ListApps(list: List<AppPackage>, context: Context, viewModel: MainViewModel, height1: Dp) {
    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 128.dp)
    ) {
        items(list.size, { list[it].icon.toString() }) { index ->
            Column(
                horizontalAlignment = Alignment.CenterHorizontally,
                modifier = Modifier
                    .combinedClickable(
                        onClick = {
                            kotlin.runCatching {
                                viewModel.startActivity(context, list[index])
                            }
                        },
                        onLongClick = {
                            viewModel.setModeEdit(true)
                        })
            ) {
                Box(contentAlignment = Alignment.Center) {
                    Image(
                        painter = painterResource(id = R.drawable.ic_bg_app),
                        contentDescription = "",
                        modifier = Modifier.size(height1 * 0.12f)
                    )
                    Image(
                        painter = rememberDrawablePainter(drawable = list[index].icon),
                        contentDescription = "",
                        modifier = Modifier.size(height1 * 0.1f)
                    )
                }
                Text(
                    text = list[index].title,
                    modifier = Modifier.padding(top = 10.dp1),
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    style = TextStyle(
                        color = Color.White,
                        fontWeight = FontWeight.Bold
                    )
                )
            }
        }
    }
}
Editor is loading...
Leave a Comment