Added delete all call logs menu & dialog

This commit is contained in:
Sylvain Berfini 2023-08-17 13:19:06 +02:00
parent 8fcf3f1baa
commit b2a89a46ca
14 changed files with 337 additions and 17 deletions

View file

@ -23,11 +23,14 @@ import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
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.view.animation.Animation import android.view.animation.Animation
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.widget.PopupWindow
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.navGraphViewModels import androidx.navigation.navGraphViewModels
@ -35,9 +38,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R import org.linphone.R
import org.linphone.databinding.CallsListFragmentBinding import org.linphone.databinding.CallsListFragmentBinding
import org.linphone.databinding.CallsListPopupMenuBinding
import org.linphone.ui.main.calls.adapter.CallsListAdapter import org.linphone.ui.main.calls.adapter.CallsListAdapter
import org.linphone.ui.main.calls.model.RemoveAllCallLogsDialogModel
import org.linphone.ui.main.calls.viewmodel.CallsListViewModel import org.linphone.ui.main.calls.viewmodel.CallsListViewModel
import org.linphone.ui.main.fragment.GenericFragment import org.linphone.ui.main.fragment.GenericFragment
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event import org.linphone.utils.Event
import org.linphone.utils.slideInToastFromTopForDuration import org.linphone.utils.slideInToastFromTopForDuration
@ -125,7 +131,7 @@ class CallsListFragment : GenericFragment() {
} }
binding.setMenuClickListener { binding.setMenuClickListener {
// TODO show popup menu with delete all history button showPopupMenu()
} }
} }
@ -140,4 +146,47 @@ class CallsListFragment : GenericFragment() {
val target = binding.greenToast.root val target = binding.greenToast.root
target.slideInToastFromTopForDuration(binding.root as ViewGroup, lifecycleScope) target.slideInToastFromTopForDuration(binding.root as ViewGroup, lifecycleScope)
} }
private fun showPopupMenu() {
val popupView: CallsListPopupMenuBinding = DataBindingUtil.inflate(
LayoutInflater.from(requireContext()),
R.layout.calls_list_popup_menu,
null,
false
)
val popupWindow = PopupWindow(
popupView.root,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
true
)
popupView.setDeleteAllHistoryClickListener {
val model = RemoveAllCallLogsDialogModel()
val dialog = DialogUtils.getRemoveAllCallLogsConfirmationDialog(
requireActivity(),
model
)
model.dismissEvent.observe(viewLifecycleOwner) {
it.consume {
dialog.dismiss()
}
}
model.confirmRemovalEvent.observe(viewLifecycleOwner) {
it.consume {
listViewModel.removeAllCallLogs()
dialog.dismiss()
}
}
dialog.show()
popupWindow.dismiss()
}
// Elevation is for showing a shadow around the popup
popupWindow.elevation = 20f
popupWindow.showAsDropDown(binding.menu, 0, 0, Gravity.BOTTOM)
}
} }

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* 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 org.linphone.ui.main.calls.model
import androidx.lifecycle.MutableLiveData
import org.linphone.utils.Event
class RemoveAllCallLogsDialogModel() {
val dismissEvent = MutableLiveData<Event<Boolean>>()
val confirmRemovalEvent = MutableLiveData<Event<Boolean>>()
fun dismiss() {
// UI thread
dismissEvent.value = Event(true)
}
fun confirmRemoval() {
// UI thread
confirmRemovalEvent.value = Event(true)
}
}

View file

