Add dynamic shortcuts for starred contacts#249
Conversation
|
I think that visible shortcuts should always be the first ones according to current sorting of Favorites tab. For example, if I sort descending by name, I want to see in shortcuts three first items by that sorting, not by the default one; if I use custom sorting, I want to have specific contacts visible at the top, so also in shortcuts. |
|
Done! I recall sorting the list at first but I must have accidentally removed it while refactoring. |
|
The changes aren't applied immediately. It's called
I didn't need to add/remove anything when I was testing it so I'm not sure why that's happening. |
|
I did it, and sorting is still not applied. |
|
I just tested it again with a fresh install and it seems to work fine. It only shows up after the second or third time I open the app after a fresh install, but after that it reflects sorting changes relatively quickly. I'm not sure where the issue is happening. Edit: Just to clarify, I'm talking about the sorting in the Favourites tab. |
|
@Aga-C can you test out the latest commit? It should work now. |
|
But you still haven't solved a problem, which is in your code: You always assume, that if order is set, that's the only way to sort, while you should check |
|
I see. Sorry about that, it seems like I fundamentally misunderstood the issue. It should be fixed now. |
|
It still doesn't show the first three items from the current sorting. Check the recording below: qemu-system-x86_64_xeknsQ9wCX.mp4Also, one of these contacts ( |
|
At this point, I genuinely have no idea where the problem is. I'm just not encountering that issue so I have no way to debug it. |
| private fun pushStarredShortcuts() { | ||
| if (VERSION.SDK_INT >= VERSION_CODES.R) { | ||
| val starred = cachedContacts.filter { it.starred == 1 && it.phoneNumbers.isNotEmpty() } | ||
| this.config.favoritesContactsOrder.let { order -> | ||
| if (!config.isCustomOrderSelected) { | ||
| starred.sorted() | ||
| } else { | ||
| val orderList = Converters().jsonToStringList(order).withIndex().associate { it.value to it.index } | ||
| starred.sortedBy { orderList[it.contactId.toString()] } | ||
| } | ||
| }.take(3).forEachIndexed { index, contact -> |
There was a problem hiding this comment.
That's a very convoluted way to access config.favoritesContactsOrder.
It's better to extract this into a separate function:
| private fun pushStarredShortcuts() { | |
| if (VERSION.SDK_INT >= VERSION_CODES.R) { | |
| val starred = cachedContacts.filter { it.starred == 1 && it.phoneNumbers.isNotEmpty() } | |
| this.config.favoritesContactsOrder.let { order -> | |
| if (!config.isCustomOrderSelected) { | |
| starred.sorted() | |
| } else { | |
| val orderList = Converters().jsonToStringList(order).withIndex().associate { it.value to it.index } | |
| starred.sortedBy { orderList[it.contactId.toString()] } | |
| } | |
| }.take(3).forEachIndexed { index, contact -> | |
| private fun getTopStarredContacts(): List<Contact> { | |
| val starred = cachedContacts.filter { it.starred == 1 && it.phoneNumbers.isNotEmpty() } | |
| return if (!config.isCustomOrderSelected) { | |
| starred.sorted() | |
| } else { | |
| val orderList = Converters().jsonToStringList(config.favoritesContactsOrder) | |
| .withIndex() | |
| .associate { it.value to it.index } | |
| starred.sortedBy { orderList[it.contactId.toString()] ?: Int.MAX_VALUE } | |
| }.take(3) | |
| } | |
| private fun pushStarredShortcuts() { | |
| if (isRPlus()) { | |
| getTopStarredContacts().forEachIndexed { index, contact -> |
Or even better, convert that sortByCustomOrder function from FavoritesFragment to an extension and reuse it here.
| import android.os.Build.VERSION | ||
| import android.os.Build.VERSION_CODES |
There was a problem hiding this comment.
| import android.os.Build.VERSION | |
| import android.os.Build.VERSION_CODES |
| var number = if (contact.phoneNumbers.size == 1) { | ||
| contact.phoneNumbers[0].normalizedNumber | ||
| } else { | ||
| contact.phoneNumbers.firstOrNull { it.isPrimary }?.normalizedNumber | ||
| } | ||
| if (number == null) { | ||
| val radioItems = contact.phoneNumbers.mapIndexed { index, item -> | ||
| RadioItem(index, item.normalizedNumber, item) | ||
| } | ||
| RadioGroupDialog(this, ArrayList(radioItems)) { | ||
| number = (it as PhoneNumber).normalizedNumber | ||
| } | ||
| } |
There was a problem hiding this comment.
Radio dialog here is bad UX, and it doesn't even work. Let's fall back to the first number when there is no primary number. Multiple numbers will be handled when #102 is done.
| var number = if (contact.phoneNumbers.size == 1) { | |
| contact.phoneNumbers[0].normalizedNumber | |
| } else { | |
| contact.phoneNumbers.firstOrNull { it.isPrimary }?.normalizedNumber | |
| } | |
| if (number == null) { | |
| val radioItems = contact.phoneNumbers.mapIndexed { index, item -> | |
| RadioItem(index, item.normalizedNumber, item) | |
| } | |
| RadioGroupDialog(this, ArrayList(radioItems)) { | |
| number = (it as PhoneNumber).normalizedNumber | |
| } | |
| } | |
| val phoneNumbers = contact.phoneNumbers | |
| var number = if (phoneNumbers.size == 1) { | |
| phoneNumbers[0].normalizedNumber | |
| } else { | |
| phoneNumbers.firstOrNull { it.isPrimary }?.normalizedNumber | |
| ?: phoneNumbers.firstOrNull()?.normalizedNumber ?: return@forEachIndexed | |
| } | |
| this.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", number, null) | ||
| } | ||
| SimpleContactsHelper(this).getShortcutImage(contact.photoUri, contact.getNameToDisplay()) { image -> | ||
| this.runOnUiThread { | ||
| val shortcut = ShortcutInfo.Builder(this, "sd$index") | ||
| .setShortLabel(contact.getNameToDisplay()) | ||
| .setIcon(Icon.createWithAdaptiveBitmap(image)) | ||
| .setIntent(intent) | ||
| .build() | ||
| this.shortcutManager.pushDynamicShortcut(shortcut) |
There was a problem hiding this comment.
| this.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", number, null) | |
| } | |
| SimpleContactsHelper(this).getShortcutImage(contact.photoUri, contact.getNameToDisplay()) { image -> | |
| this.runOnUiThread { | |
| val shortcut = ShortcutInfo.Builder(this, "sd$index") | |
| .setShortLabel(contact.getNameToDisplay()) | |
| .setIcon(Icon.createWithAdaptiveBitmap(image)) | |
| .setIntent(intent) | |
| .build() | |
| this.shortcutManager.pushDynamicShortcut(shortcut) | |
| 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", number, null) | |
| } | |
| SimpleContactsHelper(this).getShortcutImage(contact.photoUri, contact.getNameToDisplay()) { image -> | |
| runOnUiThread { | |
| val shortcut = ShortcutInfo.Builder(this, "sd$index") | |
| .setShortLabel(contact.getNameToDisplay()) | |
| .setIcon(Icon.createWithAdaptiveBitmap(image)) | |
| .setIntent(intent) | |
| .build() | |
| shortcutManager.pushDynamicShortcut(shortcut) |
|
I can reproduce the sorting issue as well. Sometimes, I get shortcuts that are not even on my favorite list. Restarting the app doesn't help. It's probably because you are relying on Also, it should directly initiate a call instead of asking for a phone app. |
|
This pull request was automatically closed due to inactivity and/or lack of response from the author. If you have further updates or additional information, please comment or reopen the PR to continue. |


What is it?
Description of the changes in your PR
ACTION_DIALinstead ofACTION_CALLif calling permission is denied.Fixes the following issue(s)
Acknowledgement