Skip to content

Commit 73d48ba

Browse files
authored
Merge pull request #746 from Adamant-im/feat/spinner-when-restore
Feat/spinner when restore
2 parents feeb952 + 8a2b4ab commit 73d48ba

File tree

14 files changed

+521
-459
lines changed

14 files changed

+521
-459
lines changed

src/components/AppToolbarCentered.vue

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,57 @@
1010
{{ subtitle }}
1111
</div>
1212
</v-toolbar-title>
13+
<v-progress-circular
14+
class="spinner"
15+
v-show="!isOnline && hasSpinner"
16+
indeterminate
17+
:size="24"
18+
/>
1319
</v-toolbar>
1420
</container>
1521
</v-row>
1622
</v-container>
1723
</template>
1824

19-
<script setup lang="ts">
25+
<script lang="ts" setup>
2026
import BackButton from '@/components/common/BackButton/BackButton.vue'
21-
import { useRoute, useRouter } from 'vue-router'
27+
import { useStore } from 'vuex'
2228
import { computed } from 'vue'
29+
import { useRoute, useRouter } from 'vue-router'
2330
24-
const props = defineProps({
25-
title: {
26-
type: String,
27-
default: undefined
28-
},
29-
subtitle: {
30-
type: String,
31-
default: undefined
32-
},
33-
flat: {
34-
type: Boolean,
35-
default: false
36-
},
37-
app: {
38-
type: Boolean,
39-
default: false
40-
},
41-
fixed: {
42-
type: Boolean,
43-
default: false
44-
},
45-
height: {
46-
type: Number,
47-
default: 56
48-
},
49-
showBack: {
50-
type: Boolean,
51-
default: true
52-
},
53-
disableMaxWidth: {
54-
type: Boolean,
55-
default: false
56-
},
57-
sticky: {
58-
type: Boolean,
59-
default: false
60-
}
31+
type Props = {
32+
title?: string
33+
subtitle?: string
34+
flat?: boolean
35+
app?: boolean
36+
fixed?: boolean
37+
height?: number
38+
showBack?: boolean
39+
hasSpinner?: boolean
40+
disableMaxWidth?: boolean
41+
sticky?: boolean
42+
}
43+
44+
const props = withDefaults(defineProps<Props>(), {
45+
title: undefined,
46+
subtitle: undefined,
47+
flat: false,
48+
app: false,
49+
fixed: false,
50+
height: 56,
51+
showBack: true,
52+
hasSpinner: false,
53+
disableMaxWidth: false,
54+
sticky: false
6155
})
6256
57+
const store = useStore()
6358
const route = useRoute()
6459
const router = useRouter()
6560
6661
const className = 'app-toolbar-centered'
6762
63+
const isOnline = computed(() => store.getters['isOnline'])
6864
const classes = computed(() => {
6965
return {
7066
'v-toolbar--fixed': props.app,
@@ -123,6 +119,14 @@ const goBack = () => {
123119
letter-spacing: 0.02em;
124120
}
125121
122+
.spinner {
123+
position: absolute;
124+
top: 50%;
125+
left: 50%;
126+
transform: translate(-50%, -50%);
127+
transition: left 0.2s ease;
128+
}
129+
126130
:deep(.v-toolbar-title:not(:first-child)) {
127131
margin-inline-start: 0;
128132
}
@@ -145,6 +149,10 @@ const goBack = () => {
145149
.v-toolbar {
146150
background-color: map.get(colors.$adm-colors, 'secondary2');
147151
}
152+
153+
.spinner {
154+
color: map.get(colors.$adm-colors, 'grey');
155+
}
148156
}
149157
}
150158
@@ -154,6 +162,10 @@ const goBack = () => {
154162
background-color: map.get(colors.$adm-colors, 'black');
155163
color: map.get(settings.$shades, 'white');
156164
}
165+
166+
.spinner {
167+
color: map.get(colors.$adm-colors, 'regular');
168+
}
157169
}
158170
}
159171
</style>

src/components/Chat/Chat.vue

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,18 @@
7474
<chat-toolbar :partner-id="partnerId">
7575
<template #avatar-toolbar>
7676
<ChatAvatar
77+
v-if="!showSpinner"
7778
class="chat-avatar"
7879
:user-id="partnerId"
7980
use-public-key
8081
@click="onClickAvatar(partnerId)"
8182
/>
83+
<v-progress-circular
84+
v-else
85+
class="connection-spinner ml-1 mr-4"
86+
indeterminate
87+
:size="32"
88+
/>
8289
</template>
8390
</chat-toolbar>
8491
</template>
@@ -298,6 +305,7 @@ import AChatAttachment from '@/components/AChat/AChatAttachment/AChatAttachment.
298305
import { useI18n } from 'vue-i18n'
299306
import { useRouter } from 'vue-router'
300307
import { useStore } from 'vuex'
308+
import { useChatsSpinner } from '@/hooks/useChatsSpinner'
301309
import ProgressIndicator from '@/components/ProgressIndicator.vue'
302310
import { useChatStateStore } from '@/stores/chat-state'
303311
@@ -308,7 +316,7 @@ const validationErrors = {
308316
messageTooLong: 'MESSAGE_LENGTH_EXCEED'
309317
}
310318
311-
const { partnerId } = defineProps({
319+
const props = defineProps({
312320
partnerId: {
313321
type: String,
314322
required: true
@@ -319,10 +327,11 @@ const emit = defineEmits(['click:chat-avatar'])
319327
const router = useRouter()
320328
const store = useStore()
321329
const { t } = useI18n()
330+
const showSpinner = useChatsSpinner()
322331
323332
const isMenuOpen = ref(false)
324333
325-
const attachments = useAttachments(partnerId)()
334+
const attachments = useAttachments(props.partnerId)()
326335
const handleAttachments = (files: FileData[]) => {
327336
const maxFileSizeExceeded = files.some(({ file }) => file.size >= UPLOAD_MAX_FILE_SIZE)
328337
const maxFileCountExceeded = attachments.list.length + files.length > UPLOAD_MAX_FILE_COUNT
@@ -367,7 +376,7 @@ const actionsDropdownMessageId = computed({
367376
set: setActionsDropdownMessageId
368377
})
369378
370-
const messages = computed(() => store.getters['chat/messages'](partnerId))
379+
const messages = computed(() => store.getters['chat/messages'](props.partnerId))
371380
const userId = computed(() => store.state.address)
372381
373382
const getPartnerName = (address: string) => {
@@ -379,17 +388,19 @@ const getUserMeta = (address: string) => ({
379388
id: address,
380389
name: address === userId.value ? t('chats.you') : getPartnerName(address)
381390
})
382-
const partners = computed(() => [getUserMeta(userId.value), getUserMeta(partnerId)])
391+
const partners = computed(() => [getUserMeta(userId.value), getUserMeta(props.partnerId)])
383392
const sendMessageOnEnter = computed<boolean>(() => store.state.options.sendMessageOnEnter)
384393
const isFulfilled = computed<boolean>(() => store.state.chat.isFulfilled)
385394
const lastMessage = computed<NormalizedChatMessageTransaction>(() =>
386-
store.getters['chat/lastMessage'](partnerId)
395+
store.getters['chat/lastMessage'](props.partnerId)
387396
)
388-
const chatPage = computed<number>(() => store.getters['chat/chatPage'](partnerId))
397+
const chatPage = computed<number>(() => store.getters['chat/chatPage'](props.partnerId))
389398
const scrollPosition = computed<number | false>(() =>
390-
store.getters['chat/scrollPosition'](partnerId)
399+
store.getters['chat/scrollPosition'](props.partnerId)
400+
)
401+
const numOfNewMessages = computed<number>(() =>
402+
store.getters['chat/numOfNewMessages'](props.partnerId)
391403
)
392-
const numOfNewMessages = computed<number>(() => store.getters['chat/numOfNewMessages'](partnerId))
393404
const replyMessage = computed<NormalizedChatMessageTransaction>(() =>
394405
store.getters['chat/messageById'](replyMessageId.value)
395406
)
@@ -399,6 +410,7 @@ const actionMessage = computed<NormalizedChatMessageTransaction>(() =>
399410
400411
const chatFormRef = ref<any>(null) // @todo type
401412
const chatRef = ref<any>(null) // @todo type
413+
402414
// Scroll to the bottom every time window focused by desktop notification
403415
watch(
404416
() => store.state.notification.desktopActivateClickCount,
@@ -445,7 +457,7 @@ onMounted(() => {
445457
if (state === 'visible' && isScrolledToBottom.value) markAsRead()
446458
})
447459
448-
const draftMessage = store.getters['draftMessage/draftReplyTold'](partnerId)
460+
const draftMessage = store.getters['draftMessage/draftReplyTold'](props.partnerId)
449461
if (draftMessage) {
450462
replyMessageId.value = draftMessage
451463
}
@@ -518,19 +530,19 @@ const cancelReplyMessage = () => {
518530
replyMessageId.value = -1
519531
store.commit('draftMessage/deleteReplyTold', {
520532
replyToId: replyMessageId.value,
521-
partnerId: partnerId
533+
partnerId: props.partnerId
522534
})
523535
}
524536
525537
const sendMessage = (message: string) => {
526-
store.dispatch('draftMessage/deleteDraft', { partnerId: partnerId })
538+
store.dispatch('draftMessage/deleteDraft', { partnerId: props.partnerId })
527539
const replyToId = replyMessageId.value !== -1 ? replyMessageId.value : undefined
528540
529541
if (attachments.list.length > 0) {
530542
store.dispatch('chat/sendAttachment', {
531543
files: attachments.list,
532544
message,
533-
recipientId: partnerId,
545+
recipientId: props.partnerId,
534546
replyToId
535547
})
536548
@@ -540,7 +552,7 @@ const sendMessage = (message: string) => {
540552
return store
541553
.dispatch('chat/sendMessage', {
542554
message,
543-
recipientId: partnerId,
555+
recipientId: props.partnerId,
544556
replyToId
545557
})
546558
.catch((err) => {
@@ -562,7 +574,7 @@ const sendReaction = (reactToId: string, emoji: string) => {
562574
closeActionsDropdown()
563575
emojiWeight.addReaction(emoji)
564576
return store.dispatch('chat/sendReaction', {
565-
recipientId: partnerId,
577+
recipientId: props.partnerId,
566578
reactToId,
567579
reactMessage: emoji
568580
})
@@ -573,7 +585,7 @@ const removeReaction = (reactToId: string, emoji: string) => {
573585
closeActionsDropdown()
574586
emojiWeight.removeReaction(emoji)
575587
return store.dispatch('chat/sendReaction', {
576-
recipientId: partnerId,
588+
recipientId: props.partnerId,
577589
reactToId,
578590
reactMessage: ''
579591
})
@@ -584,7 +596,7 @@ const onEmojiSelect = (transactionId: string, emoji: string) => {
584596
}
585597
586598
const markAsRead = () => {
587-
store.commit('chat/markAsRead', partnerId)
599+
store.commit('chat/markAsRead', props.partnerId)
588600
}
589601
590602
const onScrollTop = () => {
@@ -598,7 +610,7 @@ const onScrollBottom = () => {
598610
const onScroll = (scrollPosition: number, isBottom: boolean) => {
599611
isScrolledToBottom.value = isBottom
600612
store.commit('chat/updateScrollPosition', {
601-
contactId: partnerId,
613+
contactId: props.partnerId,
602614
scrollPosition
603615
})
604616
}
@@ -608,14 +620,14 @@ const onClickAvatar = (address: string) => {
608620
}
609621
610622
const onQuotedMessageClick = async (transactionId: string) => {
611-
let transactionIndex = store.getters['chat/indexOfMessage'](partnerId, transactionId)
623+
let transactionIndex = store.getters['chat/indexOfMessage'](props.partnerId, transactionId)
612624
613625
// if the message is not present in the store
614626
// fetch chat history until reach that message
615627
if (transactionIndex === -1) {
616628
await fetchUntilFindTransaction(transactionId)
617629
618-
transactionIndex = store.getters['chat/indexOfMessage'](partnerId, transactionId)
630+
transactionIndex = store.getters['chat/indexOfMessage'](props.partnerId, transactionId)
619631
}
620632
621633
// if after fetching chat history the message still cannot be found
@@ -688,7 +700,7 @@ const openReplyPreview = (message: NormalizedChatMessageTransaction) => {
688700
chatFormRef.value.focus()
689701
store.commit('draftMessage/saveReplyToId', {
690702
replyToId: message.id,
691-
partnerId: partnerId
703+
partnerId: props.partnerId
692704
})
693705
}
694706
@@ -722,7 +734,7 @@ const openTransaction = (transaction: NormalizedChatMessageTransaction) => {
722734
},
723735
query: {
724736
fromChat: 'true',
725-
from: `/chats/${partnerId}`
737+
from: `/chats/${props.partnerId}`
726738
}
727739
})
728740
}
@@ -738,7 +750,7 @@ const fetchChatMessages = () => {
738750
loading.value = true
739751
740752
return store
741-
.dispatch('chat/getChatRoomMessages', { contactId: partnerId })
753+
.dispatch('chat/getChatRoomMessages', { contactId: props.partnerId })
742754
.catch(() => {
743755
noMoreMessages.value = true
744756
})
@@ -749,11 +761,14 @@ const fetchChatMessages = () => {
749761
}
750762
const fetchUntilFindTransaction = (transactionId: string) => {
751763
const fetchMessages = async () => {
752-
await store.dispatch('chat/getChatRoomMessages', { contactId: partnerId })
764+
await store.dispatch('chat/getChatRoomMessages', { contactId: props.partnerId })
753765
754766
chatRef.value.maintainScrollPosition()
755767
756-
const transactionFound = store.getters['chat/partnerMessageById'](partnerId, transactionId)
768+
const transactionFound = store.getters['chat/partnerMessageById'](
769+
props.partnerId,
770+
transactionId
771+
)
757772
if (transactionFound) return
758773
759774
if (store.state.chat.offset > -1) {
@@ -794,6 +809,9 @@ const onKeyPress = (e: KeyboardEvent) => {
794809
</script>
795810

796811
<style scoped lang="scss">
812+
@use 'sass:map';
813+
@use '@/assets/styles/settings/_colors.scss';
814+
797815
.chat-menu {
798816
margin-right: 8px;
799817
}
@@ -806,4 +824,17 @@ const onKeyPress = (e: KeyboardEvent) => {
806824
.chat-avatar {
807825
margin-right: 12px;
808826
}
827+
828+
/** Themes **/
829+
.v-theme--light {
830+
.connection-spinner {
831+
color: map.get(colors.$adm-colors, 'grey');
832+
}
833+
}
834+
835+
.v-theme--dark {
836+
.connection-spinner {
837+
color: map.get(colors.$adm-colors, 'regular');
838+
}
839+
}
809840
</style>

0 commit comments

Comments
 (0)