diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml
index 961acdc64efbcd86de06fe236952995e67ca2e1b..f0dfc8bc643cbaf0d34d22975068b3031fdaadcf 100644
--- a/src/app/constant/JamiStrings.qml
+++ b/src/app/constant/JamiStrings.qml
@@ -436,7 +436,7 @@ Item {
 
     // LinkedDevices
     property string tipLinkNewDevice: qsTr("Link a new device to this account")
-    property string linkNewDevice: qsTr("Exporting account…")
+    property string linkDevice: qsTr("Exporting account…")
     property string removeDevice: qsTr("Remove Device")
     property string sureToRemoveDevice: qsTr("Are you sure you wish to remove this device?")
     property string yourPinIs: qsTr("Your PIN is:")
@@ -575,13 +575,20 @@ Item {
     // LinkDevicesDialog
     property string pinTimerInfos: qsTr("The PIN and the account password should be entered in your device within 10 minutes.")
     property string close: qsTr("Close")
-    property string enterAccountPassword: qsTr("Enter account's password")
+    property string enterAccountPassword: qsTr("Enter account password")
+    property string enterPasswordPinCode: qsTr("This account is password encrypted, enter the password to generate a PIN code.")
     property string addDevice: qsTr("Add Device")
+    property string pinExpired: qsTr("PIN expired")
+    property string onAnotherDevice: qsTr("On another device")
+    property string onAnotherDeviceInstruction: qsTr("Install and launch Jami, select \"Import from another device\" and scan the QR code.")
+    property string linkNewDevice: qsTr("Link new device")
+    property string linkingInstructions: qsTr("In Jami, scan QR code or manually enter the PIN.")
+    property string pinValidity: qsTr("The PIN code is valid for: ")
 
     // PasswordDialog
-    property string enterPassword: qsTr("Enter the password")
+    property string enterPassword: qsTr("Enter password")
     property string enterCurrentPassword: qsTr("Enter current password")
-    property string confirmRemoval: qsTr("Enter this account's password to confirm the removal of this device")
+    property string confirmRemoval: qsTr("Enter account password to confirm the removal of this device")
     property string enterNewPassword: qsTr("Enter new password")
     property string confirmNewPassword: qsTr("Confirm new password")
     property string change: qsTr("Change")
diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml
index d417bcd973a632b026c0ceacb9735e51bddb9064..7a42dd6f59051bfaa0c0fd8f9b2db2e3d0c4f56f 100644
--- a/src/app/constant/JamiTheme.qml
+++ b/src/app/constant/JamiTheme.qml
@@ -643,6 +643,9 @@ Item {
     property int settingsMenuHeaderButtonHeight: 50
     property int settingsListViewsSpacing: 10
 
+    // Link Device
+    property color pinBackgroundColor: "#D6E4EF"
+
     // MaterialRadioButton
     property int radioImageSize: 30
     property color radioBackgroundColor: darkTheme ? "#303030" : "#F0EFEF"
diff --git a/src/app/qrimageprovider.h b/src/app/qrimageprovider.h
index eba496eb0572b9da4f189e0adfe5d58728e1d692..a3e4e71d782749c3b7d99e8462486c673152b1c1 100644
--- a/src/app/qrimageprovider.h
+++ b/src/app/qrimageprovider.h
@@ -33,7 +33,7 @@ public:
                                  instance)
     {}
 
-    enum class QrType { Account, Contact };
+    enum class QrType { Account, Contact, Raw };
 
     /*
      * Id should be string like account_0 (account index),
@@ -64,6 +64,8 @@ public:
             } catch (...) {
             }
             return {QrType::Contact, {}};
+        } else if (list.contains("raw") && list.size() > 1) {
+            return {QrType::Raw, list[1]};
         }
         return {QrType::Account, {}};
     }
@@ -73,26 +75,24 @@ public:
         Q_UNUSED(size);
 
         QString uri;
-        auto indexPair = getIndexFromID(id);
+        auto [type, identifier] = getIndexFromID(id);
 
-        if (indexPair.first == QrType::Contact) {
-            uri = indexPair.second;
-        } else {
-            if (indexPair.second.isEmpty())
+        if (type == QrType::Account) {
+            if (identifier.isEmpty())
                 return QImage();
-            auto accountId = indexPair.second;
             try {
-                auto& accountInfo = lrcInstance_->getAccountInfo(accountId);
+                auto& accountInfo = lrcInstance_->getAccountInfo(identifier);
                 uri = accountInfo.profileInfo.uri;
             } catch (const std::out_of_range&) {
-                qWarning() << "Couldn't get account info for id:" << accountId;
+                qWarning() << "Couldn't get account info for id:" << identifier;
                 return QImage();
             }
-        }
+        } else
+            uri = identifier;
 
         if (!requestedSize.isEmpty())
-            return Utils::setupQRCode(uri, 0).scaled(requestedSize, Qt::KeepAspectRatio);
+            return Utils::getQRCodeImage(uri, 0).scaled(requestedSize, Qt::KeepAspectRatio);
         else
-            return Utils::setupQRCode(uri, 0);
+            return Utils::getQRCodeImage(uri, 0);
     }
 };
diff --git a/src/app/settingsview/components/LinkDeviceDialog.qml b/src/app/settingsview/components/LinkDeviceDialog.qml
index 3db9f9638e352f91a3a095c1fa667ab1896aca7c..c0ad198aa815ebe57e1b5d31461873775b9e0213 100644
--- a/src/app/settingsview/components/LinkDeviceDialog.qml
+++ b/src/app/settingsview/components/LinkDeviceDialog.qml
@@ -23,13 +23,16 @@ import net.jami.Models 1.1
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
 import "../../commoncomponents"
+import "../../mainview/components"
 
 BaseModalDialog {
     id: root
 
     signal accepted
 
-    title: JamiStrings.addDevice
+    title: JamiStrings.linkNewDevice
+
+    property bool darkTheme: UtilsAdapter.useApplicationTheme()
 
     popupContent: StackLayout {
         id: stackedWidget
@@ -47,13 +50,11 @@ BaseModalDialog {
         function setExportPage(status, pin) {
             if (status === NameDirectory.ExportOnRingStatus.SUCCESS) {
                 infoLabel.success = true;
-                yourPinLabel.visible = true;
-                exportedPIN.visible = true;
-                infoLabel.text = JamiStrings.pinTimerInfos;
+                pinRectangle.visible = true
                 exportedPIN.text = pin;
             } else {
-                infoLabel.success = false;
-                infoLabelsRowLayout.visible = false;
+                pinRectangle.success = false;
+                infoLabel.visible = true;
                 switch (status) {
                 case NameDirectory.ExportOnRingStatus.WRONG_PASSWORD:
                     infoLabel.text = JamiStrings.incorrectPassword;
@@ -86,15 +87,14 @@ BaseModalDialog {
 
             function onExportOnRingEnded(status, pin) {
                 stackedWidget.setExportPage(status, pin);
+                countdownTimer.start();
             }
         }
 
         onVisibleChanged: {
             if (visible) {
-                infoLabel.text = JamiStrings.pinTimerInfos;
                 if (CurrentAccount.hasArchivePassword) {
                     stackedWidget.currentIndex = enterPasswordPage.pageIndex;
-                    passwordEdit.forceActiveFocus();
                 } else {
                     setGeneratingPage();
                 }
@@ -107,14 +107,23 @@ BaseModalDialog {
 
             readonly property int pageIndex: 0
 
+            Component.onCompleted: passwordEdit.forceActiveFocus()
+
+            onHeightChanged: {
+                stackedWidget.height = passwordLayout.implicitHeight
+            }
+
             ColumnLayout {
+                id: passwordLayout
                 spacing: JamiTheme.preferredMarginSize
                 anchors.centerIn: parent
 
                 Label {
                     Layout.alignment: Qt.AlignCenter
+                    Layout.maximumWidth: root.width - 4 * JamiTheme.preferredMarginSize
+                    wrapMode: Text.Wrap
 
-                    text: JamiStrings.enterAccountPassword
+                    text: JamiStrings.enterPasswordPinCode
                     color: JamiTheme.textColor
                     font.pointSize: JamiTheme.textFontSize
                     font.kerning: true
@@ -122,70 +131,48 @@ BaseModalDialog {
                     verticalAlignment: Text.AlignVCenter
                 }
 
-                PasswordTextEdit {
-                    id: passwordEdit
-
-                    firstEntry: true
-                    placeholderText: JamiStrings.password
-
+                RowLayout {
                     Layout.topMargin: 10
                     Layout.leftMargin: JamiTheme.cornerIconSize
                     Layout.rightMargin: JamiTheme.cornerIconSize
-                    Layout.alignment: Qt.AlignLeft
-                    Layout.fillWidth: true
-
-                    KeyNavigation.up: btnConfirm
-                    KeyNavigation.down: KeyNavigation.up
-
-                    onDynamicTextChanged: {
-                        btnConfirm.enabled = dynamicText.length > 0;
-                    }
-                    onAccepted: btnConfirm.clicked()
-                }
-
-                RowLayout {
-                    Layout.alignment: Qt.AlignCenter
+                    spacing: JamiTheme.preferredMarginSize
                     Layout.bottomMargin: JamiTheme.preferredMarginSize
-                    spacing: 16
 
-                    MaterialButton {
-                        id: btnConfirm
+                    PasswordTextEdit {
+                        id: passwordEdit
 
-                        Layout.alignment: Qt.AlignHCenter
+                        firstEntry: true
+                        placeholderText: JamiStrings.password
 
-                        preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
-                        buttontextHeightMargin: JamiTheme.buttontextHeightMargin
+                        Layout.alignment: Qt.AlignLeft
+                        Layout.fillWidth: true
 
-                        color: enabled ? JamiTheme.buttonTintedBlack : JamiTheme.buttonTintedGrey
-                        hoveredColor: JamiTheme.buttonTintedBlackHovered
-                        pressedColor: JamiTheme.buttonTintedBlackPressed
-                        secondary: true
-                        autoAccelerator: true
-                        enabled: false
+                        KeyNavigation.up: btnConfirm
+                        KeyNavigation.down: KeyNavigation.up
 
-                        text: JamiStrings.exportAccount
-
-                        onClicked: stackedWidget.setGeneratingPage()
+                        onDynamicTextChanged: {
+                            btnConfirm.enabled = dynamicText.length > 0;
+                            btnConfirm.hoverEnabled = dynamicText.length > 0;
+                        }
+                        onAccepted: btnConfirm.clicked()
                     }
 
-                    MaterialButton {
-                        id: btnCancel
+                    JamiPushButton {
+                        id: btnConfirm
 
-                        Layout.alignment: Qt.AlignHCenter
+                        Layout.alignment: Qt.AlignCenter
+                        height: 40
+                        width: 40
+                        preferredSize: 60
 
-                        preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
-                        buttontextHeightMargin: JamiTheme.buttontextHeightMargin
+                        hoverEnabled: false
+                        enabled: false
 
-                        color: JamiTheme.buttonTintedBlack
-                        hoveredColor: JamiTheme.buttonTintedBlackHovered
-                        pressedColor: JamiTheme.buttonTintedBlackPressed
-                        secondary: true
-                        autoAccelerator: true
-                        enabled: true
+                        imageColor: JamiTheme.tintedBlue
+                        source: JamiResources.check_box_24dp_svg
 
-                        text: JamiStrings.optionCancel
+                        onClicked: stackedWidget.setGeneratingPage()
 
-                        onClicked: close()
                     }
                 }
             }
@@ -197,6 +184,11 @@ BaseModalDialog {
 
             readonly property int pageIndex: 1
 
+            onHeightChanged: {
+                stackedWidget.height = spinnerLayout.implicitHeight
+            }
+
+
             ColumnLayout {
                 id: spinnerLayout
 
@@ -206,7 +198,7 @@ BaseModalDialog {
                 Label {
                     Layout.alignment: Qt.AlignCenter
 
-                    text: JamiStrings.linkNewDevice
+                    text: JamiStrings.linkDevice
                     color: JamiTheme.textColor
                     font.pointSize: JamiTheme.headerFontSize
                     font.kerning: true
@@ -246,40 +238,171 @@ BaseModalDialog {
             ColumnLayout {
                 id: exportingLayout
 
+                spacing: JamiTheme.preferredMarginSize
+
                 Label {
-                    id: yourPinLabel
+                    id: instructionLabel
 
+                    Layout.maximumWidth: JamiTheme.preferredDialogWidth
                     Layout.alignment: Qt.AlignCenter
 
-                    text: JamiStrings.yourPinIs
                     color: JamiTheme.textColor
-                    font.pointSize: JamiTheme.headerFontSize
+                    padding: 8
+
+                    wrapMode: Text.Wrap
+                    text: JamiStrings.linkingInstructions
+                    font.pointSize: JamiTheme.textFontSize
                     font.kerning: true
                     horizontalAlignment: Text.AlignHCenter
                     verticalAlignment: Text.AlignVCenter
+
+                }
+
+                Rectangle {
+                    Layout.alignment: Qt.AlignCenter
+
+                    border.width: 3
+                    border.color: JamiTheme.textColor
+                    radius: JamiTheme.primaryRadius
+                    color: darkTheme ? JamiTheme.textColor : JamiTheme.secondaryBackgroundColor
+                    width: 170
+                    height: 170
+
+                    Image {
+                         id: qrImage
+
+                         anchors.fill: parent
+                         anchors.margins: 10
+
+                         mipmap: false
+                         smooth: false
+
+                         source: "image://qrImage/raw_" + exportedPIN.text
+                         sourceSize.width: 150
+                         sourceSize.height: 150
+                    }
+                }
+
+                Rectangle {
+                    id: pinRectangle
+
+                    radius: 15
+                    color: darkTheme ? JamiTheme.tintedBlue : JamiTheme.pinBackgroundColor
+
+                    width: exportedPIN.implicitWidth + 4 * JamiTheme.preferredMarginSize
+                    height: exportedPIN.implicitHeight + 2 * JamiTheme.preferredMarginSize
+
+                    Layout.alignment: Qt.AlignCenter
+                    Layout.margins: JamiTheme.preferredMarginSize
+
+                    MaterialLineEdit {
+                        id: exportedPIN
+
+                        padding: 0
+                        anchors.centerIn: parent
+
+                        text: JamiStrings.pin
+                        wrapMode: Text.NoWrap
+
+                        backgroundColor: darkTheme ? JamiTheme.tintedBlue : JamiTheme.pinBackgroundColor
+
+                        color: darkTheme ? JamiTheme.textColor : JamiTheme.tintedBlue
+                        selectByMouse: true
+                        readOnly: true
+                        font.pointSize: JamiTheme.headerFontSize
+                        font.kerning: true
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                    }
                 }
 
-                MaterialLineEdit {
-                    id: exportedPIN
+                RowLayout {
 
-                    padding: 0
                     Layout.alignment: Qt.AlignCenter
+                    Layout.bottomMargin: JamiTheme.preferredMarginSize
+                    spacing: 0
+
+                    Label {
+                        id: validityLabel
+
+                        Layout.alignment: Qt.AlignRight
+
+                        color: JamiTheme.textColor
+                        text: JamiStrings.pinValidity
+                        font.pointSize: JamiTheme.textFontSize
+                        font.kerning: true
+                    }
+
+                    Label {
+                        id: countdownLabel
+
+                        color: JamiTheme.textColor
+                        Layout.alignment: Qt.AlignLeft
+                        font.pointSize: JamiTheme.textFontSize
+                        font.kerning: true
+
+                        text: "10:00"
+                    }
+
+                    Timer {
+                         id: countdownTimer
+                         interval: 1000
+                         repeat: true
 
-                    text: JamiStrings.pin
-                    wrapMode: Text.NoWrap
+                         property int remainingTime: 600
+
+                         onTriggered: {
+                             remainingTime--
+
+                             var minutes = Math.floor(remainingTime / 60)
+                             var seconds = remainingTime % 60
+                             countdownLabel.text = (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds
+
+                             if (remainingTime <= 0) {
+                                 validityLabel.visible = false
+                                 countdownLabel.text = JamiStrings.pinExpired
+                                 countdownLabel.color = JamiTheme.redColor
+                                 countdownTimer.stop()
+                              }
+                          }
+                     }
+
+                }
+
+                Label {
+                    id: otherDeviceLabel
+
+                    Layout.alignment: Qt.AlignCenter
 
                     color: JamiTheme.textColor
-                    selectByMouse: true
-                    readOnly: true
-                    font.pointSize: JamiTheme.headerFontSize
+                    text: JamiStrings.onAnotherDevice
+                    font.pointSize: JamiTheme.smallFontSize
                     font.kerning: true
+                    font.bold: true
+                }
+
+                Label {
+                    id: otherInstructionLabel
+
+                    Layout.maximumWidth: JamiTheme.preferredDialogWidth
+                    Layout.bottomMargin: JamiTheme.preferredMarginSize
+                    Layout.alignment: Qt.AlignCenter
+                    wrapMode: Text.Wrap
                     horizontalAlignment: Text.AlignHCenter
                     verticalAlignment: Text.AlignVCenter
+
+                    color: JamiTheme.textColor
+                    text: JamiStrings.onAnotherDeviceInstruction
+                    font.pointSize: JamiTheme.smallFontSize
+                    font.kerning: true
                 }
 
+                // Displays error messages
                 Label {
                     id: infoLabel
 
+                    visible: false
+
                     property bool success: false
                     property int borderWidth: success ? 1 : 0
                     property int borderRadius: success ? 15 : 0
@@ -295,7 +418,6 @@ BaseModalDialog {
                     padding: success ? 8 : 0
 
                     wrapMode: Text.Wrap
-                    text: JamiStrings.pinTimerInfos
                     font.pointSize: success ? JamiTheme.textFontSize : JamiTheme.textFontSize + 3
                     font.kerning: true
                     horizontalAlignment: Text.AlignHCenter
diff --git a/src/app/settingsview/components/LinkedDevicesPage.qml b/src/app/settingsview/components/LinkedDevicesPage.qml
index da9c2f0da4f3656522f42e073f275026cb1764c4..edd1aaeb91443ef4d1e5ad322a7f3c5446f502c8 100644
--- a/src/app/settingsview/components/LinkedDevicesPage.qml
+++ b/src/app/settingsview/components/LinkedDevicesPage.qml
@@ -39,6 +39,47 @@ SettingsPageBase {
         anchors.left: parent.left
         anchors.leftMargin: JamiTheme.preferredSettingsMarginSize
 
+
+
+        Text {
+            id: linkDescription
+
+            Layout.alignment: Qt.AlignLeft
+            Layout.fillWidth: true
+
+            text: JamiStrings.linkDescription
+            color: JamiTheme.textColor
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            wrapMode: Text.WordWrap
+
+            font.pixelSize: JamiTheme.settingsDescriptionPixelSize
+            font.kerning: true
+            lineHeight: JamiTheme.wizardViewTextLineHeight
+        }
+
+        MaterialButton {
+            id: linkDeviceBtn
+
+            TextMetrics {
+                id: linkDeviceBtnTextSize
+                font.weight: Font.Bold
+                font.pixelSize: JamiTheme.wizardViewButtonFontPixelSize
+                text: linkDeviceBtn.text
+            }
+
+            preferredWidth: linkDeviceBtnTextSize.width + 2 * JamiTheme.buttontextWizzardPadding
+            Layout.bottomMargin: JamiTheme.preferredMarginSize
+
+            primary: true
+            Layout.alignment: Qt.AlignLeft
+
+            toolTipText: JamiStrings.tipLinkNewDevice
+            text: JamiStrings.linkNewDevice
+
+            onClicked: viewCoordinator.presentDialog(appWindow, "settingsview/components/LinkDeviceDialog.qml")
+        }
+
         Text {
             id: linkedDevicesTitle
 
diff --git a/src/app/settingsview/components/ManageAccountPage.qml b/src/app/settingsview/components/ManageAccountPage.qml
index e5627dc6df84bb2e14f31957960dfbcfaa370367..cfddc59f1b73814214bac6e969339abba5f7f9b9 100644
--- a/src/app/settingsview/components/ManageAccountPage.qml
+++ b/src/app/settingsview/components/ManageAccountPage.qml
@@ -218,7 +218,7 @@ SettingsPageBase {
                 Layout.alignment: Qt.AlignLeft
 
                 toolTipText: JamiStrings.tipLinkNewDevice
-                text: JamiStrings.linkAnotherDevice
+                text: JamiStrings.linkNewDevice
 
                 onClicked: viewCoordinator.presentDialog(appWindow, "settingsview/components/LinkDeviceDialog.qml")
             }
diff --git a/src/app/utils.cpp b/src/app/utils.cpp
index 57fe7e6aadde58eb19652daaa282d74fce7a94ed..78f3c8af43cdae8fe488ad3145fd3b9f3b62d00a 100644
--- a/src/app/utils.cpp
+++ b/src/app/utils.cpp
@@ -805,9 +805,9 @@ Utils::pixmapFromSvg(const QString& svg_resource, const QSize& size)
 }
 
 QImage
-Utils::setupQRCode(QString ringID, int margin)
+Utils::getQRCodeImage(QString data, int margin)
 {
-    auto qrcode = QRcode_encodeString(ringID.toStdString().c_str(),
+    auto qrcode = QRcode_encodeString(data.toStdString().c_str(),
                                       0,            // Let the version be decided by libqrencode
                                       QR_ECLEVEL_L, // Lowest level of error correction
                                       QR_MODE_8,    // 8-bit data mode
diff --git a/src/app/utils.h b/src/app/utils.h
index 6e762be25f97d5c49a04d7a7b14bea53fd7e1eb2..886d28877de9057fd1941c63500d4d4d938af236 100644
--- a/src/app/utils.h
+++ b/src/app/utils.h
@@ -119,7 +119,7 @@ QPixmap generateTintedPixmap(const QPixmap& pix, QColor color);
 QImage scaleAndFrame(const QImage photo, const QSize& size = defaultAvatarSize);
 QImage cropImage(const QImage& img);
 QPixmap pixmapFromSvg(const QString& svg_resource, const QSize& size);
-QImage setupQRCode(QString ringID, int margin);
+QImage getQRCodeImage(QString data, int margin);
 bool isImage(const QString& fileExt);
 QString generateUid();