Merge pull request #17 from KevinMidboe/refactor/chat-history
Refactor/chat history
This commit is contained in:
		| @@ -11,9 +11,7 @@ import VirtualLotteryPage from "@/components/VirtualLotteryPage"; | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   components: { |   components: { | ||||||
|     Tabs, |     Tabs | ||||||
|     GeneratePage, |  | ||||||
|     VirtualLotteryPage |  | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|   | |||||||
| @@ -43,9 +43,11 @@ | |||||||
|       <Chat |       <Chat | ||||||
|         class="outer-chat" |         class="outer-chat" | ||||||
|         :chatHistory="chatHistory" |         :chatHistory="chatHistory" | ||||||
|  |         :historyPageSize="historyPageSize" | ||||||
|         :usernameAllowed="usernameAllowed" |         :usernameAllowed="usernameAllowed" | ||||||
|         v-on:message="sendMessage" |         @loadMoreHistory="loadMoreHistory" | ||||||
|         v-on:username="setUsername" |         @message="sendMessage" | ||||||
|  |         @username="setUsername" | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
|     <Vipps class="vipps" :amount="1" /> |     <Vipps class="vipps" :amount="1" /> | ||||||
| @@ -74,6 +76,9 @@ export default { | |||||||
|       attendeesFetched: false, |       attendeesFetched: false, | ||||||
|       winnersFetched: false, |       winnersFetched: false, | ||||||
|       chatHistory: [], |       chatHistory: [], | ||||||
|  |       historyPage: 0, | ||||||
|  |       historyPageSize: 100, | ||||||
|  |       lastHistoryPage: false, | ||||||
|       usernameAccepted: false, |       usernameAccepted: false, | ||||||
|       username: null, |       username: null, | ||||||
|       wasDisconnected: false, |       wasDisconnected: false, | ||||||
| @@ -158,6 +163,15 @@ export default { | |||||||
|     sendMessage: function(msg) { |     sendMessage: function(msg) { | ||||||
|       this.socket.emit("chat", { message: msg }); |       this.socket.emit("chat", { message: msg }); | ||||||
|     }, |     }, | ||||||
|  |     loadMoreHistory: function() { | ||||||
|  |       const { historyPage, historyPageSize } = this; | ||||||
|  |       const page = historyPage + 1; | ||||||
|  |  | ||||||
|  |       getChatHistory(page * historyPageSize, historyPageSize).then(messages => { | ||||||
|  |         this.chatHistory = messages.concat(this.chatHistory); | ||||||
|  |         this.historyPage = page; | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|     getWinners: async function() { |     getWinners: async function() { | ||||||
|       let response = await winners(); |       let response = await winners(); | ||||||
|       if (response) { |       if (response) { | ||||||
|   | |||||||
| @@ -3,12 +3,18 @@ | |||||||
|     <hr /> |     <hr /> | ||||||
|     <h2>Chat</h2> |     <h2>Chat</h2> | ||||||
|     <div class="history" ref="history"> |     <div class="history" ref="history"> | ||||||
|       <div |       <div class="opaque-skirt"></div> | ||||||
|  |       <div v-if="existsMore" class="fetch-older-history"> | ||||||
|  |         <button @click="$emit('loadMoreHistory')">Hent eldre meldinger</button> | ||||||
|  |       </div> | ||||||
|  |       <div class="history-message" | ||||||
|         v-for="(history, index) in chatHistory" |         v-for="(history, index) in chatHistory" | ||||||
|         :key="`${history.username}-${history.timestamp}-${index}`" |         :key="`${history.username}-${history.timestamp}-${index}`" | ||||||
|       > |       > | ||||||
|         <span class="timestamp">[{{ getTime(history.timestamp) }}]</span> |         <div> | ||||||
|         <span class="user-name">{{ history.username }}:</span> |           <span class="user-name">{{ history.username }}</span> | ||||||
|  |           <span class="timestamp">{{ getTime(history.timestamp) }}</span> | ||||||
|  |         </div> | ||||||
|         <span class="message">{{ history.message }}</span> |         <span class="message">{{ history.message }}</span> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
| @@ -38,6 +44,9 @@ export default { | |||||||
|     }, |     }, | ||||||
|     chatHistory: { |     chatHistory: { | ||||||
|       type: Array |       type: Array | ||||||
|  |     }, | ||||||
|  |     historyPageSize: { | ||||||
|  |       type: Number | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
| @@ -45,16 +54,27 @@ export default { | |||||||
|       message: "", |       message: "", | ||||||
|       temporaryUsername: null, |       temporaryUsername: null, | ||||||
|       username: null, |       username: null, | ||||||
|       usernameSet: false |       usernameSet: false, | ||||||
|  |       existsMore: true | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
|     chatHistory: { |     chatHistory: { | ||||||
|       handler() { |       handler: function(newVal, oldVal) { | ||||||
|         if (this.$refs && this.$refs.history) { |         if (this.$refs && this.$refs.history) { | ||||||
|  |           const firstMessages = oldVal.length == 0; | ||||||
|  |           const diffLargerThanOne = newVal.length - oldVal.length > 1; | ||||||
|  |  | ||||||
|           setTimeout(() => { |           setTimeout(() => { | ||||||
|             this.$refs.history.scrollTop = this.$refs.history.scrollHeight; |             if (firstMessages || diffLargerThanOne == false) { | ||||||
|           }, 10); |               this.scrollToBottomOfHistory(); | ||||||
|  |             } else { | ||||||
|  |               this.scrollToStartOfNewMessages(); | ||||||
|  |               // what shows the load more button - if we scroll page and less than page size | ||||||
|  |               // come back we have reached a limit | ||||||
|  |               this.existsMore = newVal.length - oldVal.length == this.historyPageSize | ||||||
|  |             } | ||||||
|  |           }, 100); | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       deep: true |       deep: true | ||||||
| @@ -62,12 +82,11 @@ export default { | |||||||
|   }, |   }, | ||||||
|   mounted() { |   mounted() { | ||||||
|     let username = window.localStorage.getItem("username"); |     let username = window.localStorage.getItem("username"); | ||||||
|     if (!username) { |     if (username) { | ||||||
|       return; |       this.username = username; | ||||||
|  |       this.usernameSet = true; | ||||||
|  |       this.$emit("username", username); | ||||||
|     } |     } | ||||||
|     this.username = username; |  | ||||||
|     this.usernameSet = true; |  | ||||||
|     this.$emit("username", username); |  | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     pad: function(num) { |     pad: function(num) { | ||||||
| @@ -105,6 +124,20 @@ export default { | |||||||
|         this.usernameSet = true; |         this.usernameSet = true; | ||||||
|         this.$emit("username", this.username); |         this.$emit("username", this.username); | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     scrollToBottomOfHistory() { | ||||||
|  |       if (this.$refs && this.$refs.history) { | ||||||
|  |         const { history } = this.$refs; | ||||||
|  |         history.scrollTop = history.scrollHeight; | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     scrollToStartOfNewMessages() { | ||||||
|  |       const { history } = this.$refs; | ||||||
|  |       const histLength = history.children.length; | ||||||
|  |       const pages = Math.floor(histLength / 100); | ||||||
|  |  | ||||||
|  |       const messageToScrollTo = history.children[histLength - ((pages * 100) + 3)] | ||||||
|  |       history.scrollTop = messageToScrollTo.offsetTop; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| @@ -127,6 +160,7 @@ hr { | |||||||
| .chat-container { | .chat-container { | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   width: 50%; |   width: 50%; | ||||||
|  |   position: relative; | ||||||
|  |  | ||||||
|   @include mobile { |   @include mobile { | ||||||
|     width: 100%; |     width: 100%; | ||||||
| @@ -146,6 +180,46 @@ input { | |||||||
|   height: 75%; |   height: 75%; | ||||||
|   overflow-y: scroll; |   overflow-y: scroll; | ||||||
|  |  | ||||||
|  |   &-message { | ||||||
|  |     display: flex; | ||||||
|  |     flex-direction: column; | ||||||
|  |     margin: 0.35rem 0; | ||||||
|  |     position: relative; | ||||||
|  |  | ||||||
|  |     .user-name { | ||||||
|  |       font-weight: bold; | ||||||
|  |       font-size: 1.05rem; | ||||||
|  |       margin-right: 0.3rem; | ||||||
|  |     } | ||||||
|  |     .timestamp { | ||||||
|  |       font-size: 0.9rem; | ||||||
|  |       top: 2px; | ||||||
|  |       position: absolute; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   &-message:nth-of-type(2) { | ||||||
|  |     margin-top: 1rem; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   & .opaque-skirt { | ||||||
|  |     width: 100%; | ||||||
|  |     position: absolute; | ||||||
|  |     height: 1rem; | ||||||
|  |     z-index: 1; | ||||||
|  |     background: linear-gradient( | ||||||
|  |       to bottom, | ||||||
|  |       white, | ||||||
|  |       rgba(255, 255, 255, 0) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   & .fetch-older-history { | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: center; | ||||||
|  |     margin: 0.2rem 0 0.5rem; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @include mobile { |   @include mobile { | ||||||
|     height: 300px; |     height: 300px; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -10,12 +10,7 @@ | |||||||
|       >{{ tab.name }}</div> |       >{{ tab.name }}</div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="tab-elements"> |     <div class="tab-elements"> | ||||||
|       <component |       <component :is="tabs[chosenTab].component" /> | ||||||
|         v-for="(tab, index) in tabs" |  | ||||||
|         :key="index" |  | ||||||
|         :is="tab.component" |  | ||||||
|         :class="chosenTab == index ? null : 'hide'" |  | ||||||
|       /> |  | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| @@ -54,9 +49,6 @@ export default { | |||||||
| h1 { | h1 { | ||||||
|   text-align: center; |   text-align: center; | ||||||
| } | } | ||||||
| .hide { |  | ||||||
|   display: none; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .tab-container { | .tab-container { | ||||||
|   display: flex; |   display: flex; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user