diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0aebb899..026ec983 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,7 @@ + () + + private suspend fun getCallDetails() { + MainScope().async { + var dateParam = Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24 * 3)).time.toString() + val managedCursor = lActivity!!.managedQuery( + CallLog.Calls.CONTENT_URI, arrayOf( + CallLog.Calls.NUMBER, + CallLog.Calls.TYPE, + CallLog.Calls.DATE, + CallLog.Calls.DURATION, + CallLog.Calls.CACHED_NAME, + ), CallLog.Calls.DATE + "> ? AND " + CallLog.Calls.TYPE + " > ?", arrayOf(dateParam, "2"), CallLog.Calls.DATE + " desc") + val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER) + val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE) + val date = managedCursor.getColumnIndex(CallLog.Calls.DATE) + val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION) + val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME) +// sb.append("Call Details : ${managedCursor.count}") + var missedCalls = hashMapOf() + while (managedCursor.moveToNext()) { + val phNumber = managedCursor.getString(number) // mobile number + val callType = managedCursor.getString(type) // call type + val callDate = managedCursor.getString(date) // call date + val callDayTime: Date = Date(callDate.toLong()) + val callDuration = managedCursor.getString(duration) + val callerName = managedCursor.getString(name) + + var dir: String = "" + val dircode = callType.toInt() + when (dircode) { + CallLog.Calls.INCOMING_TYPE -> { + dir = "INCOMING_TYPE" + } + CallLog.Calls.OUTGOING_TYPE -> { + dir = "OUTGOING_TYPE" + } + CallLog.Calls.MISSED_TYPE -> { + dir = "MISSED_TYPE" + } + CallLog.Calls.VOICEMAIL_TYPE -> { + dir = "VOICEMAIL_TYPE" + } + CallLog.Calls.REJECTED_TYPE -> { + dir = "REJECTED_TYPE" + } + CallLog.Calls.BLOCKED_TYPE -> { + dir = "BLOCKED_TYPE" + } + CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> { + dir = "ANSWERED_EXTERNALLY_TYPE" + } + } +// if (dircode > 2) { + var missed: MissedCall = if (missedCalls.containsKey(phNumber)) { + missedCalls.get(phNumber)!!.apply { + count = count + 1 + } + } else { + MissedCall(1,callerName,phNumber, dircode, dir, SimpleDateFormat("yyy/MM/dd-HH:mm:ss").format(callDayTime)) + } + missedCalls.put(phNumber, missed) +// } + } + + + managedCursor.close() + return@async missedCalls + }.await().apply { + if (callList.size == this.size) { + + } else { + callList.clear() + this.forEach { t, u -> + callList.add(u) + } + } + } + } + override fun onPause() { super.onPause() /* unregister battery changes */ @@ -383,7 +474,19 @@ internal class LauncherHome : Fragment() { /* to-do list */ private fun showTodoList() { - binding.notes.adapter = TodoAdapter(null, requireContext()) + if (binding.missedCalls.isChecked == true) { + if (callList.size == 0) { + GlobalScope.launch { getCallDetails() } + } else { + BLog.LOGE("callList >>> ${callList.size}") + binding.notes.adapter = MissedCallsAdapter(callList, requireContext()) + binding.notes.post { + binding.notes.invalidate() + } + } + } else { + binding.notes.adapter = TodoAdapter(null, requireContext()) + } } /* get time format string */ @@ -422,3 +525,22 @@ internal class LauncherHome : Fragment() { } } + + +class MissedCall { + constructor(count: Int, name: String?, number: String, type: Int, typeString: String, date : String) { + this.count = count + this.name = name ?: "unknown" + this.number = number + this.type = type + this.typeString = typeString + this.date = date + } + + var count : Int = 1 + var name : String = "how" + var number : String = "" + var type : Int = 0 + var typeString : String = "" + var date : String = "" +} \ No newline at end of file diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt new file mode 100644 index 00000000..236441ba --- /dev/null +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/MissedCallsAdapter.kt @@ -0,0 +1,113 @@ +/* + * Lunar Launcher + * Copyright (C) 2022 Md Rasel Hossain + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package rasel.lunar.launcher.todos + +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.bottomsheet.BottomSheetDialog +import rasel.lunar.launcher.LauncherActivity.Companion.lActivity +import rasel.lunar.launcher.R +import rasel.lunar.launcher.databinding.ListItemBinding +import rasel.lunar.launcher.databinding.TodoDialogBinding +import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard +import rasel.lunar.launcher.home.MissedCall +import rasel.lunar.launcher.utils.BLog +import java.util.* +import kotlin.collections.ArrayList + + +internal class MissedCallsAdapter( + private val callList: ArrayList, + private val context: Context) : RecyclerView.Adapter() { + + private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer) + + override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): MissedCallsHolder { + val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + return MissedCallsHolder(binding) + } + + override fun getItemCount(): Int { +// BLog.LOGE("callList.size >>> ${callList.size}") + return callList.size + } + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: MissedCallsHolder, position: Int) { + val todo = callList[position] + BLog.LOGE("callList >>> ${callList[position]}") + holder.view.itemText.text = "\u25CF ${if(todo.name.equals("unknown")) todo.number else { todo.name}} , ${todo.typeString} : ${todo.count} : ${todo.date}" + + /* multiline texts are enabled for TodoManager */ + holder.view.itemText.isSingleLine = false + /* launch edit or update dialog on item click */ + holder.view.itemText.setOnClickListener { updateDialog(position) } + /* copy texts on long click */ + holder.view.itemText.setOnLongClickListener { + copyToClipboard(context, todo.name) + true + } + + } + + inner class MissedCallsHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) + + /* update dialog */ + private fun updateDialog(position: Int) { + val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog) + val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context)) + bottomSheetDialog.setContentView(dialogBinding.root) + bottomSheetDialog.show() + bottomSheetDialog.dismissWithAnimation = true + + val databaseHandler = DatabaseHandler(context) + val todo = databaseHandler.todos[position] + + dialogBinding.apply { + deleteAllConfirmation.visibility = View.GONE + todoInput.setText(todo.name) + todoCancel.text = context.getString(R.string.delete) + todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light)) + todoOk.text = context.getString(R.string.update) + } + + /* delete the item */ + dialogBinding.todoCancel.setOnClickListener { + + } + + /* update the item */ + dialogBinding.todoOk.setOnClickListener { + val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' } + if (updatedTodoString.isNotEmpty()) { + todo.name = updatedTodoString + databaseHandler.updateTodo(todo) + bottomSheetDialog.dismiss() + } else { + dialogBinding.todoInput.error = context.getString(R.string.empty_text_field) + } + } + } + +} diff --git a/app/src/main/res/layout/launcher_home.xml b/app/src/main/res/layout/launcher_home.xml index a61e5b2f..dda4a512 100644 --- a/app/src/main/res/layout/launcher_home.xml +++ b/app/src/main/res/layout/launcher_home.xml @@ -66,18 +66,54 @@ app:layout_constraintTop_toBottomOf="@+id/date" app:layout_constraintVertical_bias="0.100" /> + + + + + + + app:layout_constraintTop_toBottomOf="@+id/summaryChoose" />