1
0
forked from noxious/client

Fixed characters not showing after logging in, added loading screen before showing characters, worked on GM tools

This commit is contained in:
Dennis Postma 2024-06-10 02:39:00 +02:00
parent 2f7153fbfe
commit 3e003962dc
10 changed files with 85 additions and 26 deletions

View File

@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_z9k8{transform-origin:center;animation:spinner_StKS .75s infinite linear}@keyframes spinner_StKS{100%{transform:rotate(360deg)}}</style><path d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25"/><path d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" class="spinner_z9k8"/></svg>

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_qM83{animation:spinner_8HQG 1.05s infinite}.spinner_oXPr{animation-delay:.1s}.spinner_ZTLf{animation-delay:.2s}@keyframes spinner_8HQG{0%,57.14%{animation-timing-function:cubic-bezier(0.33,.66,.66,1);transform:translate(0)}28.57%{animation-timing-function:cubic-bezier(0.33,0,.66,.33);transform:translateY(-6px)}100%{transform:translate(0)}}</style><circle class="spinner_qM83" cx="4" cy="12" r="3"/><circle class="spinner_qM83 spinner_oXPr" cx="12" cy="12" r="3"/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="3"/></svg>

After

Width:  |  Height:  |  Size: 635 B

View File

@ -18,13 +18,12 @@ import Game from '@/components/Game.vue'
const screen: Ref<string> = ref('login')
const socket = useSocketStore()
socket.$subscribe(
(mutation, state) => {
socket.$subscribe((mutation, state) => {
if (!state.connection) {
screen.value = 'login'
}
if (state.connection) {
if (state.token && state.connection) {
screen.value = 'characters'
if (state.character) {

View File

@ -16,12 +16,12 @@ body {
}
h1, h2, h3, h4, h5, h6, button, a {
font-family: "Poppins";
font-family: "Poppins", serif;
color: $white;
}
p, span, li, label {
font-family: "Inter";
font-family: "Inter", serif;
color: $white;
}
button, a {
@ -37,6 +37,10 @@ button, input {
button {
text-align: center;
&.w-full {
width: 100%;
}
&.btn-cyan {
background-color: rgba($cyan, 0.5);
border: 1px solid $white;

View File

@ -1,7 +1,7 @@
<template>
<div class="character-select-screen">
<div class="ui-wrapper">
<div class="characters-wrapper">
<div class="characters-wrapper" v-if="!isLoading">
<div v-for="character in characters" :key="character.id" class="character" :class="{ active: selected_character == character.id }">
<input type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" />
<label :for="character.id">{{ character.name }}</label>
@ -23,8 +23,13 @@
</button>
</div>
</div>
<div v-else>
<div class="loading-spinner">
<img src="/assets/icons/loading-icon1.svg" />
</div>
</div>
<div class="button-wrapper">
<div class="button-wrapper" v-if="!isLoading">
<button class="btn-cyan" :disabled="!selected_character" @click="select_character()">
PLAY
<img draggable="false" src="/assets/icons/arrow.svg">
@ -55,18 +60,26 @@
<script setup lang="ts">
import { useSocketStore } from '@/stores/socket'
import { ref } from 'vue'
import { onBeforeMount, onMounted, ref } from 'vue'
import Modal from '@/components/utilities/Modal.vue'
import {type Character as CharacterT} from '@/types'
const isLoading = ref(true)
const characters = ref([])
const socket = useSocketStore()
const socket = useSocketStore();
// Fetch characters
socket.getConnection.on('character:list', (data: any) => {
characters.value = data
})
socket.getConnection.emit('character:list')
onMounted(() => {
// wait 1.5 sec
setTimeout(() => {
socket.getConnection.emit('character:list')
isLoading.value = false
}, 1000)
});
// Select character logics
const selected_character = ref(null)
@ -123,6 +136,14 @@ function create() {
content: '';
}
.loading-spinner img {
width: 5rem;
// css color
filter: invert(1);
// white
filter: invert(80%);
}
.characters-wrapper {
display: flex;
justify-content: center;

View File

@ -32,6 +32,7 @@ import { login, register } from '@/services/authentication'
import { useNotificationStore } from '@/stores/notifications'
import ZoneEditor from '@/components/utilities/zoneEditor/ZoneEditor.vue'
import Modal from '@/components/utilities/Modal.vue'
import { useSocketStore } from '@/stores/socket'
const bgm = ref('bgm')
if (bgm.value.paused) {
@ -39,6 +40,7 @@ if (bgm.value.paused) {
window.addEventListener('keydown', () => bgm.value.play())
}
const socket = useSocketStore()
const notifications = useNotificationStore()
const username = ref('')
const password = ref('')
@ -55,7 +57,11 @@ async function loginFunc() {
if (response.success === undefined) {
notifications.addNotification({ message: response.error })
return
}
socket.setToken(response.token)
socket.initConnection();
}
async function registerFunc() {
@ -70,7 +76,11 @@ async function registerFunc() {
if (response.success === undefined) {
notifications.addNotification({ message: response.error })
return
}
socket.setToken(response.token)
socket.initConnection();
}
</script>

View File

@ -45,9 +45,7 @@ const properties = defineProps({
}
})
watch(
() => properties.isModalOpen,
(value) => {
watch(() => properties.isModalOpen, (value) => {
isModalOpenRef.value = value
}
)
@ -124,6 +122,16 @@ const stopDrag = () => {
isDragging.value = false
}
watch(() => properties.modalWidth, (value) => {
width.value = value
}
)
watch(() => properties.modalHeight, (value) => {
height.value = value
}
)
onMounted(() => {
addEventListener('mousemove', drag)
addEventListener('mouseup', stopDrag)
@ -142,13 +150,11 @@ onUnmounted(() => {
// Make sure modal doesn't go off screen
watch(
() => x.value, (value) => {
watch(() => x.value, (value) => {
if (value < 0) { x.value = 0 } else if (value + width.value > window.innerWidth) { x.value = window.innerWidth - width.value }
}
)
watch(
() => y.value, (value) => {
watch(() => y.value, (value) => {
if (value < 0) { y.value = 0 } else if (value + height.value > window.innerHeight) { y.value = window.innerHeight - height.value }
}
)

View File

@ -1,10 +1,15 @@
<template>
<Modal :isModalOpen="true">
<Modal :isModalOpen="true" :closable="false" :modal-width="200" :modal-height="260">
<template #modalHeader>
<h3 class="modal-title">GM tools</h3>
</template>
<template #modalBody>
<p></p>
<div class="content">
<button class="btn-cyan w-full" type="button">Zone manager</button>
<button class="btn-cyan w-full" type="button">Player manager</button>
<button class="btn-cyan w-full" type="button">Item manager</button>
<button class="btn-cyan w-full" type="button">NPC manager</button>
</div>
</template>
</Modal>
</template>
@ -12,3 +17,11 @@
import ZoneEditor from '@/components/utilities/zoneEditor/ZoneEditor.vue'
import Modal from '@/components/utilities/Modal.vue'
</script>
<style lang="scss">
.content {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
</style>

View File

@ -7,8 +7,7 @@ export async function register(username: string, password: string, socketStore =
try {
const response = await axios.post(`${config.server_endpoint}/register`, { username, password })
useCookies().set('token', response.data.token as string)
await socketStore.setupSocketConnection()
return { success: true }
return { success: true, token: response.data.token}
} catch (error: any) {
return { error: error.response.data.message }
}
@ -18,8 +17,7 @@ export async function login(username: string, password: string, socketStore = us
try {
const response = await axios.post(`${config.server_endpoint}/login`, { username, password })
useCookies().set('token', response.data.token as string)
await socketStore.setupSocketConnection()
return { success: true }
return { success: true, token: response.data.token}
} catch (error: any) {
return { error: error.response.data.message }
}

View File

@ -6,17 +6,19 @@ import type { Character, User } from '@/types'
export const useSocketStore: StoreDefinition = defineStore('socket', {
state: () => ({
token: '' as string | null,
connection: null as Socket | null,
user: null as User | null,
character: null as Character | null
}),
getters: {
getToken: (state: any) => state.token as string,
getConnection: (state: any) => state.connection as Socket,
getUser: (state: any) => state.user as User,
getCharacter: (state: any) => state.character as Character
},
actions: {
setupSocketConnection() {
initConnection() {
this.connection = io(config.server_endpoint, {
withCredentials: true,
transports: ['websocket'],
@ -27,7 +29,7 @@ export const useSocketStore: StoreDefinition = defineStore('socket', {
this.connection.emit('login')
// set user
this.connection.on('login', (user: User) => {
this.connection.on('logged_in', (user: User) => {
this.setUser(user)
})
@ -43,11 +45,15 @@ export const useSocketStore: StoreDefinition = defineStore('socket', {
this.connection.disconnect()
this.connection = null
this.token = null
this.user = null
this.character = null
useCookies().remove('token')
},
setToken(token: string) {
this.token = token
},
setUser(user: User | null) {
this.user = user
},