@ -63,6 +63,16 @@ class CallsListViewModel : ViewModel() {
} }
} }
fun removeAllCallLogs() {
// UI thread
coreContext.postOnCoreThread { core ->
for (callLog in core.callLogs) {
core.removeCallLog(callLog)
}
computeCallLogsList(currentFilter)
}
}
private fun computeCallLogsList(filter: String) { private fun computeCallLogsList(filter: String) {
// Core thread // Core thread
val list = arrayListOf<CallLogModel>() val list = arrayListOf<CallLogModel>()

View file

@ -20,11 +20,10 @@
package org.linphone.ui.main.contacts.model package org.linphone.ui.main.contacts.model
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.linphone.ui.main.contacts.viewmodel.ContactViewModel import org.linphone.ui.main.contacts.viewmodel.ContactViewModel
import org.linphone.utils.Event import org.linphone.utils.Event
class NumberOrAddressPickerDialogModel(viewModel: ContactViewModel) : ViewModel() { class NumberOrAddressPickerDialogModel(viewModel: ContactViewModel) {
val sipAddressesAndPhoneNumbers = MutableLiveData<ArrayList<ContactNumberOrAddressModel>>() val sipAddressesAndPhoneNumbers = MutableLiveData<ArrayList<ContactNumberOrAddressModel>>()
val dismissEvent = MutableLiveData<Event<Boolean>>() val dismissEvent = MutableLiveData<Event<Boolean>>()

View file

@ -31,6 +31,8 @@ import androidx.databinding.DataBindingUtil
import org.linphone.R import org.linphone.R
import org.linphone.databinding.DialogConfirmZrtpSasBinding import org.linphone.databinding.DialogConfirmZrtpSasBinding
import org.linphone.databinding.DialogPickNumberOrAddressBinding import org.linphone.databinding.DialogPickNumberOrAddressBinding
import org.linphone.databinding.DialogRemoveAllCallLogsBinding
import org.linphone.ui.main.calls.model.RemoveAllCallLogsDialogModel
import org.linphone.ui.main.contacts.model.NumberOrAddressPickerDialogModel import org.linphone.ui.main.contacts.model.NumberOrAddressPickerDialogModel
import org.linphone.ui.voip.model.ZrtpSasConfirmationDialogModel import org.linphone.ui.voip.model.ZrtpSasConfirmationDialogModel
@ -40,7 +42,7 @@ class DialogUtils {
context: Context, context: Context,
viewModel: NumberOrAddressPickerDialogModel viewModel: NumberOrAddressPickerDialogModel
): Dialog { ): Dialog {
val dialog = Dialog(context) val dialog = Dialog(context, R.style.Theme_LinphoneDialog)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
val binding: DialogPickNumberOrAddressBinding = DataBindingUtil.inflate( val binding: DialogPickNumberOrAddressBinding = DataBindingUtil.inflate(
@ -55,7 +57,7 @@ class DialogUtils {
val d: Drawable = ColorDrawable( val d: Drawable = ColorDrawable(
ContextCompat.getColor(dialog.context, R.color.dialog_background) ContextCompat.getColor(dialog.context, R.color.dialog_background)
) )
d.alpha = 100 d.alpha = 166
dialog.window dialog.window
?.setLayout( ?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
@ -64,11 +66,40 @@ class DialogUtils {
dialog.window?.setBackgroundDrawable(d) dialog.window?.setBackgroundDrawable(d)
return dialog return dialog
} }
fun getRemoveAllCallLogsConfirmationDialog(
context: Context,
model: RemoveAllCallLogsDialogModel
): Dialog {
val dialog = Dialog(context, R.style.Theme_LinphoneDialog)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
val binding: DialogRemoveAllCallLogsBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.dialog_remove_all_call_logs,
null,
false
)
binding.viewModel = model
dialog.setContentView(binding.root)
val d: Drawable = ColorDrawable(
ContextCompat.getColor(dialog.context, R.color.dialog_background)
)
d.alpha = 166
dialog.window
?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
dialog.window?.setBackgroundDrawable(d)
return dialog
}
fun getZrtpSasConfirmationDialog( fun getZrtpSasConfirmationDialog(
context: Context, context: Context,
viewModel: ZrtpSasConfirmationDialogModel viewModel: ZrtpSasConfirmationDialogModel
): Dialog { ): Dialog {
val dialog = Dialog(context) val dialog = Dialog(context, R.style.Theme_LinphoneDialog)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
val binding: DialogConfirmZrtpSasBinding = DataBindingUtil.inflate( val binding: DialogConfirmZrtpSasBinding = DataBindingUtil.inflate(
@ -83,7 +114,7 @@ class DialogUtils {
val d: Drawable = ColorDrawable( val d: Drawable = ColorDrawable(
ContextCompat.getColor(dialog.context, R.color.dialog_background) ContextCompat.getColor(dialog.context, R.color.dialog_background)
) )
d.alpha = 100 d.alpha = 166
dialog.window dialog.window
?.setLayout( ?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,

View file

@ -41,7 +41,10 @@
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginEnd="9dp" android:layout_marginEnd="9dp"
android:adjustViewBounds="true" android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:src="@drawable/dot_menu" android:src="@drawable/dot_menu"
app:tint="@color/white" app:tint="@color/white"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -36,12 +36,14 @@
<ImageView <ImageView
android:id="@+id/menu" android:id="@+id/menu"
android:layout_width="wrap_content" android:layout_width="24dp"
android:layout_height="35dp" android:layout_height="24dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:adjustViewBounds="true" android:paddingTop="4dp"
android:padding="5dp" android:paddingBottom="4dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:src="@drawable/dot_menu" android:src="@drawable/dot_menu"
app:tint="@color/primary_color" app:tint="@color/primary_color"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -41,7 +41,10 @@
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginEnd="9dp" android:layout_marginEnd="9dp"
android:adjustViewBounds="true" android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:src="@drawable/dot_menu" android:src="@drawable/dot_menu"
app:tint="@color/white" app:tint="@color/white"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<import type="android.graphics.Typeface" />
<variable
name="deleteAllHistoryClickListener"
type="View.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_round_popup_menu_background">
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{deleteAllHistoryClickListener}"
style="@style/default_text_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Delete all history"
android:textSize="14sp"
android:textColor="@color/red_danger"
android:drawableStart="@drawable/delete"
android:drawablePadding="5dp"
app:drawableTint="@color/red_danger"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -15,7 +15,6 @@
android:onClick="@{() -> viewModel.dismiss()}" android:onClick="@{() -> viewModel.dismiss()}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/in_call_black"
android:clickable="true" android:clickable="true"
android:focusable="true"> android:focusable="true">
@ -39,10 +38,8 @@
android:src="@drawable/shape_dialog_background" android:src="@drawable/shape_dialog_background"
app:layout_constraintBottom_toBottomOf="@id/anchor" app:layout_constraintBottom_toBottomOf="@id/anchor"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title" app:layout_constraintTop_toTopOf="@id/title" />
app:layout_constraintVertical_bias="1.0" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_800" style="@style/default_text_style_800"

View file

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<import type="android.graphics.Typeface" />
<variable
name="viewModel"
type="org.linphone.ui.main.calls.model.RemoveAllCallLogsDialogModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:onClick="@{() -> viewModel.dismiss()}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true">
<ImageView
android:id="@+id/dialog_background_shadow"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/shape_dialog_orange_shadow"
app:layout_constraintBottom_toBottomOf="@id/anchor"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintTop_toTopOf="@id/dialog_background" />
<ImageView
android:id="@+id/dialog_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="2dp"
android:src="@drawable/shape_dialog_background"
app:layout_constraintBottom_toBottomOf="@id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_800"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingTop="25dp"
android:text="Do you really want to delete all calls history?"
android:textSize="16sp"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toTopOf="@id/message"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:layout_marginTop="10dp"
android:text="All calls will be deleted of the history"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/cancel"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/title" />
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.dismiss()}"
style="@style/default_text_style_600"
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:paddingBottom="13dp"
android:paddingTop="13dp"
android:gravity="center"
android:background="@drawable/secondary_button_background"
android:text="Cancel"
android:textSize="18sp"
android:textColor="@color/secondary_button_label_color"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/message"
app:layout_constraintBottom_toTopOf="@id/confirm"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.confirmRemoval()}"
style="@style/default_text_style_600"
android:id="@+id/confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:paddingBottom="13dp"
android:paddingTop="13dp"
android:gravity="center"
android:background="@drawable/primary_button_background"
android:text="Ok"
android:textSize="18sp"
android:textColor="@color/primary_button_label_color"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/cancel"
app:layout_constraintBottom_toTopOf="@id/anchor"/>
<View
android:id="@+id/anchor"
android:layout_width="wrap_content"
android:layout_height="20dp"
app:layout_constraintTop_toBottomOf="@id/confirm"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -5,7 +5,17 @@
<item name="colorPrimary">@color/primary_color</item> <item name="colorPrimary">@color/primary_color</item>
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor">@color/primary_color</item> <item name="android:statusBarColor">@color/primary_color</item>
<!-- https://developer.android.com/guide/topics/display-cutout#best_practices_for_display_cutout_support -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item> <item name="android:windowActivityTransitions">true</item>
<item name="android:windowBackground">@color/white</item>
<item name="android:navigationBarColor">@color/white</item>
</style>
<style name="Theme.LinphoneDialog" parent="Theme.Linphone">
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowBackground">@color/transparent_color</item>
<item name="android:navigationBarColor">@color/black</item>
</style> </style>
</resources> </resources>

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="transparent_color">#00000000</color>
<color name="primary_color">#FF5E00</color> <color name="primary_color">#FF5E00</color>
<color name="primary_color_disabled">#FFEACB</color> <color name="primary_color_disabled">#FFEACB</color>
<color name="primary_color_pressed">#B72D00</color> <color name="primary_color_pressed">#B72D00</color>

View file

@ -5,7 +5,17 @@
<item name="colorPrimary">@color/primary_color</item> <item name="colorPrimary">@color/primary_color</item>
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor">@color/primary_color</item> <item name="android:statusBarColor">@color/primary_color</item>
<!-- https://developer.android.com/guide/topics/display-cutout#best_practices_for_display_cutout_support -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item> <item name="android:windowActivityTransitions">true</item>
<item name="android:windowBackground">@color/white</item>
<item name="android:navigationBarColor">@color/white</item>
</style>
<style name="Theme.LinphoneDialog" parent="Theme.Linphone">
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowBackground">@color/transparent_color</item>
<item name="android:navigationBarColor">@color/black</item>
</style> </style>
</resources> </resources>