Opaque gradient over -1 msg & can fetch n+1 pages
- An opaque gradient overlay on the top message. This creates the illusion that there are more messages under that the user can scroll to. - Changed the formatting of the chat messages. - Repaired the scrolling that happens on load and when chatHistory prop list updates. If a full page arrives we want to keep the position, but on load and a single new message we want to jump to the bottom of the list. - Emitting loadMoreHistory expects a expanded list of chatHistory.
This commit is contained in:
		| @@ -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 | ||||||
| @@ -105,6 +125,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 +161,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 +181,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; | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user