This commit is contained in:
lunaticbum 2024-08-22 17:51:59 +09:00
parent 74c64c7617
commit 5cc40ee056
6 changed files with 295 additions and 18 deletions

View File

@ -18,6 +18,7 @@
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/> <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<!-- api 33+ --> <!-- api 33+ -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission <uses-permission

View File

@ -27,7 +27,10 @@ import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.CallLog
import android.provider.ContactsContract
import android.provider.Settings import android.provider.Settings
import android.util.Log
import android.view.WindowInsets import android.view.WindowInsets
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
@ -50,7 +53,6 @@ import rasel.lunar.launcher.databinding.LauncherActivityBinding
import rasel.lunar.launcher.feeds.Feeds import rasel.lunar.launcher.feeds.Feeds
import rasel.lunar.launcher.feeds.WidgetHost import rasel.lunar.launcher.feeds.WidgetHost
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_BACK_HOME
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_FIRST_LAUNCH import rasel.lunar.launcher.helpers.Constants.Companion.KEY_FIRST_LAUNCH
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_STATUS_BAR import rasel.lunar.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WINDOW_BACKGROUND import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WINDOW_BACKGROUND
@ -61,6 +63,7 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId
import rasel.lunar.launcher.helpers.ViewPagerAdapter import rasel.lunar.launcher.helpers.ViewPagerAdapter
import rasel.lunar.launcher.home.LauncherHome import rasel.lunar.launcher.home.LauncherHome
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import java.util.Date
internal class LauncherActivity : AppCompatActivity() { internal class LauncherActivity : AppCompatActivity() {
@ -152,16 +155,16 @@ internal class LauncherActivity : AppCompatActivity() {
/* set up viewpager2 */ /* set up viewpager2 */
private fun setupView() { private fun setupView() {
viewPager = binding.viewPager.apply { viewPager = binding.viewPager.apply {
adapter = ViewPagerAdapter( adapter = ViewPagerAdapter(
supportFragmentManager, supportFragmentManager,
mutableListOf(Feeds(), LauncherHome(), AppDrawer()), mutableListOf(Feeds(), LauncherHome(), AppDrawer()),
lifecycle lifecycle
) )
offscreenPageLimit = 1 offscreenPageLimit = 1
setCurrentItem(1, false) setCurrentItem(1, false)
reduceDragSensitivity() reduceDragSensitivity()
} }
} }
private fun setBgColor() { private fun setBgColor() {
@ -235,4 +238,6 @@ internal class LauncherActivity : AppCompatActivity() {
fun openSearchMenus(keyword : String, dismissCalback: DismissCalback) { fun openSearchMenus(keyword : String, dismissCalback: DismissCalback) {
SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()} SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()}
} }
} }

View File

@ -25,14 +25,23 @@ import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.provider.AlarmClock import android.provider.AlarmClock
import android.provider.CallLog
import android.text.format.DateFormat import android.text.format.DateFormat
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.Toast import android.widget.Toast
import androidx.biometric.BiometricPrompt import androidx.biometric.BiometricPrompt
import androidx.core.view.get
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.LauncherHomeBinding import rasel.lunar.launcher.databinding.LauncherHomeBinding
@ -51,10 +60,12 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod
import rasel.lunar.launcher.home.weather.WeatherExecutor import rasel.lunar.launcher.home.weather.WeatherExecutor
import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.qaccess.QuickAccess
import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.settings.SettingsActivity
import rasel.lunar.launcher.todos.MissedCallsAdapter
import rasel.lunar.launcher.todos.TodoAdapter import rasel.lunar.launcher.todos.TodoAdapter
import rasel.lunar.launcher.todos.TodoManager import rasel.lunar.launcher.todos.TodoManager
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.SimpleFingerGestures import rasel.lunar.launcher.utils.SimpleFingerGestures
import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -122,6 +133,86 @@ internal class LauncherHome : Fragment() {
} }
} }
var callList = arrayListOf<MissedCall>()
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<String>(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<String, MissedCall>()
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() { override fun onPause() {
super.onPause() super.onPause()
/* unregister battery changes */ /* unregister battery changes */
@ -383,7 +474,19 @@ internal class LauncherHome : Fragment() {
/* to-do list */ /* to-do list */
private fun showTodoList() { 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 */ /* 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 = ""
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<MissedCall>,
private val context: Context) : RecyclerView.Adapter<MissedCallsAdapter.MissedCallsHolder>() {
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)
}
}
}
}

View File

@ -66,18 +66,54 @@
app:layout_constraintTop_toBottomOf="@+id/date" app:layout_constraintTop_toBottomOf="@+id/date"
app:layout_constraintVertical_bias="0.100" /> app:layout_constraintVertical_bias="0.100" />
<RadioGroup
android:id="@+id/summaryChoose"
android:layout_width="0dp"
android:gravity="center"
app:layout_constraintLeft_toLeftOf="parent"
android:orientation="horizontal"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
>
<RadioButton
android:id="@+id/missedCalls"
android:button="@null"
android:gravity="center"
android:text="전화"
android:checked="true"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<RadioButton
android:gravity="center"
android:button="@null"
android:text="투두"
android:checked="false"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<RadioButton
android:gravity="center"
android:button="@null"
android:text="문자"
android:checked="false"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RadioGroup>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/notes" android:id="@+id/notes"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:layout_height="@dimen/zero" android:layout_height="200dp"
android:overScrollMode="never" android:overScrollMode="never"
android:padding="@dimen/fortyEight" android:padding="20dp"
android:scrollbars="none" android:scrollbars="none"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress" />
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" />
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/favAppsGroup" android:id="@+id/favAppsGroup"

View File

@ -7,7 +7,7 @@
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/itemText" android:id="@+id/itemText"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:layout_height="wrap_content" android:layout_height="40dp"
android:padding="@dimen/twelve" android:padding="@dimen/twelve"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"