diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java
index 6384e42d47..a17d5327c4 100644
--- a/src/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/src/org/thoughtcrime/securesms/ApplicationContext.java
@@ -188,6 +188,12 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
     };
     // Loki - Set up public chat manager
     lokiPublicChatManager = new LokiPublicChatManager(this);
+
+    // Loki - Update device mappings
+    setUpStorageAPIIfNeeded();
+    if (IdentityKeyUtil.hasIdentityKey(this)) {
+      LokiStorageAPI.Companion.getShared().updateUserDeviceMappings();
+    }
   }
 
   @Override
@@ -199,7 +205,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
     // Loki - Start long polling if needed
     startLongPollingIfNeeded();
     lokiPublicChatManager.startPollersIfNeeded();
-    setUpStorageAPIIfNeeded();
   }
 
   @Override
diff --git a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
index 57330e0685..b95405a8a1 100644
--- a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
+++ b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java
@@ -39,9 +39,12 @@ import android.support.v7.app.AlertDialog;
 import android.support.v7.preference.Preference;
 import android.widget.Toast;
 
+import org.jetbrains.annotations.NotNull;
 import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
 import org.thoughtcrime.securesms.loki.DeviceLinkingDialog;
+import org.thoughtcrime.securesms.loki.DeviceLinkingDialogDelegate;
 import org.thoughtcrime.securesms.loki.DeviceLinkingView;
+import org.thoughtcrime.securesms.loki.MultiDeviceUtilitiesKt;
 import org.thoughtcrime.securesms.loki.QRCodeDialog;
 import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
 import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
@@ -52,6 +55,7 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
 import org.thoughtcrime.securesms.util.DynamicLanguage;
 import org.thoughtcrime.securesms.util.DynamicTheme;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.whispersystems.signalservice.loki.api.PairingAuthorisation;
 import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
 import org.whispersystems.signalservice.loki.utilities.Analytics;
 import org.whispersystems.signalservice.loki.utilities.SerializationKt;
@@ -168,15 +172,15 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
         .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_SMS_MMS));
        */
       this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
-        .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_NOTIFICATIONS));
+        .setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_NOTIFICATIONS));
       this.findPreference(PREFERENCE_CATEGORY_APP_PROTECTION)
-        .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APP_PROTECTION));
+        .setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_APP_PROTECTION));
       /*
       this.findPreference(PREFERENCE_CATEGORY_APPEARANCE)
         .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APPEARANCE));
        */
       this.findPreference(PREFERENCE_CATEGORY_CHATS)
-        .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CHATS));
+        .setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_CHATS));
       /*
       this.findPreference(PREFERENCE_CATEGORY_DEVICES)
         .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_DEVICES));
@@ -184,19 +188,19 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
         .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED));
        */
       this.findPreference(PREFERENCE_CATEGORY_PUBLIC_KEY)
-        .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_PUBLIC_KEY));
+        .setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_PUBLIC_KEY));
       this.findPreference(PREFERENCE_CATEGORY_QR_CODE)
-        .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_QR_CODE));
+        .setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_QR_CODE));
 
       Preference linkDevicePreference = this.findPreference(PREFERENCE_CATEGORY_LINK_DEVICE);
       // Hide if this is a slave device
       linkDevicePreference.setVisible(isMasterDevice);
-      linkDevicePreference.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_LINK_DEVICE));
+      linkDevicePreference.setOnPreferenceClickListener(new CategoryClickListener(getContext(), PREFERENCE_CATEGORY_LINK_DEVICE));
 
       Preference seedPreference = this.findPreference(PREFERENCE_CATEGORY_SEED);
       // Hide if this is a slave device
       seedPreference.setVisible(isMasterDevice);
-      seedPreference.setOnPreferenceClickListener(new CategoryClickListener((PREFERENCE_CATEGORY_SEED)));
+      seedPreference.setOnPreferenceClickListener(new CategoryClickListener(getContext(), (PREFERENCE_CATEGORY_SEED)));
 
       if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
         tintIcons(getActivity());
@@ -289,10 +293,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
       this.findPreference(PREFERENCE_CATEGORY_SEED).setIcon(seed);
     }
 
-    private class CategoryClickListener implements Preference.OnPreferenceClickListener {
+    private class CategoryClickListener implements Preference.OnPreferenceClickListener, DeviceLinkingDialogDelegate {
       private String category;
+      private Context context;
 
-      CategoryClickListener(String category) {
+      CategoryClickListener(Context context,String category) {
+        this.context = context;
         this.category = category;
       }
 
@@ -345,7 +351,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
           QRCodeDialog.INSTANCE.show(getContext());
           break;
         case PREFERENCE_CATEGORY_LINK_DEVICE:
-          DeviceLinkingDialog.Companion.show(getContext(), DeviceLinkingView.Mode.Master, null);
+          DeviceLinkingDialog.Companion.show(getContext(), DeviceLinkingView.Mode.Master, this);
           break;
         case PREFERENCE_CATEGORY_SEED:
           Analytics.Companion.getShared().track("Seed Modal Shown");
@@ -388,6 +394,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
 
         return true;
       }
+
+      @Override public void sendPairingAuthorizedMessage(@NotNull PairingAuthorisation pairingAuthorisation) {
+        MultiDeviceUtilitiesKt.signAndSendPairingAuthorisationMessage(context, pairingAuthorisation);
+      }
+      @Override public void handleDeviceLinkAuthorized(@NotNull PairingAuthorisation pairingAuthorisation) {}
+      @Override public void handleDeviceLinkingDialogDismissed() {}
     }
 
     private class ProfileClickListener implements Preference.OnPreferenceClickListener {
diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java
index d51d1b3ce9..df31ce5517 100644
--- a/src/org/thoughtcrime/securesms/ConversationListActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java
@@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
 import org.thoughtcrime.securesms.util.DynamicTheme;
 import org.thoughtcrime.securesms.util.TextSecurePreferences;
 import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
+import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
 
 import java.util.List;
 
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
index 5ba7f8efbe..1160cf963f 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
@@ -2203,7 +2203,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
     boolean shouldEnableInput = isFriendsWithAnyLinkedDevices || !hasPendingFriendRequest;
     updateToggleButtonState();
     inputPanel.setEnabled(shouldEnableInput);
-    int hintID = shouldEnableInput ? R.string.activity_conversation_pending_friend_request_hint : R.string.activity_conversation_default_hint;
+    int hintID = shouldEnableInput ? R.string.activity_conversation_default_hint : R.string.activity_conversation_pending_friend_request_hint;
     inputPanel.setHint(getResources().getString(hintID));
     if (!shouldEnableInput) {
       inputPanel.composeText.requestFocus();
diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
index e7b8129e12..304f72b711 100644
--- a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
+++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
@@ -6,6 +6,7 @@ import nl.komponents.kovenant.deferred
 import nl.komponents.kovenant.functional.bind
 import nl.komponents.kovenant.functional.map
 import org.thoughtcrime.securesms.ApplicationContext
+import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
 import org.thoughtcrime.securesms.database.Address
 import org.thoughtcrime.securesms.database.DatabaseFactory
 import org.thoughtcrime.securesms.logging.Log
@@ -18,6 +19,7 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress
 import org.whispersystems.signalservice.loki.api.LokiStorageAPI
 import org.whispersystems.signalservice.loki.api.PairingAuthorisation
 import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
+import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
 
 fun getAllDeviceFriendRequestStatus(context: Context, hexEncodedPublicKey: String, storageAPI: LokiStorageAPI): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
   val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
@@ -102,4 +104,22 @@ fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey
     Log.d("Loki", "Failed to send authorisation message to: $contactHexEncodedPublicKey.")
     Promise.ofFail(e)
   }
+}
+
+fun signAndSendPairingAuthorisationMessage(context: Context, pairingAuthorisation: PairingAuthorisation) {
+  val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
+  val signedPairingAuthorisation = pairingAuthorisation.sign(PairingAuthorisation.Type.GRANT, userPrivateKey)
+  if (signedPairingAuthorisation == null || signedPairingAuthorisation.type != PairingAuthorisation.Type.GRANT) {
+    Log.d("Loki", "Failed to sign pairing authorization.")
+    return
+  }
+  retryIfNeeded(8) {
+    sendPairingAuthorisationMessage(context, pairingAuthorisation.secondaryDevicePublicKey, signedPairingAuthorisation).get()
+  }.fail {
+    Log.d("Loki", "Failed to send pairing authorization message to ${pairingAuthorisation.secondaryDevicePublicKey}.")
+  }
+  DatabaseFactory.getLokiAPIDatabase(context).insertOrUpdatePairingAuthorisation(signedPairingAuthorisation)
+  LokiStorageAPI.shared.updateUserDeviceMappings().fail { exception ->
+    Log.w("Loki", "Failed to update device mapping")
+  }
 }
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/loki/SeedActivity.kt b/src/org/thoughtcrime/securesms/loki/SeedActivity.kt
index a98b6c5a46..1eaea1308d 100644
--- a/src/org/thoughtcrime/securesms/loki/SeedActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/SeedActivity.kt
@@ -225,22 +225,6 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate {
         resetForRegistration()
     }
 
-    override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {
-        val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).privateKey.serialize()
-        val signedPairingAuthorisation = pairingAuthorisation.sign(PairingAuthorisation.Type.GRANT, userPrivateKey)
-        if (signedPairingAuthorisation == null || signedPairingAuthorisation.type != PairingAuthorisation.Type.GRANT) {
-            Log.d("Loki", "Failed to sign pairing authorization.")
-            return
-        }
-        retryIfNeeded(8) {
-            sendPairingAuthorisationMessage(this, pairingAuthorisation.secondaryDevicePublicKey, signedPairingAuthorisation).get()
-        }.fail {
-            Log.d("Loki", "Failed to send pairing authorization message to ${pairingAuthorisation.secondaryDevicePublicKey}.")
-        }
-        DatabaseFactory.getLokiAPIDatabase(this).insertOrUpdatePairingAuthorisation(signedPairingAuthorisation)
-        LokiStorageAPI.shared.updateUserDeviceMappings()
-    }
-
     private fun resetForRegistration() {
         IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey)
         TextSecurePreferences.removeLocalRegistrationId(this)
diff --git a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
index f72f614fd6..9d403bad9a 100644
--- a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
+++ b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
@@ -76,7 +76,9 @@ public class MarkReadReceiver extends BroadcastReceiver {
 
     for (MarkedMessageInfo messageInfo : markedReadMessages) {
       scheduleDeletion(context, messageInfo.getExpirationInfo());
-      syncMessageIds.add(messageInfo.getSyncMessageId());
+      if (!messageInfo.getSyncMessageId().getAddress().isGroup()) {
+        syncMessageIds.add(messageInfo.getSyncMessageId());
+      }
     }
 
     ApplicationContext.getInstance(context)