1package eu.siacs.conversations.services;
2
3import android.annotation.TargetApi;
4import android.content.Intent;
5import android.content.pm.ShortcutInfo;
6import android.content.pm.ShortcutManager;
7import android.graphics.drawable.Icon;
8import android.net.Uri;
9import android.os.Build;
10import android.util.Log;
11
12import java.util.ArrayList;
13import java.util.HashMap;
14import java.util.List;
15
16import eu.siacs.conversations.Config;
17import eu.siacs.conversations.entities.Account;
18import eu.siacs.conversations.entities.Contact;
19import eu.siacs.conversations.ui.StartConversationActivity;
20import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
21import rocks.xmpp.addr.Jid;
22
23public class ShortcutService {
24
25 private final XmppConnectionService xmppConnectionService;
26 private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor = new ReplacingSerialSingleThreadExecutor(false);
27
28 public ShortcutService(XmppConnectionService xmppConnectionService) {
29 this.xmppConnectionService = xmppConnectionService;
30 }
31
32 public void refresh() {
33 refresh(false);
34 }
35
36 public void refresh(final boolean forceUpdate) {
37 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
38 final Runnable r = new Runnable() {
39 @Override
40 public void run() {
41 refreshImpl(forceUpdate);
42 }
43 };
44 replacingSerialSingleThreadExecutor.execute(r);
45 }
46 }
47
48 @TargetApi(25)
49 public void report(Contact contact) {
50 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
51 ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class);
52 shortcutManager.reportShortcutUsed(getShortcutId(contact));
53 }
54 }
55
56 @TargetApi(25)
57 private void refreshImpl(boolean forceUpdate) {
58 List<FrequentContact> frequentContacts = xmppConnectionService.databaseBackend.getFrequentContacts(30);
59 HashMap<String,Account> accounts = new HashMap<>();
60 for(Account account : xmppConnectionService.getAccounts()) {
61 accounts.put(account.getUuid(),account);
62 }
63 List<Contact> contacts = new ArrayList<>();
64 for(FrequentContact frequentContact : frequentContacts) {
65 Account account = accounts.get(frequentContact.account);
66 if (account != null) {
67 contacts.add(account.getRoster().getContact(frequentContact.contact));
68 }
69 }
70 ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class);
71 boolean needsUpdate = forceUpdate || contactsChanged(contacts,shortcutManager.getDynamicShortcuts());
72 if (!needsUpdate) {
73 Log.d(Config.LOGTAG,"skipping shortcut update");
74 return;
75 }
76 List<ShortcutInfo> newDynamicShortCuts = new ArrayList<>();
77 for (Contact contact : contacts) {
78 ShortcutInfo shortcut = new ShortcutInfo.Builder(xmppConnectionService, getShortcutId(contact))
79 .setShortLabel(contact.getDisplayName())
80 .setIntent(getShortcutIntent(contact))
81 .setIcon(Icon.createWithBitmap(xmppConnectionService.getAvatarService().getRoundedShortcut(contact)))
82 .build();
83 newDynamicShortCuts.add(shortcut);
84 }
85 if (shortcutManager.setDynamicShortcuts(newDynamicShortCuts)) {
86 Log.d(Config.LOGTAG,"updated dynamic shortcuts");
87 } else {
88 Log.d(Config.LOGTAG, "unable to update dynamic shortcuts");
89 }
90 }
91
92 private static boolean contactsChanged(List<Contact> needles, List<ShortcutInfo> haystack) {
93 for(Contact needle : needles) {
94 if(!contactExists(needle,haystack)) {
95 return true;
96 }
97 }
98 return needles.size() != haystack.size();
99 }
100
101 @TargetApi(25)
102 private static boolean contactExists(Contact needle, List<ShortcutInfo> haystack) {
103 for(ShortcutInfo shortcutInfo : haystack) {
104 if (getShortcutId(needle).equals(shortcutInfo.getId()) && needle.getDisplayName().equals(shortcutInfo.getShortLabel())) {
105 return true;
106 }
107 }
108 return false;
109 }
110
111 private static String getShortcutId(Contact contact) {
112 return contact.getAccount().getJid().asBareJid().toString()+"#"+contact.getJid().asBareJid().toString();
113 }
114
115 private Intent getShortcutIntent(Contact contact) {
116 Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class);
117 intent.setAction(Intent.ACTION_VIEW);
118 intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toString()));
119 intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString());
120 return intent;
121 }
122
123 public static class FrequentContact {
124 private final String account;
125 private final Jid contact;
126
127 public FrequentContact(String account, Jid contact) {
128 this.account = account;
129 this.contact = contact;
130 }
131 }
132
133}