update to version 1.0.6 (package updates + translate function for match-chat)
All checks were successful
CSGOWTF/csgowtf/pipeline/pr-master This commit looks good
CSGOWTF/csgowtf/pipeline/head This commit looks good

This commit was merged in pull request #68.
This commit is contained in:
2022-02-12 03:35:10 +01:00
parent 3c43788494
commit 9ff510a9f6
6 changed files with 454 additions and 85 deletions

View File

@@ -1,20 +1,27 @@
<template>
<div class="chat-history mt-2">
<table v-if="data.chat.length > 0" class="table table-borderless">
<tbody>
<tr v-for="(m, id) in data.chat" :key="id">
<td>
{{ ConvertTickToTime(m.tick, m.tick_rate) }}
</td>
<td class="td-avatar">
<img :class="'team-color-' + m.color"
:src="constructAvatarUrl(m.avatar)"
alt="Player avatar"
class="avatar">
</td>
<td :class="m.startSide === 1 ? 'text-info' : 'text-warning'"
class="name d-flex"
@click="GoToPlayer(m.steamid64)">
<div class="container w-50">
<TranslateChatButton
v-if="data.chat.length > 0"
:translated="data.translatedText.length > 0"
class="translate-btn"
@translated="handleTranslatedText"
/>
<div v-if="data.chat.length > 0" class="chat-history mt-2">
<table class="table table-borderless">
<tbody>
<tr v-for="(m, id) in data.chat" :key="id">
<td class="td-time">
{{ ConvertTickToTime(m.tick, m.tick_rate) }}
</td>
<td class="td-avatar">
<img :class="'team-color-' + m.color"
:src="constructAvatarUrl(m.avatar)"
alt="Player avatar"
class="avatar">
</td>
<td :class="m.startSide === 1 ? 'text-info' : 'text-warning'"
class="td-name d-flex"
@click="GoToPlayer(m.steamid64)">
<span>
<i v-if="m.tracked" class="fa fa-dot-circle-o text-success tracked" title="Tracked user"/>
<span :class="(m.vac && FormatVacDate(m.vac_date, store.state.matchDetails.date) !== '')
@@ -29,19 +36,27 @@
{{ m.player }}
</span>
</span>
</td>
<td>
<i class="fa fa-caret-right"/>
<span v-if="!m.all_chat" class="ms-1">
</td>
<td class="td-icon">
<i class="fa fa-caret-right"/>
<span v-if="!m.all_chat" class="ms-1">
(team)
</span>
</td>
<td class="message">
{{ m.message }}
</td>
</tr>
</tbody>
</table>
</td>
<td class="td-message">
{{ data.translatedText.length === 0 ? m.message : data.originalChat[id].message }}
<span v-if="m.translated_from"
:class="m.translated_from ? 'text-success' : ''"
:title="`Translated from ${ISO6391.getName(m.translated_from)}`"
class="ms-2 helpicon">
<br/>
{{ m.message }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div v-else>
<h3>No chat available</h3>
</div>
@@ -51,24 +66,48 @@
<script>
import {useStore} from "vuex";
import {onMounted, reactive} from "vue";
import {GetChatHistory, constructAvatarUrl, GoToPlayer, ConvertTickToTime, FormatVacDate, truncate} from "@/utils";
import {constructAvatarUrl, ConvertTickToTime, FormatVacDate, GetChatHistory, GoToPlayer, truncate} from "@/utils";
import TranslateChatButton from "@/components/TranslateChatButton";
import ISO6391 from 'iso-639-1'
export default {
name: "MatchChatHistory",
components: {TranslateChatButton},
setup() {
const store = useStore()
const data = reactive({
chat: [],
translatedText: [],
originalChat: []
})
const handleTranslatedText = async (e) => {
const res = await e
if (res === 'original' && data.originalChat.length > 0) {
data.chat = data.originalChat
return
}
if (res === 'already translated' && data.translatedText.length > 0) {
data.chat = data.translatedText
return
}
if (res !== null) {
data.translatedText = await setPlayer(sortChatHistory(res, true))
data.chat = data.translatedText
}
}
const getChatHistory = async () => {
const resData = await GetChatHistory(store, store.state.matchDetails.match_id)
if (resData !== null)
if (resData !== null) {
data.chat = await setPlayer(sortChatHistory(resData))
data.originalChat = data.chat
}
}
const sortChatHistory = (res = {}) => {
const sortChatHistory = (res = {}, translated = false) => {
let arr = []
if (res !== {}) {
Object.keys(res).forEach(i => {
@@ -77,7 +116,9 @@ export default {
player: i,
tick: o.tick,
all_chat: o.all_chat,
message: o.message
message: o.message,
translated_from: translated ? o.translated_from : null,
translated_to: translated ? o.translated_to : null
})
arr.push(obj)
})
@@ -106,7 +147,9 @@ export default {
tick: o.tick,
tick_rate: store.state.matchDetails.tick_rate && store.state.matchDetails.tick_rate !== -1 ? store.state.matchDetails.tick_rate : 64,
all_chat: o.all_chat,
message: o.message
message: o.message,
translated_from: o.translated_from,
translated_to: o.translated_to
})
arr.push(obj)
}
@@ -119,66 +162,95 @@ export default {
getChatHistory()
})
return {data, store, constructAvatarUrl, GoToPlayer, ConvertTickToTime, FormatVacDate}
return {
data,
store,
ISO6391,
constructAvatarUrl,
GoToPlayer,
ConvertTickToTime,
FormatVacDate,
handleTranslatedText
}
}
}
</script>
<style lang="scss" scoped>
table td {
padding: .5rem;
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.avatar {
width: 20px;
height: 20px;
border-radius: 50%;
.translate-btn {
margin-top: .5rem;
}
.name {
cursor: pointer;
text-align: left;
width: 20ch;
max-width: 20ch;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.tracked {
font-size: .8rem;
margin-right: .2rem;
table {
width: 700px;
max-width: 700px;
td {
padding: .5rem;
}
.ban-shadow {
color: red;
text-shadow: 0 0 1rem orangered;
.td-time {
width: 80px;
}
}
.fa-caret-right {
font-size: 1rem;
}
.td-avatar {
width: 30px;
.avatar {
width: 20px;
height: 20px;
border-radius: 50%;
}
}
.message {
width: auto;
max-width: 40ch;
}
.td-name {
width: 250px;
max-width: 250px;
cursor: pointer;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@media screen and (max-width: 991px) {
.chat-history {
margin-left: auto;
margin-right: auto;
.tracked {
font-size: .8rem;
margin-right: .2rem;
}
.ban-shadow {
color: red;
text-shadow: 0 0 1rem orangered;
}
}
.td-icon {
width: 20px;
.fa-caret-right {
font-size: 1rem;
}
}
.td-message {
width: 320px;
}
}
@media screen and (max-width: 576px) {
.td-avatar {
display: none;
}
.name {
.td-name {
width: 120px;
max-width: 120px;
}
.td-message {
width: auto;
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="toggle-btn text-muted">
<div @click.prevent="$emit('translated', handleBtnClick())"
class="d-flex">
<span class="text-center mx-2">
<i id="toggle-off" class="fa fa-toggle-off show"/>
<i id="toggle-on" class="fa fa-toggle-on"/>
</span>
<div>
<span :class="toggle === 'translated' ? 'text-warning' : ''"
class="float-start">
<span class="text-uppercase">Translate to {{data.browserLang}}</span>
<span class="loading-icon ms-2" title="Translating..">
<i class="fa fa-spinner fa-pulse fa-fw"/>
</span>
</span>
</div>
</div>
</div>
</template>
<script>
import {onMounted, reactive, ref} from "vue";
import ISO6391 from 'iso-639-1'
import {GetChatHistoryTranslated} from "@/utils";
import {useStore} from "vuex";
export default {
name: 'TranslateChatButton',
props: {
translated: {
type: Boolean,
required: true
}
},
setup(props) {
const store = useStore()
const data = reactive({
browserIsoCode: '',
browserLangCode: '',
browserLang: '',
})
const toggle = ref('original')
const setLanguageVariables = () => {
const navLangs = navigator.languages
data.browserIsoCode = navLangs.find((l) => l.length === 5)
data.browserLangCode = navLangs[0]
if (ISO6391.validate(data.browserLangCode)) {
data.browserLang = ISO6391.getNativeName(data.browserLangCode)
} else {
data.browserIsoCode = 'en-US'
data.browserLangCode = 'en'
data.browserLang = 'English'
}
}
const handleBtnClick = async () => {
let response
const refreshButton = document.querySelector('.loading-icon .fa-spinner')
refreshButton.classList.add('show')
toggleShow()
if (!props.translated && toggle.value === 'translated') {
response = await GetChatHistoryTranslated(store, store.state.matchDetails.match_id)
}
if (props.translated && toggle.value === 'translated')
response = 'already translated'
if (toggle.value === 'original')
response = 'original'
if (refreshButton.classList.contains('show'))
refreshButton.classList.remove('show')
return response
}
const toggleShow = () => {
const offBtn = document.getElementById('toggle-off')
const onBtn = document.getElementById('toggle-on')
if (offBtn.classList.contains('show')) {
offBtn.classList.remove('show')
onBtn.classList.add('show')
toggle.value = 'translated'
} else if (onBtn.classList.contains('show')) {
onBtn.classList.remove('show')
offBtn.classList.add('show')
toggle.value = 'original'
}
}
onMounted(() => {
setLanguageVariables()
})
return {data, toggle, handleBtnClick}
},
}
</script>
<style lang="scss" scoped>
.toggle-btn {
margin: 0 auto;
cursor: pointer;
.fa {
display: none;
font-size: 1.2rem;
vertical-align: middle;
&.show {
display: inline-block;
}
}
}
</style>