Compare commits
245 Commits
Author | SHA1 | Date |
---|---|---|
Tibor Kaputa | 4a071ffdb8 | |
Tibor Kaputa | 398cccda11 | |
Tibor Kaputa | 0be61052f4 | |
Tibor Kaputa | 5a42fa5949 | |
Lionel HANNEQUIN | 82d6be03f5 | |
Lionel HANNEQUIN | d0849d14e7 | |
Lionel HANNEQUIN | a79c1aaa83 | |
Lionel HANNEQUIN | 0ac8cd4423 | |
teemue | 2f28ff28ac | |
Tibor Kaputa | 9f7174faf6 | |
Tibor Kaputa | 3a50c7a122 | |
Peter Dave Hello | 888e2acf60 | |
Anonymous | 026e5af6ad | |
Subham Jena | 610a967567 | |
gallegonovato | be737c767f | |
tibbi | 15b34495c5 | |
tibbi | 277167fa0c | |
Tibor Kaputa | 90603cc005 | |
VfBFan | fdb635a94a | |
VfBFan | 1d42405d26 | |
tibbi | a55ef54e16 | |
tibbi | 59e0074447 | |
Tibor Kaputa | 9ac6fc2edb | |
Ensar Sarajčić | 3bb3bf812a | |
Tibor Kaputa | 1c80b662ec | |
fatih ergin | 4cd5529446 | |
fatih ergin | f3a04a90cf | |
Tibor Kaputa | 9855efcf66 | |
fatih ergin | 20a34761dd | |
Tibor Kaputa | 5fbf7c2b62 | |
fatih ergin | 973d0f3ac0 | |
fatih ergin | 3959383322 | |
Tibor Kaputa | c5b7837c49 | |
Tibor Kaputa | 3195df2562 | |
mimvahedi | 82cdf138b5 | |
Anonymous | 1e2941592d | |
mimvahedi | 06d41f63ff | |
Tibor Kaputa | 9464b76036 | |
fatih ergin | 2922e1caad | |
Tibor Kaputa | 259c65420a | |
Tibor Kaputa | 425f6622ce | |
fatih ergin | 168dcc9f71 | |
fatih ergin | d65d6e884d | |
fatih ergin | 81ec7fc1de | |
fatih ergin | f962765108 | |
fatih ergin | 071a78e00a | |
J. Lavoie | bdb0936f5f | |
J. Lavoie | ef09d92b85 | |
Tibor Kaputa | 8b61786a63 | |
Slávek Banko | 8175f59672 | |
tibbi | e4610ce3a5 | |
Tibor Kaputa | ef22a2c917 | |
VfBFan | 4b59c96337 | |
josé m | ad56d6e8a6 | |
Tibor Kaputa | a48f19ca12 | |
en2sv | 430d049630 | |
Tibor Kaputa | f97a186366 | |
merkost | b3e5847b95 | |
merkost | c8539a114a | |
merkost | 20e93c6065 | |
merkost | 25b15785a0 | |
merkost | 037e8ca9d4 | |
merkost | b99a851064 | |
merkost | 7f7e179d4b | |
merkost | 96dfd3f230 | |
Tibor Kaputa | 71a1f3342f | |
Priit Jõerüüt | e7cbb530ee | |
Tibor Kaputa | 90b4a2b87a | |
tibbi | f82169b41c | |
Tibor Kaputa | 703eacc161 | |
abc0922001 | 9046ea0e2a | |
abc0922001 | 8de142542f | |
Tibor Kaputa | 44a81dc7cf | |
Tibor Kaputa | 327e3a4c55 | |
Tibor Kaputa | 0c8925f887 | |
Tibor Kaputa | 59d5e92fcd | |
merkost | a1d5164823 | |
merkost | 7096cf5912 | |
merkost | 1379c288e5 | |
merkost | 532400b8f5 | |
merkost | 5f246d6c6e | |
merkost | 0e5d0154ad | |
merkost | 8051bc19e0 | |
merkost | 04cd1db82e | |
Konstantin Merenkov | ace7f416bf | |
merkost | 6a0bc60023 | |
merkost | f8e5309dec | |
merkost | bcb76d39f2 | |
Austen Adler | 835f2ad2eb | |
tibbi | 8e7f3581b4 | |
merkost | 799ad90ec2 | |
Tibor Kaputa | e226c66e16 | |
elgratea | 7aa6c9c292 | |
Tibor Kaputa | 0a1eabdba5 | |
spkprs | d2d8a28c18 | |
merkost | e0e283cf71 | |
merkost | fe2f2e03ce | |
merkost | b825eb686c | |
merkost | c499947bc7 | |
merkost | 9f622c9e4a | |
merkost | d0c9daa3ce | |
merkost | 2311fc4af9 | |
merkost | a4130cd948 | |
merkost | e20a527527 | |
merkost | 24cc3f5344 | |
merkost | 2e889f2093 | |
merkost | c0037073d1 | |
merkost | d71b795d2f | |
merkost | eb775e870b | |
merkost | e8bee1445a | |
merkost | e17555c977 | |
merkost | dbc78642b1 | |
merkost | 0c0503d24f | |
merkost | 9f1f9172ae | |
merkost | 7eafb4aaad | |
merkost | 267e5c35f0 | |
merkost | b851c0881a | |
Tibor Kaputa | 0cd9341838 | |
Sergio Marques | 9214f5c18b | |
Priit Jõerüüt | f6f9f6a5ff | |
Dan | 0807cbbf92 | |
Rex_sa | c499b8c952 | |
Josep M. Ferrer | 42a70047d7 | |
Eric | 10af0a699e | |
Oğuz Ersen | 8c5674c790 | |
Agnieszka C | 6469c52926 | |
Guillaume | 58a8a18027 | |
VfBFan | 3c0d166b37 | |
Tibor Kaputa | ebdb8dcba6 | |
merkost | b5a863aaef | |
Tibor Kaputa | 67a8c27120 | |
Tibor Kaputa | 2e8d16c703 | |
Tibor Kaputa | 4cbafe1608 | |
Tibor Kaputa | 8c67df0abd | |
Tibor Kaputa | c8edf9a00d | |
Tibor Kaputa | f24d10166d | |
Tibor Kaputa | a2499e331a | |
merkost | 58eb9585b4 | |
merkost | 5e75ea700c | |
merkost | 6099e4d37b | |
merkost | 0ad6fcb300 | |
merkost | d8b6afe669 | |
merkost | aff820a84a | |
merkost | af9ab19185 | |
merkost | 3e4c5de826 | |
merkost | 1309097d27 | |
merkost | 1c554c33fe | |
merkost | 931a2f63d1 | |
merkost | 6fc028db33 | |
merkost | 3892c5f5d5 | |
merkost | 22a2fbb331 | |
merkost | 7f2fa6cf7e | |
merkost | ec57e45770 | |
merkost | 031b662f72 | |
merkost | 9061115b11 | |
merkost | 54778a228e | |
merkost | 2abc59adcd | |
merkost | 1c57d5e5e2 | |
merkost | d3bff0a272 | |
merkost | eeaa073d55 | |
tibbi | a23dcd5302 | |
tibbi | 76af3f6899 | |
tibbi | f27b7c4c3c | |
tibbi | 2ad1980abe | |
tibbi | f2b0428679 | |
tibbi | 7b80aa1b9f | |
Tibor Kaputa | d2fefd9e03 | |
merkost | 4a4e26d6d7 | |
Tibor Kaputa | 151dcea56e | |
Tibor Kaputa | e918621fa4 | |
tibbi | b7703457bc | |
merkost | cedcd6e304 | |
tibbi | fbe4868586 | |
tibbi | 193cb76358 | |
merkost | e0b0aac5fb | |
merkost | d575123474 | |
Tibor Kaputa | c0642f3cf5 | |
Tibor Kaputa | 571aeec977 | |
merkost | 939cba30ea | |
tibbi | 56d0a0ca07 | |
tibbi | d7b412efe7 | |
tibbi | eb6dc3a9cc | |
tibbi | 0d2bc71e79 | |
Tibor Kaputa | 4df23346d3 | |
Tibor Kaputa | 50f16ba1d1 | |
Tibor Kaputa | 6bf4f6bc16 | |
Tibor Kaputa | e5b5a55b57 | |
merkost | 0e703c2942 | |
merkost | 2aa07c54e5 | |
merkost | 444ac03727 | |
tibbi | 59d850922d | |
Tibor Kaputa | fbce7496c4 | |
Tibor Kaputa | a091e48f3f | |
merkost | a9c2d752ce | |
ngocanhtve | 18c35af83c | |
Milo Ivir | 353695f74b | |
ngocanhtve | 80082f6780 | |
Anonymous | fa0ac1df5c | |
ngocanhtve | 60a95d9624 | |
tibbi | 4b281635c2 | |
Tibor Kaputa | c63056e422 | |
Mahendra Liya | c543cc785b | |
Tibor Kaputa | 42766f0dad | |
Mahendra Liya | 8889939b60 | |
tibbi | 1ff3c56c85 | |
Tibor Kaputa | f4eae8f638 | |
Tibor Kaputa | 01467bde81 | |
Tibor Kaputa | f34379405d | |
Tibor Kaputa | b2c5b44e61 | |
Tibor Kaputa | 89dc42efd4 | |
Guillaume | 22dd4bf8f8 | |
Tibor Kaputa | d03461f9af | |
Макар Разин | a00a3b6594 | |
Agnieszka C | 105bc33a53 | |
tibbi | 74b228d147 | |
am.yazdanmanesh | 83553387b7 | |
am.yazdanmanesh | ab5cd206c7 | |
am.yazdanmanesh | 2e0e658ef0 | |
AmirMohammad Yazdanmanesh | 515590c69d | |
tibbi | 5a9de64ccd | |
tibbi | fbed6e85ed | |
tibbi | 52645539f7 | |
Tibor Kaputa | 08d09bc18a | |
Tibor Kaputa | 79407efbb2 | |
ismailnurudeen | e2455d8cf0 | |
ismailnurudeen | c12a4c18db | |
ismailnurudeen | 7c17cf5dcd | |
Tibor Kaputa | 0fb7d4dbe7 | |
ismailnurudeen | 725a8c41e4 | |
ismailnurudeen | b0454de90f | |
ismailnurudeen | 87afcc86b1 | |
ismailnurudeen | f172826116 | |
tibbi | 8fa124680a | |
tibbi | 9cd02ff987 | |
tibbi | bb048a4d33 | |
tibbi | d16c3183f2 | |
tibbi | 526cac4fed | |
tibbi | 6039c591ff | |
tibbi | 846f668d59 | |
tibbi | 7730baff13 | |
Tibor Kaputa | fde79e8558 | |
Slávek Banko | 7e7981509a | |
Tibor Kaputa | 202f14dffa | |
ismailnurudeen | 236003c5d7 | |
am.yazdanmanesh | 5cca5b51a4 |
|
@ -1,3 +1,3 @@
|
|||
github: [tibbi]
|
||||
patreon: tiborkaputa
|
||||
custom: ["https://www.paypal.com/paypalme/simplemobiletools", "https://www.simplemobiletools.com/donate"]
|
||||
custom: ["https://www.paypal.me/simplemobiletools"]
|
||||
|
|
35
CHANGELOG.md
35
CHANGELOG.md
|
@ -1,6 +1,41 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
Version 5.18.1 *(2023-09-19)*
|
||||
----------------------------
|
||||
|
||||
* Allow blocking contacts easier
|
||||
* Added a grid view to favorites
|
||||
* Added blocking calls from hidden numbers
|
||||
* Added some stability, translation and UX improvements
|
||||
|
||||
Version 5.18.0 *(2023-06-08)*
|
||||
----------------------------
|
||||
|
||||
* Fixed the inability of setting the app as default for handling calls on some devices
|
||||
* Fixed some issues with incoming calls not being shown sometimes
|
||||
* Improved speed dial handling at contacts with multiple numbers
|
||||
* Properly display organization contact names
|
||||
* Added some stability, translation and UX improvements
|
||||
|
||||
Version 5.17.8 *(2023-04-19)*
|
||||
----------------------------
|
||||
|
||||
* Avoid showing contacts without a phone number
|
||||
* Fixed multiple contact handling related glitches
|
||||
* Added some stability, translation and UX improvements
|
||||
|
||||
Version 5.17.7 *(2023-04-12)*
|
||||
----------------------------
|
||||
|
||||
* Added some stability, translation and UX improvements
|
||||
|
||||
Version 5.17.6 *(2023-04-07)*
|
||||
----------------------------
|
||||
|
||||
* Fixed number presses during call
|
||||
* Added some stability, translation and UX improvements
|
||||
|
||||
Version 5.17.5 *(2023-03-29)*
|
||||
----------------------------
|
||||
|
||||
|
|
23
README.md
23
README.md
|
@ -17,20 +17,17 @@ It comes with material design and dark theme by default, provides great user exp
|
|||
|
||||
Contains no ads or unnecessary permissions. It is fully opensource, provides customizable colors. Keeping track of call logs for different phone number is also a plus point of this app.
|
||||
|
||||
Check out the full suite of Simple Tools here:
|
||||
https://www.simplemobiletools.com
|
||||
<a href="https://f-droid.org/packages/com.simplemobiletools.dialer">Get it on F-Droid</a>
|
||||
|
||||
Facebook:
|
||||
https://www.facebook.com/simplemobiletools
|
||||
|
||||
Reddit:
|
||||
https://www.reddit.com/r/SimpleMobileTools
|
||||
|
||||
Telegram:
|
||||
https://t.me/SimpleMobileTools
|
||||
|
||||
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.dialer'><img src='https://simplemobiletools.com/images/button-google-play.svg' alt='Get it on Google Play' height='45' /></a>
|
||||
<a href='https://f-droid.org/packages/com.simplemobiletools.dialer'><img src='https://simplemobiletools.com/images/button-f-droid.png' alt='Get it on F-Droid' height='45' /></a>
|
||||
Support us:
|
||||
IBAN: SK4083300000002000965231
|
||||
Bitcoin: 19Hc8A7sWGud8sP19VXDC5a5j28UyJfpyJ
|
||||
Ethereum: 0xB7a2DD6f2408Bce77334655CF5E7639aE31feb30
|
||||
Litecoin: LYACbHTKaM9ZubKQGxJ4NRyVy1gHUuztRP
|
||||
Bitcoin Cash: qz6dvmhq5vzkcsypxpp2mnur30muxdah4gvulx3y85
|
||||
Tether: 0x250f9cC32863E59b87037a14955Ed64F879653F0
|
||||
<a href="https://paypal.me/SimpleMobileTools?country.x=SK&locale.x=en_US">PayPal</a>
|
||||
<a href="https://www.patreon.com/tiborkaputa">Patreon</a>
|
||||
|
||||
<div style="display:flex;">
|
||||
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/1_en-US.jpeg" width="30%">
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
def keystoreProperties = new Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.simplemobiletools.dialer"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 33
|
||||
versionCode 52
|
||||
versionName "5.17.5"
|
||||
setProperty("archivesBaseName", "dialer")
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile file(keystoreProperties['storeFile'])
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "variants"
|
||||
productFlavors {
|
||||
core {}
|
||||
fdroid {}
|
||||
prepaid {}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.github.SimpleMobileTools:Simple-Commons:469df84c87'
|
||||
implementation 'com.github.tibbi:IndicatorFastScroll:4524cd0b61'
|
||||
implementation 'me.grantland:autofittextview:0.2.1'
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import java.io.FileInputStream
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android)
|
||||
alias(libs.plugins.kotlinAndroid)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
base
|
||||
}
|
||||
|
||||
base {
|
||||
archivesName.set("dialer")
|
||||
}
|
||||
|
||||
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
|
||||
|
||||
defaultConfig {
|
||||
applicationId = libs.versions.app.version.appId.get()
|
||||
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
|
||||
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
|
||||
versionName = project.libs.versions.app.version.versionName.get()
|
||||
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
register("release") {
|
||||
keyAlias = keystoreProperties.getProperty("keyAlias")
|
||||
keyPassword = keystoreProperties.getProperty("keyPassword")
|
||||
storeFile = file(keystoreProperties.getProperty("storeFile"))
|
||||
storePassword = keystoreProperties.getProperty("storePassword")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions.add("variants")
|
||||
productFlavors {
|
||||
register("core")
|
||||
register("fdroid")
|
||||
register("prepaid")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
getByName("main").java.srcDirs("src/main/kotlin")
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
|
||||
sourceCompatibility = currentJavaVersionFromLibs
|
||||
targetCompatibility = currentJavaVersionFromLibs
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
|
||||
}
|
||||
|
||||
namespace = libs.versions.app.version.appId.get()
|
||||
|
||||
lint {
|
||||
checkReleaseBuilds = false
|
||||
abortOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.simple.tools.commons)
|
||||
implementation(libs.indicator.fast.scroll)
|
||||
implementation(libs.autofit.text.view)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
# Keep `Companion` object fields of serializable classes.
|
||||
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
|
||||
-if @kotlinx.serialization.Serializable class **
|
||||
-keepclassmembers class <1> {
|
||||
static <1>$Companion Companion;
|
||||
}
|
||||
|
||||
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
|
||||
-if @kotlinx.serialization.Serializable class ** {
|
||||
static **$* *;
|
||||
}
|
||||
-keepclassmembers class <2>$<3> {
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
|
||||
# Keep `INSTANCE.serializer()` of serializable objects.
|
||||
-if @kotlinx.serialization.Serializable class ** {
|
||||
public static ** INSTANCE;
|
||||
}
|
||||
-keepclassmembers class <1> {
|
||||
public static <1> INSTANCE;
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.simplemobiletools.dialer"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
|
@ -42,6 +41,7 @@
|
|||
android:appCategory="productivity"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_launcher_name"
|
||||
android:localeConfig="@xml/locale_config"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
|
@ -81,7 +81,8 @@
|
|||
android:configChanges="orientation"
|
||||
android:exported="false"
|
||||
android:label="@string/blocked_numbers"
|
||||
android:parentActivityName=".activities.SettingsActivity" />
|
||||
android:parentActivityName=".activities.SettingsActivity"
|
||||
tools:replace="android:label" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.ManageSpeedDialActivity"
|
||||
|
|
|
@ -26,13 +26,12 @@ import com.simplemobiletools.commons.extensions.*
|
|||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.SimpleListItem
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.databinding.ActivityCallBinding
|
||||
import com.simplemobiletools.dialer.dialogs.DynamicBottomSheetChooserDialog
|
||||
import com.simplemobiletools.dialer.extensions.*
|
||||
import com.simplemobiletools.dialer.helpers.*
|
||||
import com.simplemobiletools.dialer.models.AudioRoute
|
||||
import com.simplemobiletools.dialer.models.CallContact
|
||||
import kotlinx.android.synthetic.main.activity_call.*
|
||||
import kotlinx.android.synthetic.main.dialpad.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
@ -45,6 +44,8 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private val binding by viewBinding(ActivityCallBinding::inflate)
|
||||
|
||||
private var isSpeakerOn = false
|
||||
private var isMicrophoneOff = false
|
||||
private var isCallEnded = false
|
||||
|
@ -63,14 +64,14 @@ class CallActivity : SimpleActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_call)
|
||||
setContentView(binding.root)
|
||||
|
||||
if (CallManager.getPhoneState() == NoCall) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
updateTextColors(call_holder)
|
||||
updateTextColors(binding.callHolder)
|
||||
initButtons()
|
||||
audioManager.mode = AudioManager.MODE_IN_CALL
|
||||
addLockScreenFlags()
|
||||
|
@ -87,6 +88,10 @@ class CallActivity : SimpleActivity() {
|
|||
super.onResume()
|
||||
updateState()
|
||||
updateNavigationBarColor(getProperBackgroundColor())
|
||||
|
||||
if (config.isUsingSystemTheme) {
|
||||
updateStatusbarColor(getProperBackgroundColor())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -100,7 +105,7 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (dialpad_wrapper.isVisible()) {
|
||||
if (binding.dialpadWrapper.isVisible()) {
|
||||
hideDialpad()
|
||||
return
|
||||
} else {
|
||||
|
@ -113,119 +118,121 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun initButtons() {
|
||||
private fun initButtons() = binding.apply {
|
||||
if (config.disableSwipeToAnswer) {
|
||||
call_draggable.beGone()
|
||||
call_draggable_background.beGone()
|
||||
call_left_arrow.beGone()
|
||||
call_right_arrow.beGone()
|
||||
callDraggable.beGone()
|
||||
callDraggableBackground.beGone()
|
||||
callLeftArrow.beGone()
|
||||
callRightArrow.beGone()
|
||||
|
||||
call_decline.setOnClickListener {
|
||||
callDecline.setOnClickListener {
|
||||
endCall()
|
||||
}
|
||||
|
||||
call_accept.setOnClickListener {
|
||||
callAccept.setOnClickListener {
|
||||
acceptCall()
|
||||
}
|
||||
} else {
|
||||
handleSwipe()
|
||||
}
|
||||
|
||||
call_toggle_microphone.setOnClickListener {
|
||||
callToggleMicrophone.setOnClickListener {
|
||||
toggleMicrophone()
|
||||
}
|
||||
|
||||
call_toggle_speaker.setOnClickListener {
|
||||
callToggleSpeaker.setOnClickListener {
|
||||
changeCallAudioRoute()
|
||||
}
|
||||
|
||||
call_dialpad.setOnClickListener {
|
||||
callDialpad.setOnClickListener {
|
||||
toggleDialpadVisibility()
|
||||
}
|
||||
|
||||
dialpad_close.setOnClickListener {
|
||||
dialpadClose.setOnClickListener {
|
||||
hideDialpad()
|
||||
}
|
||||
|
||||
call_toggle_hold.setOnClickListener {
|
||||
callToggleHold.setOnClickListener {
|
||||
toggleHold()
|
||||
}
|
||||
|
||||
call_add.setOnClickListener {
|
||||
callAdd.setOnClickListener {
|
||||
Intent(applicationContext, DialpadActivity::class.java).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
call_swap.setOnClickListener {
|
||||
callSwap.setOnClickListener {
|
||||
CallManager.swap()
|
||||
}
|
||||
|
||||
call_merge.setOnClickListener {
|
||||
callMerge.setOnClickListener {
|
||||
CallManager.merge()
|
||||
}
|
||||
|
||||
call_manage.setOnClickListener {
|
||||
startActivity(Intent(this, ConferenceActivity::class.java))
|
||||
callManage.setOnClickListener {
|
||||
startActivity(Intent(this@CallActivity, ConferenceActivity::class.java))
|
||||
}
|
||||
|
||||
call_end.setOnClickListener {
|
||||
callEnd.setOnClickListener {
|
||||
endCall()
|
||||
}
|
||||
|
||||
dialpad_0_holder.setOnClickListener { dialpadPressed('0') }
|
||||
dialpad_1_holder.setOnClickListener { dialpadPressed('1') }
|
||||
dialpad_2_holder.setOnClickListener { dialpadPressed('2') }
|
||||
dialpad_3_holder.setOnClickListener { dialpadPressed('3') }
|
||||
dialpad_4_holder.setOnClickListener { dialpadPressed('4') }
|
||||
dialpad_5_holder.setOnClickListener { dialpadPressed('5') }
|
||||
dialpad_6_holder.setOnClickListener { dialpadPressed('6') }
|
||||
dialpad_7_holder.setOnClickListener { dialpadPressed('7') }
|
||||
dialpad_8_holder.setOnClickListener { dialpadPressed('8') }
|
||||
dialpad_9_holder.setOnClickListener { dialpadPressed('9') }
|
||||
dialpadInclude.apply {
|
||||
dialpad0Holder.setOnClickListener { dialpadPressed('0') }
|
||||
dialpad1Holder.setOnClickListener { dialpadPressed('1') }
|
||||
dialpad2Holder.setOnClickListener { dialpadPressed('2') }
|
||||
dialpad3Holder.setOnClickListener { dialpadPressed('3') }
|
||||
dialpad4Holder.setOnClickListener { dialpadPressed('4') }
|
||||
dialpad5Holder.setOnClickListener { dialpadPressed('5') }
|
||||
dialpad6Holder.setOnClickListener { dialpadPressed('6') }
|
||||
dialpad7Holder.setOnClickListener { dialpadPressed('7') }
|
||||
dialpad8Holder.setOnClickListener { dialpadPressed('8') }
|
||||
dialpad9Holder.setOnClickListener { dialpadPressed('9') }
|
||||
|
||||
arrayOf(
|
||||
dialpad_0_holder,
|
||||
dialpad_1_holder,
|
||||
dialpad_2_holder,
|
||||
dialpad_3_holder,
|
||||
dialpad_4_holder,
|
||||
dialpad_5_holder,
|
||||
dialpad_6_holder,
|
||||
dialpad_7_holder,
|
||||
dialpad_8_holder,
|
||||
dialpad_9_holder,
|
||||
dialpad_plus_holder,
|
||||
dialpad_asterisk_holder,
|
||||
dialpad_hashtag_holder
|
||||
).forEach {
|
||||
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
|
||||
it.background?.alpha = LOWER_ALPHA_INT
|
||||
arrayOf(
|
||||
dialpad0Holder,
|
||||
dialpad1Holder,
|
||||
dialpad2Holder,
|
||||
dialpad3Holder,
|
||||
dialpad4Holder,
|
||||
dialpad5Holder,
|
||||
dialpad6Holder,
|
||||
dialpad7Holder,
|
||||
dialpad8Holder,
|
||||
dialpad9Holder,
|
||||
dialpadPlusHolder,
|
||||
dialpadAsteriskHolder,
|
||||
dialpadHashtagHolder
|
||||
).forEach {
|
||||
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
|
||||
it.background?.alpha = LOWER_ALPHA_INT
|
||||
}
|
||||
|
||||
dialpad0Holder.setOnLongClickListener { dialpadPressed('+'); true }
|
||||
dialpadAsteriskHolder.setOnClickListener { dialpadPressed('*') }
|
||||
dialpadHashtagHolder.setOnClickListener { dialpadPressed('#') }
|
||||
}
|
||||
|
||||
dialpad_0_holder.setOnLongClickListener { dialpadPressed('+'); true }
|
||||
dialpad_asterisk_holder.setOnClickListener { dialpadPressed('*') }
|
||||
dialpad_hashtag_holder.setOnClickListener { dialpadPressed('#') }
|
||||
|
||||
dialpad_wrapper.setBackgroundColor(getProperBackgroundColor())
|
||||
arrayOf(dialpad_close, call_sim_image).forEach {
|
||||
dialpadWrapper.setBackgroundColor(getProperBackgroundColor())
|
||||
arrayOf(dialpadClose, callSimImage).forEach {
|
||||
it.applyColorFilter(getProperTextColor())
|
||||
}
|
||||
|
||||
val bgColor = getProperBackgroundColor()
|
||||
val inactiveColor = getInactiveButtonColor()
|
||||
arrayOf(
|
||||
call_toggle_microphone, call_toggle_speaker, call_dialpad,
|
||||
call_toggle_hold, call_add, call_swap, call_merge, call_manage
|
||||
callToggleMicrophone, callToggleSpeaker, callDialpad,
|
||||
callToggleHold, callAdd, callSwap, callMerge, callManage
|
||||
).forEach {
|
||||
it.applyColorFilter(bgColor.getContrastColor())
|
||||
it.background.applyColorFilter(inactiveColor)
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
call_toggle_microphone, call_toggle_speaker, call_dialpad,
|
||||
call_toggle_hold, call_add, call_swap, call_merge, call_manage
|
||||
callToggleMicrophone, callToggleSpeaker, callDialpad,
|
||||
callToggleHold, callAdd, callSwap, callMerge, callManage
|
||||
).forEach { imageView ->
|
||||
imageView.setOnLongClickListener {
|
||||
if (!imageView.contentDescription.isNullOrEmpty()) {
|
||||
|
@ -235,16 +242,16 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
call_sim_id.setTextColor(getProperTextColor().getContrastColor())
|
||||
dialpad_input.disableKeyboard()
|
||||
callSimId.setTextColor(getProperTextColor().getContrastColor())
|
||||
dialpadInput.disableKeyboard()
|
||||
|
||||
dialpad_wrapper.onGlobalLayout {
|
||||
dialpadHeight = dialpad_wrapper.height.toFloat()
|
||||
dialpadWrapper.onGlobalLayout {
|
||||
dialpadHeight = dialpadWrapper.height.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun handleSwipe() {
|
||||
private fun handleSwipe() = binding.apply {
|
||||
var minDragX = 0f
|
||||
var maxDragX = 0f
|
||||
var initialDraggableX = 0f
|
||||
|
@ -258,84 +265,85 @@ class CallActivity : SimpleActivity() {
|
|||
var rightArrowTranslation = 0f
|
||||
|
||||
val isRtl = isRTLLayout
|
||||
call_accept.onGlobalLayout {
|
||||
callAccept.onGlobalLayout {
|
||||
minDragX = if (isRtl) {
|
||||
call_accept.left.toFloat()
|
||||
callAccept.left.toFloat()
|
||||
} else {
|
||||
call_decline.left.toFloat()
|
||||
callDecline.left.toFloat()
|
||||
}
|
||||
|
||||
maxDragX = if (isRtl) {
|
||||
call_decline.left.toFloat()
|
||||
callDecline.left.toFloat()
|
||||
} else {
|
||||
call_accept.left.toFloat()
|
||||
callAccept.left.toFloat()
|
||||
}
|
||||
|
||||
initialDraggableX = call_draggable.left.toFloat()
|
||||
initialLeftArrowX = call_left_arrow.x
|
||||
initialRightArrowX = call_right_arrow.x
|
||||
initialLeftArrowScaleX = call_left_arrow.scaleX
|
||||
initialLeftArrowScaleY = call_left_arrow.scaleY
|
||||
initialRightArrowScaleX = call_right_arrow.scaleX
|
||||
initialRightArrowScaleY = call_right_arrow.scaleY
|
||||
initialDraggableX = callDraggable.left.toFloat()
|
||||
initialLeftArrowX = callLeftArrow.x
|
||||
initialRightArrowX = callRightArrow.x
|
||||
initialLeftArrowScaleX = callLeftArrow.scaleX
|
||||
initialLeftArrowScaleY = callLeftArrow.scaleY
|
||||
initialRightArrowScaleX = callRightArrow.scaleX
|
||||
initialRightArrowScaleY = callRightArrow.scaleY
|
||||
leftArrowTranslation = if (isRtl) {
|
||||
call_accept.x
|
||||
callAccept.x
|
||||
} else {
|
||||
-call_decline.x
|
||||
-callDecline.x
|
||||
}
|
||||
|
||||
rightArrowTranslation = if (isRtl) {
|
||||
-call_accept.x
|
||||
-callAccept.x
|
||||
} else {
|
||||
call_decline.x
|
||||
callDecline.x
|
||||
}
|
||||
|
||||
if (isRtl) {
|
||||
call_left_arrow.setImageResource(R.drawable.ic_chevron_right_vector)
|
||||
call_right_arrow.setImageResource(R.drawable.ic_chevron_left_vector)
|
||||
callLeftArrow.setImageResource(R.drawable.ic_chevron_right_vector)
|
||||
callRightArrow.setImageResource(R.drawable.ic_chevron_left_vector)
|
||||
}
|
||||
|
||||
call_left_arrow.applyColorFilter(getColor(R.color.md_red_400))
|
||||
call_right_arrow.applyColorFilter(getColor(R.color.md_green_400))
|
||||
callLeftArrow.applyColorFilter(getColor(R.color.md_red_400))
|
||||
callRightArrow.applyColorFilter(getColor(R.color.md_green_400))
|
||||
|
||||
startArrowAnimation(call_left_arrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
|
||||
startArrowAnimation(call_right_arrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
|
||||
startArrowAnimation(callLeftArrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
|
||||
startArrowAnimation(callRightArrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
|
||||
}
|
||||
|
||||
call_draggable.drawable.mutate().setTint(getProperTextColor())
|
||||
call_draggable_background.drawable.mutate().setTint(getProperTextColor())
|
||||
callDraggable.drawable.mutate().setTint(getProperTextColor())
|
||||
callDraggableBackground.drawable.mutate().setTint(getProperTextColor())
|
||||
|
||||
var lock = false
|
||||
call_draggable.setOnTouchListener { _, event ->
|
||||
callDraggable.setOnTouchListener { _, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
dragDownX = event.x
|
||||
call_draggable_background.animate().alpha(0f)
|
||||
callDraggableBackground.animate().alpha(0f)
|
||||
stopAnimation = true
|
||||
call_left_arrow.animate().alpha(0f)
|
||||
call_right_arrow.animate().alpha(0f)
|
||||
callLeftArrow.animate().alpha(0f)
|
||||
callRightArrow.animate().alpha(0f)
|
||||
lock = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
dragDownX = 0f
|
||||
call_draggable.animate().x(initialDraggableX).withEndAction {
|
||||
call_draggable_background.animate().alpha(0.2f)
|
||||
callDraggable.animate().x(initialDraggableX).withEndAction {
|
||||
callDraggableBackground.animate().alpha(0.2f)
|
||||
}
|
||||
call_draggable.setImageDrawable(getDrawable(R.drawable.ic_phone_down_vector))
|
||||
call_draggable.drawable.mutate().setTint(getProperTextColor())
|
||||
call_left_arrow.animate().alpha(1f)
|
||||
call_right_arrow.animate().alpha(1f)
|
||||
callDraggable.setImageDrawable(getDrawable(R.drawable.ic_phone_down_vector))
|
||||
callDraggable.drawable.mutate().setTint(getProperTextColor())
|
||||
callLeftArrow.animate().alpha(1f)
|
||||
callRightArrow.animate().alpha(1f)
|
||||
stopAnimation = false
|
||||
startArrowAnimation(call_left_arrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
|
||||
startArrowAnimation(call_right_arrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
|
||||
startArrowAnimation(callLeftArrow, initialLeftArrowX, initialLeftArrowScaleX, initialLeftArrowScaleY, leftArrowTranslation)
|
||||
startArrowAnimation(callRightArrow, initialRightArrowX, initialRightArrowScaleX, initialRightArrowScaleY, rightArrowTranslation)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
call_draggable.x = min(maxDragX, max(minDragX, event.rawX - dragDownX))
|
||||
callDraggable.x = min(maxDragX, max(minDragX, event.rawX - dragDownX))
|
||||
when {
|
||||
call_draggable.x >= maxDragX - 50f -> {
|
||||
callDraggable.x >= maxDragX - 50f -> {
|
||||
if (!lock) {
|
||||
lock = true
|
||||
call_draggable.performHapticFeedback()
|
||||
callDraggable.performHapticFeedback()
|
||||
if (isRtl) {
|
||||
endCall()
|
||||
} else {
|
||||
|
@ -343,10 +351,11 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
call_draggable.x <= minDragX + 50f -> {
|
||||
|
||||
callDraggable.x <= minDragX + 50f -> {
|
||||
if (!lock) {
|
||||
lock = true
|
||||
call_draggable.performHapticFeedback()
|
||||
callDraggable.performHapticFeedback()
|
||||
if (isRtl) {
|
||||
acceptCall()
|
||||
} else {
|
||||
|
@ -354,23 +363,25 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
call_draggable.x > initialDraggableX -> {
|
||||
|
||||
callDraggable.x > initialDraggableX -> {
|
||||
lock = false
|
||||
val drawableRes = if (isRtl) {
|
||||
R.drawable.ic_phone_down_red_vector
|
||||
} else {
|
||||
R.drawable.ic_phone_green_vector
|
||||
}
|
||||
call_draggable.setImageDrawable(getDrawable(drawableRes))
|
||||
callDraggable.setImageDrawable(getDrawable(drawableRes))
|
||||
}
|
||||
call_draggable.x <= initialDraggableX -> {
|
||||
|
||||
callDraggable.x <= initialDraggableX -> {
|
||||
lock = false
|
||||
val drawableRes = if (isRtl) {
|
||||
R.drawable.ic_phone_green_vector
|
||||
} else {
|
||||
R.drawable.ic_phone_down_red_vector
|
||||
}
|
||||
call_draggable.setImageDrawable(getDrawable(drawableRes))
|
||||
callDraggable.setImageDrawable(getDrawable(drawableRes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,8 +411,8 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun dialpadPressed(char: Char) {
|
||||
CallManager.keypad(this, char)
|
||||
dialpad_input.addCharacter(char)
|
||||
CallManager.keypad(char)
|
||||
binding.dialpadInput.addCharacter(char)
|
||||
}
|
||||
|
||||
private fun changeCallAudioRoute() {
|
||||
|
@ -440,9 +451,12 @@ class CallActivity : SimpleActivity() {
|
|||
|
||||
private fun updateCallAudioState(route: AudioRoute?) {
|
||||
if (route != null) {
|
||||
isMicrophoneOff = audioManager.isMicrophoneMute
|
||||
updateMicrophoneButton()
|
||||
|
||||
isSpeakerOn = route == AudioRoute.SPEAKER
|
||||
val supportedAudioRoutes = CallManager.getSupportedAudioRoutes()
|
||||
call_toggle_speaker.apply {
|
||||
binding.callToggleSpeaker.apply {
|
||||
val bluetoothConnected = supportedAudioRoutes.contains(AudioRoute.BLUETOOTH)
|
||||
contentDescription = if (bluetoothConnected) {
|
||||
getString(R.string.choose_audio_route)
|
||||
|
@ -456,7 +470,7 @@ class CallActivity : SimpleActivity() {
|
|||
setImageResource(route.iconRes)
|
||||
}
|
||||
}
|
||||
toggleButtonColor(call_toggle_speaker, enabled = route != AudioRoute.EARPIECE && route != AudioRoute.WIRED_HEADSET)
|
||||
toggleButtonColor(binding.callToggleSpeaker, enabled = route != AudioRoute.EARPIECE && route != AudioRoute.WIRED_HEADSET)
|
||||
createOrUpdateAudioRouteChooser(supportedAudioRoutes, create = false)
|
||||
|
||||
if (isSpeakerOn) {
|
||||
|
@ -469,22 +483,26 @@ class CallActivity : SimpleActivity() {
|
|||
|
||||
private fun toggleMicrophone() {
|
||||
isMicrophoneOff = !isMicrophoneOff
|
||||
toggleButtonColor(call_toggle_microphone, isMicrophoneOff)
|
||||
audioManager.isMicrophoneMute = isMicrophoneOff
|
||||
CallManager.inCallService?.setMuted(isMicrophoneOff)
|
||||
call_toggle_microphone.contentDescription = getString(if (isMicrophoneOff) R.string.turn_microphone_on else R.string.turn_microphone_off)
|
||||
updateMicrophoneButton()
|
||||
}
|
||||
|
||||
private fun updateMicrophoneButton() {
|
||||
toggleButtonColor(binding.callToggleMicrophone, isMicrophoneOff)
|
||||
binding.callToggleMicrophone.contentDescription = getString(if (isMicrophoneOff) R.string.turn_microphone_on else R.string.turn_microphone_off)
|
||||
}
|
||||
|
||||
private fun toggleDialpadVisibility() {
|
||||
if (dialpad_wrapper.isVisible()) hideDialpad() else showDialpad()
|
||||
if (binding.dialpadWrapper.isVisible()) hideDialpad() else showDialpad()
|
||||
}
|
||||
|
||||
private fun findVisibleViewsUnderDialpad(): Sequence<Pair<View, Float>> {
|
||||
return ongoing_call_holder.children.filter { it.isVisible() }.map { view -> Pair(view, view.alpha) }
|
||||
return binding.ongoingCallHolder.children.filter { it.isVisible() }.map { view -> Pair(view, view.alpha) }
|
||||
}
|
||||
|
||||
private fun showDialpad() {
|
||||
dialpad_wrapper.apply {
|
||||
binding.dialpadWrapper.apply {
|
||||
translationY = dialpadHeight
|
||||
alpha = 0f
|
||||
animate()
|
||||
|
@ -507,8 +525,8 @@ class CallActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun hideDialpad() {
|
||||
dialpad_wrapper.animate()
|
||||
.withEndAction { dialpad_wrapper.beGone() }
|
||||
binding.dialpadWrapper.animate()
|
||||
.withEndAction { binding.dialpadWrapper.beGone() }
|
||||
.setInterpolator(AccelerateDecelerateInterpolator())
|
||||
.setDuration(200L)
|
||||
.alpha(0f)
|
||||
|
@ -525,9 +543,9 @@ class CallActivity : SimpleActivity() {
|
|||
|
||||
private fun toggleHold() {
|
||||
val isOnHold = CallManager.toggleHold()
|
||||
toggleButtonColor(call_toggle_hold, isOnHold)
|
||||
call_toggle_hold.contentDescription = getString(if (isOnHold) R.string.resume_call else R.string.hold_call)
|
||||
hold_status_label.beVisibleIf(isOnHold)
|
||||
toggleButtonColor(binding.callToggleHold, isOnHold)
|
||||
binding.callToggleHold.contentDescription = getString(if (isOnHold) R.string.resume_call else R.string.hold_call)
|
||||
binding.holdStatusLabel.beVisibleIf(isOnHold)
|
||||
}
|
||||
|
||||
private fun updateOtherPersonsInfo(avatar: Bitmap?) {
|
||||
|
@ -535,21 +553,23 @@ class CallActivity : SimpleActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
caller_name_label.text = if (callContact!!.name.isNotEmpty()) callContact!!.name else getString(R.string.unknown_caller)
|
||||
if (callContact!!.number.isNotEmpty() && callContact!!.number != callContact!!.name) {
|
||||
caller_number.text = callContact!!.number
|
||||
binding.apply {
|
||||
callerNameLabel.text = if (callContact!!.name.isNotEmpty()) callContact!!.name else getString(R.string.unknown_caller)
|
||||
if (callContact!!.number.isNotEmpty() && callContact!!.number != callContact!!.name) {
|
||||
callerNumber.text = callContact!!.number
|
||||
|
||||
if (callContact!!.numberLabel.isNotEmpty()) {
|
||||
caller_number.text = "${callContact!!.number} - ${callContact!!.numberLabel}"
|
||||
if (callContact!!.numberLabel.isNotEmpty()) {
|
||||
callerNumber.text = "${callContact!!.number} - ${callContact!!.numberLabel}"
|
||||
}
|
||||
} else {
|
||||
callerNumber.beGone()
|
||||
}
|
||||
} else {
|
||||
caller_number.beGone()
|
||||
}
|
||||
|
||||
if (avatar != null) {
|
||||
caller_avatar.setImageBitmap(avatar)
|
||||
} else {
|
||||
caller_avatar.setImageDrawable(null)
|
||||
if (avatar != null) {
|
||||
callerAvatar.setImageBitmap(avatar)
|
||||
} else {
|
||||
callerAvatar.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,9 +588,11 @@ class CallActivity : SimpleActivity() {
|
|||
if (accounts.size > 1) {
|
||||
accounts.forEachIndexed { index, account ->
|
||||
if (account == CallManager.getPrimaryCall()?.details?.accountHandle) {
|
||||
call_sim_id.text = "${index + 1}"
|
||||
call_sim_id.beVisible()
|
||||
call_sim_image.beVisible()
|
||||
binding.apply {
|
||||
callSimId.text = "${index + 1}"
|
||||
callSimId.beVisible()
|
||||
callSimImage.beVisible()
|
||||
}
|
||||
|
||||
val acceptDrawableId = when (index) {
|
||||
0 -> R.drawable.ic_phone_one_vector
|
||||
|
@ -581,7 +603,7 @@ class CallActivity : SimpleActivity() {
|
|||
val rippleBg = resources.getDrawable(R.drawable.ic_call_accept, theme) as RippleDrawable
|
||||
val layerDrawable = rippleBg.findDrawableByLayerId(R.id.accept_call_background_holder) as LayerDrawable
|
||||
layerDrawable.setDrawableByLayerId(R.id.accept_call_icon, getDrawable(acceptDrawableId))
|
||||
call_accept.setImageDrawable(rippleBg)
|
||||
binding.callAccept.setImageDrawable(rippleBg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,13 +627,15 @@ class CallActivity : SimpleActivity() {
|
|||
else -> 0
|
||||
}
|
||||
|
||||
if (statusTextId != 0) {
|
||||
call_status_label.text = getString(statusTextId)
|
||||
}
|
||||
binding.apply {
|
||||
if (statusTextId != 0) {
|
||||
callStatusLabel.text = getString(statusTextId)
|
||||
}
|
||||
|
||||
call_manage.beVisibleIf(call.hasCapability(Call.Details.CAPABILITY_MANAGE_CONFERENCE))
|
||||
setActionButtonEnabled(call_swap, state == Call.STATE_ACTIVE)
|
||||
setActionButtonEnabled(call_merge, state == Call.STATE_ACTIVE)
|
||||
callManage.beVisibleIf(call.hasCapability(Call.Details.CAPABILITY_MANAGE_CONFERENCE))
|
||||
setActionButtonEnabled(callSwap, state == Call.STATE_ACTIVE)
|
||||
setActionButtonEnabled(callMerge, state == Call.STATE_ACTIVE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateState() {
|
||||
|
@ -622,8 +646,8 @@ class CallActivity : SimpleActivity() {
|
|||
val state = phoneState.call.getStateCompat()
|
||||
val isSingleCallActionsEnabled = (state == Call.STATE_ACTIVE || state == Call.STATE_DISCONNECTED
|
||||
|| state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING)
|
||||
setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled)
|
||||
setActionButtonEnabled(call_add, isSingleCallActionsEnabled)
|
||||
setActionButtonEnabled(binding.callToggleHold, isSingleCallActionsEnabled)
|
||||
setActionButtonEnabled(binding.callAdd, isSingleCallActionsEnabled)
|
||||
} else if (phoneState is TwoCalls) {
|
||||
updateCallState(phoneState.active)
|
||||
updateCallOnHoldState(phoneState.onHold)
|
||||
|
@ -637,13 +661,15 @@ class CallActivity : SimpleActivity() {
|
|||
if (hasCallOnHold) {
|
||||
getCallContact(applicationContext, call) { contact ->
|
||||
runOnUiThread {
|
||||
on_hold_caller_name.text = getContactNameOrNumber(contact)
|
||||
binding.onHoldCallerName.text = getContactNameOrNumber(contact)
|
||||
}
|
||||
}
|
||||
}
|
||||
on_hold_status_holder.beVisibleIf(hasCallOnHold)
|
||||
controls_single_call.beVisibleIf(!hasCallOnHold)
|
||||
controls_two_calls.beVisibleIf(hasCallOnHold)
|
||||
binding.apply {
|
||||
onHoldStatusHolder.beVisibleIf(hasCallOnHold)
|
||||
controlsSingleCall.beVisibleIf(!hasCallOnHold)
|
||||
controlsTwoCalls.beVisibleIf(hasCallOnHold)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCallContactInfo(call: Call?) {
|
||||
|
@ -666,18 +692,18 @@ class CallActivity : SimpleActivity() {
|
|||
|
||||
private fun initOutgoingCallUI() {
|
||||
enableProximitySensor()
|
||||
incoming_call_holder.beGone()
|
||||
ongoing_call_holder.beVisible()
|
||||
binding.incomingCallHolder.beGone()
|
||||
binding.ongoingCallHolder.beVisible()
|
||||
}
|
||||
|
||||
private fun callRinging() {
|
||||
incoming_call_holder.beVisible()
|
||||
binding.incomingCallHolder.beVisible()
|
||||
}
|
||||
|
||||
private fun callStarted() {
|
||||
enableProximitySensor()
|
||||
incoming_call_holder.beGone()
|
||||
ongoing_call_holder.beVisible()
|
||||
binding.incomingCallHolder.beGone()
|
||||
binding.ongoingCallHolder.beVisible()
|
||||
callDurationHandler.removeCallbacks(updateCallDurationTask)
|
||||
callDurationHandler.post(updateCallDurationTask)
|
||||
}
|
||||
|
@ -708,13 +734,13 @@ class CallActivity : SimpleActivity() {
|
|||
isCallEnded = true
|
||||
if (callDuration > 0) {
|
||||
runOnUiThread {
|
||||
call_status_label.text = "${callDuration.getFormattedDuration()} (${getString(R.string.call_ended)})"
|
||||
binding.callStatusLabel.text = "${callDuration.getFormattedDuration()} (${getString(R.string.call_ended)})"
|
||||
Handler().postDelayed({
|
||||
finishAndRemoveTask()
|
||||
}, 3000)
|
||||
}
|
||||
} else {
|
||||
call_status_label.text = getString(R.string.call_ended)
|
||||
binding.callStatusLabel.text = getString(R.string.call_ended)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +765,7 @@ class CallActivity : SimpleActivity() {
|
|||
override fun run() {
|
||||
callDuration = CallManager.getPrimaryCall().getCallDuration()
|
||||
if (!isCallEnded) {
|
||||
call_status_label.text = callDuration.getFormattedDuration()
|
||||
binding.callStatusLabel.text = callDuration.getFormattedDuration()
|
||||
callDurationHandler.postDelayed(this, 1000)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
package com.simplemobiletools.dialer.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.commons.helpers.NavigationIcon
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.adapters.ConferenceCallsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.ActivityConferenceBinding
|
||||
import com.simplemobiletools.dialer.helpers.CallManager
|
||||
import kotlinx.android.synthetic.main.activity_conference.*
|
||||
|
||||
class ConferenceActivity : SimpleActivity() {
|
||||
private val binding by viewBinding(ActivityConferenceBinding::inflate)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_conference)
|
||||
updateMaterialActivityViews(conference_coordinator, conference_list, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(conference_list, conference_toolbar)
|
||||
conference_list.adapter = ConferenceCallsAdapter(this, conference_list, ArrayList(CallManager.getConferenceCalls())) {}
|
||||
setContentView(binding.root)
|
||||
binding.apply {
|
||||
updateMaterialActivityViews(conferenceCoordinator, conferenceList, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(conferenceList, conferenceToolbar)
|
||||
conferenceList.adapter = ConferenceCallsAdapter(this@ConferenceActivity, conferenceList, ArrayList(CallManager.getConferenceCalls())) {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupToolbar(conference_toolbar, NavigationIcon.Arrow)
|
||||
setupToolbar(binding.conferenceToolbar, NavigationIcon.Arrow)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,22 +20,23 @@ import android.view.ViewConfiguration
|
|||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
||||
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.ActivityDialpadBinding
|
||||
import com.simplemobiletools.dialer.extensions.*
|
||||
import com.simplemobiletools.dialer.helpers.DIALPAD_TONE_LENGTH_MS
|
||||
import com.simplemobiletools.dialer.helpers.ToneGeneratorHelper
|
||||
import com.simplemobiletools.dialer.models.SpeedDial
|
||||
import kotlinx.android.synthetic.main.activity_dialpad.*
|
||||
import kotlinx.android.synthetic.main.activity_dialpad.dialpad_holder
|
||||
import kotlinx.android.synthetic.main.dialpad.*
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class DialpadActivity : SimpleActivity() {
|
||||
private val binding by viewBinding(ActivityDialpadBinding::inflate)
|
||||
|
||||
private var allContacts = ArrayList<Contact>()
|
||||
private var speedDialValues = ArrayList<SpeedDial>()
|
||||
private val russianCharsMap = HashMap<Char, Int>()
|
||||
|
@ -48,48 +49,53 @@ class DialpadActivity : SimpleActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_dialpad)
|
||||
setContentView(binding.root)
|
||||
hasRussianLocale = Locale.getDefault().language == "ru"
|
||||
|
||||
updateMaterialActivityViews(dialpad_coordinator, dialpad_holder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(dialpad_list, dialpad_toolbar)
|
||||
binding.apply {
|
||||
updateMaterialActivityViews(dialpadCoordinator, dialpadHolder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(dialpadList, dialpadToolbar)
|
||||
}
|
||||
|
||||
updateNavigationBarColor(getProperBackgroundColor())
|
||||
|
||||
if (checkAppSideloading()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (config.hideDialpadNumbers) {
|
||||
dialpad_1_holder.isVisible = false
|
||||
dialpad_2_holder.isVisible = false
|
||||
dialpad_3_holder.isVisible = false
|
||||
dialpad_4_holder.isVisible = false
|
||||
dialpad_5_holder.isVisible = false
|
||||
dialpad_6_holder.isVisible = false
|
||||
dialpad_7_holder.isVisible = false
|
||||
dialpad_8_holder.isVisible = false
|
||||
dialpad_9_holder.isVisible = false
|
||||
dialpad_plus_holder.isVisible = true
|
||||
dialpad_0_holder.visibility = View.INVISIBLE
|
||||
}
|
||||
binding.dialpadWrapper.apply {
|
||||
if (config.hideDialpadNumbers) {
|
||||
dialpad1Holder.isVisible = false
|
||||
dialpad2Holder.isVisible = false
|
||||
dialpad3Holder.isVisible = false
|
||||
dialpad4Holder.isVisible = false
|
||||
dialpad5Holder.isVisible = false
|
||||
dialpad6Holder.isVisible = false
|
||||
dialpad7Holder.isVisible = false
|
||||
dialpad8Holder.isVisible = false
|
||||
dialpad9Holder.isVisible = false
|
||||
dialpadPlusHolder.isVisible = true
|
||||
dialpad0Holder.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
dialpad_0_holder,
|
||||
dialpad_1_holder,
|
||||
dialpad_2_holder,
|
||||
dialpad_3_holder,
|
||||
dialpad_4_holder,
|
||||
dialpad_5_holder,
|
||||
dialpad_6_holder,
|
||||
dialpad_7_holder,
|
||||
dialpad_8_holder,
|
||||
dialpad_9_holder,
|
||||
dialpad_plus_holder,
|
||||
dialpad_asterisk_holder,
|
||||
dialpad_hashtag_holder
|
||||
).forEach {
|
||||
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
|
||||
it.background?.alpha = LOWER_ALPHA_INT
|
||||
arrayOf(
|
||||
dialpad0Holder,
|
||||
dialpad1Holder,
|
||||
dialpad2Holder,
|
||||
dialpad3Holder,
|
||||
dialpad4Holder,
|
||||
dialpad5Holder,
|
||||
dialpad6Holder,
|
||||
dialpad7Holder,
|
||||
dialpad8Holder,
|
||||
dialpad9Holder,
|
||||
dialpadPlusHolder,
|
||||
dialpadAsteriskHolder,
|
||||
dialpadHashtagHolder
|
||||
).forEach {
|
||||
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme)
|
||||
it.background?.alpha = LOWER_ALPHA_INT
|
||||
}
|
||||
}
|
||||
|
||||
setupOptionsMenu()
|
||||
|
@ -98,57 +104,65 @@ class DialpadActivity : SimpleActivity() {
|
|||
|
||||
toneGeneratorHelper = ToneGeneratorHelper(this, DIALPAD_TONE_LENGTH_MS)
|
||||
|
||||
if (hasRussianLocale) {
|
||||
initRussianChars()
|
||||
dialpad_2_letters.append("\nАБВГ")
|
||||
dialpad_3_letters.append("\nДЕЁЖЗ")
|
||||
dialpad_4_letters.append("\nИЙКЛ")
|
||||
dialpad_5_letters.append("\nМНОП")
|
||||
dialpad_6_letters.append("\nРСТУ")
|
||||
dialpad_7_letters.append("\nФХЦЧ")
|
||||
dialpad_8_letters.append("\nШЩЪЫ")
|
||||
dialpad_9_letters.append("\nЬЭЮЯ")
|
||||
binding.dialpadWrapper.apply {
|
||||
if (hasRussianLocale) {
|
||||
initRussianChars()
|
||||
dialpad2Letters.append("\nАБВГ")
|
||||
dialpad3Letters.append("\nДЕЁЖЗ")
|
||||
dialpad4Letters.append("\nИЙКЛ")
|
||||
dialpad5Letters.append("\nМНОП")
|
||||
dialpad6Letters.append("\nРСТУ")
|
||||
dialpad7Letters.append("\nФХЦЧ")
|
||||
dialpad8Letters.append("\nШЩЪЫ")
|
||||
dialpad9Letters.append("\nЬЭЮЯ")
|
||||
|
||||
val fontSize = resources.getDimension(R.dimen.small_text_size)
|
||||
arrayOf(
|
||||
dialpad_2_letters, dialpad_3_letters, dialpad_4_letters, dialpad_5_letters, dialpad_6_letters, dialpad_7_letters, dialpad_8_letters,
|
||||
dialpad_9_letters
|
||||
).forEach {
|
||||
it.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
val fontSize = resources.getDimension(R.dimen.small_text_size)
|
||||
arrayOf(
|
||||
dialpad2Letters, dialpad3Letters, dialpad4Letters, dialpad5Letters, dialpad6Letters, dialpad7Letters, dialpad8Letters,
|
||||
dialpad9Letters
|
||||
).forEach {
|
||||
it.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
}
|
||||
}
|
||||
|
||||
setupCharClick(dialpad1Holder, '1')
|
||||
setupCharClick(dialpad2Holder, '2')
|
||||
setupCharClick(dialpad3Holder, '3')
|
||||
setupCharClick(dialpad4Holder, '4')
|
||||
setupCharClick(dialpad5Holder, '5')
|
||||
setupCharClick(dialpad6Holder, '6')
|
||||
setupCharClick(dialpad7Holder, '7')
|
||||
setupCharClick(dialpad8Holder, '8')
|
||||
setupCharClick(dialpad9Holder, '9')
|
||||
setupCharClick(dialpad0Holder, '0')
|
||||
setupCharClick(dialpadPlusHolder, '+', longClickable = false)
|
||||
setupCharClick(dialpadAsteriskHolder, '*', longClickable = false)
|
||||
setupCharClick(dialpadHashtagHolder, '#', longClickable = false)
|
||||
}
|
||||
|
||||
setupCharClick(dialpad_1_holder, '1')
|
||||
setupCharClick(dialpad_2_holder, '2')
|
||||
setupCharClick(dialpad_3_holder, '3')
|
||||
setupCharClick(dialpad_4_holder, '4')
|
||||
setupCharClick(dialpad_5_holder, '5')
|
||||
setupCharClick(dialpad_6_holder, '6')
|
||||
setupCharClick(dialpad_7_holder, '7')
|
||||
setupCharClick(dialpad_8_holder, '8')
|
||||
setupCharClick(dialpad_9_holder, '9')
|
||||
setupCharClick(dialpad_0_holder, '0')
|
||||
setupCharClick(dialpad_plus_holder, '+', longClickable = false)
|
||||
setupCharClick(dialpad_asterisk_holder, '*', longClickable = false)
|
||||
setupCharClick(dialpad_hashtag_holder, '#', longClickable = false)
|
||||
binding.apply {
|
||||
dialpadClearChar.setOnClickListener { clearChar(it) }
|
||||
dialpadClearChar.setOnLongClickListener { clearInput(); true }
|
||||
dialpadCallButton.setOnClickListener { initCall(dialpadInput.value, 0) }
|
||||
dialpadInput.onTextChangeListener { dialpadValueChanged(it) }
|
||||
dialpadInput.requestFocus()
|
||||
dialpadInput.disableKeyboard()
|
||||
}
|
||||
|
||||
dialpad_clear_char.setOnClickListener { clearChar(it) }
|
||||
dialpad_clear_char.setOnLongClickListener { clearInput(); true }
|
||||
dialpad_call_button.setOnClickListener { initCall(dialpad_input.value, 0) }
|
||||
dialpad_input.onTextChangeListener { dialpadValueChanged(it) }
|
||||
dialpad_input.requestFocus()
|
||||
|
||||
ContactsHelper(this).getContacts{ gotContacts(it) }
|
||||
dialpad_input.disableKeyboard()
|
||||
ContactsHelper(this).getContacts(showOnlyContactsWithNumbers = true) { allContacts ->
|
||||
gotContacts(allContacts)
|
||||
}
|
||||
|
||||
val properPrimaryColor = getProperPrimaryColor()
|
||||
val callIconId = if (areMultipleSIMsAvailable()) {
|
||||
val callIcon = resources.getColoredDrawableWithColor(R.drawable.ic_phone_two_vector, properPrimaryColor.getContrastColor())
|
||||
dialpad_call_two_button.setImageDrawable(callIcon)
|
||||
dialpad_call_two_button.background.applyColorFilter(properPrimaryColor)
|
||||
dialpad_call_two_button.beVisible()
|
||||
dialpad_call_two_button.setOnClickListener {
|
||||
initCall(dialpad_input.value, 1)
|
||||
binding.apply {
|
||||
dialpadCallTwoButton.setImageDrawable(callIcon)
|
||||
dialpadCallTwoButton.background.applyColorFilter(properPrimaryColor)
|
||||
dialpadCallTwoButton.beVisible()
|
||||
dialpadCallTwoButton.setOnClickListener {
|
||||
initCall(dialpadInput.value, 1)
|
||||
}
|
||||
}
|
||||
|
||||
R.drawable.ic_phone_one_vector
|
||||
|
@ -156,27 +170,29 @@ class DialpadActivity : SimpleActivity() {
|
|||
R.drawable.ic_phone_vector
|
||||
}
|
||||
|
||||
val callIcon = resources.getColoredDrawableWithColor(callIconId, properPrimaryColor.getContrastColor())
|
||||
dialpad_call_button.setImageDrawable(callIcon)
|
||||
dialpad_call_button.background.applyColorFilter(properPrimaryColor)
|
||||
binding.apply {
|
||||
val callIcon = resources.getColoredDrawableWithColor(callIconId, properPrimaryColor.getContrastColor())
|
||||
dialpadCallButton.setImageDrawable(callIcon)
|
||||
dialpadCallButton.background.applyColorFilter(properPrimaryColor)
|
||||
|
||||
letter_fastscroller.textColor = getProperTextColor().getColorStateList()
|
||||
letter_fastscroller.pressedTextColor = properPrimaryColor
|
||||
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
|
||||
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
letterFastscroller.textColor = getProperTextColor().getColorStateList()
|
||||
letterFastscroller.pressedTextColor = properPrimaryColor
|
||||
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
|
||||
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateTextColors(dialpad_holder)
|
||||
dialpad_clear_char.applyColorFilter(getProperTextColor())
|
||||
updateTextColors(binding.dialpadHolder)
|
||||
binding.dialpadClearChar.applyColorFilter(getProperTextColor())
|
||||
updateNavigationBarColor(getProperBackgroundColor())
|
||||
setupToolbar(dialpad_toolbar, NavigationIcon.Arrow)
|
||||
setupToolbar(binding.dialpadToolbar, NavigationIcon.Arrow)
|
||||
}
|
||||
|
||||
private fun setupOptionsMenu() {
|
||||
dialpad_toolbar.setOnMenuItemClickListener { menuItem ->
|
||||
binding.dialpadToolbar.setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.add_number_to_contact -> addNumberToContact()
|
||||
else -> return@setOnMenuItemClickListener false
|
||||
|
@ -188,8 +204,8 @@ class DialpadActivity : SimpleActivity() {
|
|||
private fun checkDialIntent(): Boolean {
|
||||
return if ((intent.action == Intent.ACTION_DIAL || intent.action == Intent.ACTION_VIEW) && intent.data != null && intent.dataString?.contains("tel:") == true) {
|
||||
val number = Uri.decode(intent.dataString).substringAfter("tel:")
|
||||
dialpad_input.setText(number)
|
||||
dialpad_input.setSelection(number.length)
|
||||
binding.dialpadInput.setText(number)
|
||||
binding.dialpadInput.setSelection(number.length)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -200,23 +216,23 @@ class DialpadActivity : SimpleActivity() {
|
|||
Intent().apply {
|
||||
action = Intent.ACTION_INSERT_OR_EDIT
|
||||
type = "vnd.android.cursor.item/contact"
|
||||
putExtra(KEY_PHONE, dialpad_input.value)
|
||||
putExtra(KEY_PHONE, binding.dialpadInput.value)
|
||||
launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dialpadPressed(char: Char, view: View?) {
|
||||
dialpad_input.addCharacter(char)
|
||||
binding.dialpadInput.addCharacter(char)
|
||||
maybePerformDialpadHapticFeedback(view)
|
||||
}
|
||||
|
||||
private fun clearChar(view: View) {
|
||||
dialpad_input.dispatchKeyEvent(dialpad_input.getKeyEvent(KeyEvent.KEYCODE_DEL))
|
||||
binding.dialpadInput.dispatchKeyEvent(binding.dialpadInput.getKeyEvent(KeyEvent.KEYCODE_DEL))
|
||||
maybePerformDialpadHapticFeedback(view)
|
||||
}
|
||||
|
||||
private fun clearInput() {
|
||||
dialpad_input.setText("")
|
||||
binding.dialpadInput.setText("")
|
||||
}
|
||||
|
||||
private fun gotContacts(newContacts: ArrayList<Contact>) {
|
||||
|
@ -229,7 +245,7 @@ class DialpadActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
runOnUiThread {
|
||||
if (!checkDialIntent() && dialpad_input.value.isEmpty()) {
|
||||
if (!checkDialIntent() && binding.dialpadInput.value.isEmpty()) {
|
||||
dialpadValueChanged("")
|
||||
}
|
||||
}
|
||||
|
@ -253,14 +269,14 @@ class DialpadActivity : SimpleActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
(dialpad_list.adapter as? ContactsAdapter)?.finishActMode()
|
||||
(binding.dialpadList.adapter as? ContactsAdapter)?.finishActMode()
|
||||
|
||||
val filtered = allContacts.filter {
|
||||
var convertedName = PhoneNumberUtils.convertKeypadLettersToDigits(it.name.normalizeString())
|
||||
|
||||
if (hasRussianLocale) {
|
||||
var currConvertedName = ""
|
||||
convertedName.toLowerCase().forEach { char ->
|
||||
convertedName.lowercase(Locale.getDefault()).forEach { char ->
|
||||
val convertedChar = russianCharsMap.getOrElse(char) { char }
|
||||
currConvertedName += convertedChar
|
||||
}
|
||||
|
@ -272,45 +288,69 @@ class DialpadActivity : SimpleActivity() {
|
|||
!it.doesContainPhoneNumber(text)
|
||||
}).toMutableList() as ArrayList<Contact>
|
||||
|
||||
letter_fastscroller.setupWithRecyclerView(dialpad_list, { position ->
|
||||
binding.letterFastscroller.setupWithRecyclerView(binding.dialpadList, { position ->
|
||||
try {
|
||||
val name = filtered[position].getNameToDisplay()
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()))
|
||||
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()))
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
})
|
||||
|
||||
ContactsAdapter(this, filtered, dialpad_list, null, text) {
|
||||
startCallIntent((it as Contact).phoneNumbers.first().normalizedNumber)
|
||||
ContactsAdapter(
|
||||
activity = this,
|
||||
contacts = filtered,
|
||||
recyclerView = binding.dialpadList,
|
||||
highlightText = text
|
||||
) {
|
||||
val contact = it as Contact
|
||||
if (config.showCallConfirmation) {
|
||||
CallConfirmationDialog(this@DialpadActivity, contact.getNameToDisplay()) {
|
||||
startCallIntent(contact.getPrimaryNumber() ?: return@CallConfirmationDialog)
|
||||
}
|
||||
} else {
|
||||
startCallIntent(contact.getPrimaryNumber() ?: return@ContactsAdapter)
|
||||
}
|
||||
}.apply {
|
||||
dialpad_list.adapter = this
|
||||
binding.dialpadList.adapter = this
|
||||
}
|
||||
|
||||
dialpad_placeholder.beVisibleIf(filtered.isEmpty())
|
||||
dialpad_list.beVisibleIf(filtered.isNotEmpty())
|
||||
binding.dialpadPlaceholder.beVisibleIf(filtered.isEmpty())
|
||||
binding.dialpadList.beVisibleIf(filtered.isNotEmpty())
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
if (requestCode == REQUEST_CODE_SET_DEFAULT_DIALER && isDefaultDialer()) {
|
||||
dialpadValueChanged(dialpad_input.value)
|
||||
dialpadValueChanged(binding.dialpadInput.value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initCall(number: String = dialpad_input.value, handleIndex: Int) {
|
||||
private fun initCall(number: String = binding.dialpadInput.value, handleIndex: Int) {
|
||||
if (number.isNotEmpty()) {
|
||||
if (handleIndex != -1 && areMultipleSIMsAvailable()) {
|
||||
callContactWithSim(number, handleIndex == 0)
|
||||
if (config.showCallConfirmation) {
|
||||
CallConfirmationDialog(this, number) {
|
||||
callContactWithSim(number, handleIndex == 0)
|
||||
}
|
||||
} else {
|
||||
callContactWithSim(number, handleIndex == 0)
|
||||
}
|
||||
} else {
|
||||
startCallIntent(number)
|
||||
if (config.showCallConfirmation) {
|
||||
CallConfirmationDialog(this, number) {
|
||||
startCallIntent(number)
|
||||
}
|
||||
} else {
|
||||
startCallIntent(number)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun speedDial(id: Int): Boolean {
|
||||
if (dialpad_input.value.length == 1) {
|
||||
if (binding.dialpadInput.value.length == 1) {
|
||||
val speedDial = speedDialValues.firstOrNull { it.id == id }
|
||||
if (speedDial?.isValid() == true) {
|
||||
initCall(speedDial.number, -1)
|
||||
|
@ -384,12 +424,14 @@ class DialpadActivity : SimpleActivity() {
|
|||
}, longPressTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
stopDialpadTone(char)
|
||||
if (longClickable) {
|
||||
longPressHandler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val viewContainsTouchEvent = if (event.rawX.isNaN() || event.rawY.isNaN()) {
|
||||
false
|
||||
|
|
|
@ -16,43 +16,47 @@ import android.widget.TextView
|
|||
import android.widget.Toast
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.simplemobiletools.commons.dialogs.ChangeViewTypeDialog
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.FAQItem
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.dialer.BuildConfig
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.adapters.ViewPagerAdapter
|
||||
import com.simplemobiletools.dialer.databinding.ActivityMainBinding
|
||||
import com.simplemobiletools.dialer.dialogs.ChangeSortingDialog
|
||||
import com.simplemobiletools.dialer.dialogs.FilterContactSourcesDialog
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.extensions.launchCreateNewContactIntent
|
||||
import com.simplemobiletools.dialer.fragments.ContactsFragment
|
||||
import com.simplemobiletools.dialer.fragments.FavoritesFragment
|
||||
import com.simplemobiletools.dialer.fragments.MyViewPagerFragment
|
||||
import com.simplemobiletools.dialer.helpers.OPEN_DIAL_PAD_AT_LAUNCH
|
||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||
import com.simplemobiletools.dialer.helpers.tabsList
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_contacts.*
|
||||
import kotlinx.android.synthetic.main.fragment_favorites.*
|
||||
import kotlinx.android.synthetic.main.fragment_recents.*
|
||||
import com.simplemobiletools.dialer.fragments.RecentsFragment
|
||||
import com.simplemobiletools.dialer.helpers.*
|
||||
import me.grantland.widget.AutofitHelper
|
||||
|
||||
class MainActivity : SimpleActivity() {
|
||||
private val binding by viewBinding(ActivityMainBinding::inflate)
|
||||
|
||||
private var launchedDialer = false
|
||||
private var storedShowTabs = 0
|
||||
private var storedFontSize = 0
|
||||
private var storedStartNameWithSurname = false
|
||||
var cachedContacts = ArrayList<Contact>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setContentView(binding.root)
|
||||
appLaunched(BuildConfig.APPLICATION_ID)
|
||||
setupOptionsMenu()
|
||||
refreshMenuItems()
|
||||
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = true)
|
||||
updateMaterialActivityViews(binding.mainCoordinator, binding.mainHolder, useTransparentNavigation = false, useTopSearchMenu = true)
|
||||
|
||||
launchedDialer = savedInstanceState?.getBoolean(OPEN_DIAL_PAD_AT_LAUNCH) ?: false
|
||||
|
||||
|
@ -60,7 +64,7 @@ class MainActivity : SimpleActivity() {
|
|||
checkContactPermissions()
|
||||
|
||||
if (!config.wasOverlaySnackbarConfirmed && !Settings.canDrawOverlays(this)) {
|
||||
val snackbar = Snackbar.make(main_holder, R.string.allow_displaying_over_other_apps, Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok) {
|
||||
val snackbar = Snackbar.make(binding.mainHolder, R.string.allow_displaying_over_other_apps, Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok) {
|
||||
config.wasOverlaySnackbarConfirmed = true
|
||||
startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
|
||||
}
|
||||
|
@ -73,14 +77,14 @@ class MainActivity : SimpleActivity() {
|
|||
|
||||
handleNotificationPermission { granted ->
|
||||
if (!granted) {
|
||||
toast(R.string.no_post_notifications_permissions)
|
||||
PermissionRequiredDialog(this, R.string.allow_notifications_incoming_calls, { openNotificationSettings() })
|
||||
}
|
||||
}
|
||||
} else {
|
||||
launchSetDefaultDialerIntent()
|
||||
}
|
||||
|
||||
if (isQPlus() && config.blockUnknownNumbers) {
|
||||
if (isQPlus() && (config.blockUnknownNumbers || config.blockHiddenNumbers)) {
|
||||
setDefaultCallerIdApp()
|
||||
}
|
||||
|
||||
|
@ -99,9 +103,9 @@ class MainActivity : SimpleActivity() {
|
|||
updateMenuColors()
|
||||
val properPrimaryColor = getProperPrimaryColor()
|
||||
val dialpadIcon = resources.getColoredDrawableWithColor(R.drawable.ic_dialpad_vector, properPrimaryColor.getContrastColor())
|
||||
main_dialpad_button.setImageDrawable(dialpadIcon)
|
||||
binding.mainDialpadButton.setImageDrawable(dialpadIcon)
|
||||
|
||||
updateTextColors(main_holder)
|
||||
updateTextColors(binding.mainHolder)
|
||||
setupTabColors()
|
||||
|
||||
getAllFragments().forEach {
|
||||
|
@ -110,18 +114,25 @@ class MainActivity : SimpleActivity() {
|
|||
|
||||
val configStartNameWithSurname = config.startNameWithSurname
|
||||
if (storedStartNameWithSurname != configStartNameWithSurname) {
|
||||
contacts_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
||||
favorites_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
||||
getContactsFragment()?.startNameWithSurnameChanged(configStartNameWithSurname)
|
||||
getFavoritesFragment()?.startNameWithSurnameChanged(configStartNameWithSurname)
|
||||
storedStartNameWithSurname = config.startNameWithSurname
|
||||
}
|
||||
|
||||
if (!main_menu.isSearchOpen) {
|
||||
if (!binding.mainMenu.isSearchOpen) {
|
||||
refreshItems(true)
|
||||
}
|
||||
|
||||
val configFontSize = config.fontSize
|
||||
if (storedFontSize != configFontSize) {
|
||||
getAllFragments().forEach {
|
||||
it?.fontSizeChanged()
|
||||
}
|
||||
}
|
||||
|
||||
checkShortcuts()
|
||||
Handler().postDelayed({
|
||||
recents_fragment?.refreshItems()
|
||||
getRecentsFragment()?.refreshItems()
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
|
@ -129,7 +140,7 @@ class MainActivity : SimpleActivity() {
|
|||
super.onPause()
|
||||
storedShowTabs = config.showTabs
|
||||
storedStartNameWithSurname = config.startNameWithSurname
|
||||
config.lastUsedViewPagerPage = view_pager.currentItem
|
||||
config.lastUsedViewPagerPage = binding.viewPager.currentItem
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
|
@ -140,6 +151,7 @@ class MainActivity : SimpleActivity() {
|
|||
} else if (requestCode == REQUEST_CODE_SET_DEFAULT_CALLER_ID && resultCode != Activity.RESULT_OK) {
|
||||
toast(R.string.must_make_default_caller_id_app, length = Toast.LENGTH_LONG)
|
||||
baseConfig.blockUnknownNumbers = false
|
||||
baseConfig.blockHiddenNumbers = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,8 +166,8 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (main_menu.isSearchOpen) {
|
||||
main_menu.closeSearch()
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
binding.mainMenu.closeSearch()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
@ -163,47 +175,76 @@ class MainActivity : SimpleActivity() {
|
|||
|
||||
private fun refreshMenuItems() {
|
||||
val currentFragment = getCurrentFragment()
|
||||
main_menu.getToolbar().menu.apply {
|
||||
findItem(R.id.clear_call_history).isVisible = currentFragment == recents_fragment
|
||||
findItem(R.id.sort).isVisible = currentFragment != recents_fragment
|
||||
findItem(R.id.create_new_contact).isVisible = currentFragment == contacts_fragment
|
||||
binding.mainMenu.getToolbar().menu.apply {
|
||||
findItem(R.id.clear_call_history).isVisible = currentFragment == getRecentsFragment()
|
||||
findItem(R.id.sort).isVisible = currentFragment != getRecentsFragment()
|
||||
findItem(R.id.create_new_contact).isVisible = currentFragment == getContactsFragment()
|
||||
findItem(R.id.change_view_type).isVisible = currentFragment == getFavoritesFragment()
|
||||
findItem(R.id.column_count).isVisible = currentFragment == getFavoritesFragment() && config.viewType == VIEW_TYPE_GRID
|
||||
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupOptionsMenu() {
|
||||
main_menu.getToolbar().inflateMenu(R.menu.menu)
|
||||
main_menu.toggleHideOnScroll(false)
|
||||
main_menu.setupMenu()
|
||||
binding.mainMenu.apply {
|
||||
getToolbar().inflateMenu(R.menu.menu)
|
||||
toggleHideOnScroll(false)
|
||||
setupMenu()
|
||||
|
||||
main_menu.onSearchClosedListener = {
|
||||
getAllFragments().forEach {
|
||||
it?.onSearchQueryChanged("")
|
||||
onSearchClosedListener = {
|
||||
getAllFragments().forEach {
|
||||
it?.onSearchQueryChanged("")
|
||||
}
|
||||
}
|
||||
|
||||
onSearchTextChangedListener = { text ->
|
||||
getCurrentFragment()?.onSearchQueryChanged(text)
|
||||
}
|
||||
|
||||
getToolbar().setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.clear_call_history -> clearCallHistory()
|
||||
R.id.create_new_contact -> launchCreateNewContactIntent()
|
||||
R.id.sort -> showSortingDialog(showCustomSorting = getCurrentFragment() is FavoritesFragment)
|
||||
R.id.filter -> showFilterDialog()
|
||||
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
|
||||
R.id.settings -> launchSettings()
|
||||
R.id.change_view_type -> changeViewType()
|
||||
R.id.column_count -> changeColumnCount()
|
||||
R.id.about -> launchAbout()
|
||||
else -> return@setOnMenuItemClickListener false
|
||||
}
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main_menu.onSearchTextChangedListener = { text ->
|
||||
getCurrentFragment()?.onSearchQueryChanged(text)
|
||||
private fun changeColumnCount() {
|
||||
val items = ArrayList<RadioItem>()
|
||||
for (i in 1..CONTACTS_GRID_MAX_COLUMNS_COUNT) {
|
||||
items.add(RadioItem(i, resources.getQuantityString(R.plurals.column_counts, i, i)))
|
||||
}
|
||||
|
||||
main_menu.getToolbar().setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.clear_call_history -> clearCallHistory()
|
||||
R.id.create_new_contact -> launchCreateNewContactIntent()
|
||||
R.id.sort -> showSortingDialog(showCustomSorting = getCurrentFragment() is FavoritesFragment)
|
||||
R.id.filter -> showFilterDialog()
|
||||
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
|
||||
R.id.settings -> launchSettings()
|
||||
R.id.about -> launchAbout()
|
||||
else -> return@setOnMenuItemClickListener false
|
||||
val currentColumnCount = config.contactsGridColumnCount
|
||||
RadioGroupDialog(this, ArrayList(items), currentColumnCount) {
|
||||
val newColumnCount = it as Int
|
||||
if (currentColumnCount != newColumnCount) {
|
||||
config.contactsGridColumnCount = newColumnCount
|
||||
getFavoritesFragment()?.columnCountChanged()
|
||||
}
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeViewType() {
|
||||
ChangeViewTypeDialog(this) {
|
||||
refreshMenuItems()
|
||||
getFavoritesFragment()?.refreshItems()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMenuColors() {
|
||||
updateStatusbarColor(getProperBackgroundColor())
|
||||
main_menu.updateColors()
|
||||
binding.mainMenu.updateColors()
|
||||
}
|
||||
|
||||
private fun checkContactPermissions() {
|
||||
|
@ -213,11 +254,11 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun clearCallHistory() {
|
||||
val confirmationText = "${getString(R.string.remove_confirmation)}\n\n${getString(R.string.cannot_be_undone)}"
|
||||
val confirmationText = "${getString(R.string.clear_history_confirmation)}\n\n${getString(R.string.cannot_be_undone)}"
|
||||
ConfirmationDialog(this, confirmationText) {
|
||||
RecentsHelper(this).removeAllRecentCalls(this) {
|
||||
runOnUiThread {
|
||||
recents_fragment?.refreshItems()
|
||||
getRecentsFragment()?.refreshItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,24 +296,24 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun setupTabColors() {
|
||||
val activeView = main_tabs_holder.getTabAt(view_pager.currentItem)?.customView
|
||||
updateBottomTabItemColors(activeView, true, getSelectedTabDrawableIds()[view_pager.currentItem])
|
||||
val activeView = binding.mainTabsHolder.getTabAt(binding.viewPager.currentItem)?.customView
|
||||
updateBottomTabItemColors(activeView, true, getSelectedTabDrawableIds()[binding.viewPager.currentItem])
|
||||
|
||||
getInactiveTabIndexes(view_pager.currentItem).forEach { index ->
|
||||
val inactiveView = main_tabs_holder.getTabAt(index)?.customView
|
||||
getInactiveTabIndexes(binding.viewPager.currentItem).forEach { index ->
|
||||
val inactiveView = binding.mainTabsHolder.getTabAt(index)?.customView
|
||||
updateBottomTabItemColors(inactiveView, false, getDeselectedTabDrawableIds()[index])
|
||||
}
|
||||
|
||||
val bottomBarColor = getBottomNavigationBackgroundColor()
|
||||
main_tabs_holder.setBackgroundColor(bottomBarColor)
|
||||
binding.mainTabsHolder.setBackgroundColor(bottomBarColor)
|
||||
updateNavigationBarColor(bottomBarColor)
|
||||
}
|
||||
|
||||
private fun getInactiveTabIndexes(activeIndex: Int) = (0 until main_tabs_holder.tabCount).filter { it != activeIndex }
|
||||
private fun getInactiveTabIndexes(activeIndex: Int) = (0 until binding.mainTabsHolder.tabCount).filter { it != activeIndex }
|
||||
|
||||
private fun getSelectedTabDrawableIds(): ArrayList<Int> {
|
||||
private fun getSelectedTabDrawableIds(): List<Int> {
|
||||
val showTabs = config.showTabs
|
||||
val icons = ArrayList<Int>()
|
||||
val icons = mutableListOf<Int>()
|
||||
|
||||
if (showTabs and TAB_CONTACTS != 0) {
|
||||
icons.add(R.drawable.ic_person_vector)
|
||||
|
@ -309,14 +350,14 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun initFragments() {
|
||||
view_pager.offscreenPageLimit = 2
|
||||
view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
binding.viewPager.offscreenPageLimit = 2
|
||||
binding.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
main_tabs_holder.getTabAt(position)?.select()
|
||||
binding.mainTabsHolder.getTabAt(position)?.select()
|
||||
getAllFragments().forEach {
|
||||
it?.finishActMode()
|
||||
}
|
||||
|
@ -325,29 +366,29 @@ class MainActivity : SimpleActivity() {
|
|||
})
|
||||
|
||||
// selecting the proper tab sometimes glitches, add an extra selector to make sure we have it right
|
||||
main_tabs_holder.onGlobalLayout {
|
||||
binding.mainTabsHolder.onGlobalLayout {
|
||||
Handler().postDelayed({
|
||||
var wantedTab = getDefaultTab()
|
||||
|
||||
// open the Recents tab if we got here by clicking a missed call notification
|
||||
if (intent.action == Intent.ACTION_VIEW && config.showTabs and TAB_CALL_HISTORY > 0) {
|
||||
wantedTab = main_tabs_holder.tabCount - 1
|
||||
wantedTab = binding.mainTabsHolder.tabCount - 1
|
||||
|
||||
ensureBackgroundThread {
|
||||
clearMissedCalls()
|
||||
}
|
||||
}
|
||||
|
||||
main_tabs_holder.getTabAt(wantedTab)?.select()
|
||||
binding.mainTabsHolder.getTabAt(wantedTab)?.select()
|
||||
refreshMenuItems()
|
||||
}, 100L)
|
||||
}
|
||||
|
||||
main_dialpad_button.setOnClickListener {
|
||||
binding.mainDialpadButton.setOnClickListener {
|
||||
launchDialpad()
|
||||
}
|
||||
|
||||
view_pager.onGlobalLayout {
|
||||
binding.viewPager.onGlobalLayout {
|
||||
refreshMenuItems()
|
||||
}
|
||||
|
||||
|
@ -358,31 +399,31 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun setupTabs() {
|
||||
view_pager.adapter = null
|
||||
main_tabs_holder.removeAllTabs()
|
||||
binding.viewPager.adapter = null
|
||||
binding.mainTabsHolder.removeAllTabs()
|
||||
tabsList.forEachIndexed { index, value ->
|
||||
if (config.showTabs and value != 0) {
|
||||
main_tabs_holder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
|
||||
binding.mainTabsHolder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
|
||||
customView?.findViewById<ImageView>(R.id.tab_item_icon)?.setImageDrawable(getTabIcon(index))
|
||||
customView?.findViewById<TextView>(R.id.tab_item_label)?.text = getTabLabel(index)
|
||||
AutofitHelper.create(customView?.findViewById(R.id.tab_item_label))
|
||||
main_tabs_holder.addTab(this)
|
||||
binding.mainTabsHolder.addTab(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main_tabs_holder.onTabSelectionChanged(
|
||||
binding.mainTabsHolder.onTabSelectionChanged(
|
||||
tabUnselectedAction = {
|
||||
updateBottomTabItemColors(it.customView, false, getDeselectedTabDrawableIds()[it.position])
|
||||
},
|
||||
tabSelectedAction = {
|
||||
main_menu.closeSearch()
|
||||
view_pager.currentItem = it.position
|
||||
binding.mainMenu.closeSearch()
|
||||
binding.viewPager.currentItem = it.position
|
||||
updateBottomTabItemColors(it.customView, true, getSelectedTabDrawableIds()[it.position])
|
||||
}
|
||||
)
|
||||
|
||||
main_tabs_holder.beGoneIf(main_tabs_holder.tabCount == 1)
|
||||
binding.mainTabsHolder.beGoneIf(binding.mainTabsHolder.tabCount == 1)
|
||||
storedShowTabs = config.showTabs
|
||||
storedStartNameWithSurname = config.startNameWithSurname
|
||||
}
|
||||
|
@ -412,14 +453,16 @@ class MainActivity : SimpleActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
if (view_pager.adapter == null) {
|
||||
view_pager.adapter = ViewPagerAdapter(this)
|
||||
view_pager.currentItem = if (openLastTab) config.lastUsedViewPagerPage else getDefaultTab()
|
||||
view_pager.onGlobalLayout {
|
||||
binding.apply {
|
||||
if (viewPager.adapter == null) {
|
||||
viewPager.adapter = ViewPagerAdapter(this@MainActivity)
|
||||
viewPager.currentItem = if (openLastTab) config.lastUsedViewPagerPage else getDefaultTab()
|
||||
viewPager.onGlobalLayout {
|
||||
refreshFragments()
|
||||
}
|
||||
} else {
|
||||
refreshFragments()
|
||||
}
|
||||
} else {
|
||||
refreshFragments()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,36 +473,42 @@ class MainActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
fun refreshFragments() {
|
||||
contacts_fragment?.refreshItems()
|
||||
favorites_fragment?.refreshItems()
|
||||
recents_fragment?.refreshItems()
|
||||
getContactsFragment()?.refreshItems()
|
||||
getFavoritesFragment()?.refreshItems()
|
||||
getRecentsFragment()?.refreshItems()
|
||||
}
|
||||
|
||||
private fun getAllFragments(): ArrayList<MyViewPagerFragment?> {
|
||||
private fun getAllFragments(): ArrayList<MyViewPagerFragment<*>?> {
|
||||
val showTabs = config.showTabs
|
||||
val fragments = arrayListOf<MyViewPagerFragment?>()
|
||||
val fragments = arrayListOf<MyViewPagerFragment<*>?>()
|
||||
|
||||
if (showTabs and TAB_CONTACTS > 0) {
|
||||
fragments.add(contacts_fragment)
|
||||
fragments.add(getContactsFragment())
|
||||
}
|
||||
|
||||
if (showTabs and TAB_FAVORITES > 0) {
|
||||
fragments.add(favorites_fragment)
|
||||
fragments.add(getFavoritesFragment())
|
||||
}
|
||||
|
||||
if (showTabs and TAB_CALL_HISTORY > 0) {
|
||||
fragments.add(recents_fragment)
|
||||
fragments.add(getRecentsFragment())
|
||||
}
|
||||
|
||||
return fragments
|
||||
}
|
||||
|
||||
private fun getCurrentFragment(): MyViewPagerFragment? = getAllFragments().getOrNull(view_pager.currentItem)
|
||||
private fun getCurrentFragment(): MyViewPagerFragment<*>? = getAllFragments().getOrNull(binding.viewPager.currentItem)
|
||||
|
||||
private fun getContactsFragment(): ContactsFragment? = findViewById(R.id.contacts_fragment)
|
||||
|
||||
private fun getFavoritesFragment(): FavoritesFragment? = findViewById(R.id.favorites_fragment)
|
||||
|
||||
private fun getRecentsFragment(): RecentsFragment? = findViewById(R.id.recents_fragment)
|
||||
|
||||
private fun getDefaultTab(): Int {
|
||||
val showTabsMask = config.showTabs
|
||||
return when (config.defaultTab) {
|
||||
TAB_LAST_USED -> if (config.lastUsedViewPagerPage < main_tabs_holder.tabCount) config.lastUsedViewPagerPage else 0
|
||||
TAB_LAST_USED -> if (config.lastUsedViewPagerPage < binding.mainTabsHolder.tabCount) config.lastUsedViewPagerPage else 0
|
||||
TAB_CONTACTS -> 0
|
||||
TAB_FAVORITES -> if (showTabsMask and TAB_CONTACTS > 0) 1 else 0
|
||||
else -> {
|
||||
|
@ -518,40 +567,42 @@ class MainActivity : SimpleActivity() {
|
|||
|
||||
private fun showSortingDialog(showCustomSorting: Boolean) {
|
||||
ChangeSortingDialog(this, showCustomSorting) {
|
||||
favorites_fragment?.refreshItems {
|
||||
if (main_menu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
|
||||
getFavoritesFragment()?.refreshItems {
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
|
||||
contacts_fragment?.refreshItems {
|
||||
if (main_menu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
|
||||
getContactsFragment()?.refreshItems {
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showFilterDialog() {
|
||||
FilterContactSourcesDialog(this) {
|
||||
favorites_fragment?.refreshItems {
|
||||
if (main_menu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
|
||||
getFavoritesFragment()?.refreshItems {
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
|
||||
contacts_fragment?.refreshItems {
|
||||
if (main_menu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
|
||||
getContactsFragment()?.refreshItems {
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
|
||||
recents_fragment.refreshItems{
|
||||
if (main_menu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(main_menu.getCurrentQuery())
|
||||
getRecentsFragment()?.refreshItems {
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun cacheContacts(contacts: List<Contact>) {
|
||||
try {
|
||||
cachedContacts.clear()
|
||||
|
|
|
@ -2,42 +2,58 @@ package com.simplemobiletools.dialer.activities
|
|||
|
||||
import android.os.Bundle
|
||||
import com.google.gson.Gson
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.commons.helpers.ContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
||||
import com.simplemobiletools.commons.helpers.NavigationIcon
|
||||
import com.simplemobiletools.commons.models.PhoneNumber
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.adapters.SpeedDialAdapter
|
||||
import com.simplemobiletools.dialer.databinding.ActivityManageSpeedDialBinding
|
||||
import com.simplemobiletools.dialer.dialogs.SelectContactDialog
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.interfaces.RemoveSpeedDialListener
|
||||
import com.simplemobiletools.dialer.models.SpeedDial
|
||||
import kotlinx.android.synthetic.main.activity_manage_speed_dial.*
|
||||
|
||||
class ManageSpeedDialActivity : SimpleActivity(), RemoveSpeedDialListener {
|
||||
private var allContacts = ArrayList<Contact>()
|
||||
private var speedDialValues = ArrayList<SpeedDial>()
|
||||
private val binding by viewBinding(ActivityManageSpeedDialBinding::inflate)
|
||||
|
||||
private var allContacts = mutableListOf<Contact>()
|
||||
private var speedDialValues = mutableListOf<SpeedDial>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_manage_speed_dial)
|
||||
setContentView(binding.root)
|
||||
|
||||
updateMaterialActivityViews(manage_speed_dial_coordinator, manage_speed_dial_holder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(manage_speed_dial_scrollview, manage_speed_dial_toolbar)
|
||||
binding.apply {
|
||||
updateMaterialActivityViews(manageSpeedDialCoordinator, manageSpeedDialHolder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(manageSpeedDialScrollview, manageSpeedDialToolbar)
|
||||
|
||||
}
|
||||
|
||||
speedDialValues = config.getSpeedDialValues()
|
||||
updateAdapter()
|
||||
ContactsHelper(this).getContacts(false) { contacts ->
|
||||
allContacts = contacts
|
||||
|
||||
ContactsHelper(this).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
allContacts.addAll(contacts)
|
||||
|
||||
val privateCursor = getMyContactsCursor(false, true)
|
||||
val privateContacts = MyContactsContentProvider.getContacts(this, privateCursor)
|
||||
allContacts.addAll(privateContacts)
|
||||
allContacts.sort()
|
||||
}
|
||||
|
||||
updateTextColors(manage_speed_dial_scrollview)
|
||||
updateTextColors(binding.manageSpeedDialScrollview)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupToolbar(manage_speed_dial_toolbar, NavigationIcon.Arrow)
|
||||
setupToolbar(binding.manageSpeedDialToolbar, NavigationIcon.Arrow)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -46,21 +62,38 @@ class ManageSpeedDialActivity : SimpleActivity(), RemoveSpeedDialListener {
|
|||
}
|
||||
|
||||
private fun updateAdapter() {
|
||||
SpeedDialAdapter(this, speedDialValues, this, speed_dial_list) {
|
||||
SpeedDialAdapter(this, speedDialValues, this, binding.speedDialList) {
|
||||
val clickedContact = it as SpeedDial
|
||||
if (allContacts.isEmpty()) {
|
||||
return@SpeedDialAdapter
|
||||
}
|
||||
|
||||
SelectContactDialog(this, allContacts) { selectedContact ->
|
||||
speedDialValues.first { it.id == clickedContact.id }.apply {
|
||||
displayName = selectedContact.getNameToDisplay()
|
||||
number = selectedContact.phoneNumbers.first().normalizedNumber
|
||||
if (selectedContact.phoneNumbers.size > 1) {
|
||||
val radioItems = selectedContact.phoneNumbers.mapIndexed { index, item ->
|
||||
RadioItem(index, item.normalizedNumber, item)
|
||||
}
|
||||
val userPhoneNumbersList = selectedContact.phoneNumbers.map { it.value }
|
||||
val checkedItemId = userPhoneNumbersList.indexOf(clickedContact.number)
|
||||
RadioGroupDialog(this, ArrayList(radioItems), checkedItemId = checkedItemId) { selectedValue ->
|
||||
val selectedNumber = selectedValue as PhoneNumber
|
||||
speedDialValues.first { it.id == clickedContact.id }.apply {
|
||||
displayName = selectedContact.getNameToDisplay()
|
||||
number = selectedNumber.normalizedNumber
|
||||
}
|
||||
updateAdapter()
|
||||
}
|
||||
} else {
|
||||
speedDialValues.first { it.id == clickedContact.id }.apply {
|
||||
displayName = selectedContact.getNameToDisplay()
|
||||
number = selectedContact.phoneNumbers.first().normalizedNumber
|
||||
}
|
||||
updateAdapter()
|
||||
}
|
||||
updateAdapter()
|
||||
|
||||
}
|
||||
}.apply {
|
||||
speed_dial_list.adapter = this
|
||||
binding.speedDialList.adapter = this
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@ package com.simplemobiletools.dialer.activities
|
|||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
|
||||
import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog
|
||||
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
|
||||
|
@ -13,26 +15,54 @@ import com.simplemobiletools.commons.extensions.*
|
|||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.databinding.ActivitySettingsBinding
|
||||
import com.simplemobiletools.dialer.dialogs.ExportCallHistoryDialog
|
||||
import com.simplemobiletools.dialer.dialogs.ManageVisibleTabsDialog
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||
import com.simplemobiletools.dialer.models.RecentCall
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class SettingsActivity : SimpleActivity() {
|
||||
companion object {
|
||||
private const val CALL_HISTORY_FILE_TYPE = "application/json"
|
||||
}
|
||||
|
||||
private val binding by viewBinding(ActivitySettingsBinding::inflate)
|
||||
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
if (uri != null) {
|
||||
toast(R.string.importing)
|
||||
importCallHistory(uri)
|
||||
}
|
||||
}
|
||||
|
||||
private val saveDocument = registerForActivityResult(ActivityResultContracts.CreateDocument(CALL_HISTORY_FILE_TYPE)) { uri ->
|
||||
if (uri != null) {
|
||||
toast(R.string.exporting)
|
||||
RecentsHelper(this).getRecentCalls(false, Int.MAX_VALUE) { recents ->
|
||||
exportCallHistory(recents, uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
setContentView(binding.root)
|
||||
|
||||
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
|
||||
binding.apply {
|
||||
updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(settingsNestedScrollview, settingsToolbar)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupToolbar(settings_toolbar, NavigationIcon.Arrow)
|
||||
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
|
||||
|
||||
setupPurchaseThankYou()
|
||||
setupCustomizeColors()
|
||||
|
@ -54,15 +84,20 @@ class SettingsActivity : SimpleActivity() {
|
|||
setupDisableProximitySensor()
|
||||
setupDisableSwipeToAnswer()
|
||||
setupAlwaysShowFullscreen()
|
||||
updateTextColors(settings_holder)
|
||||
setupCallsExport()
|
||||
setupCallsImport()
|
||||
updateTextColors(binding.settingsHolder)
|
||||
|
||||
arrayOf(
|
||||
settings_color_customization_section_label,
|
||||
settings_general_settings_label,
|
||||
settings_startup_label,
|
||||
settings_calls_label
|
||||
).forEach {
|
||||
it.setTextColor(getProperPrimaryColor())
|
||||
binding.apply {
|
||||
arrayOf(
|
||||
settingsColorCustomizationSectionLabel,
|
||||
settingsGeneralSettingsLabel,
|
||||
settingsStartupLabel,
|
||||
settingsCallsLabel,
|
||||
settingsMigrationSectionLabel
|
||||
).forEach {
|
||||
it.setTextColor(getProperPrimaryColor())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,55 +107,61 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun setupPurchaseThankYou() {
|
||||
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled())
|
||||
settings_purchase_thank_you_holder.setOnClickListener {
|
||||
binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
|
||||
binding.settingsPurchaseThankYouHolder.setOnClickListener {
|
||||
launchPurchaseThankYouIntent()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeColors() {
|
||||
settings_color_customization_label.text = getCustomizeColorsString()
|
||||
settings_color_customization_holder.setOnClickListener {
|
||||
binding.settingsColorCustomizationLabel.text = getCustomizeColorsString()
|
||||
binding.settingsColorCustomizationHolder.setOnClickListener {
|
||||
handleCustomizeColorsClick()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUseEnglish() {
|
||||
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
|
||||
settings_use_english.isChecked = config.useEnglish
|
||||
settings_use_english_holder.setOnClickListener {
|
||||
settings_use_english.toggle()
|
||||
config.useEnglish = settings_use_english.isChecked
|
||||
exitProcess(0)
|
||||
binding.apply {
|
||||
settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
|
||||
settingsUseEnglish.isChecked = config.useEnglish
|
||||
settingsUseEnglishHolder.setOnClickListener {
|
||||
settingsUseEnglish.toggle()
|
||||
config.useEnglish = settingsUseEnglish.isChecked
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupLanguage() {
|
||||
settings_language.text = Locale.getDefault().displayLanguage
|
||||
settings_language_holder.beVisibleIf(isTiramisuPlus())
|
||||
settings_language_holder.setOnClickListener {
|
||||
launchChangeAppLanguageIntent()
|
||||
binding.apply {
|
||||
settingsLanguage.text = Locale.getDefault().displayLanguage
|
||||
settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
|
||||
settingsLanguageHolder.setOnClickListener {
|
||||
launchChangeAppLanguageIntent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// support for device-wise blocking came on Android 7, rely only on that
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
private fun setupManageBlockedNumbers() {
|
||||
settings_manage_blocked_numbers_label.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
|
||||
settings_manage_blocked_numbers_holder.beVisibleIf(isNougatPlus())
|
||||
settings_manage_blocked_numbers_holder.setOnClickListener {
|
||||
if (isOrWasThankYouInstalled()) {
|
||||
Intent(this, ManageBlockedNumbersActivity::class.java).apply {
|
||||
startActivity(this)
|
||||
binding.apply {
|
||||
settingsManageBlockedNumbersLabel.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
|
||||
settingsManageBlockedNumbersHolder.beVisibleIf(isNougatPlus())
|
||||
settingsManageBlockedNumbersHolder.setOnClickListener {
|
||||
if (isOrWasThankYouInstalled()) {
|
||||
Intent(this@SettingsActivity, ManageBlockedNumbersActivity::class.java).apply {
|
||||
startActivity(this)
|
||||
}
|
||||
} else {
|
||||
FeatureLockedDialog(this@SettingsActivity) { }
|
||||
}
|
||||
} else {
|
||||
FeatureLockedDialog(this) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupManageSpeedDial() {
|
||||
settings_manage_speed_dial_holder.setOnClickListener {
|
||||
binding.settingsManageSpeedDialHolder.setOnClickListener {
|
||||
Intent(this, ManageSpeedDialActivity::class.java).apply {
|
||||
startActivity(this)
|
||||
}
|
||||
|
@ -128,14 +169,14 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun setupChangeDateTimeFormat() {
|
||||
settings_change_date_time_format_holder.setOnClickListener {
|
||||
binding.settingsChangeDateTimeFormatHolder.setOnClickListener {
|
||||
ChangeDateTimeFormatDialog(this) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFontSize() {
|
||||
settings_font_size.text = getFontSizeText()
|
||||
settings_font_size_holder.setOnClickListener {
|
||||
binding.settingsFontSize.text = getFontSizeText()
|
||||
binding.settingsFontSizeHolder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
|
||||
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
|
||||
|
@ -145,20 +186,20 @@ class SettingsActivity : SimpleActivity() {
|
|||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
|
||||
config.fontSize = it as Int
|
||||
settings_font_size.text = getFontSizeText()
|
||||
binding.settingsFontSize.text = getFontSizeText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupManageShownTabs() {
|
||||
settings_manage_tabs_holder.setOnClickListener {
|
||||
binding.settingsManageTabsHolder.setOnClickListener {
|
||||
ManageVisibleTabsDialog(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDefaultTab() {
|
||||
settings_default_tab.text = getDefaultTabText()
|
||||
settings_default_tab_holder.setOnClickListener {
|
||||
binding.settingsDefaultTab.text = getDefaultTabText()
|
||||
binding.settingsDefaultTabHolder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(TAB_CONTACTS, getString(R.string.contacts_tab)),
|
||||
RadioItem(TAB_FAVORITES, getString(R.string.favorites_tab)),
|
||||
|
@ -168,7 +209,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.defaultTab) {
|
||||
config.defaultTab = it as Int
|
||||
settings_default_tab.text = getDefaultTabText()
|
||||
binding.settingsDefaultTab.text = getDefaultTabText()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,82 +224,159 @@ class SettingsActivity : SimpleActivity() {
|
|||
)
|
||||
|
||||
private fun setupDialPadOpen() {
|
||||
settings_open_dialpad_at_launch.isChecked = config.openDialPadAtLaunch
|
||||
settings_open_dialpad_at_launch_holder.setOnClickListener {
|
||||
settings_open_dialpad_at_launch.toggle()
|
||||
config.openDialPadAtLaunch = settings_open_dialpad_at_launch.isChecked
|
||||
binding.apply {
|
||||
settingsOpenDialpadAtLaunch.isChecked = config.openDialPadAtLaunch
|
||||
settingsOpenDialpadAtLaunchHolder.setOnClickListener {
|
||||
settingsOpenDialpadAtLaunch.toggle()
|
||||
config.openDialPadAtLaunch = settingsOpenDialpadAtLaunch.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupGroupSubsequentCalls() {
|
||||
settings_group_subsequent_calls.isChecked = config.groupSubsequentCalls
|
||||
settings_group_subsequent_calls_holder.setOnClickListener {
|
||||
settings_group_subsequent_calls.toggle()
|
||||
config.groupSubsequentCalls = settings_group_subsequent_calls.isChecked
|
||||
binding.apply {
|
||||
settingsGroupSubsequentCalls.isChecked = config.groupSubsequentCalls
|
||||
settingsGroupSubsequentCallsHolder.setOnClickListener {
|
||||
settingsGroupSubsequentCalls.toggle()
|
||||
config.groupSubsequentCalls = settingsGroupSubsequentCalls.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupStartNameWithSurname() {
|
||||
settings_start_name_with_surname.isChecked = config.startNameWithSurname
|
||||
settings_start_name_with_surname_holder.setOnClickListener {
|
||||
settings_start_name_with_surname.toggle()
|
||||
config.startNameWithSurname = settings_start_name_with_surname.isChecked
|
||||
binding.apply {
|
||||
settingsStartNameWithSurname.isChecked = config.startNameWithSurname
|
||||
settingsStartNameWithSurnameHolder.setOnClickListener {
|
||||
settingsStartNameWithSurname.toggle()
|
||||
config.startNameWithSurname = settingsStartNameWithSurname.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDialpadVibrations() {
|
||||
settings_dialpad_vibration.isChecked = config.dialpadVibration
|
||||
settings_dialpad_vibration_holder.setOnClickListener {
|
||||
settings_dialpad_vibration.toggle()
|
||||
config.dialpadVibration = settings_dialpad_vibration.isChecked
|
||||
binding.apply {
|
||||
settingsDialpadVibration.isChecked = config.dialpadVibration
|
||||
settingsDialpadVibrationHolder.setOnClickListener {
|
||||
settingsDialpadVibration.toggle()
|
||||
config.dialpadVibration = settingsDialpadVibration.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDialpadNumbers() {
|
||||
settings_hide_dialpad_numbers.isChecked = config.hideDialpadNumbers
|
||||
settings_hide_dialpad_numbers_holder.setOnClickListener {
|
||||
settings_hide_dialpad_numbers.toggle()
|
||||
config.hideDialpadNumbers = settings_hide_dialpad_numbers.isChecked
|
||||
binding.apply {
|
||||
settingsHideDialpadNumbers.isChecked = config.hideDialpadNumbers
|
||||
settingsHideDialpadNumbersHolder.setOnClickListener {
|
||||
settingsHideDialpadNumbers.toggle()
|
||||
config.hideDialpadNumbers = settingsHideDialpadNumbers.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDialpadBeeps() {
|
||||
settings_dialpad_beeps.isChecked = config.dialpadBeeps
|
||||
settings_dialpad_beeps_holder.setOnClickListener {
|
||||
settings_dialpad_beeps.toggle()
|
||||
config.dialpadBeeps = settings_dialpad_beeps.isChecked
|
||||
binding.apply {
|
||||
settingsDialpadBeeps.isChecked = config.dialpadBeeps
|
||||
settingsDialpadBeepsHolder.setOnClickListener {
|
||||
settingsDialpadBeeps.toggle()
|
||||
config.dialpadBeeps = settingsDialpadBeeps.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupShowCallConfirmation() {
|
||||
settings_show_call_confirmation.isChecked = config.showCallConfirmation
|
||||
settings_show_call_confirmation_holder.setOnClickListener {
|
||||
settings_show_call_confirmation.toggle()
|
||||
config.showCallConfirmation = settings_show_call_confirmation.isChecked
|
||||
binding.apply {
|
||||
settingsShowCallConfirmation.isChecked = config.showCallConfirmation
|
||||
settingsShowCallConfirmationHolder.setOnClickListener {
|
||||
settingsShowCallConfirmation.toggle()
|
||||
config.showCallConfirmation = settingsShowCallConfirmation.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDisableProximitySensor() {
|
||||
settings_disable_proximity_sensor.isChecked = config.disableProximitySensor
|
||||
settings_disable_proximity_sensor_holder.setOnClickListener {
|
||||
settings_disable_proximity_sensor.toggle()
|
||||
config.disableProximitySensor = settings_disable_proximity_sensor.isChecked
|
||||
binding.apply {
|
||||
settingsDisableProximitySensor.isChecked = config.disableProximitySensor
|
||||
settingsDisableProximitySensorHolder.setOnClickListener {
|
||||
settingsDisableProximitySensor.toggle()
|
||||
config.disableProximitySensor = settingsDisableProximitySensor.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDisableSwipeToAnswer() {
|
||||
settings_disable_swipe_to_answer.isChecked = config.disableSwipeToAnswer
|
||||
settings_disable_swipe_to_answer_holder.setOnClickListener {
|
||||
settings_disable_swipe_to_answer.toggle()
|
||||
config.disableSwipeToAnswer = settings_disable_swipe_to_answer.isChecked
|
||||
binding.apply {
|
||||
settingsDisableSwipeToAnswer.isChecked = config.disableSwipeToAnswer
|
||||
settingsDisableSwipeToAnswerHolder.setOnClickListener {
|
||||
settingsDisableSwipeToAnswer.toggle()
|
||||
config.disableSwipeToAnswer = settingsDisableSwipeToAnswer.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAlwaysShowFullscreen() {
|
||||
settings_always_show_fullscreen.isChecked = config.alwaysShowFullscreen
|
||||
settings_always_show_fullscreen_holder.setOnClickListener {
|
||||
settings_always_show_fullscreen.toggle()
|
||||
config.alwaysShowFullscreen = settings_always_show_fullscreen.isChecked
|
||||
binding.apply {
|
||||
settingsAlwaysShowFullscreen.isChecked = config.alwaysShowFullscreen
|
||||
settingsAlwaysShowFullscreenHolder.setOnClickListener {
|
||||
settingsAlwaysShowFullscreen.toggle()
|
||||
config.alwaysShowFullscreen = settingsAlwaysShowFullscreen.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCallsExport() {
|
||||
binding.settingsExportCallsHolder.setOnClickListener {
|
||||
ExportCallHistoryDialog(this) { filename ->
|
||||
saveDocument.launch(filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCallsImport() {
|
||||
binding.settingsImportCallsHolder.setOnClickListener {
|
||||
getContent.launch(CALL_HISTORY_FILE_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun importCallHistory(uri: Uri) {
|
||||
try {
|
||||
val jsonString = contentResolver.openInputStream(uri)!!.use { inputStream ->
|
||||
inputStream.bufferedReader().readText()
|
||||
}
|
||||
|
||||
val objects = Json.decodeFromString<List<RecentCall>>(jsonString)
|
||||
|
||||
if (objects.isEmpty()) {
|
||||
toast(R.string.no_entries_for_importing)
|
||||
return
|
||||
}
|
||||
|
||||
RecentsHelper(this).restoreRecentCalls(this, objects) {
|
||||
toast(R.string.importing_successful)
|
||||
}
|
||||
} catch (_: SerializationException) {
|
||||
toast(R.string.invalid_file_format)
|
||||
} catch (_: IllegalArgumentException) {
|
||||
toast(R.string.invalid_file_format)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportCallHistory(recents: List<RecentCall>, uri: Uri) {
|
||||
if (recents.isEmpty()) {
|
||||
toast(R.string.no_entries_for_exporting)
|
||||
} else {
|
||||
try {
|
||||
val outputStream = contentResolver.openOutputStream(uri)!!
|
||||
|
||||
val jsonString = Json.encodeToString(recents)
|
||||
outputStream.use {
|
||||
it.write(jsonString.toByteArray())
|
||||
}
|
||||
toast(R.string.exporting_successful)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
|||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.databinding.ItemConferenceCallBinding
|
||||
import com.simplemobiletools.dialer.extensions.hasCapability
|
||||
import com.simplemobiletools.dialer.helpers.getCallContact
|
||||
import kotlinx.android.synthetic.main.item_conference_call.view.*
|
||||
|
||||
class ConferenceCallsAdapter(
|
||||
activity: SimpleActivity, recyclerView: MyRecyclerView, val data: ArrayList<Call>, itemClick: (Any) -> Unit
|
||||
|
@ -39,55 +39,63 @@ class ConferenceCallsAdapter(
|
|||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conference_call, parent)
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return createViewHolder(ItemConferenceCallBinding.inflate(layoutInflater, parent, false).root)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val call = data[position]
|
||||
holder.bindView(call, allowSingleClick = false, allowLongClick = false) { itemView, _ ->
|
||||
getCallContact(itemView.context, call) { callContact ->
|
||||
itemView.post {
|
||||
itemView.item_conference_call_name.text = callContact.name.ifEmpty { itemView.context.getString(R.string.unknown_caller) }
|
||||
SimpleContactsHelper(activity).loadContactImage(
|
||||
callContact.photoUri,
|
||||
itemView.item_conference_call_image,
|
||||
callContact.name,
|
||||
activity.getDrawable(R.drawable.ic_person_vector)
|
||||
)
|
||||
ItemConferenceCallBinding.bind(itemView).apply {
|
||||
getCallContact(itemView.context, call) { callContact ->
|
||||
root.post {
|
||||
itemConferenceCallName.text = callContact.name.ifEmpty { itemView.context.getString(R.string.unknown_caller) }
|
||||
SimpleContactsHelper(activity).loadContactImage(
|
||||
callContact.photoUri,
|
||||
itemConferenceCallImage,
|
||||
callContact.name,
|
||||
activity.getDrawable(R.drawable.ic_person_vector)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
val canSeparate = call.hasCapability(Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE)
|
||||
val canDisconnect = call.hasCapability(Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE)
|
||||
itemView.item_conference_call_split.isEnabled = canSeparate
|
||||
itemView.item_conference_call_split.alpha = if (canSeparate) 1.0f else LOWER_ALPHA
|
||||
itemView.item_conference_call_split.setOnClickListener {
|
||||
call.splitFromConference()
|
||||
data.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
if (data.size == 1) {
|
||||
activity.finish()
|
||||
|
||||
val canSeparate = call.hasCapability(Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE)
|
||||
val canDisconnect = call.hasCapability(Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE)
|
||||
itemConferenceCallSplit.isEnabled = canSeparate
|
||||
itemConferenceCallSplit.alpha = if (canSeparate) 1.0f else LOWER_ALPHA
|
||||
itemConferenceCallSplit.setOnClickListener {
|
||||
call.splitFromConference()
|
||||
data.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
if (data.size == 1) {
|
||||
activity.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
itemView.item_conference_call_split.setOnLongClickListener {
|
||||
if (!it.contentDescription.isNullOrEmpty()) {
|
||||
itemView.context.toast(it.contentDescription.toString())
|
||||
|
||||
itemConferenceCallSplit.setOnLongClickListener {
|
||||
if (!it.contentDescription.isNullOrEmpty()) {
|
||||
root.context.toast(it.contentDescription.toString())
|
||||
}
|
||||
true
|
||||
}
|
||||
true
|
||||
}
|
||||
itemView.item_conference_call_end.isEnabled = canDisconnect
|
||||
itemView.item_conference_call_end.alpha = if (canDisconnect) 1.0f else LOWER_ALPHA
|
||||
itemView.item_conference_call_end.setOnClickListener {
|
||||
call.disconnect()
|
||||
data.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
if (data.size == 1) {
|
||||
activity.finish()
|
||||
|
||||
itemConferenceCallEnd.isEnabled = canDisconnect
|
||||
itemConferenceCallEnd.alpha = if (canDisconnect) 1.0f else LOWER_ALPHA
|
||||
itemConferenceCallEnd.setOnClickListener {
|
||||
call.disconnect()
|
||||
data.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
if (data.size == 1) {
|
||||
activity.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
itemView.item_conference_call_end.setOnLongClickListener {
|
||||
if (!it.contentDescription.isNullOrEmpty()) {
|
||||
itemView.context.toast(it.contentDescription.toString())
|
||||
|
||||
itemConferenceCallEnd.setOnLongClickListener {
|
||||
if (!it.contentDescription.isNullOrEmpty()) {
|
||||
root.context.toast(it.contentDescription.toString())
|
||||
}
|
||||
true
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
|
@ -96,7 +104,9 @@ class ConferenceCallsAdapter(
|
|||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing) {
|
||||
Glide.with(activity).clear(holder.itemView.item_conference_call_image)
|
||||
ItemConferenceCallBinding.bind(holder.itemView).apply {
|
||||
Glide.with(activity).clear(itemConferenceCallImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,24 +7,22 @@ import android.graphics.drawable.Icon
|
|||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import android.util.TypedValue
|
||||
import android.view.Menu
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.view.*
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.bumptech.glide.Glide
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.databinding.ItemContactWithoutNumberBinding
|
||||
import com.simplemobiletools.commons.databinding.ItemContactWithoutNumberGridBinding
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS
|
||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.isOreoPlus
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.interfaces.ItemMoveCallback
|
||||
import com.simplemobiletools.commons.interfaces.ItemTouchHelperContract
|
||||
import com.simplemobiletools.commons.interfaces.StartReorderDragListener
|
||||
|
@ -41,26 +39,35 @@ import java.util.*
|
|||
|
||||
class ContactsAdapter(
|
||||
activity: SimpleActivity,
|
||||
var contacts: ArrayList<Contact>,
|
||||
var contacts: MutableList<Contact>,
|
||||
recyclerView: MyRecyclerView,
|
||||
val refreshItemsListener: RefreshItemsListener? = null,
|
||||
highlightText: String = "",
|
||||
val showDeleteButton: Boolean = true,
|
||||
private val refreshItemsListener: RefreshItemsListener? = null,
|
||||
var viewType: Int = VIEW_TYPE_LIST,
|
||||
private val showDeleteButton: Boolean = true,
|
||||
private val enableDrag: Boolean = false,
|
||||
private val allowLongClick: Boolean = true,
|
||||
itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick), ItemTouchHelperContract {
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick),
|
||||
ItemTouchHelperContract, MyRecyclerView.MyZoomListener {
|
||||
|
||||
private var textToHighlight = highlightText
|
||||
private var fontSize = activity.getTextSize()
|
||||
var fontSize: Float = activity.getTextSize()
|
||||
private var touchHelper: ItemTouchHelper? = null
|
||||
private var startReorderDragListener: StartReorderDragListener? = null
|
||||
var onDragEndListener: (() -> Unit)? = null
|
||||
var onSpanCountListener: (Int) -> Unit = {}
|
||||
|
||||
|
||||
init {
|
||||
setupDragListener(true)
|
||||
|
||||
if (recyclerView.layoutManager is GridLayoutManager) {
|
||||
setupZoomListener(this)
|
||||
}
|
||||
|
||||
if (enableDrag) {
|
||||
touchHelper = ItemTouchHelper(ItemMoveCallback(this))
|
||||
touchHelper = ItemTouchHelper(ItemMoveCallback(this, viewType == VIEW_TYPE_GRID))
|
||||
touchHelper!!.attachToRecyclerView(recyclerView)
|
||||
|
||||
startReorderDragListener = object : StartReorderDragListener {
|
||||
|
@ -81,12 +88,16 @@ class ContactsAdapter(
|
|||
menu.apply {
|
||||
findItem(R.id.cab_call_sim_1).isVisible = hasMultipleSIMs && isOneItemSelected
|
||||
findItem(R.id.cab_call_sim_2).isVisible = hasMultipleSIMs && isOneItemSelected
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && activity.config.getCustomSIM(selectedNumber) != ""
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && (activity.config.getCustomSIM(selectedNumber) ?: "") != ""
|
||||
|
||||
findItem(R.id.cab_delete).isVisible = showDeleteButton
|
||||
findItem(R.id.cab_create_shortcut).title = activity.addLockedLabelIfNeeded(R.string.create_shortcut)
|
||||
findItem(R.id.cab_create_shortcut).isVisible = isOneItemSelected && isOreoPlus()
|
||||
findItem(R.id.cab_view_details).isVisible = isOneItemSelected
|
||||
findItem(R.id.cab_block_unblock_contact).isVisible = isOneItemSelected && isNougatPlus()
|
||||
getCabBlockContactTitle { title ->
|
||||
findItem(R.id.cab_block_unblock_contact).title = title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +107,7 @@ class ContactsAdapter(
|
|||
}
|
||||
|
||||
when (id) {
|
||||
R.id.cab_block_unblock_contact -> tryBlockingUnblocking()
|
||||
R.id.cab_call_sim_1 -> callContact(true)
|
||||
R.id.cab_call_sim_2 -> callContact(false)
|
||||
R.id.cab_remove_default_sim -> removeDefaultSIM()
|
||||
|
@ -123,21 +135,94 @@ class ContactsAdapter(
|
|||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_contact_without_number, parent)
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding = Binding.getByItemViewType(viewType).inflate(layoutInflater, parent, false)
|
||||
return createViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return viewType
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val contact = contacts[position]
|
||||
holder.bindView(contact, true, true) { itemView, layoutPosition ->
|
||||
setupView(itemView, contact, holder)
|
||||
holder.bindView(contact, true, allowLongClick) { itemView, layoutPosition ->
|
||||
val viewType = getItemViewType(position)
|
||||
setupView(Binding.getByItemViewType(viewType).bind(itemView), contact, holder)
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
}
|
||||
|
||||
override fun getItemCount() = contacts.size
|
||||
|
||||
fun updateItems(newItems: ArrayList<Contact>, highlightText: String = "") {
|
||||
private fun getCabBlockContactTitle(callback: (String) -> Unit) {
|
||||
val contact = getSelectedItems().firstOrNull() ?: return callback("")
|
||||
|
||||
activity.isContactBlocked(contact) { blocked ->
|
||||
val cabItemTitleRes = if (blocked) {
|
||||
R.string.unblock_contact
|
||||
} else {
|
||||
R.string.block_contact
|
||||
}
|
||||
|
||||
callback(activity.addLockedLabelIfNeeded(cabItemTitleRes))
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryBlockingUnblocking() {
|
||||
val contact = getSelectedItems().firstOrNull() ?: return
|
||||
|
||||
if (activity.isOrWasThankYouInstalled()) {
|
||||
activity.isContactBlocked(contact) { blocked ->
|
||||
if (blocked) {
|
||||
tryUnblocking(contact)
|
||||
} else {
|
||||
tryBlocking(contact)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FeatureLockedDialog(activity) { }
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryBlocking(contact: Contact) {
|
||||
askConfirmBlock(contact) { contactBlocked ->
|
||||
val resultMsg = if (contactBlocked) {
|
||||
R.string.block_contact_success
|
||||
} else {
|
||||
R.string.block_contact_fail
|
||||
}
|
||||
|
||||
activity.toast(resultMsg)
|
||||
finishActMode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryUnblocking(contact: Contact) {
|
||||
val contactUnblocked = activity.unblockContact(contact)
|
||||
val resultMsg = if (contactUnblocked) {
|
||||
R.string.unblock_contact_success
|
||||
} else {
|
||||
R.string.unblock_contact_fail
|
||||
}
|
||||
|
||||
activity.toast(resultMsg)
|
||||
finishActMode()
|
||||
}
|
||||
|
||||
private fun askConfirmBlock(contact: Contact, callback: (Boolean) -> Unit) {
|
||||
val baseString = R.string.block_confirmation
|
||||
val question = String.format(resources.getString(baseString), contact.name)
|
||||
|
||||
ConfirmationDialog(activity, question) {
|
||||
val contactBlocked = activity.blockContact(contact)
|
||||
callback(contactBlocked)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateItems(newItems: List<Contact>, highlightText: String = "") {
|
||||
if (newItems.hashCode() != contacts.hashCode()) {
|
||||
contacts = newItems.clone() as ArrayList<Contact>
|
||||
contacts = ArrayList(newItems)
|
||||
textToHighlight = highlightText
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
|
@ -224,9 +309,7 @@ class ContactsAdapter(
|
|||
private fun getSelectedItems() = contacts.filter { selectedKeys.contains(it.rawId) } as ArrayList<Contact>
|
||||
|
||||
private fun getSelectedPhoneNumber(): String? {
|
||||
val numbers = getSelectedItems().firstOrNull()?.phoneNumbers
|
||||
val primaryNumber = numbers?.firstOrNull { it.isPrimary }
|
||||
return primaryNumber?.normalizedNumber ?: numbers?.firstOrNull()?.normalizedNumber
|
||||
return getSelectedItems().firstOrNull()?.getPrimaryNumber()
|
||||
}
|
||||
|
||||
private fun tryCreateShortcut() {
|
||||
|
@ -247,7 +330,7 @@ class ContactsAdapter(
|
|||
activity.handlePermission(PERMISSION_CALL_PHONE) { hasPermission ->
|
||||
val action = if (hasPermission) Intent.ACTION_CALL else Intent.ACTION_DIAL
|
||||
val intent = Intent(action).apply {
|
||||
data = Uri.fromParts("tel", contact.phoneNumbers.first().normalizedNumber, null)
|
||||
data = Uri.fromParts("tel", getSelectedPhoneNumber(), null)
|
||||
}
|
||||
|
||||
val shortcut = ShortcutInfo.Builder(activity, contact.hashCode().toString())
|
||||
|
@ -266,14 +349,17 @@ class ContactsAdapter(
|
|||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing) {
|
||||
Glide.with(activity).clear(holder.itemView.findViewById<ImageView>(R.id.item_contact_image))
|
||||
Binding.getByItemViewType(holder.itemViewType).bind(holder.itemView).apply {
|
||||
Glide.with(activity).clear(itemContactImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupView(view: View, contact: Contact, holder: ViewHolder) {
|
||||
view.apply {
|
||||
findViewById<FrameLayout>(R.id.item_contact_frame).isSelected = selectedKeys.contains(contact.rawId)
|
||||
findViewById<TextView>(R.id.item_contact_name).apply {
|
||||
private fun setupView(binding: ItemViewBinding, contact: Contact, holder: ViewHolder) {
|
||||
binding.apply {
|
||||
root.setupViewBackground(activity)
|
||||
itemContactFrame.isSelected = selectedKeys.contains(contact.rawId)
|
||||
itemContactName.apply {
|
||||
setTextColor(textColor)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
|
||||
|
@ -287,9 +373,8 @@ class ContactsAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
val dragIcon = findViewById<ImageView>(R.id.drag_handle_icon)
|
||||
if (enableDrag && textToHighlight.isEmpty()) {
|
||||
dragIcon.apply {
|
||||
dragHandleIcon.apply {
|
||||
beVisibleIf(selectedKeys.isNotEmpty())
|
||||
applyColorFilter(textColor)
|
||||
setOnTouchListener { _, event ->
|
||||
|
@ -300,14 +385,14 @@ class ContactsAdapter(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
dragIcon.apply {
|
||||
dragHandleIcon.apply {
|
||||
beGone()
|
||||
setOnTouchListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
if (!activity.isDestroyed) {
|
||||
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.getNameToDisplay())
|
||||
SimpleContactsHelper(root.context).loadContactImage(contact.photoUri, itemContactImage, contact.getNameToDisplay())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,4 +418,86 @@ class ContactsAdapter(
|
|||
override fun onRowClear(myViewHolder: ViewHolder?) {
|
||||
onDragEndListener?.invoke()
|
||||
}
|
||||
|
||||
override fun zoomIn() {
|
||||
val layoutManager = recyclerView.layoutManager
|
||||
if (layoutManager is GridLayoutManager) {
|
||||
val currentSpanCount = layoutManager.spanCount
|
||||
val newSpanCount = (currentSpanCount - 1).coerceIn(1, CONTACTS_GRID_MAX_COLUMNS_COUNT)
|
||||
layoutManager.spanCount = newSpanCount
|
||||
recyclerView.requestLayout()
|
||||
onSpanCountListener(newSpanCount)
|
||||
}
|
||||
}
|
||||
|
||||
override fun zoomOut() {
|
||||
val layoutManager = recyclerView.layoutManager
|
||||
if (layoutManager is GridLayoutManager) {
|
||||
val currentSpanCount = layoutManager.spanCount
|
||||
val newSpanCount = (currentSpanCount + 1).coerceIn(1, CONTACTS_GRID_MAX_COLUMNS_COUNT)
|
||||
layoutManager.spanCount = newSpanCount
|
||||
recyclerView.requestLayout()
|
||||
onSpanCountListener(newSpanCount)
|
||||
}
|
||||
}
|
||||
|
||||
private sealed interface Binding {
|
||||
companion object {
|
||||
fun getByItemViewType(viewType: Int): Binding {
|
||||
return when (viewType) {
|
||||
VIEW_TYPE_GRID -> ItemContactGrid
|
||||
else -> ItemContact
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding
|
||||
|
||||
fun bind(view: View): ItemViewBinding
|
||||
|
||||
data object ItemContactGrid : Binding {
|
||||
override fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding {
|
||||
return ItemContactGridBindingAdapter(ItemContactWithoutNumberGridBinding.inflate(layoutInflater, viewGroup, attachToRoot))
|
||||
}
|
||||
|
||||
override fun bind(view: View): ItemViewBinding {
|
||||
return ItemContactGridBindingAdapter(ItemContactWithoutNumberGridBinding.bind(view))
|
||||
}
|
||||
}
|
||||
|
||||
data object ItemContact : Binding {
|
||||
override fun inflate(layoutInflater: LayoutInflater, viewGroup: ViewGroup, attachToRoot: Boolean): ItemViewBinding {
|
||||
return ItemContactBindingAdapter(ItemContactWithoutNumberBinding.inflate(layoutInflater, viewGroup, attachToRoot))
|
||||
}
|
||||
|
||||
override fun bind(view: View): ItemViewBinding {
|
||||
return ItemContactBindingAdapter(ItemContactWithoutNumberBinding.bind(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface ItemViewBinding : ViewBinding {
|
||||
val itemContactName: TextView
|
||||
val itemContactImage: ImageView
|
||||
val itemContactFrame: ConstraintLayout
|
||||
val dragHandleIcon: ImageView
|
||||
}
|
||||
|
||||
private class ItemContactGridBindingAdapter(val binding: ItemContactWithoutNumberGridBinding) : ItemViewBinding {
|
||||
override val itemContactName = binding.itemContactName
|
||||
override val itemContactImage = binding.itemContactImage
|
||||
override val itemContactFrame = binding.itemContactFrame
|
||||
override val dragHandleIcon = binding.dragHandleIcon
|
||||
|
||||
override fun getRoot(): View = binding.root
|
||||
}
|
||||
|
||||
private class ItemContactBindingAdapter(val binding: ItemContactWithoutNumberBinding) : ItemViewBinding {
|
||||
override val itemContactName = binding.itemContactName
|
||||
override val itemContactImage = binding.itemContactImage
|
||||
override val itemContactFrame = binding.itemContactFrame
|
||||
override val dragHandleIcon = binding.dragHandleIcon
|
||||
|
||||
override fun getRoot(): View = binding.root
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@ import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
|||
import com.simplemobiletools.commons.extensions.getProperTextColor
|
||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.commons.models.contacts.ContactSource
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import kotlinx.android.synthetic.main.item_filter_contact_source.view.*
|
||||
import com.simplemobiletools.dialer.databinding.ItemFilterContactSourceBinding
|
||||
|
||||
class FilterContactSourcesAdapter(
|
||||
val activity: SimpleActivity,
|
||||
|
@ -45,8 +44,8 @@ class FilterContactSourcesAdapter(
|
|||
fun getSelectedContactSources() = contactSources.filter { selectedKeys.contains(it.hashCode()) }
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = activity.layoutInflater.inflate(R.layout.item_filter_contact_source, parent, false)
|
||||
return ViewHolder(view)
|
||||
val binding = ItemFilterContactSourceBinding.inflate(activity.layoutInflater, parent, false)
|
||||
return ViewHolder(binding.root)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
|
@ -59,16 +58,16 @@ class FilterContactSourcesAdapter(
|
|||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
fun bindView(contactSource: ContactSource): View {
|
||||
val isSelected = selectedKeys.contains(contactSource.hashCode())
|
||||
itemView.apply {
|
||||
filter_contact_source_checkbox.isChecked = isSelected
|
||||
filter_contact_source_checkbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
|
||||
ItemFilterContactSourceBinding.bind(itemView).apply {
|
||||
filterContactSourceCheckbox.isChecked = isSelected
|
||||
filterContactSourceCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
|
||||
val countText = if (contactSource.count >= 0) " (${contactSource.count})" else ""
|
||||
val displayName = "${contactSource.publicName}$countText"
|
||||
filter_contact_source_checkbox.text = displayName
|
||||
filter_contact_source_holder.setOnClickListener { viewClicked(!isSelected, contactSource) }
|
||||
}
|
||||
filterContactSourceCheckbox.text = displayName
|
||||
filterContactSourceHolder.setOnClickListener { viewClicked(!isSelected, contactSource) }
|
||||
|
||||
return itemView
|
||||
return root
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewClicked(select: Boolean, contactSource: ContactSource) {
|
||||
|
|
|
@ -19,16 +19,16 @@ import com.simplemobiletools.commons.views.MyRecyclerView
|
|||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.MainActivity
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.databinding.ItemRecentCallBinding
|
||||
import com.simplemobiletools.dialer.dialogs.ShowGroupedCallsDialog
|
||||
import com.simplemobiletools.dialer.extensions.*
|
||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
||||
import com.simplemobiletools.dialer.models.RecentCall
|
||||
import kotlinx.android.synthetic.main.item_recent_call.view.*
|
||||
|
||||
class RecentCallsAdapter(
|
||||
activity: SimpleActivity,
|
||||
var recentCalls: ArrayList<RecentCall>,
|
||||
private var recentCalls: MutableList<RecentCall>,
|
||||
recyclerView: MyRecyclerView,
|
||||
private val refreshItemsListener: RefreshItemsListener?,
|
||||
private val showOverflowMenu: Boolean,
|
||||
|
@ -38,7 +38,7 @@ class RecentCallsAdapter(
|
|||
private lateinit var outgoingCallIcon: Drawable
|
||||
private lateinit var incomingCallIcon: Drawable
|
||||
private lateinit var incomingMissedCallIcon: Drawable
|
||||
private var fontSize = activity.getTextSize()
|
||||
var fontSize: Float = activity.getTextSize()
|
||||
private val areMultipleSIMsAvailable = activity.areMultipleSIMsAvailable()
|
||||
private val redColor = resources.getColor(R.color.md_red_700)
|
||||
private var textToHighlight = ""
|
||||
|
@ -60,7 +60,7 @@ class RecentCallsAdapter(
|
|||
menu.apply {
|
||||
findItem(R.id.cab_call_sim_1).isVisible = hasMultipleSIMs && isOneItemSelected
|
||||
findItem(R.id.cab_call_sim_2).isVisible = hasMultipleSIMs && isOneItemSelected
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && activity.config.getCustomSIM(selectedNumber) != ""
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = isOneItemSelected && (activity.config.getCustomSIM(selectedNumber) ?: "") != ""
|
||||
|
||||
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(R.string.block_number)
|
||||
findItem(R.id.cab_block_number).isVisible = isNougatPlus()
|
||||
|
@ -103,12 +103,19 @@ class RecentCallsAdapter(
|
|||
|
||||
override fun onActionModeDestroyed() {}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_recent_call, parent)
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return createViewHolder(ItemRecentCallBinding.inflate(layoutInflater, parent, false).root)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val recentCall = recentCalls[position]
|
||||
holder.bindView(recentCall, refreshItemsListener != null, refreshItemsListener != null) { itemView, layoutPosition ->
|
||||
setupView(itemView, recentCall)
|
||||
holder.bindView(
|
||||
any = recentCall,
|
||||
allowSingleClick = refreshItemsListener != null && !recentCall.isUnknownNumber,
|
||||
allowLongClick = refreshItemsListener != null && !recentCall.isUnknownNumber
|
||||
) { itemView, _ ->
|
||||
val binding = ItemRecentCallBinding.bind(itemView)
|
||||
setupView(binding, recentCall)
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
}
|
||||
|
@ -118,7 +125,9 @@ class RecentCallsAdapter(
|
|||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing) {
|
||||
Glide.with(activity).clear(holder.itemView.item_recents_image)
|
||||
ItemRecentCallBinding.bind(holder.itemView).apply {
|
||||
Glide.with(activity).clear(itemRecentsImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,8 +245,8 @@ class RecentCallsAdapter(
|
|||
RecentsHelper(activity).removeRecentCalls(idsToRemove) {
|
||||
recentCalls.removeAll(callsToRemove)
|
||||
activity.runOnUiThread {
|
||||
refreshItemsListener?.refreshItems()
|
||||
if (recentCalls.isEmpty()) {
|
||||
refreshItemsListener?.refreshItems()
|
||||
finishActMode()
|
||||
} else {
|
||||
removeSelectedItems(positions)
|
||||
|
@ -256,10 +265,11 @@ class RecentCallsAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun updateItems(newItems: ArrayList<RecentCall>, highlightText: String = "") {
|
||||
fun updateItems(newItems: List<RecentCall>, highlightText: String = "") {
|
||||
if (newItems.hashCode() != recentCalls.hashCode()) {
|
||||
recentCalls = newItems.clone() as ArrayList<RecentCall>
|
||||
recentCalls = newItems.toMutableList()
|
||||
textToHighlight = highlightText
|
||||
recyclerView.resetItemCount()
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
} else if (textToHighlight != highlightText) {
|
||||
|
@ -272,9 +282,10 @@ class RecentCallsAdapter(
|
|||
|
||||
private fun getSelectedPhoneNumber() = getSelectedItems().firstOrNull()?.phoneNumber
|
||||
|
||||
private fun setupView(view: View, call: RecentCall) {
|
||||
view.apply {
|
||||
item_recents_holder.isSelected = selectedKeys.contains(call.id)
|
||||
private fun setupView(binding: ItemRecentCallBinding, call: RecentCall) {
|
||||
binding.apply {
|
||||
val currentFontSize = fontSize
|
||||
itemRecentsHolder.isSelected = selectedKeys.contains(call.id)
|
||||
val name = findContactByCall(call)?.getNameToDisplay() ?: call.name
|
||||
var nameToShow = SpannableString(name)
|
||||
if (call.specificType.isNotEmpty()) {
|
||||
|
@ -294,37 +305,37 @@ class RecentCallsAdapter(
|
|||
nameToShow = SpannableString(nameToShow.toString().highlightTextPart(textToHighlight, properPrimaryColor))
|
||||
}
|
||||
|
||||
item_recents_name.apply {
|
||||
itemRecentsName.apply {
|
||||
text = nameToShow
|
||||
setTextColor(textColor)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize)
|
||||
}
|
||||
|
||||
item_recents_date_time.apply {
|
||||
itemRecentsDateTime.apply {
|
||||
text = call.startTS.formatDateOrTime(context, refreshItemsListener != null, false)
|
||||
setTextColor(if (call.type == Calls.MISSED_TYPE) redColor else textColor)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize * 0.8f)
|
||||
}
|
||||
|
||||
item_recents_duration.apply {
|
||||
itemRecentsDuration.apply {
|
||||
text = call.duration.getFormattedDuration()
|
||||
setTextColor(textColor)
|
||||
beVisibleIf(call.type != Calls.MISSED_TYPE && call.type != Calls.REJECTED_TYPE && call.duration > 0)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, currentFontSize * 0.8f)
|
||||
if (!showOverflowMenu) {
|
||||
item_recents_duration.setPadding(0, 0, durationPadding, 0)
|
||||
itemRecentsDuration.setPadding(0, 0, durationPadding, 0)
|
||||
}
|
||||
}
|
||||
|
||||
item_recents_sim_image.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
|
||||
item_recents_sim_id.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
|
||||
itemRecentsSimImage.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
|
||||
itemRecentsSimId.beVisibleIf(areMultipleSIMsAvailable && call.simID != -1)
|
||||
if (areMultipleSIMsAvailable && call.simID != -1) {
|
||||
item_recents_sim_image.applyColorFilter(textColor)
|
||||
item_recents_sim_id.setTextColor(textColor.getContrastColor())
|
||||
item_recents_sim_id.text = call.simID.toString()
|
||||
itemRecentsSimImage.applyColorFilter(textColor)
|
||||
itemRecentsSimId.setTextColor(textColor.getContrastColor())
|
||||
itemRecentsSimId.text = call.simID.toString()
|
||||
}
|
||||
|
||||
SimpleContactsHelper(context).loadContactImage(call.photoUri, item_recents_image, call.name)
|
||||
SimpleContactsHelper(root.context).loadContactImage(call.photoUri, itemRecentsImage, call.name)
|
||||
|
||||
val drawable = when (call.type) {
|
||||
Calls.OUTGOING_TYPE -> outgoingCallIcon
|
||||
|
@ -332,17 +343,15 @@ class RecentCallsAdapter(
|
|||
else -> incomingCallIcon
|
||||
}
|
||||
|
||||
item_recents_type.setImageDrawable(drawable)
|
||||
itemRecentsType.setImageDrawable(drawable)
|
||||
|
||||
overflow_menu_icon.beVisibleIf(showOverflowMenu)
|
||||
if (showOverflowMenu) {
|
||||
overflow_menu_icon.drawable.apply {
|
||||
mutate()
|
||||
setTint(activity.getProperTextColor())
|
||||
}
|
||||
overflow_menu_icon.setOnClickListener {
|
||||
showPopupMenu(overflow_menu_anchor, call)
|
||||
}
|
||||
overflowMenuIcon.beVisibleIf(showOverflowMenu)
|
||||
overflowMenuIcon.drawable.apply {
|
||||
mutate()
|
||||
setTint(activity.getProperTextColor())
|
||||
}
|
||||
overflowMenuIcon.setOnClickListener {
|
||||
showPopupMenu(overflowMenuAnchor, call)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -358,14 +367,19 @@ class RecentCallsAdapter(
|
|||
inflate(R.menu.menu_recent_item_options)
|
||||
menu.apply {
|
||||
val areMultipleSIMsAvailable = activity.areMultipleSIMsAvailable()
|
||||
findItem(R.id.cab_call).isVisible = !areMultipleSIMsAvailable
|
||||
findItem(R.id.cab_call_sim_1).isVisible = areMultipleSIMsAvailable
|
||||
findItem(R.id.cab_call_sim_2).isVisible = areMultipleSIMsAvailable
|
||||
findItem(R.id.cab_view_details).isVisible = contact != null
|
||||
findItem(R.id.cab_call).isVisible = !areMultipleSIMsAvailable && !call.isUnknownNumber
|
||||
findItem(R.id.cab_call_sim_1).isVisible = areMultipleSIMsAvailable && !call.isUnknownNumber
|
||||
findItem(R.id.cab_call_sim_2).isVisible = areMultipleSIMsAvailable && !call.isUnknownNumber
|
||||
findItem(R.id.cab_send_sms).isVisible = !call.isUnknownNumber
|
||||
findItem(R.id.cab_view_details).isVisible = contact != null && !call.isUnknownNumber
|
||||
findItem(R.id.cab_add_number).isVisible = !call.isUnknownNumber
|
||||
findItem(R.id.cab_copy_number).isVisible = !call.isUnknownNumber
|
||||
findItem(R.id.cab_show_call_details).isVisible = !call.isUnknownNumber
|
||||
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(R.string.block_number)
|
||||
findItem(R.id.cab_block_number).isVisible = isNougatPlus()
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = activity.config.getCustomSIM(selectedNumber) != ""
|
||||
findItem(R.id.cab_block_number).isVisible = isNougatPlus() && !call.isUnknownNumber
|
||||
findItem(R.id.cab_remove_default_sim).isVisible = (activity.config.getCustomSIM(selectedNumber) ?: "") != "" && !call.isUnknownNumber
|
||||
}
|
||||
|
||||
setOnMenuItemClickListener { item ->
|
||||
val callId = call.id
|
||||
when (item.itemId) {
|
||||
|
@ -374,49 +388,59 @@ class RecentCallsAdapter(
|
|||
callContact()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_call_sim_1 -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
callContact(true)
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_call_sim_2 -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
callContact(false)
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_send_sms -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
sendSMS()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_view_details -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
launchContactDetailsIntent(contact)
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_add_number -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
addNumberToContact()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_show_call_details -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
showCallDetails()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_block_number -> {
|
||||
selectedKeys.add(callId)
|
||||
tryBlocking()
|
||||
}
|
||||
|
||||
R.id.cab_remove -> {
|
||||
selectedKeys.add(callId)
|
||||
askConfirmRemove()
|
||||
}
|
||||
|
||||
R.id.cab_copy_number -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
copyNumber()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_remove_default_sim -> {
|
||||
executeItemMenuOperation(callId) {
|
||||
removeDefaultSIM()
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
package com.simplemobiletools.dialer.adapters
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.databinding.ItemSpeedDialBinding
|
||||
import com.simplemobiletools.dialer.interfaces.RemoveSpeedDialListener
|
||||
import com.simplemobiletools.dialer.models.SpeedDial
|
||||
import kotlinx.android.synthetic.main.item_speed_dial.view.*
|
||||
import java.util.*
|
||||
|
||||
class SpeedDialAdapter(
|
||||
activity: SimpleActivity, var speedDialValues: ArrayList<SpeedDial>, private val removeListener: RemoveSpeedDialListener,
|
||||
activity: SimpleActivity, var speedDialValues: List<SpeedDial>, private val removeListener: RemoveSpeedDialListener,
|
||||
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
init {
|
||||
|
@ -46,12 +44,15 @@ class SpeedDialAdapter(
|
|||
|
||||
override fun onActionModeDestroyed() {}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_speed_dial, parent)
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return createViewHolder(ItemSpeedDialBinding.inflate(layoutInflater, parent, false).root)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val speedDial = speedDialValues[position]
|
||||
holder.bindView(speedDial, true, true) { itemView, layoutPosition ->
|
||||
setupView(itemView, speedDial)
|
||||
val binding = ItemSpeedDialBinding.bind(itemView)
|
||||
setupView(binding, speedDial)
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
}
|
||||
|
@ -66,12 +67,12 @@ class SpeedDialAdapter(
|
|||
finishActMode()
|
||||
}
|
||||
|
||||
private fun setupView(view: View, speedDial: SpeedDial) {
|
||||
view.apply {
|
||||
private fun setupView(binding: ItemSpeedDialBinding, speedDial: SpeedDial) {
|
||||
binding.apply {
|
||||
var displayName = "${speedDial.id}. "
|
||||
displayName += if (speedDial.isValid()) speedDial.displayName else ""
|
||||
|
||||
speed_dial_label.apply {
|
||||
speedDialLabel.apply {
|
||||
text = displayName
|
||||
isSelected = selectedKeys.contains(speedDial.hashCode())
|
||||
setTextColor(textColor)
|
||||
|
|
|
@ -19,7 +19,7 @@ class ViewPagerAdapter(val activity: SimpleActivity) : PagerAdapter() {
|
|||
val view = activity.layoutInflater.inflate(layout, container, false)
|
||||
container.addView(view)
|
||||
|
||||
(view as MyViewPagerFragment).apply {
|
||||
(view as MyViewPagerFragment<*>).apply {
|
||||
setupFragment(activity)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,24 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|||
import com.simplemobiletools.commons.extensions.beGoneIf
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.databinding.DialogChangeSortingBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import kotlinx.android.synthetic.main.dialog_change_sorting.view.*
|
||||
|
||||
class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCustomSorting: Boolean = false, private val callback: () -> Unit) {
|
||||
private val binding by activity.viewBinding(DialogChangeSortingBinding::inflate)
|
||||
|
||||
private var currSorting = 0
|
||||
private var config = activity.config
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_change_sorting, null)
|
||||
|
||||
init {
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this, R.string.sort_by)
|
||||
activity.setupDialogStuff(binding.root, this, R.string.sort_by)
|
||||
}
|
||||
|
||||
currSorting = if (showCustomSorting && config.isCustomOrderSelected) {
|
||||
|
@ -33,43 +35,41 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCust
|
|||
}
|
||||
|
||||
private fun setupSortRadio() {
|
||||
val sortingRadio = view.sorting_dialog_radio_sorting
|
||||
binding.apply {
|
||||
sortingDialogRadioSorting.setOnCheckedChangeListener { group, checkedId ->
|
||||
val isCustomSorting = checkedId == sortingDialogRadioCustom.id
|
||||
sortingDialogRadioOrder.beGoneIf(isCustomSorting)
|
||||
divider.beGoneIf(isCustomSorting)
|
||||
}
|
||||
|
||||
sortingRadio.setOnCheckedChangeListener { group, checkedId ->
|
||||
val isCustomSorting = checkedId == sortingRadio.sorting_dialog_radio_custom.id
|
||||
view.sorting_dialog_radio_order.beGoneIf(isCustomSorting)
|
||||
view.divider.beGoneIf(isCustomSorting)
|
||||
}
|
||||
val sortBtn = when {
|
||||
currSorting and SORT_BY_FIRST_NAME != 0 -> sortingDialogRadioFirstName
|
||||
currSorting and SORT_BY_MIDDLE_NAME != 0 -> sortingDialogRadioMiddleName
|
||||
currSorting and SORT_BY_SURNAME != 0 -> sortingDialogRadioSurname
|
||||
currSorting and SORT_BY_FULL_NAME != 0 -> sortingDialogRadioFullName
|
||||
currSorting and SORT_BY_CUSTOM != 0 -> sortingDialogRadioCustom
|
||||
else -> sortingDialogRadioDateCreated
|
||||
}
|
||||
sortBtn.isChecked = true
|
||||
|
||||
val sortBtn = when {
|
||||
currSorting and SORT_BY_FIRST_NAME != 0 -> sortingRadio.sorting_dialog_radio_first_name
|
||||
currSorting and SORT_BY_MIDDLE_NAME != 0 -> sortingRadio.sorting_dialog_radio_middle_name
|
||||
currSorting and SORT_BY_SURNAME != 0 -> sortingRadio.sorting_dialog_radio_surname
|
||||
currSorting and SORT_BY_FULL_NAME != 0 -> sortingRadio.sorting_dialog_radio_full_name
|
||||
currSorting and SORT_BY_CUSTOM != 0 -> sortingRadio.sorting_dialog_radio_custom
|
||||
else -> sortingRadio.sorting_dialog_radio_date_created
|
||||
if (showCustomSorting) {
|
||||
sortingDialogRadioCustom.isChecked = config.isCustomOrderSelected
|
||||
}
|
||||
sortingDialogRadioCustom.beGoneIf(!showCustomSorting)
|
||||
}
|
||||
sortBtn.isChecked = true
|
||||
|
||||
if (showCustomSorting) {
|
||||
sortingRadio.sorting_dialog_radio_custom.isChecked = config.isCustomOrderSelected
|
||||
}
|
||||
view.sorting_dialog_radio_custom.beGoneIf(!showCustomSorting)
|
||||
}
|
||||
|
||||
private fun setupOrderRadio() {
|
||||
val orderRadio = view.sorting_dialog_radio_order
|
||||
var orderBtn = orderRadio.sorting_dialog_radio_ascending
|
||||
|
||||
var orderBtn = binding.sortingDialogRadioAscending
|
||||
if (currSorting and SORT_DESCENDING != 0) {
|
||||
orderBtn = orderRadio.sorting_dialog_radio_descending
|
||||
orderBtn = binding.sortingDialogRadioDescending
|
||||
}
|
||||
|
||||
orderBtn.isChecked = true
|
||||
}
|
||||
|
||||
private fun dialogConfirmed() {
|
||||
val sortingRadio = view.sorting_dialog_radio_sorting
|
||||
var sorting = when (sortingRadio.checkedRadioButtonId) {
|
||||
var sorting = when (binding.sortingDialogRadioSorting.checkedRadioButtonId) {
|
||||
R.id.sorting_dialog_radio_first_name -> SORT_BY_FIRST_NAME
|
||||
R.id.sorting_dialog_radio_middle_name -> SORT_BY_MIDDLE_NAME
|
||||
R.id.sorting_dialog_radio_surname -> SORT_BY_SURNAME
|
||||
|
@ -78,7 +78,7 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, private val showCust
|
|||
else -> SORT_BY_DATE_CREATED
|
||||
}
|
||||
|
||||
if (sorting != SORT_BY_CUSTOM && view.sorting_dialog_radio_order.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
|
||||
if (sorting != SORT_BY_CUSTOM && binding.sortingDialogRadioOrder.checkedRadioButtonId == R.id.sorting_dialog_radio_descending) {
|
||||
sorting = sorting or SORT_DESCENDING
|
||||
}
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@ import androidx.fragment.app.FragmentManager
|
|||
import com.simplemobiletools.commons.adapters.SimpleListItemAdapter
|
||||
import com.simplemobiletools.commons.fragments.BaseBottomSheetDialogFragment
|
||||
import com.simplemobiletools.commons.models.SimpleListItem
|
||||
import com.simplemobiletools.dialer.R
|
||||
import kotlinx.android.synthetic.main.layout_simple_recycler_view.*
|
||||
import com.simplemobiletools.dialer.databinding.LayoutSimpleRecyclerViewBinding
|
||||
|
||||
// same as BottomSheetChooserDialog but with dynamic updates
|
||||
class DynamicBottomSheetChooserDialog : BaseBottomSheetDialogFragment() {
|
||||
private lateinit var binding: LayoutSimpleRecyclerViewBinding
|
||||
|
||||
var onItemClick: ((SimpleListItem) -> Unit)? = null
|
||||
|
||||
override fun setupContentView(parent: ViewGroup) {
|
||||
val child = layoutInflater.inflate(R.layout.layout_simple_recycler_view, parent, false)
|
||||
parent.addView(child)
|
||||
binding = LayoutSimpleRecyclerViewBinding.inflate(layoutInflater, parent, false)
|
||||
parent.addView(binding.root)
|
||||
setupRecyclerView()
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,13 @@ class DynamicBottomSheetChooserDialog : BaseBottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
private fun getRecyclerViewAdapter(): SimpleListItemAdapter {
|
||||
var adapter = recycler_view.adapter as? SimpleListItemAdapter
|
||||
var adapter = binding.recyclerView.adapter as? SimpleListItemAdapter
|
||||
if (adapter == null) {
|
||||
adapter = SimpleListItemAdapter(requireActivity()) {
|
||||
onItemClick?.invoke(it)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
recycler_view.adapter = adapter
|
||||
binding.recyclerView.adapter = adapter
|
||||
}
|
||||
return adapter
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.simplemobiletools.dialer.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.databinding.DialogExportCallHistoryBinding
|
||||
|
||||
class ExportCallHistoryDialog(val activity: SimpleActivity, callback: (filename: String) -> Unit) {
|
||||
|
||||
init {
|
||||
val binding = DialogExportCallHistoryBinding.inflate(activity.layoutInflater).apply {
|
||||
exportCallHistoryFilename.setText("call_history_${activity.getCurrentFormattedDateTime()}")
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder().setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null).apply {
|
||||
activity.setupDialogStuff(binding.root, this, R.string.export_call_history) { alertDialog ->
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
|
||||
val filename = binding.exportCallHistoryFilename.value
|
||||
when {
|
||||
filename.isEmpty() -> activity.toast(R.string.empty_name)
|
||||
filename.isAValidFilename() -> {
|
||||
callback(filename)
|
||||
alertDialog.dismiss()
|
||||
}
|
||||
|
||||
else -> activity.toast(R.string.invalid_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +1,36 @@
|
|||
package com.simplemobiletools.dialer.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.commons.extensions.getVisibleContactSources
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.ContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
||||
import com.simplemobiletools.commons.models.contacts.*
|
||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.commons.models.contacts.ContactSource
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.FilterContactSourcesAdapter
|
||||
import com.simplemobiletools.dialer.databinding.DialogFilterContactSourcesBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import kotlinx.android.synthetic.main.dialog_filter_contact_sources.view.*
|
||||
|
||||
class FilterContactSourcesDialog(val activity: SimpleActivity, private val callback: () -> Unit) {
|
||||
private val binding by activity.viewBinding(DialogFilterContactSourcesBinding::inflate)
|
||||
|
||||
private var dialog: AlertDialog? = null
|
||||
private val view = activity.layoutInflater.inflate(R.layout.dialog_filter_contact_sources, null)
|
||||
private var contactSources = ArrayList<ContactSource>()
|
||||
private var contacts = ArrayList<Contact>()
|
||||
private var isContactSourcesReady = false
|
||||
private var isContactsReady = false
|
||||
|
||||
init {
|
||||
val contactHelper = ContactsHelper(activity)
|
||||
contactHelper.getContactSources { contactSources ->
|
||||
val contactHelper = ContactsHelper(activity)
|
||||
contactHelper.getContactSources { contactSources ->
|
||||
contactSources.mapTo(this@FilterContactSourcesDialog.contactSources) { it.copy() }
|
||||
isContactSourcesReady = true
|
||||
processDataIfReady()
|
||||
}
|
||||
|
||||
contactHelper.getContacts(getAll = true) {
|
||||
contactHelper.getContacts(getAll = true, showOnlyContactsWithNumbers = true) {
|
||||
it.mapTo(contacts) { contact -> contact.copy() }
|
||||
val privateCursor = activity.getMyContactsCursor(false, true)
|
||||
val privateContacts = MyContactsContentProvider.getContacts(activity, privateCursor)
|
||||
|
@ -61,14 +60,14 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
|
|||
|
||||
activity.runOnUiThread {
|
||||
val selectedSources = activity.getVisibleContactSources()
|
||||
view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, contactSourcesWithCount, selectedSources)
|
||||
binding.filterContactSourcesList.adapter = FilterContactSourcesAdapter(activity, contactSourcesWithCount, selectedSources)
|
||||
|
||||
if (dialog == null) {
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok) { dialogInterface, i -> confirmContactSources() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
activity.setupDialogStuff(binding.root, this) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +76,7 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
|
|||
}
|
||||
|
||||
private fun confirmContactSources() {
|
||||
val selectedContactSources = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedContactSources()
|
||||
val selectedContactSources = (binding.filterContactSourcesList.adapter as FilterContactSourcesAdapter).getSelectedContactSources()
|
||||
val ignoredContactSources = contactSources.filter { !selectedContactSources.contains(it) }.map {
|
||||
if (it.type == SMT_PRIVATE) SMT_PRIVATE else it.getFullIdentifier()
|
||||
}.toHashSet()
|
||||
|
|
|
@ -3,16 +3,18 @@ package com.simplemobiletools.dialer.dialogs
|
|||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.commons.helpers.TAB_CALL_HISTORY
|
||||
import com.simplemobiletools.commons.helpers.TAB_CONTACTS
|
||||
import com.simplemobiletools.commons.helpers.TAB_FAVORITES
|
||||
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.databinding.DialogManageVisibleTabsBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.helpers.ALL_TABS_MASK
|
||||
|
||||
class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null)
|
||||
private val binding by activity.viewBinding(DialogManageVisibleTabsBinding::inflate)
|
||||
private val tabs = LinkedHashMap<Int, Int>()
|
||||
|
||||
init {
|
||||
|
@ -24,21 +26,21 @@ class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
|
|||
|
||||
val showTabs = activity.config.showTabs
|
||||
for ((key, value) in tabs) {
|
||||
view.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
|
||||
binding.root.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
activity.setupDialogStuff(binding.root, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dialogConfirmed() {
|
||||
var result = 0
|
||||
for ((key, value) in tabs) {
|
||||
if (view.findViewById<MyAppCompatCheckbox>(value).isChecked) {
|
||||
if (binding.root.findViewById<MyAppCompatCheckbox>(value).isChecked) {
|
||||
result += key
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,36 @@
|
|||
package com.simplemobiletools.dialer.dialogs
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.KeyEvent
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.commons.views.MySearchMenu
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.ContactsAdapter
|
||||
import kotlinx.android.synthetic.main.dialog_select_contact.view.*
|
||||
import java.util.*
|
||||
import com.simplemobiletools.dialer.databinding.DialogSelectContactBinding
|
||||
import java.util.Locale
|
||||
|
||||
class SelectContactDialog(val activity: SimpleActivity, val contacts: List<Contact>, val callback: (selectedContact: Contact) -> Unit) {
|
||||
private val binding by activity.viewBinding(DialogSelectContactBinding::inflate)
|
||||
|
||||
class SelectContactDialog(val activity: SimpleActivity, contacts: ArrayList<Contact>, val callback: (selectedContact: Contact) -> Unit) {
|
||||
private var dialog: AlertDialog? = null
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_select_contact, null)
|
||||
|
||||
init {
|
||||
view.apply {
|
||||
letter_fastscroller.textColor = context.getProperTextColor().getColorStateList()
|
||||
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
|
||||
letter_fastscroller_thumb.textColor = context.getProperPrimaryColor().getContrastColor()
|
||||
letter_fastscroller_thumb.thumbColor = context.getProperPrimaryColor().getColorStateList()
|
||||
binding.apply {
|
||||
letterFastscroller.textColor = activity.getProperTextColor().getColorStateList()
|
||||
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
|
||||
letterFastscrollerThumb.textColor = activity.getProperPrimaryColor().getContrastColor()
|
||||
letterFastscrollerThumb.thumbColor = activity.getProperPrimaryColor().getColorStateList()
|
||||
|
||||
letter_fastscroller.setupWithRecyclerView(select_contact_list, { position ->
|
||||
try {
|
||||
val name = contacts[position].getNameToDisplay()
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()))
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
})
|
||||
setupLetterFastScroller(contacts)
|
||||
configureSearchView()
|
||||
|
||||
select_contact_list.adapter = ContactsAdapter(activity, contacts, select_contact_list) {
|
||||
selectContactList.adapter = ContactsAdapter(activity, contacts.toMutableList(), selectContactList, allowLongClick = false) {
|
||||
callback(it as Contact)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
@ -39,10 +38,105 @@ class SelectContactDialog(val activity: SimpleActivity, contacts: ArrayList<Cont
|
|||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnKeyListener { _, i, keyEvent ->
|
||||
if (keyEvent.action == KeyEvent.ACTION_UP && i == KeyEvent.KEYCODE_BACK) {
|
||||
backPressed()
|
||||
}
|
||||
true
|
||||
}
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
activity.setupDialogStuff(binding.root, this, R.string.choose_contact) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupLetterFastScroller(contacts: List<Contact>) {
|
||||
binding.letterFastscroller.setupWithRecyclerView(binding.selectContactList, { position ->
|
||||
try {
|
||||
val name = contacts[position].getNameToDisplay()
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()))
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun configureSearchView() = with(binding.contactSearchView) {
|
||||
updateHintText(context.getString(R.string.search_contacts))
|
||||
binding.topToolbarSearch.imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
|
||||
toggleHideOnScroll(true)
|
||||
setupMenu()
|
||||
setSearchViewListeners()
|
||||
updateSearchViewUi()
|
||||
}
|
||||
|
||||
private fun MySearchMenu.updateSearchViewUi() {
|
||||
getToolbar().beInvisible()
|
||||
updateColors()
|
||||
setBackgroundColor(Color.TRANSPARENT)
|
||||
binding.topAppBarLayout.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
private fun MySearchMenu.setSearchViewListeners() {
|
||||
onSearchOpenListener = {
|
||||
updateSearchViewLeftIcon(R.drawable.ic_cross_vector)
|
||||
}
|
||||
onSearchClosedListener = {
|
||||
binding.topToolbarSearch.clearFocus()
|
||||
activity.hideKeyboard(binding.topToolbarSearch)
|
||||
updateSearchViewLeftIcon(R.drawable.ic_search_vector)
|
||||
}
|
||||
|
||||
onSearchTextChangedListener = { text ->
|
||||
filterContactListBySearchQuery(text)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSearchViewLeftIcon(iconResId: Int) = with(binding.root.findViewById<ImageView>(R.id.top_toolbar_search_icon)) {
|
||||
post {
|
||||
setImageResource(iconResId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterContactListBySearchQuery(query: String) {
|
||||
val adapter = binding.selectContactList.adapter as? ContactsAdapter
|
||||
var contactsToShow = contacts
|
||||
if (query.isNotEmpty()) {
|
||||
contactsToShow = contacts.filter { it.name.contains(query, true) }
|
||||
}
|
||||
checkPlaceholderVisibility(contactsToShow)
|
||||
|
||||
if (adapter?.contacts != contactsToShow) {
|
||||
adapter?.updateItems(contactsToShow)
|
||||
setupLetterFastScroller(contactsToShow)
|
||||
|
||||
binding.selectContactList.apply {
|
||||
post {
|
||||
scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPlaceholderVisibility(contacts: List<Contact>) = with(binding) {
|
||||
contactsEmptyPlaceholder.beVisibleIf(contacts.isEmpty())
|
||||
|
||||
if (contactSearchView.isSearchOpen) {
|
||||
contactsEmptyPlaceholder.text = activity.getString(R.string.no_items_found)
|
||||
}
|
||||
|
||||
letterFastscroller.beVisibleIf(contactsEmptyPlaceholder.isGone())
|
||||
letterFastscrollerThumb.beVisibleIf(contactsEmptyPlaceholder.isGone())
|
||||
}
|
||||
|
||||
private fun backPressed() {
|
||||
if (binding.contactSearchView.isSearchOpen) {
|
||||
binding.contactSearchView.closeSearch()
|
||||
} else {
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ import androidx.appcompat.app.AlertDialog
|
|||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.databinding.DialogSelectSimBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.extensions.getAvailableSIMCardLabels
|
||||
import kotlinx.android.synthetic.main.dialog_select_sim.view.*
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class SelectSIMDialog(
|
||||
|
@ -22,28 +23,25 @@ class SelectSIMDialog(
|
|||
val callback: (handle: PhoneAccountHandle?) -> Unit
|
||||
) {
|
||||
private var dialog: AlertDialog? = null
|
||||
private val view = activity.layoutInflater.inflate(R.layout.dialog_select_sim, null)
|
||||
private val binding by activity.viewBinding(DialogSelectSimBinding::inflate)
|
||||
|
||||
init {
|
||||
val radioGroup = view.select_sim_radio_group
|
||||
view.apply {
|
||||
select_sim_remember_holder.setOnClickListener {
|
||||
select_sim_remember.toggle()
|
||||
}
|
||||
binding.selectSimRememberHolder.setOnClickListener {
|
||||
binding.selectSimRemember.toggle()
|
||||
}
|
||||
|
||||
activity.getAvailableSIMCardLabels().forEachIndexed { index, SIMAccount ->
|
||||
val radioButton = (activity.layoutInflater.inflate(R.layout.radio_button, null) as RadioButton).apply {
|
||||
text = "${index + 1} - ${SIMAccount.label}"
|
||||
id = index
|
||||
setOnClickListener { selectedSIM(SIMAccount.handle, SIMAccount.label) }
|
||||
setOnClickListener { selectedSIM(SIMAccount.handle) }
|
||||
}
|
||||
radioGroup!!.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
binding.selectSimRadioGroup.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
activity.setupDialogStuff(binding.root, this) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +51,9 @@ class SelectSIMDialog(
|
|||
}
|
||||
}
|
||||
|
||||
private fun selectedSIM(handle: PhoneAccountHandle, label: String) {
|
||||
if (view.select_sim_remember.isChecked) {
|
||||
activity.config.saveCustomSIM(phoneNumber, label)
|
||||
private fun selectedSIM(handle: PhoneAccountHandle) {
|
||||
if (binding.selectSimRemember.isChecked) {
|
||||
activity.config.saveCustomSIM(phoneNumber, handle)
|
||||
}
|
||||
|
||||
callback(handle)
|
||||
|
|
|
@ -4,33 +4,31 @@ import androidx.appcompat.app.AlertDialog
|
|||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.commons.extensions.viewBinding
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.DialogShowGroupedCallsBinding
|
||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||
import com.simplemobiletools.dialer.models.RecentCall
|
||||
import kotlinx.android.synthetic.main.dialog_show_grouped_calls.view.*
|
||||
|
||||
class ShowGroupedCallsDialog(val activity: BaseSimpleActivity, callIds: ArrayList<Int>) {
|
||||
private var dialog: AlertDialog? = null
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_show_grouped_calls, null)
|
||||
private val binding by activity.viewBinding(DialogShowGroupedCallsBinding::inflate)
|
||||
|
||||
init {
|
||||
view.apply {
|
||||
RecentsHelper(activity).getRecentCalls(false) { allRecents ->
|
||||
val recents = allRecents.filter { callIds.contains(it.id) }.toMutableList() as ArrayList<RecentCall>
|
||||
activity.runOnUiThread {
|
||||
RecentCallsAdapter(activity as SimpleActivity, recents, select_grouped_calls_list, null, false) {
|
||||
}.apply {
|
||||
select_grouped_calls_list.adapter = this
|
||||
}
|
||||
RecentsHelper(activity).getRecentCalls(false) { allRecents ->
|
||||
val recents = allRecents.filter { callIds.contains(it.id) }.toMutableList() as ArrayList<RecentCall>
|
||||
activity.runOnUiThread {
|
||||
RecentCallsAdapter(activity as SimpleActivity, recents, binding.selectGroupedCallsList, null, false) {
|
||||
}.apply {
|
||||
binding.selectGroupedCallsList.adapter = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
activity.setupDialogStuff(binding.root, this) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,12 +76,10 @@ fun SimpleActivity.getHandleToUse(intent: Intent?, phoneNumber: String, callback
|
|||
val defaultHandle = telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL)
|
||||
when {
|
||||
intent?.hasExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE) == true -> callback(intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE)!!)
|
||||
config.getCustomSIM(phoneNumber)?.isNotEmpty() == true -> {
|
||||
val storedLabel = Uri.decode(config.getCustomSIM(phoneNumber))
|
||||
val availableSIMs = getAvailableSIMCardLabels()
|
||||
val firstOrNull = availableSIMs.firstOrNull { it.label == storedLabel }?.handle ?: availableSIMs.first().handle
|
||||
callback(firstOrNull)
|
||||
config.getCustomSIM(phoneNumber) != null -> {
|
||||
callback(config.getCustomSIM(phoneNumber))
|
||||
}
|
||||
|
||||
defaultHandle != null -> callback(defaultHandle)
|
||||
else -> {
|
||||
SelectSIMDialog(this, phoneNumber, onDismiss = {
|
||||
|
|
|
@ -16,8 +16,8 @@ val Context.audioManager: AudioManager get() = getSystemService(Context.AUDIO_SE
|
|||
val Context.powerManager: PowerManager get() = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun Context.getAvailableSIMCardLabels(): ArrayList<SIMAccount> {
|
||||
val SIMAccounts = ArrayList<SIMAccount>()
|
||||
fun Context.getAvailableSIMCardLabels(): List<SIMAccount> {
|
||||
val SIMAccounts = mutableListOf<SIMAccount>()
|
||||
try {
|
||||
telecomManager.callCapablePhoneAccounts.forEachIndexed { index, account ->
|
||||
val phoneAccount = telecomManager.getPhoneAccount(account)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package com.simplemobiletools.dialer.extensions
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.telecom.PhoneAccountHandle
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.simplemobiletools.dialer.models.PhoneAccountHandleModel
|
||||
|
||||
fun SharedPreferences.Editor.putPhoneAccountHandle(
|
||||
key: String,
|
||||
parcelable: PhoneAccountHandle
|
||||
): SharedPreferences.Editor {
|
||||
val componentName = parcelable.componentName
|
||||
val myPhoneAccountHandleModel = PhoneAccountHandleModel(
|
||||
componentName.packageName, componentName.className, parcelable.id
|
||||
)
|
||||
val json = Gson().toJson(myPhoneAccountHandleModel)
|
||||
return putString(key, json)
|
||||
}
|
||||
|
||||
inline fun <reified T : PhoneAccountHandleModel?> SharedPreferences.getPhoneAccountHandleModel(
|
||||
key: String,
|
||||
default: T
|
||||
): T {
|
||||
val json = getString(key, null)
|
||||
return try {
|
||||
if (json != null) {
|
||||
Gson().fromJson(json, T::class.java)
|
||||
} else {
|
||||
default
|
||||
}
|
||||
} catch (_: JsonSyntaxException) {
|
||||
default
|
||||
}
|
||||
}
|
|
@ -11,15 +11,24 @@ import com.simplemobiletools.dialer.R
|
|||
import com.simplemobiletools.dialer.activities.MainActivity
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.FragmentContactsBinding
|
||||
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
|
||||
import com.simplemobiletools.dialer.extensions.launchCreateNewContactIntent
|
||||
import com.simplemobiletools.dialer.extensions.startContactDetailsIntent
|
||||
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
||||
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
|
||||
class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.LettersInnerBinding>(context, attributeSet),
|
||||
RefreshItemsListener {
|
||||
private lateinit var binding: FragmentLettersLayoutBinding
|
||||
private var allContacts = ArrayList<Contact>()
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
binding = FragmentLettersLayoutBinding.bind(FragmentContactsBinding.bind(this).contactsFragment)
|
||||
innerBinding = LettersInnerBinding(binding)
|
||||
}
|
||||
|
||||
override fun setupFragment() {
|
||||
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
|
||||
R.string.no_contacts_found
|
||||
|
@ -27,7 +36,7 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
|
|||
R.string.could_not_access_contacts
|
||||
}
|
||||
|
||||
fragment_placeholder.text = context.getString(placeholderResId)
|
||||
binding.fragmentPlaceholder.text = context.getString(placeholderResId)
|
||||
|
||||
val placeholderActionResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
|
||||
R.string.create_new_contact
|
||||
|
@ -35,7 +44,7 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
|
|||
R.string.request_access
|
||||
}
|
||||
|
||||
fragment_placeholder_2.apply {
|
||||
binding.fragmentPlaceholder2.apply {
|
||||
text = context.getString(placeholderActionResId)
|
||||
underlineText()
|
||||
setOnClickListener {
|
||||
|
@ -49,20 +58,22 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
|
|||
}
|
||||
|
||||
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
|
||||
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
|
||||
fragment_placeholder.setTextColor(textColor)
|
||||
fragment_placeholder_2.setTextColor(properPrimaryColor)
|
||||
binding.apply {
|
||||
(fragmentList?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
|
||||
fragmentPlaceholder.setTextColor(textColor)
|
||||
fragmentPlaceholder2.setTextColor(properPrimaryColor)
|
||||
|
||||
letter_fastscroller.textColor = textColor.getColorStateList()
|
||||
letter_fastscroller.pressedTextColor = properPrimaryColor
|
||||
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
|
||||
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
letterFastscroller.textColor = textColor.getColorStateList()
|
||||
letterFastscroller.pressedTextColor = properPrimaryColor
|
||||
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
|
||||
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshItems(callback: (() -> Unit)?) {
|
||||
val privateCursor = context?.getMyContactsCursor(false, true)
|
||||
ContactsHelper(context).getContacts { contacts ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
allContacts = contacts
|
||||
|
||||
if (SMT_PRIVATE !in context.baseConfig.ignoredContactSources) {
|
||||
|
@ -82,40 +93,48 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
|
|||
}
|
||||
|
||||
private fun gotContacts(contacts: ArrayList<Contact>) {
|
||||
setupLetterFastscroller(contacts)
|
||||
setupLetterFastScroller(contacts)
|
||||
if (contacts.isEmpty()) {
|
||||
fragment_placeholder.beVisible()
|
||||
fragment_placeholder_2.beVisible()
|
||||
fragment_list.beGone()
|
||||
binding.apply {
|
||||
fragmentPlaceholder.beVisible()
|
||||
fragmentPlaceholder2.beVisible()
|
||||
fragmentList.beGone()
|
||||
}
|
||||
} else {
|
||||
fragment_placeholder.beGone()
|
||||
fragment_placeholder_2.beGone()
|
||||
fragment_list.beVisible()
|
||||
binding.apply {
|
||||
fragmentPlaceholder.beGone()
|
||||
fragmentPlaceholder2.beGone()
|
||||
fragmentList.beVisible()
|
||||
}
|
||||
|
||||
val currAdapter = fragment_list.adapter
|
||||
if (currAdapter == null) {
|
||||
ContactsAdapter(activity as SimpleActivity, contacts, fragment_list, this) {
|
||||
if (binding.fragmentList.adapter == null) {
|
||||
ContactsAdapter(
|
||||
activity = activity as SimpleActivity,
|
||||
contacts = contacts,
|
||||
recyclerView = binding.fragmentList,
|
||||
refreshItemsListener = this
|
||||
) {
|
||||
val contact = it as Contact
|
||||
activity?.startContactDetailsIntent(contact)
|
||||
}.apply {
|
||||
fragment_list.adapter = this
|
||||
binding.fragmentList.adapter = this
|
||||
}
|
||||
|
||||
if (context.areSystemAnimationsEnabled) {
|
||||
fragment_list.scheduleLayoutAnimation()
|
||||
binding.fragmentList.scheduleLayoutAnimation()
|
||||
}
|
||||
} else {
|
||||
(currAdapter as ContactsAdapter).updateItems(contacts)
|
||||
(binding.fragmentList.adapter as ContactsAdapter).updateItems(contacts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupLetterFastscroller(contacts: ArrayList<Contact>) {
|
||||
letter_fastscroller.setupWithRecyclerView(fragment_list, { position ->
|
||||
private fun setupLetterFastScroller(contacts: ArrayList<Contact>) {
|
||||
binding.letterFastscroller.setupWithRecyclerView(binding.fragmentList, { position ->
|
||||
try {
|
||||
val name = contacts[position].getNameToDisplay()
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString())
|
||||
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()).normalizeString())
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
|
@ -123,43 +142,44 @@ class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
|
|||
}
|
||||
|
||||
override fun onSearchClosed() {
|
||||
fragment_placeholder.beVisibleIf(allContacts.isEmpty())
|
||||
(fragment_list.adapter as? ContactsAdapter)?.updateItems(allContacts)
|
||||
setupLetterFastscroller(allContacts)
|
||||
binding.fragmentPlaceholder.beVisibleIf(allContacts.isEmpty())
|
||||
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(allContacts)
|
||||
setupLetterFastScroller(allContacts)
|
||||
}
|
||||
|
||||
override fun onSearchQueryChanged(text: String) {
|
||||
val shouldNormalize = text.normalizeString() == text
|
||||
val filtered = allContacts.filter {
|
||||
getProperText(it.getNameToDisplay(), shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.nickname, shouldNormalize).contains(text, true) ||
|
||||
it.phoneNumbers.any {
|
||||
text.normalizePhoneNumber().isNotEmpty() && it.normalizedNumber.contains(text.normalizePhoneNumber(), true)
|
||||
} ||
|
||||
it.emails.any { it.value.contains(text, true) } ||
|
||||
it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } ||
|
||||
it.IMs.any { it.value.contains(text, true) } ||
|
||||
getProperText(it.notes, shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.organization.company, shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) ||
|
||||
it.websites.any { it.contains(text, true) }
|
||||
} as ArrayList
|
||||
val shouldNormalize = text.normalizeString() == text
|
||||
val filtered = allContacts.filter {
|
||||
getProperText(it.getNameToDisplay(), shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.nickname, shouldNormalize).contains(text, true) ||
|
||||
it.phoneNumbers.any {
|
||||
text.normalizePhoneNumber().isNotEmpty() && it.normalizedNumber.contains(text.normalizePhoneNumber(), true)
|
||||
} ||
|
||||
it.emails.any { it.value.contains(text, true) } ||
|
||||
it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } ||
|
||||
it.IMs.any { it.value.contains(text, true) } ||
|
||||
getProperText(it.notes, shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.organization.company, shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) ||
|
||||
it.websites.any { it.contains(text, true) }
|
||||
} as ArrayList
|
||||
|
||||
filtered.sortBy {
|
||||
val nameToDisplay = it.getNameToDisplay()
|
||||
!getProperText(nameToDisplay, shouldNormalize).startsWith(text, true) && !nameToDisplay.contains(text, true)
|
||||
}
|
||||
|
||||
fragment_placeholder.beVisibleIf(filtered.isEmpty())
|
||||
(fragment_list.adapter as? ContactsAdapter)?.updateItems(filtered, text)
|
||||
setupLetterFastscroller(filtered)
|
||||
filtered.sortBy {
|
||||
val nameToDisplay = it.getNameToDisplay()
|
||||
!getProperText(nameToDisplay, shouldNormalize).startsWith(text, true) && !nameToDisplay.contains(text, true)
|
||||
}
|
||||
|
||||
binding.fragmentPlaceholder.beVisibleIf(filtered.isEmpty())
|
||||
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(filtered, text)
|
||||
setupLetterFastScroller(filtered)
|
||||
}
|
||||
|
||||
private fun requestReadContactsPermission() {
|
||||
activity?.handlePermission(PERMISSION_READ_CONTACTS) {
|
||||
if (it) {
|
||||
fragment_placeholder.text = context.getString(R.string.no_contacts_found)
|
||||
fragment_placeholder_2.text = context.getString(R.string.create_new_contact)
|
||||
ContactsHelper(context).getContacts(false) { contacts ->
|
||||
binding.fragmentPlaceholder.text = context.getString(R.string.no_contacts_found)
|
||||
binding.fragmentPlaceholder2.text = context.getString(R.string.create_new_contact)
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
activity?.runOnUiThread {
|
||||
gotContacts(contacts)
|
||||
}
|
||||
|
|
|
@ -6,26 +6,32 @@ import com.google.gson.Gson
|
|||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.ContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS
|
||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.commons.views.MyGridLayoutManager
|
||||
import com.simplemobiletools.commons.views.MyLinearLayoutManager
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.FragmentFavoritesBinding
|
||||
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.helpers.Converters
|
||||
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
||||
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
|
||||
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.LettersInnerBinding>(context, attributeSet),
|
||||
RefreshItemsListener {
|
||||
private lateinit var binding: FragmentLettersLayoutBinding
|
||||
private var allContacts = ArrayList<Contact>()
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
binding = FragmentLettersLayoutBinding.bind(FragmentFavoritesBinding.bind(this).favoritesFragment)
|
||||
innerBinding = LettersInnerBinding(binding)
|
||||
}
|
||||
|
||||
override fun setupFragment() {
|
||||
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CONTACTS)) {
|
||||
R.string.no_contacts_found
|
||||
|
@ -33,28 +39,32 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
R.string.could_not_access_contacts
|
||||
}
|
||||
|
||||
fragment_placeholder.text = context.getString(placeholderResId)
|
||||
fragment_placeholder_2.beGone()
|
||||
binding.fragmentPlaceholder.text = context.getString(placeholderResId)
|
||||
binding.fragmentPlaceholder2.beGone()
|
||||
}
|
||||
|
||||
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
|
||||
fragment_placeholder.setTextColor(textColor)
|
||||
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
|
||||
binding.apply {
|
||||
fragmentPlaceholder.setTextColor(textColor)
|
||||
(fragmentList.adapter as? MyRecyclerViewAdapter)?.updateTextColor(textColor)
|
||||
|
||||
letter_fastscroller.textColor = textColor.getColorStateList()
|
||||
letter_fastscroller.pressedTextColor = properPrimaryColor
|
||||
letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller)
|
||||
letter_fastscroller_thumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letter_fastscroller_thumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
letterFastscroller.textColor = textColor.getColorStateList()
|
||||
letterFastscroller.pressedTextColor = properPrimaryColor
|
||||
letterFastscrollerThumb.setupWithFastScroller(letterFastscroller)
|
||||
letterFastscrollerThumb.textColor = properPrimaryColor.getContrastColor()
|
||||
letterFastscrollerThumb.thumbColor = properPrimaryColor.getColorStateList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshItems(callback: (() -> Unit)?) {
|
||||
val privateCursor = context?.getMyContactsCursor(true, true)
|
||||
ContactsHelper(context).getContacts { contacts ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
allContacts = contacts
|
||||
|
||||
if (SMT_PRIVATE !in context.baseConfig.ignoredContactSources) {
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||
val privateCursor = context?.getMyContactsCursor(true, true)
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor).map {
|
||||
it.copy(starred = 1)
|
||||
}
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
allContacts.addAll(privateContacts)
|
||||
allContacts.sort()
|
||||
|
@ -76,53 +86,79 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
}
|
||||
|
||||
private fun gotContacts(contacts: ArrayList<Contact>) {
|
||||
setupLetterFastscroller(contacts)
|
||||
if (contacts.isEmpty()) {
|
||||
fragment_placeholder.beVisible()
|
||||
fragment_list.beGone()
|
||||
} else {
|
||||
fragment_placeholder.beGone()
|
||||
fragment_list.beVisible()
|
||||
|
||||
val currAdapter = fragment_list.adapter
|
||||
if (currAdapter == null) {
|
||||
ContactsAdapter(
|
||||
activity = activity as SimpleActivity,
|
||||
contacts = contacts,
|
||||
recyclerView = fragment_list,
|
||||
refreshItemsListener = this,
|
||||
showDeleteButton = false,
|
||||
enableDrag = true,
|
||||
) {
|
||||
if (context.config.showCallConfirmation) {
|
||||
CallConfirmationDialog(activity as SimpleActivity, (it as Contact).getNameToDisplay()) {
|
||||
callContact(it)
|
||||
}
|
||||
} else {
|
||||
callContact(it as Contact)
|
||||
}
|
||||
}.apply {
|
||||
fragment_list.adapter = this
|
||||
|
||||
onDragEndListener = {
|
||||
val adapter = fragment_list?.adapter
|
||||
if (adapter is ContactsAdapter) {
|
||||
val items = adapter.contacts
|
||||
saveCustomOrderToPrefs(items)
|
||||
setupLetterFastscroller(items)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.areSystemAnimationsEnabled) {
|
||||
fragment_list.scheduleLayoutAnimation()
|
||||
}
|
||||
setupLetterFastScroller(contacts)
|
||||
binding.apply {
|
||||
if (contacts.isEmpty()) {
|
||||
fragmentPlaceholder.beVisible()
|
||||
fragmentList.beGone()
|
||||
} else {
|
||||
(currAdapter as ContactsAdapter).updateItems(contacts)
|
||||
fragmentPlaceholder.beGone()
|
||||
fragmentList.beVisible()
|
||||
|
||||
updateListAdapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateListAdapter() {
|
||||
val viewType = context.config.viewType
|
||||
setViewType(viewType)
|
||||
|
||||
val currAdapter = binding.fragmentList.adapter as ContactsAdapter?
|
||||
if (currAdapter == null) {
|
||||
ContactsAdapter(
|
||||
activity = activity as SimpleActivity,
|
||||
contacts = allContacts,
|
||||
recyclerView = binding.fragmentList,
|
||||
refreshItemsListener = this,
|
||||
viewType = viewType,
|
||||
showDeleteButton = false,
|
||||
enableDrag = true,
|
||||
) {
|
||||
if (context.config.showCallConfirmation) {
|
||||
CallConfirmationDialog(activity as SimpleActivity, (it as Contact).getNameToDisplay()) {
|
||||
activity?.apply {
|
||||
initiateCall(it) { launchCallIntent(it) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
activity?.apply {
|
||||
initiateCall(it as Contact) { launchCallIntent(it) }
|
||||
}
|
||||
}
|
||||
}.apply {
|
||||
binding.fragmentList.adapter = this
|
||||
|
||||
onDragEndListener = {
|
||||
val adapter = binding.fragmentList.adapter
|
||||
if (adapter is ContactsAdapter) {
|
||||
val items = adapter.contacts
|
||||
saveCustomOrderToPrefs(items)
|
||||
setupLetterFastScroller(items)
|
||||
}
|
||||
}
|
||||
|
||||
onSpanCountListener = { newSpanCount ->
|
||||
context.config.contactsGridColumnCount = newSpanCount
|
||||
}
|
||||
}
|
||||
|
||||
if (context.areSystemAnimationsEnabled) {
|
||||
binding.fragmentList.scheduleLayoutAnimation()
|
||||
}
|
||||
} else {
|
||||
currAdapter.viewType = viewType
|
||||
currAdapter.updateItems(allContacts)
|
||||
}
|
||||
}
|
||||
|
||||
fun columnCountChanged() {
|
||||
(binding.fragmentList.layoutManager as MyGridLayoutManager).spanCount = context!!.config.contactsGridColumnCount
|
||||
binding.fragmentList.adapter?.apply {
|
||||
notifyItemRangeChanged(0, allContacts.size)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sortByCustomOrder(favorites: List<Contact>): ArrayList<Contact> {
|
||||
val favoritesOrder = activity!!.config.favoritesContactsOrder
|
||||
|
||||
|
@ -137,7 +173,7 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
return ArrayList(sorted)
|
||||
}
|
||||
|
||||
private fun saveCustomOrderToPrefs(items: ArrayList<Contact>) {
|
||||
private fun saveCustomOrderToPrefs(items: List<Contact>) {
|
||||
activity?.apply {
|
||||
val orderIds = items.map { it.contactId }
|
||||
val orderGsonString = Gson().toJson(orderIds)
|
||||
|
@ -145,36 +181,12 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
}
|
||||
}
|
||||
|
||||
private fun callContact(simpleContact: Contact) {
|
||||
val phoneNumbers = simpleContact.phoneNumbers
|
||||
if (phoneNumbers.isEmpty()) {
|
||||
return
|
||||
} else if (phoneNumbers.size <= 1) {
|
||||
activity?.launchCallIntent(phoneNumbers.first().normalizedNumber)
|
||||
} else {
|
||||
val primaryNumber = simpleContact.phoneNumbers.find { it.isPrimary }
|
||||
if (primaryNumber != null) {
|
||||
activity?.launchCallIntent(primaryNumber.value)
|
||||
} else {
|
||||
val items = ArrayList<RadioItem>()
|
||||
phoneNumbers.forEachIndexed { index, phoneNumber ->
|
||||
val type = context.getPhoneNumberTypeText(phoneNumber.type, phoneNumber.label)
|
||||
items.add(RadioItem(index, "${phoneNumber.normalizedNumber} ($type)", phoneNumber.normalizedNumber))
|
||||
}
|
||||
|
||||
RadioGroupDialog(activity!!, items) {
|
||||
activity?.launchCallIntent(it as String)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupLetterFastscroller(contacts: ArrayList<Contact>) {
|
||||
letter_fastscroller.setupWithRecyclerView(fragment_list, { position ->
|
||||
private fun setupLetterFastScroller(contacts: List<Contact>) {
|
||||
binding.letterFastscroller.setupWithRecyclerView(binding.fragmentList, { position ->
|
||||
try {
|
||||
val name = contacts[position].getNameToDisplay()
|
||||
val character = if (name.isNotEmpty()) name.substring(0, 1) else ""
|
||||
FastScrollItemIndicator.Text(character.toUpperCase(Locale.getDefault()).normalizeString())
|
||||
FastScrollItemIndicator.Text(character.uppercase(Locale.getDefault()).normalizeString())
|
||||
} catch (e: Exception) {
|
||||
FastScrollItemIndicator.Text("")
|
||||
}
|
||||
|
@ -182,9 +194,9 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
}
|
||||
|
||||
override fun onSearchClosed() {
|
||||
fragment_placeholder.beVisibleIf(allContacts.isEmpty())
|
||||
(fragment_list.adapter as? ContactsAdapter)?.updateItems(allContacts)
|
||||
setupLetterFastscroller(allContacts)
|
||||
binding.fragmentPlaceholder.beVisibleIf(allContacts.isEmpty())
|
||||
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(allContacts)
|
||||
setupLetterFastScroller(allContacts)
|
||||
}
|
||||
|
||||
override fun onSearchQueryChanged(text: String) {
|
||||
|
@ -194,8 +206,21 @@ class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPa
|
|||
it.name.startsWith(text, true)
|
||||
}.toMutableList() as ArrayList<Contact>
|
||||
|
||||
fragment_placeholder.beVisibleIf(contacts.isEmpty())
|
||||
(fragment_list.adapter as? ContactsAdapter)?.updateItems(contacts, text)
|
||||
setupLetterFastscroller(contacts)
|
||||
binding.fragmentPlaceholder.beVisibleIf(contacts.isEmpty())
|
||||
(binding.fragmentList.adapter as? ContactsAdapter)?.updateItems(contacts, text)
|
||||
setupLetterFastScroller(contacts)
|
||||
}
|
||||
|
||||
private fun setViewType(viewType: Int) {
|
||||
val spanCount = context.config.contactsGridColumnCount
|
||||
|
||||
val layoutManager = if (viewType == VIEW_TYPE_GRID) {
|
||||
binding.letterFastscroller.beGone()
|
||||
MyGridLayoutManager(context, spanCount)
|
||||
} else {
|
||||
binding.letterFastscroller.beVisible()
|
||||
MyLinearLayoutManager(context)
|
||||
}
|
||||
binding.fragmentList.layoutManager = layoutManager
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,19 +6,23 @@ import android.widget.RelativeLayout
|
|||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.getProperTextColor
|
||||
import com.simplemobiletools.commons.extensions.getTextSize
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.dialer.activities.MainActivity
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.FragmentLettersLayoutBinding
|
||||
import com.simplemobiletools.dialer.databinding.FragmentRecentsBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.helpers.Config
|
||||
import kotlinx.android.synthetic.main.fragment_letters_layout.view.*
|
||||
import kotlinx.android.synthetic.main.fragment_recents.view.*
|
||||
|
||||
abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) : RelativeLayout(context, attributeSet) {
|
||||
abstract class MyViewPagerFragment<BINDING : MyViewPagerFragment.InnerBinding>(context: Context, attributeSet: AttributeSet) :
|
||||
RelativeLayout(context, attributeSet) {
|
||||
protected var activity: SimpleActivity? = null
|
||||
|
||||
protected lateinit var innerBinding: BINDING
|
||||
private lateinit var config: Config
|
||||
|
||||
fun setupFragment(activity: SimpleActivity) {
|
||||
|
@ -33,7 +37,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
|||
|
||||
fun startNameWithSurnameChanged(startNameWithSurname: Boolean) {
|
||||
if (this !is RecentsFragment) {
|
||||
(fragment_list.adapter as? ContactsAdapter)?.apply {
|
||||
(innerBinding.fragmentList?.adapter as? ContactsAdapter)?.apply {
|
||||
config.sorting = if (startNameWithSurname) SORT_BY_SURNAME else SORT_BY_FIRST_NAME
|
||||
(this@MyViewPagerFragment.activity!! as MainActivity).refreshFragments()
|
||||
}
|
||||
|
@ -41,8 +45,22 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
|||
}
|
||||
|
||||
fun finishActMode() {
|
||||
(fragment_list?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
|
||||
(recents_list?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
|
||||
(innerBinding.fragmentList?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
|
||||
(innerBinding.recentsList?.adapter as? MyRecyclerViewAdapter)?.finishActMode()
|
||||
}
|
||||
|
||||
fun fontSizeChanged() {
|
||||
if (this is RecentsFragment) {
|
||||
(innerBinding.recentsList?.adapter as? RecentCallsAdapter)?.apply {
|
||||
fontSize = activity.getTextSize()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
(innerBinding.fragmentList?.adapter as? ContactsAdapter)?.apply {
|
||||
fontSize = activity.getTextSize()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun setupFragment()
|
||||
|
@ -52,4 +70,19 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
|||
abstract fun onSearchClosed()
|
||||
|
||||
abstract fun onSearchQueryChanged(text: String)
|
||||
|
||||
interface InnerBinding {
|
||||
val fragmentList: MyRecyclerView?
|
||||
val recentsList: MyRecyclerView?
|
||||
}
|
||||
|
||||
class LettersInnerBinding(val binding: FragmentLettersLayoutBinding) : InnerBinding {
|
||||
override val fragmentList: MyRecyclerView = binding.fragmentList
|
||||
override val recentsList = null
|
||||
}
|
||||
|
||||
class RecentsInnerBinding(val binding: FragmentRecentsBinding) : InnerBinding {
|
||||
override val fragmentList = null
|
||||
override val recentsList = binding.recentsList
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,17 +8,29 @@ import com.simplemobiletools.commons.helpers.ContactsHelper
|
|||
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
|
||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.dialer.R
|
||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
|
||||
import com.simplemobiletools.dialer.databinding.FragmentRecentsBinding
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.helpers.MIN_RECENTS_THRESHOLD
|
||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
||||
import com.simplemobiletools.dialer.models.RecentCall
|
||||
import kotlinx.android.synthetic.main.fragment_recents.view.*
|
||||
|
||||
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
|
||||
private var allRecentCalls = ArrayList<RecentCall>()
|
||||
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment<MyViewPagerFragment.RecentsInnerBinding>(context, attributeSet),
|
||||
RefreshItemsListener {
|
||||
private lateinit var binding: FragmentRecentsBinding
|
||||
private var allRecentCalls = listOf<RecentCall>()
|
||||
private var recentsAdapter: RecentCallsAdapter? = null
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
binding = FragmentRecentsBinding.bind(this)
|
||||
innerBinding = RecentsInnerBinding(binding)
|
||||
}
|
||||
|
||||
override fun setupFragment() {
|
||||
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
||||
|
@ -27,8 +39,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
R.string.could_not_access_the_call_history
|
||||
}
|
||||
|
||||
recents_placeholder.text = context.getString(placeholderResId)
|
||||
recents_placeholder_2.apply {
|
||||
binding.recentsPlaceholder.text = context.getString(placeholderResId)
|
||||
binding.recentsPlaceholder2.apply {
|
||||
underlineText()
|
||||
setOnClickListener {
|
||||
requestCallLogPermission()
|
||||
|
@ -37,10 +49,10 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
}
|
||||
|
||||
override fun setupColors(textColor: Int, primaryColor: Int, properPrimaryColor: Int) {
|
||||
recents_placeholder.setTextColor(textColor)
|
||||
recents_placeholder_2.setTextColor(properPrimaryColor)
|
||||
binding.recentsPlaceholder.setTextColor(textColor)
|
||||
binding.recentsPlaceholder2.setTextColor(properPrimaryColor)
|
||||
|
||||
(recents_list?.adapter as? RecentCallsAdapter)?.apply {
|
||||
recentsAdapter?.apply {
|
||||
initDrawables()
|
||||
updateTextColor(textColor)
|
||||
}
|
||||
|
@ -49,36 +61,14 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
override fun refreshItems(callback: (() -> Unit)?) {
|
||||
val privateCursor = context?.getMyContactsCursor(false, true)
|
||||
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
||||
RecentsHelper(context).getRecentCalls(groupSubsequentCalls) { recents ->
|
||||
ContactsHelper(context).getContacts { contacts ->
|
||||
val querySize = allRecentCalls.size.coerceAtLeast(MIN_RECENTS_THRESHOLD)
|
||||
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||
|
||||
recents.filter { it.phoneNumber == it.name }.forEach { recent ->
|
||||
var wasNameFilled = false
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
|
||||
if (privateContact != null) {
|
||||
recent.name = privateContact.getNameToDisplay()
|
||||
wasNameFilled = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasNameFilled) {
|
||||
val contact = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
|
||||
if (contact != null) {
|
||||
recent.name = contact.getNameToDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
allRecentCalls = recents
|
||||
|
||||
// hide private contacts from recent calls
|
||||
if (SMT_PRIVATE in context.baseConfig.ignoredContactSources) {
|
||||
allRecentCalls = recents.filterNot { recent ->
|
||||
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
|
||||
recent.phoneNumber in privateNumbers
|
||||
} as ArrayList
|
||||
}
|
||||
.setNamesIfEmpty(contacts, privateContacts)
|
||||
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
|
||||
|
||||
activity?.runOnUiThread {
|
||||
gotRecents(allRecentCalls)
|
||||
|
@ -87,19 +77,22 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
}
|
||||
}
|
||||
|
||||
private fun gotRecents(recents: ArrayList<RecentCall>) {
|
||||
private fun gotRecents(recents: List<RecentCall>) {
|
||||
if (recents.isEmpty()) {
|
||||
recents_placeholder.beVisible()
|
||||
recents_placeholder_2.beGoneIf(context.hasPermission(PERMISSION_READ_CALL_LOG))
|
||||
recents_list.beGone()
|
||||
binding.apply {
|
||||
recentsPlaceholder.beVisible()
|
||||
recentsPlaceholder2.beGoneIf(context.hasPermission(PERMISSION_READ_CALL_LOG))
|
||||
recentsList.beGone()
|
||||
}
|
||||
} else {
|
||||
recents_placeholder.beGone()
|
||||
recents_placeholder_2.beGone()
|
||||
recents_list.beVisible()
|
||||
binding.apply {
|
||||
recentsPlaceholder.beGone()
|
||||
recentsPlaceholder2.beGone()
|
||||
recentsList.beVisible()
|
||||
}
|
||||
|
||||
val currAdapter = recents_list.adapter
|
||||
if (currAdapter == null) {
|
||||
RecentCallsAdapter(activity as SimpleActivity, recents, recents_list, this, true) {
|
||||
if (binding.recentsList.adapter == null) {
|
||||
recentsAdapter = RecentCallsAdapter(activity as SimpleActivity, recents.toMutableList(), binding.recentsList, this, true) {
|
||||
val recentCall = it as RecentCall
|
||||
if (context.config.showCallConfirmation) {
|
||||
CallConfirmationDialog(activity as SimpleActivity, recentCall.name) {
|
||||
|
@ -108,15 +101,43 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
} else {
|
||||
activity?.launchCallIntent(recentCall.phoneNumber)
|
||||
}
|
||||
}.apply {
|
||||
recents_list.adapter = this
|
||||
}
|
||||
|
||||
binding.recentsList.adapter = recentsAdapter
|
||||
|
||||
if (context.areSystemAnimationsEnabled) {
|
||||
recents_list.scheduleLayoutAnimation()
|
||||
binding.recentsList.scheduleLayoutAnimation()
|
||||
}
|
||||
|
||||
binding.recentsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
|
||||
override fun updateTop() {}
|
||||
|
||||
override fun updateBottom() {
|
||||
getMoreRecentCalls()
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
(currAdapter as RecentCallsAdapter).updateItems(recents)
|
||||
recentsAdapter?.updateItems(recents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMoreRecentCalls() {
|
||||
val privateCursor = context?.getMyContactsCursor(false, true)
|
||||
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
||||
val querySize = allRecentCalls.size.plus(MIN_RECENTS_THRESHOLD)
|
||||
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||
|
||||
allRecentCalls = recents
|
||||
.setNamesIfEmpty(contacts, privateContacts)
|
||||
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
|
||||
|
||||
activity?.runOnUiThread {
|
||||
gotRecents(allRecentCalls)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,8 +145,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
private fun requestCallLogPermission() {
|
||||
activity?.handlePermission(PERMISSION_READ_CALL_LOG) {
|
||||
if (it) {
|
||||
recents_placeholder.text = context.getString(R.string.no_previous_calls)
|
||||
recents_placeholder_2.beGone()
|
||||
binding.recentsPlaceholder.text = context.getString(R.string.no_previous_calls)
|
||||
binding.recentsPlaceholder2.beGone()
|
||||
|
||||
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
||||
RecentsHelper(context).getRecentCalls(groupSubsequentCalls) { recents ->
|
||||
|
@ -138,8 +159,8 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
}
|
||||
|
||||
override fun onSearchClosed() {
|
||||
recents_placeholder.beVisibleIf(allRecentCalls.isEmpty())
|
||||
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(allRecentCalls)
|
||||
binding.recentsPlaceholder.beVisibleIf(allRecentCalls.isEmpty())
|
||||
recentsAdapter?.updateItems(allRecentCalls)
|
||||
}
|
||||
|
||||
override fun onSearchQueryChanged(text: String) {
|
||||
|
@ -149,7 +170,37 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||
it.name.startsWith(text, true)
|
||||
}.toMutableList() as ArrayList<RecentCall>
|
||||
|
||||
recents_placeholder.beVisibleIf(recentCalls.isEmpty())
|
||||
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(recentCalls, text)
|
||||
binding.recentsPlaceholder.beVisibleIf(recentCalls.isEmpty())
|
||||
recentsAdapter?.updateItems(recentCalls, text)
|
||||
}
|
||||
}
|
||||
|
||||
// hide private contacts from recent calls
|
||||
private fun List<RecentCall>.hidePrivateContacts(privateContacts: List<Contact>, shouldHide: Boolean): List<RecentCall> {
|
||||
return if (shouldHide) {
|
||||
filterNot { recent ->
|
||||
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
|
||||
recent.phoneNumber in privateNumbers
|
||||
}
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<RecentCall>.setNamesIfEmpty(contacts: List<Contact>, privateContacts: List<Contact>): ArrayList<RecentCall> {
|
||||
val contactsWithNumbers = contacts.filter { it.phoneNumbers.isNotEmpty() }
|
||||
return map { recent ->
|
||||
if (recent.phoneNumber == recent.name) {
|
||||
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
|
||||
val contact = contactsWithNumbers.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
|
||||
|
||||
when {
|
||||
privateContact != null -> recent.copy(name = privateContact.getNameToDisplay())
|
||||
contact != null -> recent.copy(name = contact.getNameToDisplay())
|
||||
else -> recent
|
||||
}
|
||||
} else {
|
||||
recent
|
||||
}
|
||||
} as ArrayList
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ fun getCallContact(context: Context, call: Call?, callback: (CallContact) -> Uni
|
|||
val uri = Uri.decode(handle)
|
||||
if (uri.startsWith("tel:")) {
|
||||
val number = uri.substringAfter("tel:")
|
||||
ContactsHelper(context).getContacts{ contacts ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
contacts.addAll(privateContacts)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.simplemobiletools.dialer.helpers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.telecom.Call
|
||||
import android.telecom.CallAudioState
|
||||
import android.telecom.InCallService
|
||||
import android.telecom.VideoProfile
|
||||
import com.simplemobiletools.dialer.extensions.config
|
||||
import com.simplemobiletools.dialer.extensions.getStateCompat
|
||||
import com.simplemobiletools.dialer.extensions.hasCapability
|
||||
import com.simplemobiletools.dialer.extensions.isConference
|
||||
|
@ -202,13 +200,11 @@ class CallManager {
|
|||
|
||||
fun getState() = getPrimaryCall()?.getStateCompat()
|
||||
|
||||
fun keypad(context: Context, char: Char) {
|
||||
if (context.config.dialpadBeeps) {
|
||||
fun keypad(char: Char) {
|
||||
call?.playDtmfTone(char)
|
||||
Handler().postDelayed({
|
||||
call?.stopDtmfTone()
|
||||
}, DIALPAD_TONE_LENGTH_MS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ class CallNotificationManager(private val context: Context) {
|
|||
val builder = NotificationCompat.Builder(context, channelId)
|
||||
.setSmallIcon(R.drawable.ic_phone_vector)
|
||||
.setContentIntent(openAppPendingIntent)
|
||||
.setPriority(if (isHighPriority) NotificationCompat.PRIORITY_MAX else NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setPriority(if (isHighPriority) NotificationManager.IMPORTANCE_HIGH else NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setCategory(Notification.CATEGORY_CALL)
|
||||
.setCustomContentView(collapsedView)
|
||||
.setOngoing(true)
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package com.simplemobiletools.dialer.helpers
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.telecom.PhoneAccountHandle
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
import com.simplemobiletools.dialer.extensions.getPhoneAccountHandleModel
|
||||
import com.simplemobiletools.dialer.extensions.putPhoneAccountHandle
|
||||
import com.simplemobiletools.dialer.models.SpeedDial
|
||||
|
||||
class Config(context: Context) : BaseConfig(context) {
|
||||
companion object {
|
||||
fun newInstance(context: Context) = Config(context)
|
||||
}
|
||||
|
||||
fun getSpeedDialValues(): ArrayList<SpeedDial> {
|
||||
val speedDialType = object : TypeToken<List<SpeedDial>>() {}.type
|
||||
val speedDialValues = Gson().fromJson<ArrayList<SpeedDial>>(speedDial, speedDialType) ?: ArrayList(1)
|
||||
|
@ -25,15 +29,27 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
return speedDialValues
|
||||
}
|
||||
|
||||
fun saveCustomSIM(number: String, SIMlabel: String) {
|
||||
prefs.edit().putString(REMEMBER_SIM_PREFIX + number, Uri.encode(SIMlabel)).apply()
|
||||
fun saveCustomSIM(number: String, handle: PhoneAccountHandle) {
|
||||
prefs.edit().putPhoneAccountHandle(REMEMBER_SIM_PREFIX + number, handle).apply()
|
||||
}
|
||||
|
||||
fun getCustomSIM(number: String) = prefs.getString(REMEMBER_SIM_PREFIX + number, "")
|
||||
fun getCustomSIM(number: String): PhoneAccountHandle? {
|
||||
val myPhoneAccountHandle = prefs.getPhoneAccountHandleModel(REMEMBER_SIM_PREFIX + number, null)
|
||||
return if (myPhoneAccountHandle != null) {
|
||||
val packageName = myPhoneAccountHandle.packageName
|
||||
val className = myPhoneAccountHandle.className
|
||||
val componentName = ComponentName(packageName, className)
|
||||
val id = myPhoneAccountHandle.id
|
||||
PhoneAccountHandle(componentName, id)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun removeCustomSIM(number: String) {
|
||||
prefs.edit().remove(REMEMBER_SIM_PREFIX + number).apply()
|
||||
}
|
||||
|
||||
var showTabs: Int
|
||||
get() = prefs.getInt(SHOW_TABS, ALL_TABS_MASK)
|
||||
set(showTabs) = prefs.edit().putInt(SHOW_TABS, showTabs).apply()
|
||||
|
|
|
@ -19,6 +19,7 @@ const val DIALPAD_VIBRATION = "dialpad_vibration"
|
|||
const val DIALPAD_BEEPS = "dialpad_beeps"
|
||||
const val HIDE_DIALPAD_NUMBERS = "hide_dialpad_numbers"
|
||||
const val ALWAYS_SHOW_FULLSCREEN = "always_show_fullscreen"
|
||||
|
||||
const val ALL_TABS_MASK = TAB_CONTACTS or TAB_FAVORITES or TAB_CALL_HISTORY
|
||||
|
||||
val tabsList = arrayListOf(TAB_CONTACTS, TAB_FAVORITES, TAB_CALL_HISTORY)
|
||||
|
@ -28,3 +29,5 @@ const val ACCEPT_CALL = PATH + "accept_call"
|
|||
const val DECLINE_CALL = PATH + "decline_call"
|
||||
|
||||
const val DIALPAD_TONE_LENGTH_MS = 150L // The length of DTMF tones in milliseconds
|
||||
|
||||
const val MIN_RECENTS_THRESHOLD = 30
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.simplemobiletools.dialer.helpers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.provider.CallLog.Calls
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
|
@ -13,10 +14,10 @@ import com.simplemobiletools.dialer.models.RecentCall
|
|||
|
||||
class RecentsHelper(private val context: Context) {
|
||||
private val COMPARABLE_PHONE_NUMBER_LENGTH = 9
|
||||
private val QUERY_LIMIT = "200"
|
||||
private val QUERY_LIMIT = 200
|
||||
private val contentUri = Calls.CONTENT_URI
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getRecentCalls(groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
|
||||
fun getRecentCalls(groupSubsequentCalls: Boolean, maxSize: Int = QUERY_LIMIT, callback: (List<RecentCall>) -> Unit) {
|
||||
val privateCursor = context.getMyContactsCursor(false, true)
|
||||
ensureBackgroundThread {
|
||||
if (!context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
||||
|
@ -24,27 +25,26 @@ class RecentsHelper(private val context: Context) {
|
|||
return@ensureBackgroundThread
|
||||
}
|
||||
|
||||
ContactsHelper(context).getContacts(false) { contacts ->
|
||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
contacts.addAll(privateContacts)
|
||||
}
|
||||
|
||||
getRecents(contacts, groupSubsequentCalls, callback)
|
||||
getRecents(contacts, groupSubsequentCalls, maxSize, callback = callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun getRecents(contacts: ArrayList<Contact>, groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
|
||||
private fun getRecents(contacts: List<Contact>, groupSubsequentCalls: Boolean, maxSize: Int, callback: (List<RecentCall>) -> Unit) {
|
||||
|
||||
var recentCalls = ArrayList<RecentCall>()
|
||||
val recentCalls = mutableListOf<RecentCall>()
|
||||
var previousRecentCallFrom = ""
|
||||
var previousStartTS = 0
|
||||
val contactsNumbersMap = HashMap<String, String>()
|
||||
val contactPhotosMap = HashMap<String, String>()
|
||||
|
||||
val uri = Calls.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
Calls._ID,
|
||||
Calls.NUMBER,
|
||||
|
@ -63,14 +63,14 @@ class RecentsHelper(private val context: Context) {
|
|||
|
||||
val cursor = if (isNougatPlus()) {
|
||||
// https://issuetracker.google.com/issues/175198972?pli=1#comment6
|
||||
val limitedUri = uri.buildUpon()
|
||||
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT)
|
||||
val limitedUri = contentUri.buildUpon()
|
||||
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT.toString())
|
||||
.build()
|
||||
val sortOrder = "${Calls._ID} DESC"
|
||||
val sortOrder = "${Calls.DATE} DESC"
|
||||
context.contentResolver.query(limitedUri, projection, null, null, sortOrder)
|
||||
} else {
|
||||
val sortOrder = "${Calls._ID} DESC LIMIT $QUERY_LIMIT"
|
||||
context.contentResolver.query(uri, projection, null, null, sortOrder)
|
||||
val sortOrder = "${Calls.DATE} DESC LIMIT $QUERY_LIMIT"
|
||||
context.contentResolver.query(contentUri, projection, null, null, sortOrder)
|
||||
}
|
||||
|
||||
val contactsWithMultipleNumbers = contacts.filter { it.phoneNumbers.size > 1 }
|
||||
|
@ -82,16 +82,25 @@ class RecentsHelper(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
cursor?.use {
|
||||
if (!cursor.moveToFirst()) {
|
||||
return@use
|
||||
}
|
||||
|
||||
do {
|
||||
val id = cursor.getIntValue(Calls._ID)
|
||||
val number = cursor.getStringValue(Calls.NUMBER) ?: continue
|
||||
var name = cursor.getStringValue(Calls.CACHED_NAME)
|
||||
if (name == null || name.isEmpty()) {
|
||||
name = number
|
||||
var isUnknownNumber = false
|
||||
val number = cursor.getStringValueOrNull(Calls.NUMBER)
|
||||
if (number == null || number == "-1") {
|
||||
isUnknownNumber = true
|
||||
}
|
||||
|
||||
if (name == number) {
|
||||
var name = cursor.getStringValueOrNull(Calls.CACHED_NAME)
|
||||
if (name.isNullOrEmpty() || name == "-1") {
|
||||
name = number.orEmpty()
|
||||
}
|
||||
|
||||
if (name == number && !isUnknownNumber) {
|
||||
if (contactsNumbersMap.containsKey(number)) {
|
||||
name = contactsNumbersMap[number]!!
|
||||
} else {
|
||||
|
@ -100,7 +109,10 @@ class RecentsHelper(private val context: Context) {
|
|||
name = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { contact ->
|
||||
val curNumber = contact.phoneNumbers.first().normalizedNumber
|
||||
if (curNumber.length >= COMPARABLE_PHONE_NUMBER_LENGTH) {
|
||||
if (curNumber.substring(curNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH) == normalizedNumber.substring(normalizedNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH)) {
|
||||
if (curNumber.substring(curNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH) == normalizedNumber.substring(
|
||||
normalizedNumber.length - COMPARABLE_PHONE_NUMBER_LENGTH
|
||||
)
|
||||
) {
|
||||
contactsNumbersMap[number] = contact.getNameToDisplay()
|
||||
return@firstOrNull true
|
||||
}
|
||||
|
@ -111,12 +123,12 @@ class RecentsHelper(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if (name.isEmpty()) {
|
||||
if (name.isEmpty() || name == "-1") {
|
||||
name = context.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
var photoUri = cursor.getStringValue(Calls.CACHED_PHOTO_URI) ?: ""
|
||||
if (photoUri.isEmpty()) {
|
||||
if (photoUri.isEmpty() && !number.isNullOrEmpty()) {
|
||||
if (contactPhotosMap.containsKey(number)) {
|
||||
photoUri = contactPhotosMap[number]!!
|
||||
} else {
|
||||
|
@ -139,7 +151,7 @@ class RecentsHelper(private val context: Context) {
|
|||
val type = cursor.getIntValue(Calls.TYPE)
|
||||
val accountId = cursor.getStringValue(Calls.PHONE_ACCOUNT_ID)
|
||||
val simID = accountIdToSimIDMap[accountId] ?: -1
|
||||
val neighbourIDs = ArrayList<Int>()
|
||||
val neighbourIDs = mutableListOf<Int>()
|
||||
var specificNumber = ""
|
||||
var specificType = ""
|
||||
|
||||
|
@ -153,7 +165,20 @@ class RecentsHelper(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
val recentCall = RecentCall(id, number, name, photoUri, startTS, duration, type, neighbourIDs, simID, specificNumber, specificType)
|
||||
val recentCall = RecentCall(
|
||||
id = id,
|
||||
phoneNumber = number.orEmpty(),
|
||||
name = name,
|
||||
photoUri = photoUri,
|
||||
startTS = startTS,
|
||||
duration = duration,
|
||||
type = type,
|
||||
neighbourIDs = neighbourIDs,
|
||||
simID = simID,
|
||||
specificNumber = specificNumber,
|
||||
specificType = specificType,
|
||||
isUnknownNumber = isUnknownNumber
|
||||
)
|
||||
|
||||
// if we have multiple missed calls from the same number, show it just once
|
||||
if (!groupSubsequentCalls || "$number$name$simID" != previousRecentCallFrom) {
|
||||
|
@ -163,23 +188,23 @@ class RecentsHelper(private val context: Context) {
|
|||
}
|
||||
|
||||
previousRecentCallFrom = "$number$name$simID"
|
||||
} while (cursor.moveToNext())
|
||||
} while (cursor.moveToNext() && recentCalls.size < maxSize)
|
||||
}
|
||||
cursor?.close()
|
||||
|
||||
val blockedNumbers = context.getBlockedNumbers()
|
||||
recentCalls = recentCalls.filter { !context.isNumberBlocked(it.phoneNumber, blockedNumbers) }.toMutableList() as ArrayList<RecentCall>
|
||||
callback(recentCalls)
|
||||
|
||||
val recentResult = recentCalls
|
||||
.filter { !context.isNumberBlocked(it.phoneNumber, blockedNumbers) }
|
||||
|
||||
callback(recentResult)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun removeRecentCalls(ids: ArrayList<Int>, callback: () -> Unit) {
|
||||
fun removeRecentCalls(ids: List<Int>, callback: () -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
val uri = Calls.CONTENT_URI
|
||||
ids.chunked(30).forEach { chunk ->
|
||||
val selection = "${Calls._ID} IN (${getQuestionMarks(chunk.size)})"
|
||||
val selectionArgs = chunk.map { it.toString() }.toTypedArray()
|
||||
context.contentResolver.delete(uri, selection, selectionArgs)
|
||||
context.contentResolver.delete(contentUri, selection, selectionArgs)
|
||||
}
|
||||
callback()
|
||||
}
|
||||
|
@ -190,8 +215,30 @@ class RecentsHelper(private val context: Context) {
|
|||
activity.handlePermission(PERMISSION_WRITE_CALL_LOG) {
|
||||
if (it) {
|
||||
ensureBackgroundThread {
|
||||
val uri = Calls.CONTENT_URI
|
||||
context.contentResolver.delete(uri, null, null)
|
||||
context.contentResolver.delete(contentUri, null, null)
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun restoreRecentCalls(activity: SimpleActivity, objects: List<RecentCall>, callback: () -> Unit) {
|
||||
activity.handlePermission(PERMISSION_WRITE_CALL_LOG) {
|
||||
if (it) {
|
||||
ensureBackgroundThread {
|
||||
val values = objects
|
||||
.sortedBy { it.startTS }
|
||||
.map {
|
||||
ContentValues().apply {
|
||||
put(Calls.NUMBER, it.phoneNumber)
|
||||
put(Calls.TYPE, it.type)
|
||||
put(Calls.DATE, it.startTS.toLong() * 1000L)
|
||||
put(Calls.DURATION, it.duration)
|
||||
put(Calls.CACHED_NAME, it.name)
|
||||
}
|
||||
}.toTypedArray()
|
||||
|
||||
context.contentResolver.bulkInsert(contentUri, values)
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.simplemobiletools.dialer.models
|
||||
|
||||
data class PhoneAccountHandleModel(
|
||||
val packageName: String,
|
||||
val className: String,
|
||||
val id: String
|
||||
)
|
|
@ -3,10 +3,24 @@ package com.simplemobiletools.dialer.models
|
|||
import android.telephony.PhoneNumberUtils
|
||||
import com.simplemobiletools.commons.extensions.normalizePhoneNumber
|
||||
|
||||
// model used at displaying recent calls, for contacts with multiple numbers specifify the number and type
|
||||
/**
|
||||
* Used at displaying recent calls.
|
||||
* For contacts with multiple numbers specify the number and type
|
||||
*/
|
||||
@kotlinx.serialization.Serializable
|
||||
data class RecentCall(
|
||||
var id: Int, var phoneNumber: String, var name: String, var photoUri: String, var startTS: Int, var duration: Int, var type: Int,
|
||||
var neighbourIDs: ArrayList<Int>, val simID: Int, var specificNumber: String, var specificType: String
|
||||
val id: Int,
|
||||
val phoneNumber: String,
|
||||
val name: String,
|
||||
val photoUri: String,
|
||||
val startTS: Int,
|
||||
val duration: Int,
|
||||
val type: Int,
|
||||
val neighbourIDs: MutableList<Int>,
|
||||
val simID: Int,
|
||||
val specificNumber: String,
|
||||
val specificType: String,
|
||||
val isUnknownNumber: Boolean,
|
||||
) {
|
||||
fun doesContainPhoneNumber(text: String): Boolean {
|
||||
val normalizedText = text.normalizePhoneNumber()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.simplemobiletools.dialer.services
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.telecom.Call
|
||||
import android.telecom.CallScreeningService
|
||||
|
@ -15,17 +14,27 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
|||
class SimpleCallScreeningService : CallScreeningService() {
|
||||
|
||||
override fun onScreenCall(callDetails: Call.Details) {
|
||||
val number = Uri.decode(callDetails.handle?.toString())?.substringAfter("tel:")
|
||||
if (number != null && isNumberBlocked(number.normalizePhoneNumber())) {
|
||||
respondToCall(callDetails, isBlocked = true)
|
||||
} else if (number != null && baseConfig.blockUnknownNumbers) {
|
||||
val simpleContactsHelper = SimpleContactsHelper(this)
|
||||
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
||||
simpleContactsHelper.exists(number, privateCursor) { exists ->
|
||||
respondToCall(callDetails, isBlocked = !exists)
|
||||
val number = callDetails.handle?.schemeSpecificPart
|
||||
when {
|
||||
number != null && isNumberBlocked(number.normalizePhoneNumber()) -> {
|
||||
respondToCall(callDetails, isBlocked = true)
|
||||
}
|
||||
|
||||
number != null && baseConfig.blockUnknownNumbers -> {
|
||||
val simpleContactsHelper = SimpleContactsHelper(this)
|
||||
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
||||
simpleContactsHelper.exists(number, privateCursor) { exists ->
|
||||
respondToCall(callDetails, isBlocked = !exists)
|
||||
}
|
||||
}
|
||||
|
||||
number == null && baseConfig.blockHiddenNumbers -> {
|
||||
respondToCall(callDetails, isBlocked = true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
respondToCall(callDetails, isBlocked = false)
|
||||
}
|
||||
} else {
|
||||
respondToCall(callDetails, isBlocked = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@
|
|||
android:layout_width="@dimen/dialpad_button_size"
|
||||
android:layout_height="@dimen/dialpad_button_size"
|
||||
android:contentDescription="@string/end_call"
|
||||
android:src="@drawable/ic_call_decline"
|
||||
android:src="@drawable/ic_call_end"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -318,7 +318,7 @@
|
|||
android:clickable="false"
|
||||
android:contentDescription="@string/decline_call"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_call_decline"
|
||||
android:src="@drawable/ic_call_end"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/call_draggable"
|
||||
app:layout_constraintEnd_toStartOf="@+id/call_draggable"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
|
|
|
@ -393,6 +393,47 @@
|
|||
android:text="@string/show_incoming_calls_full_screen" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/settings_migration_divider"
|
||||
layout="@layout/divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_migration_section_label"
|
||||
style="@style/SettingsSectionLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/migrating" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_export_calls_holder"
|
||||
style="@style/SettingsHolderTextViewOneLinerStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_export_calls"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/export_call_history" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_import_calls_holder"
|
||||
style="@style/SettingsHolderTextViewOneLinerStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_import_calls"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/import_call_history" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/export_contacts_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/export_call_history_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextInputLayout
|
||||
android:id="@+id/export_call_history_filename_hint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:hint="@string/filename_without_json"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/export_call_history_filename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="@dimen/bigger_text_size" />
|
||||
|
||||
</com.simplemobiletools.commons.views.MyTextInputLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -5,10 +5,33 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySearchMenu
|
||||
android:id="@+id/contact_search_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/contacts_empty_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_search_view"
|
||||
android:alpha="0.8"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:text="@string/no_contacts_found"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:textStyle="italic"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||
android:id="@+id/select_contact_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contacts_empty_placeholder"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="none"
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
|
||||
|
@ -17,6 +40,7 @@
|
|||
android:id="@+id/letter_fastscroller"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_search_view"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:paddingTop="@dimen/big_margin"
|
||||
android:paddingBottom="@dimen/big_margin" />
|
||||
|
@ -29,5 +53,4 @@
|
|||
android:layout_alignBottom="@+id/letter_fastscroller"
|
||||
android:layout_marginEnd="@dimen/activity_margin"
|
||||
android:layout_toStartOf="@+id/letter_fastscroller" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
android:layout_marginEnd="@dimen/small_margin"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:textDirection="locale"
|
||||
android:textAlignment="viewStart"
|
||||
android:textDirection="locale"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
app:layout_constraintBottom_toTopOf="@id/item_recents_date_time"
|
||||
app:layout_constraintEnd_toStartOf="@+id/overflow_menu_icon"
|
||||
app:layout_constraintStart_toEndOf="@+id/item_recents_image"
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
android:showAsAction="always"
|
||||
android:title="@string/send_sms"
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/cab_block_unblock_contact"
|
||||
android:icon="@drawable/ic_minus_circle_vector"
|
||||
android:title="@string/block_contact"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/cab_create_shortcut"
|
||||
android:showAsAction="never"
|
||||
|
|
|
@ -24,6 +24,16 @@
|
|||
android:icon="@drawable/ic_delete_vector"
|
||||
android:title="@string/clear_call_history"
|
||||
app:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/change_view_type"
|
||||
android:icon="@drawable/ic_change_view_vector"
|
||||
android:title="@string/change_view_type"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/column_count"
|
||||
android:icon="@drawable/ic_column_count_vector"
|
||||
android:title="@string/column_count"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/settings"
|
||||
android:icon="@drawable/ic_settings_cog_vector"
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">استبدل التمرير عند الرد على المكالمات الواردة بالنقر</string>
|
||||
<string name="show_incoming_calls_full_screen">عرض المكالمات الواردة دائما في وضع ملء الشاشة</string>
|
||||
<string name="hide_dialpad_numbers">اخفي ارقام لوحت المفاتيح</string>
|
||||
<string name="export_call_history">تصدير سجل المكالمات</string>
|
||||
<string name="import_call_history">استيراد سجل المكالمات</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">أسمع مكالمات واردة، ولكن الشاشة لا تعمل. ماذا أفعل؟</string>
|
||||
<string name="faq_1_text">يمكن أن يكون لمثل هذه المشكلات العديد من الأسباب الخاصة بالجهاز والنظام ، والتي يصعب تحديدها بشكل عام. يجب أن تنظر حولك في إعدادات جهازك وتأكد من السماح للتطبيق بالظهور عندما يكون في الخلفية والسماح بالعرض فوق التطبيقات الأخرى.</string>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<string name="asterisk">Зорачка</string>
|
||||
<string name="hashtag">Рашотка</string>
|
||||
<string name="call_number">Нумар выкліку</string>
|
||||
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
|
||||
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
|
||||
<string name="dialpad_beeps">Уключыць гукавыя сігналы пры націсканні кнопак панэлі набору</string>
|
||||
<string name="dialpad_vibrations">Уключыць вібрацыю пры націсканні кнопак панэлі набору</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Тэлефон</string>
|
||||
<string name="accept">Прыняць</string>
|
||||
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Выкарыстоўваць націсканне замест перацягвання пры адказе на ўваходныя выклікі</string>
|
||||
<string name="show_incoming_calls_full_screen">Заўсёды паказваць уваходныя выклікі ў поўнаэкранным рэжыме</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<string name="asterisk">Звездичка</string>
|
||||
<string name="hashtag">Диез</string>
|
||||
<string name="call_number">Номер</string>
|
||||
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
|
||||
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
|
||||
<string name="dialpad_beeps">Активиране на звукови сигнали при докосване на бутоните на клавиатурата за набиране</string>
|
||||
<string name="dialpad_vibrations">Активиране на вибрации при докосване на бутоните на клавиатурата за набиране</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Телефон</string>
|
||||
<string name="accept">Приемане</string>
|
||||
|
@ -54,13 +54,13 @@
|
|||
<string name="call_add">Добавяне на обаждане</string>
|
||||
<string name="conference_manage">Управление на конферентен разговор</string>
|
||||
<string name="conference">Конференция</string>
|
||||
<string name="audio_route_speaker">Speaker</string>
|
||||
<string name="audio_route_earpiece">Earpiece</string>
|
||||
<string name="audio_route_speaker">Високоговорител</string>
|
||||
<string name="audio_route_earpiece">Слушалки</string>
|
||||
<string name="audio_route_bluetooth">Bluetooth</string>
|
||||
<string name="audio_route_wired_headset">Wired Headset</string>
|
||||
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
|
||||
<string name="choose_audio_route">Choose audio route</string>
|
||||
<string name="calling_blocked_number">The number you are calling is blocked</string>
|
||||
<string name="audio_route_wired_headset">Слушалки с кабел</string>
|
||||
<string name="audio_route_wired_or_earpiece">Жични или безжични слушалки</string>
|
||||
<string name="choose_audio_route">Изберете аудио източник</string>
|
||||
<string name="calling_blocked_number">Номерът, на който звъните, е блокиран</string>
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">Бързо набиране</string>
|
||||
<string name="manage_speed_dial">Управление на бързото набиране</string>
|
||||
|
@ -70,14 +70,15 @@
|
|||
<string name="open_dialpad_by_default">При стартиране се отваря панела за набиране</string>
|
||||
<string name="disable_proximity_sensor">Изключване на сензора за близост по време на обаждания</string>
|
||||
<string name="disable_swipe_to_answer">Смяна на плъзгането с докосване при отговаряне на обаждания</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
|
||||
<string name="show_incoming_calls_full_screen">Винаги показвай входящите повиквания на цял екран</string>
|
||||
<string name="hide_dialpad_numbers">Скриване на номерата на клавиатурата за набиране</string>
|
||||
<string name="export_call_history">Експортиране на хронология на обажданията</string>
|
||||
<string name="import_call_history">Импортиране на хронология на обажданията</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
<string name="faq_1_title">Чувам входящи повиквания, но екранът не се включва. Какво мога да направя\?</string>
|
||||
<string name="faq_1_text">Такива проблеми могат да имат много специфични за устройството и системата причини, трудно е да се каже като цяло. Трябва да се огледате в настройките на вашето устройство и да се уверите, че на приложението е разрешено да изскача, когато е във фонов режим и да позволява показване върху други приложения.</string>
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Substitueix el lliscament en respondre a les trucades entrants per fer clic</string>
|
||||
<string name="show_incoming_calls_full_screen">Mostra sempre les trucades entrants a pantalla completa</string>
|
||||
<string name="hide_dialpad_numbers">Oculta els números del teclat numèric</string>
|
||||
<string name="export_call_history">Exporta l\'historial de trucades</string>
|
||||
<string name="import_call_history">Importa l\'historial de trucades</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Sento trucades entrants, però la pantalla no s\'encén. Què puc fer\?</string>
|
||||
<string name="faq_1_text">Aquests problemes poden tenir moltes raons específiques del dispositiu i del sistema, difícils de dir en general. Hauríeu de mirar per la configuració del dispositiu i assegurar-vos que l\'aplicació pugui aparèixer en segon pla i permetre que es mostri sobre altres aplicacions.</string>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<string name="audio_route_wired_headset">Náhlavní souprava s kabelem</string>
|
||||
<string name="audio_route_wired_or_earpiece">Kabel nebo sluchátka</string>
|
||||
<string name="choose_audio_route">Vybrat směrování zvuku</string>
|
||||
<string name="calling_blocked_number">The number you are calling is blocked</string>
|
||||
<string name="calling_blocked_number">Číslo, které voláte, je blokované</string>
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">Rychlé vytáčení</string>
|
||||
<string name="manage_speed_dial">Spravovat rychlá vytáčení</string>
|
||||
|
@ -71,8 +71,9 @@
|
|||
<string name="disable_proximity_sensor">Vypnout senzor přiblížení během hovoru</string>
|
||||
<string name="disable_swipe_to_answer">Nahradit přejetí prstem při odpovídání na příchozí hovory za klepnutí</string>
|
||||
<string name="show_incoming_calls_full_screen">Vždy zobrazovat příchozí hovory na celou obrazovku</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
|
||||
<string name="hide_dialpad_numbers">Skrýt čísla číselníku</string>
|
||||
<string name="export_call_history">Exportovat historii volání</string>
|
||||
<string name="import_call_history">Importovat historii volání</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Slyším příchozí hovor, ale obrazovka se nezapne. Co mohu dělat\?</string>
|
||||
<string name="faq_1_text">Takové problémy mohou mít mnoho důvodů specifických pro zařízení a systém, takže je těžké říci něco obecně. Měli byste zkontrolovat nastavení zařízení a ujistit se, že se aplikace může otevřít, když běží na pozadí, a umožnit zobrazení přes jiné aplikace.</string>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Erstat swipe ved besvarelse af indgående opkald med at klikke på</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Kan du ikke finde nogle strenge? Der er mere på
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<string name="default_phone_app_prompt">Bitte machen Sie diese Anwendung zur Standard-Telefonanwendung</string>
|
||||
<string name="allow_displaying_over_other_apps">Bitte erlauben Sie die Anzeige über andere Anwendungen für ein zuverlässiges Verhalten</string>
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">Kein Zugriff auf Kontakte</string>
|
||||
<string name="could_not_access_contacts">Kein Zugriff auf deine Kontakte möglich</string>
|
||||
<!-- Recents -->
|
||||
<string name="no_previous_calls">Anrufliste ist leer</string>
|
||||
<string name="could_not_access_the_call_history">Kein Zugriff auf Anrufliste</string>
|
||||
<string name="could_not_access_the_call_history">Kein Zugriff auf die Anrufliste möglich</string>
|
||||
<string name="request_access">Zugriff anfordern</string>
|
||||
<string name="remove_confirmation">Sollen wirklich die ausgewählten Einträge aus der Anrufliste gelöscht werden\?</string>
|
||||
<string name="clear_history_confirmation">Soll wirklich die gesamte Anrufliste gelöscht werden\?</string>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<string name="hold_call">Anruf halten</string>
|
||||
<string name="resume_call">Anruf fortsetzen</string>
|
||||
<string name="call_on_hold">In der Warteschleife</string>
|
||||
<string name="call_swap">Anrufe austauschen</string>
|
||||
<string name="call_swap">Anrufe wechseln</string>
|
||||
<string name="call_merge">Anrufe zusammenführen</string>
|
||||
<string name="call_split">Anruf teilen</string>
|
||||
<string name="call_add">Anruf hinzufügen</string>
|
||||
|
@ -70,8 +70,10 @@
|
|||
<string name="open_dialpad_by_default">Beim Öffnen der App immer das Wähltastenfeld öffnen</string>
|
||||
<string name="disable_proximity_sensor">Näherungssensor bei Anrufen deaktivieren</string>
|
||||
<string name="disable_swipe_to_answer">Anrufe durch Klicken statt durch Streichen annehmen</string>
|
||||
<string name="show_incoming_calls_full_screen">Eingehende Anrufe immer im Vollbildmodus anzeigen</string>
|
||||
<string name="show_incoming_calls_full_screen">Eingehende Anrufe immer im Vollbild anzeigen</string>
|
||||
<string name="hide_dialpad_numbers">Wähltastenfeld-Nummern ausblenden</string>
|
||||
<string name="export_call_history">Anrufliste exportieren</string>
|
||||
<string name="import_call_history">Anrufliste importieren</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ich höre eingehende Anrufe, aber der Bildschirm schaltet sich nicht ein. Was kann ich tun\?</string>
|
||||
<string name="faq_1_text">Eine allgemeine Antwort auf die Frage ist schwer, denn solche Probleme können viele geräte- und systemspezifische Gründe haben. Du solltest dich in den Einstellungen des Geräts umsehen und sicherstellen, dass die App im Hintergrund angezeigt werden darf und die Einblendung über anderen Apps erlaubt ist.</string>
|
||||
|
|
|
@ -72,11 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">Αντικατάσταση Σάρωσης με Κλικ στην απάντηση εισερχόμενων κλήσεων</string>
|
||||
<string name="show_incoming_calls_full_screen">Να εμφανίζονται πάντα οι εισερχόμενες κλήσεις σε πλήρη οθόνη</string>
|
||||
<string name="hide_dialpad_numbers">Απόκρυψη αριθμών πληκτρολογίου</string>
|
||||
<string name="export_call_history">Εξαγωγή ιστορικού κλήσεων</string>
|
||||
<string name="import_call_history">Εισαγωγή ιστορικού κλήσεων</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ακούω εισερχόμενες κλήσεις, αλλά η οθόνη δεν ανάβει. Τι μπορώ να κάνω;</string>
|
||||
<string name="faq_1_text">Τέτοια θέματα μπορεί να έχουν πολλούς λόγους που σχετίζονται με τη συσκευή και το σύστημα, και είναι δύσκολο να ειπωθούν γενικά. Θα πρέπει να ψάξετε στις ρυθμίσεις της συσκευής σας και να βεβαιωθείτε ότι η εφαρμογή επιτρέπεται να εμφανίζεται όταν βρίσκεται στο παρασκήνιο και να επιτρέπει την εμφάνισή της πάνω από άλλες εφαρμογές.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Reemplazar deslizar para responder llamadas entrantes a pulsar</string>
|
||||
<string name="show_incoming_calls_full_screen">Siempre mostrar llamadas entrantes en pantalla completa</string>
|
||||
<string name="hide_dialpad_numbers">Ocultar los números del teclado</string>
|
||||
<string name="export_call_history">Exportar el historial de llamadas</string>
|
||||
<string name="import_call_history">Importar el historial de llamadas</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Escucho las llamadas entrantes, pero la pantalla no se enciende. ¿Qué puedo hacer\?</string>
|
||||
<string name="faq_1_text">Estos problemas pueden deberse a muchas razones específicas del dispositivo y del sistema, es difícil decirlo en general. Deberías mirar en la configuración de tu dispositivo y asegurarte de que la aplicación tiene permiso para aparecer cuando está en segundo plano y permitir la aplicación se muestre sobre otras aplicaciones.</string>
|
||||
|
|
|
@ -70,11 +70,13 @@
|
|||
<string name="open_dialpad_by_default">Rakenduse avamisel näita vaikimisi numbriklahvistikku</string>
|
||||
<string name="disable_proximity_sensor">Kõnede ajaks lülita lähedusandur välja</string>
|
||||
<string name="disable_swipe_to_answer">Kõnele vastamisel kasuta viipamise asemel klõpsimist</string>
|
||||
<string name="show_incoming_calls_full_screen">Kuvage sissetulevad kõned alati täisekraanil</string>
|
||||
<string name="show_incoming_calls_full_screen">Alati näita sissetulevad kõned täisekraanivaates</string>
|
||||
<string name="hide_dialpad_numbers">Peida numbriklahvistik</string>
|
||||
<string name="export_call_history">Ekspordi kõnede ajalugu</string>
|
||||
<string name="import_call_history">Impordi kõnede ajalugu</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ma kuulen sissetulevaid kõnesid, kuid ekraan ei lülitu sisse. Mida ma saan teha\?</string>
|
||||
<string name="faq_1_text">Sellistel probleemidel võib olla palju seadme- ja süsteemispetsiifilisi põhjusi, raske öelda üldiselt. Peaksite oma seadme seadetes ringi vaatama ja veenduma, et rakendusel on lubatud taustal hüpata ja lubada kuvamist üle teiste rakenduste.</string>
|
||||
<string name="faq_1_text">Üldist vastust pole, sellistel probleemidel võib olla palju seadme- ja süsteemispetsiifilisi põhjusi. Peaksid oma nutiseadme seadistustes ringi vaatama ja veenduma, et rakendusel on lubatud taustalt aknaid avada ja lubada kuvamist rakenduste peal.</string>
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">تلفن ساده</string>
|
||||
<string name="app_launcher_name">تلفن</string>
|
||||
<string name="default_phone_app_prompt">لطفا این برنامه را به عنوان پیشگزیده تنظیم کنید</string>
|
||||
<string name="allow_displaying_over_other_apps">برای عملکرد صحیح برنامه لطفا اجازه دهید روی برنامههای دیگر نمایش داده شود</string>
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">دسترسی به مخاطبین شما امکانپذیر نیست</string>
|
||||
<!-- Recents -->
|
||||
<string name="no_previous_calls">هیچ تماس قبلی پیدا نشد</string>
|
||||
<string name="could_not_access_the_call_history">دسترسی به تاریخچهٔ تماس شما امکانپذیر نیست</string>
|
||||
<string name="request_access">درخواست دسترسی</string>
|
||||
<string name="remove_confirmation">مطمئنید که میخواهید مورد انتخاب شده را از تاریخچه تماس حدف کنید؟</string>
|
||||
<string name="clear_history_confirmation">مطمئنید که میخواهید تمام تاریخچه تماس حدف کنید؟</string>
|
||||
<string name="show_grouped_calls">نمایش تماسهای گروهبندی شده</string>
|
||||
<string name="clear_call_history">پاک کردن تاریخچه تماس</string>
|
||||
<string name="show_call_details">نمایش اطلاعات تماس</string>
|
||||
<!-- Dialpad -->
|
||||
<string name="dialpad">شمارهگیر</string>
|
||||
<string name="asterisk">ستاره</string>
|
||||
<string name="hashtag">مربع</string>
|
||||
<string name="call_number">شماره تماس</string>
|
||||
<string name="dialpad_beeps">فعال کردن صدا هنگام لمس دکمههای شمارهگیر</string>
|
||||
<string name="dialpad_vibrations">فعال کردن لرزش هنگام لمس دکمههای شمارهگیر</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">تلفن</string>
|
||||
<string name="accept">پذیرش</string>
|
||||
<string name="accept_call">پذیرفتن تماس</string>
|
||||
<string name="decline">نپذیرفتن</string>
|
||||
<string name="decline_call">نپذیرفتن تماس</string>
|
||||
<string name="unknown_caller">تماس ناشناس</string>
|
||||
<string name="is_calling">تماس گرفته…</string>
|
||||
<string name="dialing">شمارهگیری…</string>
|
||||
<string name="call_ended">تماس پایان یافت</string>
|
||||
<string name="call_ending">پایان دادن مکالمه</string>
|
||||
<string name="ongoing_call">تماس در حال انجام</string>
|
||||
<string name="select_sim">انتخاب سیمکارت برای تماس</string>
|
||||
<string name="always_use_this_sim">برای این شماره همیشه از همین سیمکارت استفاده کن</string>
|
||||
<string name="unset_default_sim">برداشتن سیمکارت پیشفرض</string>
|
||||
<string name="calls">تماسها</string>
|
||||
<string name="turn_microphone_on">روشن کردن میکروفون</string>
|
||||
<string name="turn_microphone_off">خاموش کردن میکروفون</string>
|
||||
<string name="turn_speaker_on">روشن کردن بلندگو</string>
|
||||
<string name="turn_speaker_off">خاموش کردن بلندگو</string>
|
||||
<string name="show_dialpad">نمایش شمارهگیر</string>
|
||||
<string name="hide_dialpad">بستن شمارهگیر</string>
|
||||
<string name="end_call">پایان تماس</string>
|
||||
<string name="hold_call">انتظار تماس</string>
|
||||
<string name="resume_call">ادامه تماس</string>
|
||||
<string name="call_on_hold">در انتظار</string>
|
||||
<string name="call_swap">Swap calls</string>
|
||||
<string name="call_merge">Merge calls</string>
|
||||
<string name="call_split">Split call</string>
|
||||
<string name="call_add">افزودن تماس</string>
|
||||
<string name="conference_manage">Manage conference call</string>
|
||||
<string name="conference">Conference</string>
|
||||
<string name="audio_route_speaker">بلندگو</string>
|
||||
<string name="audio_route_earpiece">هدفون</string>
|
||||
<string name="audio_route_bluetooth">بلوتوث</string>
|
||||
<string name="audio_route_wired_headset">هدست سیمی</string>
|
||||
<string name="audio_route_wired_or_earpiece">سیمی یا هدفون</string>
|
||||
<string name="choose_audio_route">انتخاب مسیر صدا</string>
|
||||
<string name="calling_blocked_number">شمارهای که با آن تماس گرفتهاید مسدود است</string>
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">شمارهگیری سریع</string>
|
||||
<string name="manage_speed_dial">مدیریت شمارهگیری سریع</string>
|
||||
<string name="speed_dial_label">یک شماره را انتخاب کنید تا مخاطبی را به آن اختصاص دهید. با لمس طولانی آن شماره در شمارهگیر میتوانید به سرعت با آن تماس بگیرید.</string>
|
||||
<!-- Settings -->
|
||||
<string name="group_subsequent_calls">گروهبندی تماسهای پشتهم از یک شماره در تاریخچهٔ تماس</string>
|
||||
<string name="open_dialpad_by_default">باز کردن شمارهگیر به طور پیشفرض هنگام باز شدن برنامه</string>
|
||||
<string name="disable_swipe_to_answer">پاسخ دادن به تماس با استفاده از کلیک به جای کشیدن</string>
|
||||
<string name="disable_proximity_sensor">غیرفعال کردن حسگر مجاورت هنگام مکالمه</string>
|
||||
<string name="show_incoming_calls_full_screen">تماسهای ورودی همیشه بصورت تمامصفحه نمایش داده شوند</string>
|
||||
<string name="hide_dialpad_numbers">مخفی کردن اعداد شمارهگیر</string>
|
||||
<string name="export_call_history">خروجی گرفتن تاریخچهٔ تماس</string>
|
||||
<string name="import_call_history">وارد کردن تاریخچهٔ تماس</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">من صدای تماس ورودی را میشنوم اما نمایشگر روشن نمیشود. باید چه کاری انجام دهم؟</string>
|
||||
<string name="faq_1_text">این مشکل ممکن است بسته به دلایل مشکلات مختلفی در دستگاه و سامانه رخ دهد، بنابراین جواب کلی برای آن سخت است. باید تنظیمات دستگاهتان را بررسی کنید و مطمئن شوید که برنامه اجازه دارد در پسزمینه اجرا شود و روی برنامههای دیگر نمایش داده شود.</string>
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Vastaa puheluihin painalluksella pyyhkäisyn sijaan</string>
|
||||
<string name="show_incoming_calls_full_screen">Näytä saapuvat puhelut aina koko näytöllä</string>
|
||||
<string name="hide_dialpad_numbers">Piilota numeronäppäimet</string>
|
||||
<string name="export_call_history">Vie puheluhistoria</string>
|
||||
<string name="import_call_history">Tuo puheluhistoria</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Kuulen saapuvat puhelut, mutta näyttö on pimeänä. Mitä voin tehdä\?</string>
|
||||
<string name="faq_1_text">Tällaisiin ongelmiin voi olla monia laite- ja järjestelmäkohtaisia syitä, joiden yleistäminen on hankalaa. Kannattaa tutkia laitteen asetuksia ja varmistaa, että sovelluksella on oikeus ponnahtaa esiin taustalta ja näkyä muiden sovellusten päällä.</string>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Simple Téléphone</string>
|
||||
<string name="app_name">Téléphone simple</string>
|
||||
<string name="app_launcher_name">Téléphone</string>
|
||||
<string name="default_phone_app_prompt">Veuillez faire de cette application votre application de téléphone par défaut</string>
|
||||
<string name="allow_displaying_over_other_apps">Veuillez permettre l\'affichage sur d\'autres applications pour un comportement fiable</string>
|
||||
|
@ -20,10 +20,10 @@
|
|||
<string name="asterisk">Étoile</string>
|
||||
<string name="hashtag">Dièse</string>
|
||||
<string name="call_number">Numéro d\'appel</string>
|
||||
<string name="dialpad_beeps">Activer les bips lors des clics sur les boutons du clavier numérique</string>
|
||||
<string name="dialpad_vibrations">Activation des vibrations lors des clics sur les boutons du clavier</string>
|
||||
<string name="dialpad_beeps">Activer les sons lors de l\'appui sur les touches du pavé numérique</string>
|
||||
<string name="dialpad_vibrations">Activer les vibrations lors de l\'appui sur les touches du pavé numérique</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Clavier</string>
|
||||
<string name="dialer">Pavé numérique</string>
|
||||
<string name="accept">Accepter</string>
|
||||
<string name="accept_call">Accepter l\'appel</string>
|
||||
<string name="decline">Décliner</string>
|
||||
|
@ -42,8 +42,8 @@
|
|||
<string name="turn_microphone_off">Désactiver le microphone</string>
|
||||
<string name="turn_speaker_on">Activer le haut-parleur</string>
|
||||
<string name="turn_speaker_off">Désactiver le haut-parleur</string>
|
||||
<string name="show_dialpad">Afficher le clavier</string>
|
||||
<string name="hide_dialpad">Masquer le clavier</string>
|
||||
<string name="show_dialpad">Afficher le pavé numérique</string>
|
||||
<string name="hide_dialpad">Masquer le pavé numérique</string>
|
||||
<string name="end_call">Finir l\'appel</string>
|
||||
<string name="hold_call">Mettre l\'appel en attente</string>
|
||||
<string name="resume_call">Reprendre l\'appel</string>
|
||||
|
@ -71,7 +71,9 @@
|
|||
<string name="disable_proximity_sensor">Désactiver le capteur de proximité pendant les appels</string>
|
||||
<string name="disable_swipe_to_answer">Remplacer le balayage pour répondre aux appels entrants par un clic</string>
|
||||
<string name="show_incoming_calls_full_screen">Toujours afficher les appels entrants en plein écran</string>
|
||||
<string name="hide_dialpad_numbers">Masquer les numéros du clavier</string>
|
||||
<string name="hide_dialpad_numbers">Masquer les numéros du pavé numérique</string>
|
||||
<string name="export_call_history">Exporter l\'historique d\'appels</string>
|
||||
<string name="import_call_history">Importer l\'historique d\'appels</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">J\'entends les appels entrants, mais l\'écran ne s\'allume pas. Que puis-je faire \?</string>
|
||||
<string name="faq_1_text">Ces problèmes peuvent avoir de nombreuses raisons spécifiques à l\'appareil et au système, il est difficile d\'en parler en général. Vous devriez consulter les paramètres de votre appareil et vous assurer que l\'application est autorisée à apparaître en arrière-plan et à s\'afficher au-dessus des autres applications.</string>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Simple Dialer</string>
|
||||
<string name="app_name">Simple Marcador</string>
|
||||
<string name="app_launcher_name">Marcador</string>
|
||||
<string name="default_phone_app_prompt">Fai que sexa a aplición do Teléfono por predeterminada</string>
|
||||
<string name="allow_displaying_over_other_apps">Permite mostrala por riba doutras aplicacións para un comportamento fiable</string>
|
||||
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Substituír o xesto de desprazar por un click para responder</string>
|
||||
<string name="show_incoming_calls_full_screen">Mostrar sempre as chamadas entrantes a pantalla enteira</string>
|
||||
<string name="hide_dialpad_numbers">Ocultalos números do teclado</string>
|
||||
<string name="export_call_history">Exportar historial de chamadas</string>
|
||||
<string name="import_call_history">Importar historial de chamadas</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Escoito chamadas entrantes, pero a pantalla non se acende. Que podo facer\?</string>
|
||||
<string name="faq_1_text">Estes problemas poden ter moitas razóns específicas do dispositivo e do sistema, difíciles de dicir en xeral. Debes mirar ao teu redor na configuración do teu dispositivo e asegurarte de que a aplicación pode aparecer cando está en segundo plano e permitir que se vexa sobre outras aplicacións.</string>
|
||||
|
@ -79,4 +81,4 @@
|
|||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<string name="app_name">Jednostavan birač</string>
|
||||
<string name="app_launcher_name">Birač</string>
|
||||
<string name="default_phone_app_prompt">Postavi ovu aplikaciju kao standardnu aplikaciju za telefon</string>
|
||||
<string name="allow_displaying_over_other_apps">Za pouzdano ponašanje birača dopusti prikaz ispred drugih aplikacija</string>
|
||||
<string name="allow_displaying_over_other_apps">Za pouzdano ponašanje dozvoli prikazivanje ispred drugih aplikacija</string>
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">Nije moguće pristupiti tvojim kontaktima</string>
|
||||
<!-- Recents -->
|
||||
|
@ -69,14 +69,17 @@
|
|||
<string name="group_subsequent_calls">Grupiraj naknadne pozive s istim brojem u zapisniku poziva</string>
|
||||
<string name="open_dialpad_by_default">Otvori brojčanik prema zadanim postavkama kada se aplikacija otvori</string>
|
||||
<string name="disable_proximity_sensor">Isključi senzor blizine tijekom poziva</string>
|
||||
<string name="disable_swipe_to_answer">Zamijeni povlačenje prstom za odgovaranje na dolazne pozive pritiskom</string>
|
||||
<string name="disable_swipe_to_answer">Prihvati pozive dodirom umjesto povlačenjem</string>
|
||||
<string name="show_incoming_calls_full_screen">Uvijek prikaži dolazne pozive u cjeloekranskom prikazu</string>
|
||||
<string name="hide_dialpad_numbers">Sakrij brojeve tipkovnice telefona</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Čujem dolazne pozive, ali ekran se ne uključuje. Što mogu učiniti\?</string>
|
||||
<string name="faq_1_title">Čujem dolazne pozive, ali se ekran ne uključuje. Što mogu učiniti\?</string>
|
||||
<string name="faq_1_text">Takvi problemi mogu imati mnogo razloga specifičnih za uređaj i sustav, koje je teško reći općenito. Trebali biste pogledati uokolo u postavkama svog uređaja i provjeriti je li aplikaciji dopušteno iskakanje u pozadini i dopuštenje prikazivanja preko drugih aplikacija.</string>
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,11 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">Csúsztatás kattintásra cserélése a bejövő hívásoknál</string>
|
||||
<string name="show_incoming_calls_full_screen">Bejövő hívások megjelenítése mindig teljes képernyőn</string>
|
||||
<string name="hide_dialpad_numbers">Tárcsázószámok elrejtése</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Bejövő hívást hallok, de a képernyő nem kapcsol be. Mit tehetek\?</string>
|
||||
<string name="faq_1_text">Az ilyen problémáknak számos eszköz- és rendszerfüggő oka lehet, általánosságban nehéz megmondani. Nézzen körül az eszközbeállításokban, és győződjön meg róla, hogy az alkalmazás előbújhat-e a háttérből, és megjelenhet-e más alkalmazások felett.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,11 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">Ganti menggesek saat menanggapi panggilan masuk dengan mengklik</string>
|
||||
<string name="show_incoming_calls_full_screen">Selalu tampilkan panggilan masuk dengan layar penuh</string>
|
||||
<string name="hide_dialpad_numbers">Sembunyikan nomor tombol papan</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Saya mendengar panggilan masuk, tetapi layarnya tidak menyala\? Apa yang bisa saya lakukan\?</string>
|
||||
<string name="faq_1_text">Beberapa masalah dapat memiliki alasan perangkat dan sistem spesifik, tidak mudah untuk diberi tahu secara umum. Anda seharusnya melihat dalam pengaturan perangkat Anda dan memastikan bahwa aplikasi diperbolehkan untuk muncul ketika dalam latar belakang dan memperbolehkan menampilkan di atas aplikasi lain.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Sostituisci lo scorrimento nel rispondere alle chiamate in arrivo con un clic</string>
|
||||
<string name="show_incoming_calls_full_screen">Visualizza sempre le chiamate in arrivo a schermo intero</string>
|
||||
<string name="hide_dialpad_numbers">Nascondi i numeri del tastierino</string>
|
||||
<string name="export_call_history">Esporta la cronologia delle chiamate</string>
|
||||
<string name="import_call_history">Importa la cronologia delle chiamate</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Sento le chiamate in arrivo, ma lo schermo non si accende. Cosa posso fare\?</string>
|
||||
<string name="faq_1_text">Tali problemi possono avere molte ragioni specifiche per il dispositivo e il sistema, è difficile identificarle in generale. Dovresti dare un\'occhiata alle impostazioni del dispositivo e assicurarti che l\'app sia autorizzata a comparire quando è in background e che permetta la visualizzazione sopra le altre app.</string>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">החלף החלקה בתגובה לשיחות נכנסות בלחיצה</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,11 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">着信に応答する際のスワイプ操作をタップ操作に置き換える</string>
|
||||
<string name="show_incoming_calls_full_screen">着信通知を常に全画面で表示する</string>
|
||||
<string name="hide_dialpad_numbers">ダイヤルパッドの番号を表示しない</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">着信音は聞こえるのですが、画面がつきません。どうしたらよいですか?</string>
|
||||
<string name="faq_1_text">このような問題は、端末やシステム固有の理由が多く、一概には言えません。端末の設定を見て、アプリがバックグラウンドでポップアップすることを許可しているか、他のアプリの上に表示することを許可しているかを確認する必要があります。</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Atsiliepiant į įeinančius skambučius perbraukimą pakeiskite paspaudimu</string>
|
||||
<string name="show_incoming_calls_full_screen">Visada rodykite įeinančius skambučius per visą ekraną</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,9 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">ഇൻകമിംഗ് കോളുകളോട് പ്രതികരിക്കുമ്പോൾ സ്വൈപ്പിംഗ് മാറ്റി പകരം ഇൻകമിംഗ് കോളിൽ ക്ലിക്ക് ചെയ്യുക</string>
|
||||
<string name="show_incoming_calls_full_screen">എല്ലായ്പ്പോഴും ഇൻകമിംഗ് കോളുകൾ പൂർണ്ണ സ്ക്രീനിൽ പ്രദർശിപ്പിക്കുക</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">ഞാൻ ഇൻകമിംഗ് കോളുകൾ കേൾക്കുന്നു, പക്ഷേ സ്ക്രീൻ ഓണാക്കുന്നില്ല. എനിക്ക് എന്ത് ചെയ്യാൻ കഴിയും\?</string>
|
||||
<string name="faq_1_text">അത്തരം പ്രശ്നങ്ങൾക്ക് ഉപകരണത്തിനും സിസ്റ്റത്തിനും പ്രത്യേക കാരണങ്ങളുണ്ടാകാം, പൊതുവായി പറയാൻ പ്രയാസമാണ്. നിങ്ങളുടെ ഉപകരണ ക്രമീകരണങ്ങളിൽ നിങ്ങൾ ചുറ്റും നോക്കുകയും പശ്ചാത്തലത്തിലായിരിക്കുമ്പോൾ ആപ്പ് പോപ്പ് അപ്പ് ചെയ്യാൻ അനുവദിക്കുകയും മറ്റ് ആപ്പുകളിൽ പ്രദർശിപ്പിക്കാൻ അനുവദിക്കുകയും വേണം.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Erstatt sveiping ved å svare på innkommende anrop med å klikke</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
<string name="call_ended">Gesprek beëindigd</string>
|
||||
<string name="call_ending">Einde gesprek</string>
|
||||
<string name="ongoing_call">Huidig gesprek</string>
|
||||
<string name="select_sim">Kies een SIM-kaart voor dit gesprek</string>
|
||||
<string name="always_use_this_sim">Altijd deze SIM voor dit nummer gebruiken</string>
|
||||
<string name="unset_default_sim">Standaard-SIM uitzetten</string>
|
||||
<string name="select_sim">Kies een simkaart voor dit gesprek</string>
|
||||
<string name="always_use_this_sim">Altijd deze simkaart voor dit nummer gebruiken</string>
|
||||
<string name="unset_default_sim">Geen standaard-simkaart</string>
|
||||
<string name="calls">Gesprekken</string>
|
||||
<string name="turn_microphone_on">Microfoon inschakelen</string>
|
||||
<string name="turn_microphone_off">Microfoon uitschakelen</string>
|
||||
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Vervang vegen door klikken bij het aannemen van gesprekken</string>
|
||||
<string name="show_incoming_calls_full_screen">Inkomende gesprekken altijd op volledig scherm tonen</string>
|
||||
<string name="hide_dialpad_numbers">Toetsenblokcijfers verbergen</string>
|
||||
<string name="export_call_history">Gespreksgeschiedenis exporteren</string>
|
||||
<string name="import_call_history">Gespreksgeschiedenis importeren</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ik hoor dat er een gesprek binnenkomt, maar het scherm gaat niet aan. Wat kan ik doen\?</string>
|
||||
<string name="faq_1_text">Dit soort problemen kan vele oorzaken hebben, specifiek voor bepaalde apparaten en software. Controleer in ieder geval of voor deze app in de systeeminstellingen \"Weergeven vóór andere apps\" is toegestaan en of bij meldingen voor inkomende gesprekken \"Weergeven op scherm\" is ingeschakeld.</string>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Simple Dialer</string>
|
||||
<string name="app_launcher_name">Dialer</string>
|
||||
<string name="default_phone_app_prompt">Please make this app the default Phone app</string>
|
||||
<string name="allow_displaying_over_other_apps">Please allow displaying over other apps for reliable behaviour</string>
|
||||
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">Could not access your contacts</string>
|
||||
|
||||
<!-- Recents -->
|
||||
<string name="no_previous_calls">No previous calls have been found</string>
|
||||
<string name="could_not_access_the_call_history">Could not access the call history</string>
|
||||
<string name="request_access">Request access</string>
|
||||
<string name="remove_confirmation">Are you sure you want to remove the selected items from the Call History?</string>
|
||||
<string name="clear_history_confirmation">Are you sure you want to remove everything from the Call History?</string>
|
||||
<string name="show_grouped_calls">Show grouped calls</string>
|
||||
<string name="clear_call_history">Clear call history</string>
|
||||
<string name="show_call_details">Show call details</string>
|
||||
|
||||
<!-- Dialpad -->
|
||||
<string name="dialpad">Dialpad</string>
|
||||
<string name="asterisk">Asterisk</string>
|
||||
<string name="hashtag">Hashtag</string>
|
||||
<string name="call_number">Call number</string>
|
||||
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
|
||||
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
|
||||
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Dialer</string>
|
||||
<string name="accept">Accept</string>
|
||||
<string name="accept_call">Accept call</string>
|
||||
<string name="decline">Decline</string>
|
||||
<string name="decline_call">Decline call</string>
|
||||
<string name="unknown_caller">Unknown Caller</string>
|
||||
<string name="is_calling">Is Calling…</string>
|
||||
<string name="dialing">Dialing…</string>
|
||||
<string name="call_ended">Call Ended</string>
|
||||
<string name="call_ending">Call Ending</string>
|
||||
<string name="ongoing_call">Ongoing Call</string>
|
||||
<string name="select_sim">Select a SIM for this call</string>
|
||||
<string name="always_use_this_sim">Always use this SIM for this number</string>
|
||||
<string name="unset_default_sim">Unset default SIM</string>
|
||||
<string name="calls">Calls</string>
|
||||
<string name="turn_microphone_on">Turn microphone on</string>
|
||||
<string name="turn_microphone_off">Turn microphone off</string>
|
||||
<string name="turn_speaker_on">Turn speaker on</string>
|
||||
<string name="turn_speaker_off">Turn speaker off</string>
|
||||
<string name="show_dialpad">Show dialpad</string>
|
||||
<string name="hide_dialpad">Hide dialpad</string>
|
||||
<string name="end_call">End call</string>
|
||||
<string name="hold_call">Hold call</string>
|
||||
<string name="resume_call">Resume call</string>
|
||||
<string name="call_on_hold">On Hold</string>
|
||||
<string name="call_swap">Swap calls</string>
|
||||
<string name="call_merge">Merge calls</string>
|
||||
<string name="call_split">Split call</string>
|
||||
<string name="call_add">Add call</string>
|
||||
<string name="conference_manage">Manage conference call</string>
|
||||
<string name="conference">Conference</string>
|
||||
<string name="audio_route_speaker">Speaker</string>
|
||||
<string name="audio_route_earpiece">Earpiece</string>
|
||||
<string name="audio_route_bluetooth">Bluetooth</string>
|
||||
<string name="audio_route_wired_headset">Wired Headset</string>
|
||||
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
|
||||
<string name="choose_audio_route">Choose audio route</string>
|
||||
<string name="calling_blocked_number">The number you are calling is blocked</string>
|
||||
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">Speed dial</string>
|
||||
<string name="manage_speed_dial">Manage speed dial</string>
|
||||
<string name="speed_dial_label">Click on a number to assign a contact to it. You can then quickly call the given contact by long pressing the given number at the dialer.</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="group_subsequent_calls">Group subsequent calls with the same number at the call log</string>
|
||||
<string name="open_dialpad_by_default">Open the dialpad by default when the app opens</string>
|
||||
<string name="disable_proximity_sensor">Disable proximity sensor during calls</string>
|
||||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
|
@ -72,8 +72,11 @@
|
|||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do\?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Zastąp naciśnięciem gest przesunięcia do odpowiadania na połączenia przychodzące</string>
|
||||
<string name="show_incoming_calls_full_screen">Zawsze wyświetlaj połączenia przychodzące na pełnym ekranie</string>
|
||||
<string name="hide_dialpad_numbers">Ukryj cyfry panelu wybierania</string>
|
||||
<string name="export_call_history">Eksportuj historię połączeń</string>
|
||||
<string name="import_call_history">Importuj historię połączeń</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Słyszę połączenia przychodzące, ale ekran się nie włącza. Co mogę zrobić\?</string>
|
||||
<string name="faq_1_text">Takie problemy mogą mieć wiele przyczyn specyficznych dla urządzenia i systemu; ogólnie trudno powiedzieć. Powinieneś/powinnaś rozejrzeć się w ustawieniach swojego urządzenia i upewnić się, że aplikacja może pojawiać się, gdy jest w tle, i wyświetlać się nad innymi aplikacjami.</string>
|
||||
|
|
|
@ -72,9 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Clicar em vez de deslizar para responder chamadas</string>
|
||||
<string name="show_incoming_calls_full_screen">Sempre exibir as chamadas recebidas em tela cheia</string>
|
||||
<string name="hide_dialpad_numbers">Ocultar números do teclado</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Ouço chamadas recebidas, mas a tela não liga. O que eu posso fazer?</string>
|
||||
<string name="faq_1_text">Esses problemas podem ter muitos motivos específicos do dispositivo e do sistema, difíceis de dizer em geral. Você deve olhar em volta nas configurações do seu dispositivo e certificar-se de que o aplicativo pode aparecer quando estiver em segundo plano e permitir a exibição sobre outros aplicativos.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Clicar em vez de deslizar para atender</string>
|
||||
<string name="show_incoming_calls_full_screen">Mostrar em ecrã completo as chamadas recebidas</string>
|
||||
<string name="hide_dialpad_numbers">Ocultar números no marcador</string>
|
||||
<string name="export_call_history">Exportar registo de chamadas</string>
|
||||
<string name="import_call_history">Importar registo de chamadas</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Estou a ouvir som mas o ecrã não liga. O que posso fazer\?</string>
|
||||
<string name="faq_1_text">Esses problemas podem ter muitos motivos específicos do dispositivo e do sistema, difíceis de dizer em geral. Aceda às definições do sistema e certifique-se de que concedeu as permissões necessárias tais como permitir exibição por cima das outras aplicações.</string>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Înlocuiți glisarea pentru a răspunde la apelurile primite cu o singură apăsare</string>
|
||||
<string name="show_incoming_calls_full_screen">Afișați întotdeauna apelurile primite pe întreg ecranul</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Aud apelurile primite, dar ecranul nu se aprinde. Ce pot face\?</string>
|
||||
<string name="faq_1_text">Aceste probleme pot avea multe motive specifice dispozitivului și sistemului, fiind greu de spus în general. Ar trebui să vă uitați în setările dispozitivului și să vă asigurați că aplicația este permisă să apară atunci când este în fundal și că permite afișarea peste alte aplicații.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,11 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">Использовать нажатие вместо перетаскивания при ответе на входящие вызовы</string>
|
||||
<string name="show_incoming_calls_full_screen">Всегда отображать входящие вызовы на полный экран</string>
|
||||
<string name="hide_dialpad_numbers">Скрыть цифры на номеронабирателе</string>
|
||||
<string name="export_call_history">Экспорт истории звонков</string>
|
||||
<string name="import_call_history">Импорт истории звонков</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Я слышу сигналы входящих вызовов, но экран не включается. Что можно сделать\?</string>
|
||||
<string name="faq_1_text">Такие проблемы могут иметь множество специфических для устройства и системы причин, о которых трудно говорить в общем. Следует проверить настройки устройства и убедиться, что приложению разрешено отображение всплывающих уведомлений в фоновом режиме и отображение поверх других приложений.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,10 +72,12 @@
|
|||
<string name="disable_swipe_to_answer">Nahradiť potiahnutie prstom pri odpovedaní na prichádzajúce hovory kliknutím</string>
|
||||
<string name="show_incoming_calls_full_screen">Stále zobraziť prichádzajúce hovory na celú obrazovku</string>
|
||||
<string name="hide_dialpad_numbers">Skryť čísla na číselníku</string>
|
||||
|
||||
<string name="export_call_history">Exportovať históriu volaní</string>
|
||||
<string name="import_call_history">Importovať históriu volaní</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Počujem prichádzajúce hovory, obrazovka sa ale nezapne. Čo s tým?</string>
|
||||
<string name="faq_1_text">Takéto problémy majú často dôvody špecifické pre dané zariadenie alebo systém, ťažko teda dať všeobecné riešenie. Mali by ste sa poobzerať v nasteniach zariadenia a uistiť sa, že apka má povolenie na zobrazovanie sa z pozadia a na zobrazovanie sa nad ostatnými apkami.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,12 +72,15 @@
|
|||
<string name="disable_swipe_to_answer">Pri odzivanju na dohodne klice zamenjajte poteg s prstom na odziv s klikanjem</string>
|
||||
<string name="show_incoming_calls_full_screen">Dohodne klice vedno prikaži na celotnem zaslonu</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Slišim dohodne klice, vendar se zaslon ne vklopi. Kaj lahko storim\?</string>
|
||||
<string name="faq_1_text">Takšne težave imajo lahko veliko razlogov, ki so specifični za napravo in sistem, zato jih je na splošno težko opredeliti. Oglejte si nastavitve naprave in se prepričajte, da je aplikaciji dovoljeno, da se prikaže, ko je v ozadju, in da omogoča prikaz nad drugimi aplikacijami.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -72,8 +72,11 @@
|
|||
<string name="disable_swipe_to_answer">Замените превлачење при одговарању на долазне позиве кликом</string>
|
||||
<string name="show_incoming_calls_full_screen">Увек прикажи долазне позиве преко целог екрана</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Чујем долазне позиве, али екран се не укључује. Шта могу да урадим\?</string>
|
||||
<string name="faq_1_text">Такви проблеми могу имати много специфичних разлога за уређај и систем, што је уопштено тешко рећи. Требало би да погледате около у подешавањима уређаја и уверите се да је апликацији дозвољено да искаче када је у позадини и да дозволи приказивање преко других апликација.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Ersätt svepning vid besvarande av inkommande samtal med tryckning</string>
|
||||
<string name="show_incoming_calls_full_screen">Visa alltid inkommande samtal i helskärm</string>
|
||||
<string name="hide_dialpad_numbers">Dölj knappsatsens siffror</string>
|
||||
<string name="export_call_history">Exportera samtalshistorik</string>
|
||||
<string name="import_call_history">Importera samtalshistorik</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Jag hör inkommande samtal men skärmen vaknar inte. Vad gör jag\?</string>
|
||||
<string name="faq_1_text">Sådana problem kan bero specifikt på apparat eller ditt sytem, det är svårt att svara på generellt. Du bör kolla i dina inställningar och säkerställa att appen har behörighet att synas i förgrunden och tillåts att synas över andra appar.</string>
|
||||
|
|
|
@ -72,10 +72,13 @@
|
|||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Gelen aramalara yanıt vermek için kaydırmayı tıklamayla değiştir</string>
|
||||
<string name="show_incoming_calls_full_screen">Gelen aramaları her zaman tam ekranda görüntüle</string>
|
||||
<string name="hide_dialpad_numbers">Tuş takımı numaralarını gizle</string>
|
||||
<string name="export_call_history">Arama geçmişini dışa aktar</string>
|
||||
<string name="import_call_history">Arama geçmişini içe aktar</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Gelen aramaları duyuyorum ama ekran açılmıyor. Ne yapabilirim\?</string>
|
||||
<string name="faq_1_text">Bu tür sorunların aygıta ve sisteme özgü birçok nedeni olabilir, genel olarak söylemek zor. Aygıt ayarlarınıza bakmalı ve uygulamanın arka plandayken açılmasına ve diğer uygulamaların üzerinde görüntülenmesine izin verildiğinden emin olmalısınız.</string>
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">Замінити перетягування на натискання під час відповіді на вхідні виклики</string>
|
||||
<string name="show_incoming_calls_full_screen">Завжди відображати вхідні дзвінки на весь екран</string>
|
||||
<string name="hide_dialpad_numbers">Приховати номери цифрової клавіатури</string>
|
||||
<string name="export_call_history">Експорт журналу дзвінків</string>
|
||||
<string name="import_call_history">Імпорт історії дзвінків</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Я чую вхідні дзвінки, але екран не вмикається. Що я можу зробити\?</string>
|
||||
<string name="faq_1_text">Такі проблеми можуть мати багато специфічних для пристрою та системи причин, важко сказати в цілому. Вам слід подивитися в налаштуваннях свого пристрою та переконатися, що застосунку дозволено відображати у фоновому режимі та дозволяти відображення над іншими застосунками.</string>
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Trình quay số đơn giản</string>
|
||||
<string name="app_launcher_name">Trình quay số</string>
|
||||
<string name="default_phone_app_prompt">Vui lòng đặt ứng dụng này làm ứng dụng Điện thoại mặc định</string>
|
||||
<string name="allow_displaying_over_other_apps">Vui lòng cho phép hiển thị trên các ứng dụng khác để có hành vi đáng tin cậy</string>
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">Không thể truy cập danh bạ của bạn</string>
|
||||
<!-- Recents -->
|
||||
<string name="no_previous_calls">Không tìm thấy cuộc gọi nào trước đây</string>
|
||||
<string name="could_not_access_the_call_history">Không vào được lịch sử cuộc gọi</string>
|
||||
<string name="request_access">Yêu cầu quyền truy cập</string>
|
||||
<string name="remove_confirmation">Bạn có chắc chắn muốn xóa các mục đã chọn khỏi Lịch sử cuộc gọi không\?</string>
|
||||
<string name="clear_history_confirmation">Bạn có chắc chắn muốn xóa mọi thứ khỏi Lịch sử cuộc gọi không\?</string>
|
||||
<string name="show_grouped_calls">Hiển thị các cuộc gọi được nhóm</string>
|
||||
<string name="clear_call_history">Xóa lịch sử cuộc gọi</string>
|
||||
<string name="show_call_details">Hiển thị chi tiết cuộc gọi</string>
|
||||
<!-- Dialpad -->
|
||||
<string name="dialpad">Bàn phím quay số</string>
|
||||
<string name="asterisk">Dấu hoa thị</string>
|
||||
<string name="hashtag">Dấu thăng</string>
|
||||
<string name="call_number">Số điện thoại</string>
|
||||
<string name="dialpad_beeps">Bật tiếng bíp khi bấm vào nút quay số</string>
|
||||
<string name="dialpad_vibrations">Bật rung khi nhấp vào nút quay số</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Trình quay số</string>
|
||||
<string name="accept">Chấp nhận</string>
|
||||
<string name="accept_call">Chấp nhận cuộc gọi</string>
|
||||
<string name="decline">Từ chối</string>
|
||||
<string name="decline_call">Từ chối cuộc gọi</string>
|
||||
<string name="unknown_caller">Người gọi Không xác định</string>
|
||||
<string name="is_calling">Đang gọi…</string>
|
||||
<string name="dialing">Đang quay số…</string>
|
||||
<string name="call_ended">Cuộc gọi kết thúc</string>
|
||||
<string name="call_ending">Đang kết thúc cuộc gọi</string>
|
||||
<string name="ongoing_call">Cuộc gọi đang diễn ra</string>
|
||||
<string name="select_sim">Chọn một SIM cho cuộc gọi này</string>
|
||||
<string name="always_use_this_sim">Luôn sử dụng SIM này cho số này</string>
|
||||
<string name="unset_default_sim">Bỏ đặt SIM mặc định</string>
|
||||
<string name="calls">Cuộc gọi</string>
|
||||
<string name="turn_microphone_on">Bật micrô</string>
|
||||
<string name="turn_microphone_off">Tắt micrô</string>
|
||||
<string name="turn_speaker_on">Bật loa</string>
|
||||
<string name="turn_speaker_off">Tắt loa</string>
|
||||
<string name="show_dialpad">Hiển thị bàn phím quay số</string>
|
||||
<string name="hide_dialpad">Ẩn bàn phím quay số</string>
|
||||
<string name="end_call">Kết thúc cuộc gọi</string>
|
||||
<string name="hold_call">Giữ cuộc gọi</string>
|
||||
<string name="resume_call">Tiếp tục cuộc gọi</string>
|
||||
<string name="call_on_hold">Đang chờ</string>
|
||||
<string name="call_swap">Hoán đổi cuộc gọi</string>
|
||||
<string name="call_merge">Hợp nhất các cuộc gọi</string>
|
||||
<string name="call_split">Tách cuộc gọi</string>
|
||||
<string name="call_add">Thêm cuộc gọi</string>
|
||||
<string name="conference_manage">Quản lý cuộc gọi hội nghị</string>
|
||||
<string name="conference">Hội nghị</string>
|
||||
<string name="audio_route_speaker">Loa</string>
|
||||
<string name="audio_route_earpiece">Ống nghe</string>
|
||||
<string name="audio_route_bluetooth">Bluetooth</string>
|
||||
<string name="audio_route_wired_headset">Tai nghe có dây</string>
|
||||
<string name="audio_route_wired_or_earpiece">Có dây hoặc Tai nghe</string>
|
||||
<string name="choose_audio_route">Chọn tuyến đường âm thanh</string>
|
||||
<string name="calling_blocked_number">Số bạn đang gọi bị chặn</string>
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">Quay số nhanh</string>
|
||||
<string name="manage_speed_dial">Quản lý quay số nhanh</string>
|
||||
<string name="speed_dial_label">Bấm vào một số để chỉ định một số liên lạc cho nó. Sau đó, bạn có thể nhanh chóng gọi cho số liên lạc đã cho bằng cách nhấn và giữ số đã cho ở trình quay số.</string>
|
||||
<!-- Settings -->
|
||||
<string name="group_subsequent_calls">Nhóm các cuộc gọi tiếp theo với cùng một số trong nhật ký cuộc gọi</string>
|
||||
<string name="open_dialpad_by_default">Mở bàn phím quay số theo mặc định khi mở ứng dụng</string>
|
||||
<string name="disable_proximity_sensor">Tắt cảm biến tiệm cận trong khi gọi</string>
|
||||
<string name="disable_swipe_to_answer">Thay thế thao tác vuốt khi trả lời cuộc gọi đến bằng thao tác nhấp</string>
|
||||
<string name="show_incoming_calls_full_screen">Luôn hiển thị các cuộc gọi đến trên toàn màn hình</string>
|
||||
<string name="hide_dialpad_numbers">Ẩn số bàn phím quay số</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Tôi nghe thấy cuộc gọi đến, nhưng màn hình không bật. Tôi có thể làm gì\?</string>
|
||||
<string name="faq_1_text">Những vấn đề như vậy có thể có nhiều lý do cụ thể của thiết bị và hệ thống, khó nói chung. Bạn nên xem trong cài đặt thiết bị của mình và đảm bảo rằng ứng dụng được phép bật lên khi ở chế độ nền và cho phép hiển thị trên các ứng dụng khác.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
|
@ -72,6 +72,8 @@
|
|||
<string name="disable_swipe_to_answer">用点击代替滑动来接听来电</string>
|
||||
<string name="show_incoming_calls_full_screen">始终全屏显示来电</string>
|
||||
<string name="hide_dialpad_numbers">隐藏拨号盘号码</string>
|
||||
<string name="export_call_history">导出通话记录</string>
|
||||
<string name="import_call_history">导入通话记录</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">我听到来电声音,但屏幕不亮。我该怎么办\?</string>
|
||||
<string name="faq_1_text">这样的问题可能有很多设备和系统的具体原因,很难笼统地说。你应该查看你的设备设置,确保应用在后台时被允许弹出,并允许其显示在其他应用上方。</string>
|
||||
|
|
|
@ -2,82 +2,83 @@
|
|||
<resources>
|
||||
<string name="app_name">Simple Dialer</string>
|
||||
<string name="app_launcher_name">Dialer</string>
|
||||
<string name="default_phone_app_prompt">請將本 app 設為預設的電話 app</string>
|
||||
<string name="allow_displaying_over_other_apps">Please allow displaying over other apps for reliable behaviour</string>
|
||||
<string name="default_phone_app_prompt">請將此 app 設為預設的電話 app</string>
|
||||
<string name="allow_displaying_over_other_apps">請允許在其他 app 上顯示以確保可靠的行為</string>
|
||||
<!-- Contacts -->
|
||||
<string name="could_not_access_contacts">無法存取您的通訊錄</string>
|
||||
<string name="could_not_access_contacts">無法存取您的聯絡人</string>
|
||||
<!-- Recents -->
|
||||
<string name="no_previous_calls">No previous calls have been found</string>
|
||||
<string name="could_not_access_the_call_history">無法存取通話歷史紀錄</string>
|
||||
<string name="request_access">Request access</string>
|
||||
<string name="remove_confirmation">您確定要從通話記錄中移除所選的項目嗎?</string>
|
||||
<string name="clear_history_confirmation">您確定要通話記錄中所有的項目嗎?</string>
|
||||
<string name="no_previous_calls">找不到先前的通話紀錄</string>
|
||||
<string name="could_not_access_the_call_history">無法存取通話紀錄</string>
|
||||
<string name="request_access">請求存取權限</string>
|
||||
<string name="remove_confirmation">您確定要從通話紀錄中移除所選的項目嗎?</string>
|
||||
<string name="clear_history_confirmation">您確定要清除通話紀錄中的所有項目嗎?</string>
|
||||
<string name="show_grouped_calls">顯示群組通話</string>
|
||||
<string name="clear_call_history">清除通話記錄</string>
|
||||
<string name="show_call_details">顯示通話詳情</string>
|
||||
<string name="clear_call_history">清除通話紀錄</string>
|
||||
<string name="show_call_details">顯示通話詳細資訊</string>
|
||||
<!-- Dialpad -->
|
||||
<string name="dialpad">Dialpad</string>
|
||||
<string name="asterisk">Asterisk</string>
|
||||
<string name="hashtag">Hashtag</string>
|
||||
<string name="call_number">通話號碼</string>
|
||||
<string name="dialpad_beeps">Enable beeps on dialpad button clicks</string>
|
||||
<string name="dialpad_vibrations">Enable vibrations on dialpad button clicks</string>
|
||||
<string name="dialpad">撥號鍵盤</string>
|
||||
<string name="asterisk">星號</string>
|
||||
<string name="hashtag">井號</string>
|
||||
<string name="call_number">撥打電話號碼</string>
|
||||
<string name="dialpad_beeps">啟用撥號鍵盤按鈕點選的提示音</string>
|
||||
<string name="dialpad_vibrations">啟用撥號鍵盤按鈕點選的震動</string>
|
||||
<!-- Dialer -->
|
||||
<string name="dialer">Dialer</string>
|
||||
<string name="accept">Accept</string>
|
||||
<string name="accept_call">Accept call</string>
|
||||
<string name="decline">Decline</string>
|
||||
<string name="decline_call">Decline call</string>
|
||||
<string name="unknown_caller">Unknown Caller</string>
|
||||
<string name="is_calling">Is Calling…</string>
|
||||
<string name="dialer">撥號器</string>
|
||||
<string name="accept">接受</string>
|
||||
<string name="accept_call">接聽來電</string>
|
||||
<string name="decline">拒絕</string>
|
||||
<string name="decline_call">拒絕來電</string>
|
||||
<string name="unknown_caller">未知來電者</string>
|
||||
<string name="is_calling">正在撥打……</string>
|
||||
<string name="dialing">撥號中……</string>
|
||||
<string name="call_ended">通話結束</string>
|
||||
<string name="call_ending">即將結束通話</string>
|
||||
<string name="select_sim">選擇此通話用的 SIM 卡</string>
|
||||
<string name="ongoing_call">Ongoing Call</string>
|
||||
<string name="always_use_this_sim">Always use this SIM for this number</string>
|
||||
<string name="unset_default_sim">Unset default SIM</string>
|
||||
<string name="calls">Calls</string>
|
||||
<string name="turn_microphone_on">Turn microphone on</string>
|
||||
<string name="turn_microphone_off">Turn microphone off</string>
|
||||
<string name="turn_speaker_on">Turn speaker on</string>
|
||||
<string name="turn_speaker_off">Turn speaker off</string>
|
||||
<string name="show_dialpad">Show dialpad</string>
|
||||
<string name="hide_dialpad">Hide dialpad</string>
|
||||
<string name="end_call">End call</string>
|
||||
<string name="hold_call">Hold call</string>
|
||||
<string name="resume_call">Resume call</string>
|
||||
<string name="call_on_hold">On Hold</string>
|
||||
<string name="call_swap">Swap calls</string>
|
||||
<string name="call_merge">Merge calls</string>
|
||||
<string name="call_split">Split call</string>
|
||||
<string name="call_add">Add call</string>
|
||||
<string name="conference_manage">Manage conference call</string>
|
||||
<string name="conference">Conference</string>
|
||||
<string name="audio_route_speaker">Speaker</string>
|
||||
<string name="audio_route_earpiece">Earpiece</string>
|
||||
<string name="audio_route_bluetooth">Bluetooth</string>
|
||||
<string name="audio_route_wired_headset">Wired Headset</string>
|
||||
<string name="audio_route_wired_or_earpiece">Wired or Earpiece</string>
|
||||
<string name="choose_audio_route">Choose audio route</string>
|
||||
<string name="calling_blocked_number">The number you are calling is blocked</string>
|
||||
<string name="call_ending">通話即將結束</string>
|
||||
<string name="select_sim">選擇此通話的 SIM 卡</string>
|
||||
<string name="ongoing_call">進行中的通話</string>
|
||||
<string name="always_use_this_sim">總是使用此 SIM 卡撥打這個號碼</string>
|
||||
<string name="unset_default_sim">取消設定預設 SIM 卡</string>
|
||||
<string name="calls">通話</string>
|
||||
<string name="turn_microphone_on">開啟麥克風</string>
|
||||
<string name="turn_microphone_off">關閉麥克風</string>
|
||||
<string name="turn_speaker_on">開啟免持聽筒</string>
|
||||
<string name="turn_speaker_off">關閉免持聽筒</string>
|
||||
<string name="show_dialpad">顯示撥號鍵盤</string>
|
||||
<string name="hide_dialpad">隱藏撥號鍵盤</string>
|
||||
<string name="end_call">結束通話</string>
|
||||
<string name="hold_call">保留通話</string>
|
||||
<string name="resume_call">恢復通話</string>
|
||||
<string name="call_on_hold">保留中</string>
|
||||
<string name="call_swap">切換通話</string>
|
||||
<string name="call_merge">合併通話</string>
|
||||
<string name="call_split">分割通話</string>
|
||||
<string name="call_add">新增通話</string>
|
||||
<string name="conference_manage">管理會議通話</string>
|
||||
<string name="conference">會議通話</string>
|
||||
<string name="audio_route_speaker">免持聽筒</string>
|
||||
<string name="audio_route_earpiece">耳機</string>
|
||||
<string name="audio_route_bluetooth">藍牙</string>
|
||||
<string name="audio_route_wired_headset">有線耳機</string>
|
||||
<string name="audio_route_wired_or_earpiece">有線或耳機</string>
|
||||
<string name="choose_audio_route">選擇音訊路徑</string>
|
||||
<string name="calling_blocked_number">您撥打的號碼已被封鎖</string>
|
||||
<!-- Speed dial -->
|
||||
<string name="speed_dial">Speed dial</string>
|
||||
<string name="manage_speed_dial">Manage speed dial</string>
|
||||
<string name="speed_dial_label">Click on a number to assign a contact to it. You can then quickly call the given contact by long pressing the given number at the dialer.</string>
|
||||
<string name="speed_dial">快速撥號</string>
|
||||
<string name="manage_speed_dial">管理快速撥號</string>
|
||||
<string name="speed_dial_label">點選一個號碼以指定聯絡人。然後您可以在撥號器長按該號碼快速撥打給該聯絡人。</string>
|
||||
<!-- Settings -->
|
||||
<string name="group_subsequent_calls">Group subsequent calls with the same number at the call log</string>
|
||||
<string name="open_dialpad_by_default">Open the dialpad by default when the app opens</string>
|
||||
<string name="disable_proximity_sensor">Disable proximity sensor during calls</string>
|
||||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
|
||||
<string name="group_subsequent_calls">將通話紀錄中相同號碼的連續通話分組</string>
|
||||
<string name="open_dialpad_by_default">當 app 開啟時預設開啟撥號鍵盤</string>
|
||||
<string name="disable_proximity_sensor">通話時停用接近感應器</string>
|
||||
<string name="disable_swipe_to_answer">用點選來取代滑動回應來電</string>
|
||||
<string name="show_incoming_calls_full_screen">總是全螢幕顯示來電</string>
|
||||
<string name="hide_dialpad_numbers">隱藏撥號鍵盤數字</string>
|
||||
<string name="export_call_history">匯出通話紀錄</string>
|
||||
<string name="import_call_history">匯入通話紀錄</string>
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
<string name="faq_1_title">我聽到來電,但螢幕沒有亮起。我該怎麼辦?</string>
|
||||
<string name="faq_1_text">這種問題可能有許多與裝置和系統特定的原因,一般來說很難確定。您應該查看您的裝置設定,並確保 app 被允許在背景時彈出並允許在其他 app 上顯示。</string>
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
||||
</resources>
|
|
@ -78,10 +78,13 @@
|
|||
<string name="disable_swipe_to_answer">Replace swiping at responding to incoming calls with clicking</string>
|
||||
<string name="show_incoming_calls_full_screen">Always display incoming calls on full screen</string>
|
||||
<string name="hide_dialpad_numbers">Hide dialpad numbers</string>
|
||||
<string name="export_call_history">Export call history</string>
|
||||
<string name="import_call_history">Import call history</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I hear incoming calls, but the screen doesn\'t turn on. What can I do?</string>
|
||||
<string name="faq_1_text">Such issues can have many device and system specific reasons, hard to say in general. You should look around in your device settings and make sure that the app is allowed to pop up when in background and allow displaying over other apps.</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
|
|
28
build.gradle
28
build.gradle
|
@ -1,28 +0,0 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
plugins {
|
||||
alias(libs.plugins.android).apply(false)
|
||||
alias(libs.plugins.kotlinAndroid).apply(false)
|
||||
alias(libs.plugins.kotlinSerialization).apply(false)
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
* Fixed number presses during call
|
||||
* Added some stability, translation and UX improvements
|
|
@ -0,0 +1 @@
|
|||
* Added some stability, translation and UX improvements
|
|
@ -0,0 +1,3 @@
|
|||
* Avoid showing contacts without a phone number
|
||||
* Fixed multiple contact handling related glitches
|
||||
* Added some stability, translation and UX improvements
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue