Added shortcuts in drawer menu if configured in remote prov

This commit is contained in:
Sylvain Berfini 2024-09-19 16:46:44 +02:00
parent e74ebb0d81
commit 0e451dcc8a
9 changed files with 170 additions and 4 deletions

View file

@ -131,7 +131,7 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
.maxSizePercent(0.02)
.build()
}
.networkCachePolicy(CachePolicy.DISABLED)
.networkCachePolicy(CachePolicy.ENABLED)
.diskCachePolicy(diskCachePolicy)
.memoryCachePolicy(CachePolicy.ENABLED)
.build()

View file

@ -20,6 +20,7 @@
package org.linphone.ui.main.fragment
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
@ -129,6 +130,19 @@ class DrawerMenuFragment : GenericMainFragment() {
}
}
viewModel.openLinkInBrowserEvent.observe(viewLifecycleOwner) {
it.consume { link ->
try {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
startActivity(browserIntent)
} catch (ise: IllegalStateException) {
Log.e(
"$TAG Can't start ACTION_VIEW intent for URL [$link], IllegalStateException: $ise"
)
}
}
}
sharedViewModel.refreshDrawerMenuAccountsListEvent.observe(viewLifecycleOwner) {
it.consume { recreate ->
if (recreate) {

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2010-2024 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.model
data class ShortcutModel(
val label: String,
val iconUrl: String,
val link: String,
private val lambda: (link: String) -> Unit
) {
fun clicked() {
lambda.invoke(link)
}
}

View file

@ -32,6 +32,7 @@ import org.linphone.core.CoreListenerStub
import org.linphone.core.tools.Log
import org.linphone.ui.GenericViewModel
import org.linphone.ui.main.model.AccountModel
import org.linphone.ui.main.model.ShortcutModel
import org.linphone.utils.Event
class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
@ -47,6 +48,8 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
val hideSettings = MutableLiveData<Boolean>()
val shortcuts = MutableLiveData<ArrayList<ShortcutModel>>()
val startAssistantEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
@ -63,6 +66,10 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
MutableLiveData<Event<String>>()
}
val openLinkInBrowserEvent: MutableLiveData<Event<String>> by lazy {
MutableLiveData<Event<String>>()
}
private val coreListener = object : CoreListenerStub() {
@WorkerThread
override fun onDefaultAccountChanged(core: Core, account: Account?) {
@ -104,8 +111,9 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
if (status != ConfiguringState.Skipped) {
accounts.value.orEmpty().forEach(AccountModel::destroy)
Log.i("$TAG Configuring status is [$status], reload accounts")
Log.i("$TAG Configuring status is [$status], reload accounts & shortcuts")
computeAccountsList()
computeShortcuts()
}
}
}
@ -118,6 +126,7 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
hideSettings.postValue(corePreferences.hideSettings)
computeAccountsList()
computeShortcuts()
}
}
@ -173,7 +182,7 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
val maxAccount = corePreferences.maxAccountsCount
val accountsCount = list.size
val maxAccountsReached = maxAccount > 0 && accountsCount >= maxAccount
val maxAccountsReached = maxAccount in 1..accountsCount
if (maxAccountsReached) {
Log.w(
"$TAG Max number of allowed accounts reached [$maxAccount], hiding add account button"
@ -181,4 +190,29 @@ class DrawerMenuViewModel @UiThread constructor() : GenericViewModel() {
}
hideAddAccount.postValue(maxAccountsReached)
}
@WorkerThread
private fun computeShortcuts() {
val config = coreContext.core.config
val shortcutsList = arrayListOf<ShortcutModel>()
val shortcutsCount = config.getInt("ui", "shortcut_count", 0)
if (shortcutsCount > 0) {
Log.i("$TAG Found [$shortcutsCount] shortcuts to display")
for (i in 0 until shortcutsCount) {
val key = "shortcut_$i"
val label = config.getString(key, "name", "").orEmpty()
val iconUrl = config.getString(key, "icon", "").orEmpty()
val linkUrl = config.getString(key, "link", "").orEmpty()
val shortcutModel = ShortcutModel(
label,
iconUrl,
linkUrl
) { link ->
openLinkInBrowserEvent.postValue(Event(link))
}
shortcutsList.add(shortcutModel)
}
}
shortcuts.postValue(shortcutsList)
}
}

View file

@ -284,6 +284,22 @@ fun AppCompatTextView.setColor(@ColorRes color: Int) {
setTextColor(context.getColor(color))
}
@UiThread
@BindingAdapter("coilUrl")
fun ImageView.loadUrlImage(url: String?) {
if (!url.isNullOrEmpty()) {
load(url) {
listener(
onError = { _, result ->
Log.e(
"$TAG Error getting shortcut icon from URL [$url]: ${result.throwable}"
)
}
)
}
}
}
@UiThread
@BindingAdapter("coilFile")
fun ImageView.loadFileImage(file: String?) {

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="256"
android:viewportHeight="256">
<path
android:pathData="M224,104a8,8 0,0 1,-16 0L208,59.32l-66.33,66.34a8,8 0,0 1,-11.32 -11.32L196.68,48L152,48a8,8 0,0 1,0 -16h64a8,8 0,0 1,8 8ZM184,128a8,8 0,0 0,-8 8v72L48,208L48,80h72a8,8 0,0 0,0 -16L48,64A16,16 0,0 0,32 80L32,208a16,16 0,0 0,16 16L176,224a16,16 0,0 0,16 -16L192,136A8,8 0,0 0,184 128Z"
android:fillColor="#4e6074"/>
</vector>

View file

@ -135,6 +135,21 @@
android:background="?attr/color_main2_200"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/shortcuts" />
<LinearLayout
android:id="@+id/shortcuts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
android:visibility="@{viewModel.shortcuts.empty ? View.GONE : View.VISIBLE, default=gone}"
app:entries="@{viewModel.shortcuts}"
app:layout="@{@layout/drawer_shortcuts_list_cell}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/settings" />
<androidx.appcompat.widget.AppCompatTextView

View file

@ -0,0 +1,47 @@
<?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" />
<variable
name="model"
type="org.linphone.ui.main.model.ShortcutModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<ImageView
android:onClick="@{() -> model.clicked()}"
android:id="@+id/shortcut_icon"
android:layout_width="wrap_content"
android:layout_height="@dimen/icon_size"
android:adjustViewBounds="true"
coilUrl="@{model.iconUrl}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> model.clicked()}"
style="@style/header_style"
android:id="@+id/shortcut_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@{model.label, default=`Shortcut`}"
android:drawableEnd="@drawable/arrow_square_out"
android:drawablePadding="8dp"
app:drawableTint="?attr/color_main2_500"
app:layout_constraintStart_toEndOf="@id/shortcut_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -218,7 +218,7 @@
android:layout_marginTop="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:text="@string/settings_calls_change_ringtone_title"
android:drawableEnd="@drawable/caret_right"
android:drawableEnd="@drawable/arrow_square_out"
android:drawableTint="?attr/color_main2_600"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toStartOf="parent"