-
+
+
{{ t(`chats.placeholder.${key}`) }}
-
-
- {{ t('chats.placeholder.public-key') }}
+
+
+
+ {{ t('chats.placeholder.public-key') }}
+
+
+ {{ t('chats.placeholder.key-missing') }}
+
@@ -22,6 +30,7 @@ const { t } = useI18n()
defineProps<{
showPlaceholder: boolean
isGettingPublicKey: boolean
+ isKeyMissing: boolean
}>()
const className = 'chat-placeholder'
@@ -64,6 +73,11 @@ const keys = ['encrypted', 'ipfs', 'anonymous', 'censorship']
}
}
+ &__spinner {
+ margin-bottom: 4px;
+ margin-right: 4px;
+ }
+
&__row {
width: 100%;
text-align: center;
diff --git a/src/locales/en.json b/src/locales/en.json
index 58df71db4..bd0d13250 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -38,6 +38,7 @@
"censorship": "⛓\uFE0F Censorship-resistant blockchain architecture",
"encrypted": "\uD83D\uDD10 End-to-end encrypted across all devices",
"ipfs": "☁\uFE0F Decentralized IPFS storage for files/media",
+ "key-missing": "Unable to start a chat, public key is missing",
"public-key": "Retrieving your partner’s key to encrypt messages…"
},
"received_label": "Received",
diff --git a/src/locales/ru.json b/src/locales/ru.json
index ef62e43b5..3f76b3350 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -38,6 +38,7 @@
"censorship": "⛓\uFE0F Устойчивая к цензуре блокчейн-архитектура",
"encrypted": "\uD83D\uDD10 Сквозное шифрование на всех устройствах",
"ipfs": "☁\uFE0F Распределенное IPFS-хранилище файлов и медиа",
+ "key-missing": "Невозможно начать чат, публичного ключа не существует",
"public-key": "Получаю ключ вашего собеседника для шифрования сообщений…"
},
"received_label": "Получили",
From 9788df991f8711ceaf8bcc34c170238a292b8276 Mon Sep 17 00:00:00 2001
From: skranee <125743202+skranee@users.noreply.github.com>
Date: Thu, 17 Apr 2025 12:52:53 +0300
Subject: [PATCH 08/18] refactor: AChatForm to composition API
---
src/components/AChat/AChatForm.vue | 463 ++++++++++++++---------------
1 file changed, 227 insertions(+), 236 deletions(-)
diff --git a/src/components/AChat/AChatForm.vue b/src/components/AChat/AChatForm.vue
index 409d6388d..9fd427297 100644
--- a/src/components/AChat/AChatForm.vue
+++ b/src/components/AChat/AChatForm.vue
@@ -43,262 +43,253 @@
-
diff --git a/src/components/AChat/AChatForm.vue b/src/components/AChat/AChatForm.vue
index b3d052815..7bf572fdc 100644
--- a/src/components/AChat/AChatForm.vue
+++ b/src/components/AChat/AChatForm.vue
@@ -10,7 +10,7 @@
v-model="message"
@input="onInput"
:placeholder="placeholder"
- :disabled="isKeyMissing"
+ :disabled="shouldDisableInput"
hide-details
single-line
auto-grow
@@ -60,7 +60,7 @@ type Props = {
showSendButton?: boolean
sendOnEnter?: boolean
label?: string
- isKeyMissing?: boolean
+ shouldDisableInput?: boolean
showDivider?: boolean
validator: (message: string) => string | false
}
@@ -71,7 +71,7 @@ const props = withDefaults(defineProps
(), {
showSendButton: true,
sendOnEnter: true,
label: undefined,
- isKeyMissing: false,
+ shouldDisableInput: false,
showDivider: false
})
diff --git a/src/components/Chat/Chat.vue b/src/components/Chat/Chat.vue
index 58d1c776e..468d1bfb0 100644
--- a/src/components/Chat/Chat.vue
+++ b/src/components/Chat/Chat.vue
@@ -202,7 +202,7 @@
:send-on-enter="sendMessageOnEnter"
:show-divider="true"
:label="t('chats.message')"
- :is-key-missing="isKeyMissing"
+ :should-disable-input="shouldDisableInput"
:message-text="
$route.query.messageText || $store.getters['draftMessage/draftMessage'](partnerId)
"
@@ -308,6 +308,7 @@ import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
import ChatPlaceholder from '@/components/Chat/ChatPlaceholder.vue'
+import { watchImmediate } from '@vueuse/core'
const validationErrors = {
emptyMessage: 'EMPTY_MESSAGE',
@@ -365,8 +366,16 @@ const isGettingPublicKey = ref(false)
const isKeyMissing = ref(false)
const messages = computed(() => store.getters['chat/messages'](props.partnerId))
+const userMessages = computed(() =>
+ messages.value.filter(
+ (message: NormalizedChatMessageTransaction) => message.senderId === userId.value
+ )
+)
const userId = computed(() => store.state.address)
const isNewChat = computed(() => store.getters['chat/isNewChat'](props.partnerId))
+const shouldDisableInput = computed(
+ () => isGettingPublicKey.value || isKeyMissing.value || !store.state.publicKeys[props.partnerId]
+)
const getPartnerName = (address: string) => {
const name: string = store.getters['partners/displayName'](address) || ''
@@ -432,12 +441,24 @@ watch(replyMessageId, (messageId) => {
})
})
+watch(userMessages, () => {
+ if (noMoreMessages.value) {
+ showNewChatPlaceholder.value = !userMessages.value.length
+ }
+})
+
+watchImmediate(messages, (updatedMessages) => {
+ if (isFulfilled.value && !updatedMessages.length) {
+ store.commit('chat/addNewChat', { partnerId: props.partnerId })
+ }
+})
+
onBeforeMount(() => {
window.addEventListener('keyup', onKeyPress)
})
-onMounted(async () => {
- if (chatPage.value <= 0) await fetchChatMessages()
+async function handleEmptyChat() {
+ showNewChatPlaceholder.value = !userMessages.value.length
if (!messages.value.length) {
store.commit('chat/addNewChat', { partnerId: props.partnerId })
@@ -448,13 +469,16 @@ onMounted(async () => {
await createChat(props.partnerId, partnerName)
}
+}
- const userMessages = messages.value.filter(
- (message: NormalizedChatMessageTransaction) =>
- message.senderId && message.senderId === userId.value
- )
+onMounted(async () => {
+ if (isNewChat.value) {
+ showNewChatPlaceholder.value = true
+ }
- showNewChatPlaceholder.value = !userMessages.length
+ if (chatPage.value <= 0) await fetchChatMessages()
+
+ await handleEmptyChat()
scrollBehavior()
nextTick(() => {
@@ -485,14 +509,9 @@ async function createChat(partnerId: string, partnerName: string) {
partnerId,
partnerName
})
- } catch (err: unknown) {
- const message = err instanceof Error ? err.message : 'Unknown error'
+ } catch {
vibrate.long()
isKeyMissing.value = true
-
- store.dispatch('snackbar/show', {
- message: message
- })
} finally {
isGettingPublicKey.value = false
}
diff --git a/src/components/Chat/ChatPlaceholder.vue b/src/components/Chat/ChatPlaceholder.vue
index ce1f7705c..ba4cb2b5e 100644
--- a/src/components/Chat/ChatPlaceholder.vue
+++ b/src/components/Chat/ChatPlaceholder.vue
@@ -1,7 +1,7 @@
-
+
{{ t(`chats.placeholder.${key}`) }}
@@ -15,14 +15,16 @@
{{ t('chats.placeholder.public-key') }}
diff --git a/src/components/ChatStartDialog.vue b/src/components/ChatStartDialog.vue
index 9ae200579..2208aa1a9 100644
--- a/src/components/ChatStartDialog.vue
+++ b/src/components/ChatStartDialog.vue
@@ -136,13 +136,7 @@ export default {
return Promise.reject(new Error(this.$t('chats.incorrect_address')))
}
- return this.$emit(
- 'start-chat',
- this.recipientAddress,
- this.uriMessage,
- this.recipientName,
- true
- )
+ this.$emit('start-chat', this.recipientAddress, this.uriMessage, this.recipientName, true)
},
/**
diff --git a/src/locales/en.json b/src/locales/en.json
index 034847c9a..068d6f682 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -38,7 +38,11 @@
"censorship": "⛓\uFE0F Censorship-resistant blockchain architecture",
"encrypted": "\uD83D\uDD10 End-to-end encrypted across all devices",
"ipfs": "☁\uFE0F Decentralized IPFS storage for files/media",
- "key-missing": "Unable to start a chat, public key is missing",
+ "can_not_message": "Cannot message this user yet—their account isn't activated",
+ "what_does_it_mean": {
+ "text": "What does it mean?",
+ "link": "https://news.adamant.im/chats-and-uninitialized-accounts-in-adamant-5035438e2fcd"
+ },
"public-key": "Retrieving your partner’s key to encrypt messages…"
},
"received_label": "Received",
diff --git a/src/locales/ru.json b/src/locales/ru.json
index 5ece842c4..08c315e9e 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -38,7 +38,11 @@
"censorship": "⛓\uFE0F Устойчивая к цензуре блокчейн-архитектура",
"encrypted": "\uD83D\uDD10 Сквозное шифрование на всех устройствах",
"ipfs": "☁\uFE0F Распределенное IPFS-хранилище файлов и медиа",
- "key-missing": "Невозможно начать чат, публичного ключа не существует",
+ "can_not_message": "Написать этому пользователю пока не получится — его аккаунт не активирован",
+ "what_does_it_mean": {
+ "text": "Что это значит?",
+ "link": "https://news.adamant.im/chats-and-uninitialized-accounts-in-adamant-5035438e2fcd"
+ },
"public-key": "Получаю ключ вашего собеседника для шифрования сообщений…"
},
"received_label": "Получили",
From 81c3bc047f73a6070a28b461a68a08998f27cf53 Mon Sep 17 00:00:00 2001
From: skranee <125743202+skranee@users.noreply.github.com>
Date: Sun, 20 Apr 2025 00:45:22 +0300
Subject: [PATCH 12/18] refactor: declare function after component lifecycle
stages
---
src/components/Chat/Chat.vue | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/components/Chat/Chat.vue b/src/components/Chat/Chat.vue
index 468d1bfb0..d2cefdba7 100644
--- a/src/components/Chat/Chat.vue
+++ b/src/components/Chat/Chat.vue
@@ -457,20 +457,6 @@ onBeforeMount(() => {
window.addEventListener('keyup', onKeyPress)
})
-async function handleEmptyChat() {
- showNewChatPlaceholder.value = !userMessages.value.length
-
- if (!messages.value.length) {
- store.commit('chat/addNewChat', { partnerId: props.partnerId })
- }
-
- if (isNewChat.value) {
- const partnerName = store.getters['chat/getPartnerName'](props.partnerId)
-
- await createChat(props.partnerId, partnerName)
- }
-}
-
onMounted(async () => {
if (isNewChat.value) {
showNewChatPlaceholder.value = true
@@ -502,6 +488,20 @@ onBeforeUnmount(() => {
}
})
+async function handleEmptyChat() {
+ showNewChatPlaceholder.value = !userMessages.value.length
+
+ if (!messages.value.length) {
+ store.commit('chat/addNewChat', { partnerId: props.partnerId })
+ }
+
+ if (isNewChat.value) {
+ const partnerName = store.getters['chat/getPartnerName'](props.partnerId)
+
+ await createChat(props.partnerId, partnerName)
+ }
+}
+
async function createChat(partnerId: string, partnerName: string) {
try {
isGettingPublicKey.value = true
From a65e875414877cefd3ec86c88a43f68b9fdf1e52 Mon Sep 17 00:00:00 2001
From: skranee <125743202+skranee@users.noreply.github.com>
Date: Tue, 29 Apr 2025 17:55:30 +0300
Subject: [PATCH 13/18] refactor: fix styles
---
src/assets/styles/components/_chat.scss | 2 ++
src/components/AChat/AChat.vue | 13 ++++++++++++-
src/components/Chat/Chat.vue | 1 +
src/components/Chat/ChatPlaceholder.vue | 9 ++++++---
4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/assets/styles/components/_chat.scss b/src/assets/styles/components/_chat.scss
index 921925782..87f31f3f3 100644
--- a/src/assets/styles/components/_chat.scss
+++ b/src/assets/styles/components/_chat.scss
@@ -19,6 +19,8 @@ $chat-avatar-size: 40px;
$scroll-bar-width: 4px;
+$placeholder-height: 248px;
+
.a-chat {
display: block;
text-decoration: none;
diff --git a/src/components/AChat/AChat.vue b/src/components/AChat/AChat.vue
index e6295bcdf..5710b19d3 100644
--- a/src/components/AChat/AChat.vue
+++ b/src/components/AChat/AChat.vue
@@ -10,7 +10,7 @@
@@ -253,6 +253,17 @@ defineExpose({