-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Create ChatSettings component, overhaul chat input UI * Simplify chat component * Create ChatInput component isolate textbox input for better performance * Remove unused components from chat index * Make chat input clearable * Fix null message when input is cleared * Switch autoscroll function * Begin work on ChatMessages wrapper * Add counter back to input * Use ChatMessages container * Convert ChatMessage to functional component * Code Cleanup Remove old chat code and clean up files * Improve viewerlist scrolling * Load chat settings async * Remove vuetify components from functional component * Reduce chat message line height * Improve chat message typography * Revert line height * ViewerList scroll improvement, restore settings divider
- Loading branch information
1 parent
3763ece
commit 1b9d7cf
Showing
11 changed files
with
668 additions
and
402 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
<template> | ||
<!-- Chat Input --> | ||
<v-sheet class="px-2 py-2" color="black"> | ||
<div class="d-flex"> | ||
<v-text-field | ||
ref="chatmessageinput" | ||
:value="getMessage" | ||
:label="`Chat as ${username}...`" | ||
color="yellow" | ||
autocomplete="off" | ||
autocorrect="off" | ||
autocapitalize="off" | ||
spellcheck="true" | ||
single-line | ||
validate-on-blur | ||
outlined | ||
dense | ||
clearable | ||
:error="error" | ||
counter="300" | ||
@change="value => this.setMessage( value )" | ||
@keyup.enter.prevent="sendMessage" | ||
@keyup.prevent="event => lastMessageHandler(event)" | ||
@cut="event => lastMessageHandler(event)" | ||
></v-text-field> | ||
</div> | ||
|
||
<div class="d-flex"> | ||
<v-menu | ||
v-model="showChatSettings" | ||
:close-on-content-click="false" | ||
:close-on-click="false" | ||
transition="slide-x-transition" | ||
:max-width="320" | ||
top | ||
right | ||
offset-y | ||
> | ||
<template #activator="{ on }"> | ||
<v-btn | ||
v-on="on" | ||
small | ||
text | ||
icon | ||
> | ||
<v-icon>settings</v-icon> | ||
</v-btn> | ||
</template> | ||
<chat-settings | ||
@close="showChatSettings = false" | ||
></chat-settings> | ||
</v-menu> | ||
|
||
<v-spacer/> | ||
|
||
<v-btn | ||
small | ||
color="yellow black--text" | ||
class="px-2" | ||
@click="sendMessage" | ||
> | ||
send | ||
<v-icon small>send</v-icon> | ||
</v-btn> | ||
</div> | ||
|
||
</v-sheet> | ||
</template> | ||
|
||
<script> | ||
import { mapState, mapMutations } from 'vuex' | ||
const ChatSettings = () => import( '@/components/Chat/ChatSettings' ); | ||
export default { | ||
name: 'ChatInput', | ||
components: { | ||
ChatSettings, | ||
}, | ||
props: { | ||
username: { type: String }, | ||
}, | ||
data() { | ||
return { | ||
showChatSettings: false, | ||
messageBuffer: [], | ||
messageBufferIndex: 0, | ||
} | ||
}, | ||
methods: { | ||
...mapMutations( 'chat', { | ||
setMessage: 'SET_CHAT_MESSAGE', | ||
}), | ||
sendMessage() { | ||
if ( this.getMessage.length > 300 ) return; | ||
this.$emit( 'send' ); | ||
this.messageBuffer.push(this.getMessage); | ||
this.messageBuffer = this.messageBuffer.splice(-10); | ||
this.messageBufferIndex = this.messageBuffer.length; | ||
this.setMessage( '' ); | ||
}, | ||
lastMessageHandler ( event ) { | ||
if ( !event.srcElement.value || event.srcElement.value === this.messageBuffer[ this.messageBufferIndex ] ) { | ||
// Up Arrow (keyCode 38) | ||
if ( event.key === 'ArrowUp' ) { | ||
this.messageBufferIndex -= ( this.messageBufferIndex > 0 ) ? 1 : 0; | ||
this.setMessage( this.messageBuffer[ this.messageBufferIndex ] ); | ||
event.preventDefault(); | ||
} | ||
// Down Arrow (keyCode 40) | ||
else if ( event.key === 'ArrowDown' ) { | ||
this.messageBufferIndex += ( this.messageBufferIndex < this.messageBuffer.length ) ? 1 : 0; | ||
if ( this.messageBufferIndex === this.messageBuffer.length ) this.setMessage( '' ); | ||
else this.setMessage( this.messageBuffer[ this.messageBufferIndex ] ); | ||
event.preventDefault(); | ||
} | ||
// Idk why this is needed | ||
else { | ||
// this.message = ''; | ||
} | ||
} | ||
if ( event.type === 'cut' ) { | ||
setTimeout( () => { | ||
if ( !event.srcElement.value ) { | ||
this.setMessage( '' ); | ||
} | ||
}, 20 ); | ||
} | ||
}, | ||
}, | ||
computed: { | ||
...mapState( 'chat', { | ||
getMessage: 'message', | ||
}), | ||
error () { | ||
return this.getMessage.length > 300; | ||
} | ||
}, | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<template> | ||
<v-flex | ||
id="inner-chat" | ||
fill-height | ||
style="overflow: hidden;" | ||
> | ||
<div | ||
id="chat-scroll" | ||
ref="scroller" | ||
style="overflow-y: scroll; will-change: transform;" | ||
> | ||
<chat-message | ||
v-for="item in messages" | ||
:key="item.timestamp" | ||
:username="item.username" | ||
:display-name="item.username" | ||
:user-styling="{ color: item.userColor ? item.userColor : '#9e9e9e' }" | ||
:channel="item.channel" | ||
:timestamp="getTime(item.timestamp)" | ||
:avatar="item.avatar" | ||
:color="item.color" | ||
@reply="addUserTag" | ||
> | ||
<div | ||
class="body-2" | ||
:style="{ lineHeight: 1.5, }" | ||
v-html="item.message" | ||
></div> | ||
</chat-message> | ||
</div> | ||
</v-flex> | ||
</template> | ||
|
||
<script> | ||
import moment from 'moment' | ||
import ChatMessage from '@/components/Chat/ChatMessage' | ||
export default { | ||
name: 'ChatMessages', | ||
components: { | ||
ChatMessage, | ||
}, | ||
props: { | ||
messages: { type: Array }, | ||
showTimestamps: { type: Boolean }, | ||
}, | ||
data() { | ||
return { | ||
chatContainer: null, | ||
} | ||
}, | ||
methods: { | ||
addUserTag ( user ) { | ||
this.$emit('reply', user); | ||
}, | ||
checkIfBottom () { | ||
const scrollTop = this.chatContainer.scrollTop; | ||
const clientHeight = this.chatContainer.clientHeight; // or offsetHeight | ||
const scrollHeight = this.chatContainer.scrollHeight; | ||
return scrollTop + clientHeight >= scrollHeight - document.querySelector("#chat-scroll > div:last-child").clientHeight; | ||
}, | ||
async scrollToBottom ( force ) { | ||
// If we are NOT at the bottom && NOT forcing scroll, bail early | ||
if ( !this.checkIfBottom() && !force ) return; | ||
// Scroll to last message | ||
this.chatContainer.scroll({ | ||
top: this.chatContainer.scrollHeight, | ||
behavior: 'smooth', | ||
}); | ||
setTimeout( () => { | ||
this.chatContainer.scroll({ | ||
top: this.chatContainer.scrollHeight, | ||
behavior: 'smooth', | ||
}); | ||
}, 500 ); | ||
}, | ||
jumpToBottom () { | ||
this.chatContainer.scrollTop = this.chatContainer.scrollHeight + 750; | ||
}, | ||
getTime ( timestamp ) { | ||
return this.showTimestamps ? `[${moment( timestamp ).format( 'HH:mm' )}]` : ''; | ||
}, | ||
onScroll ( event ) { | ||
console.log( `At Bottom: ${this.checkIfBottom()}` ); | ||
}, | ||
}, | ||
computed: {}, | ||
watch: { | ||
/*messages: async function () { | ||
// await this.scrollToBottom(true); | ||
},*/ | ||
}, | ||
async mounted () { | ||
this.chatContainer = this.$refs.scroller; | ||
// this.chatContainer.addEventListener( 'scroll', e => this.onScroll(e) ); | ||
}, | ||
} | ||
</script> |
Oops, something went wrong.