This commit is contained in:
Christoph Stahl 2022-11-21 18:30:18 +01:00
parent e463329d3e
commit 8a0a07424a
9 changed files with 141 additions and 27 deletions

35
package-lock.json generated
View file

@ -15,7 +15,8 @@
"@fortawesome/vue-fontawesome": "^3.0.2",
"foundation-sites": "^6.7.5",
"socket.io-client": "^4.5.3",
"vue": "^3.2.41"
"vue": "^3.2.41",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.1.2",
@ -200,6 +201,11 @@
"@vue/shared": "3.2.45"
}
},
"node_modules/@vue/devtools-api": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz",
"integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ=="
},
"node_modules/@vue/reactivity": {
"version": "3.2.45",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz",
@ -941,6 +947,20 @@
"@vue/shared": "3.2.45"
}
},
"node_modules/vue-router": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
"integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==",
"dependencies": {
"@vue/devtools-api": "^6.4.5"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/what-input": {
"version": "5.2.12",
"resolved": "https://registry.npmjs.org/what-input/-/what-input-5.2.12.tgz",
@ -1102,6 +1122,11 @@
"@vue/shared": "3.2.45"
}
},
"@vue/devtools-api": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz",
"integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ=="
},
"@vue/reactivity": {
"version": "3.2.45",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz",
@ -1535,6 +1560,14 @@
"@vue/shared": "3.2.45"
}
},
"vue-router": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
"integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==",
"requires": {
"@vue/devtools-api": "^6.4.5"
}
},
"what-input": {
"version": "5.2.12",
"resolved": "https://registry.npmjs.org/what-input/-/what-input-5.2.12.tgz",

View file

@ -14,7 +14,8 @@
"@fortawesome/vue-fontawesome": "^3.0.2",
"foundation-sites": "^6.7.5",
"socket.io-client": "^4.5.3",
"vue": "^3.2.41"
"vue": "^3.2.41",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.1.2",

View file

@ -1,13 +1,13 @@
<script setup>
import { computed, ref, onMounted, onDeactivated } from 'vue'
import $ from 'jquery'
import { io } from "socket.io-client"
import { useRoute, useRouter } from 'vue-router'
import MobileLayout from './components/MobileLayout.vue'
import DesktopLayout from './components/DesktopLayout.vue'
onMounted(() => {
window.addEventListener("resize", resizeBrowserHandler)
})
const router=useRouter()
function resizeBrowserHandler (e) {
is_small.value = (e.target.innerWidth < 768)
@ -16,13 +16,28 @@ function resizeBrowserHandler (e) {
const is_small = ref(window.innerWidth < 768)
const state = ref({
'search': {'searchTerm': '', 'searchResults': []},
'queue': [
{'artist': 'Artist A', 'title': 'Songname A', 'album': 'Album A', 'performer': "Performer A"} ,
{'artist': 'Artist B', 'title': 'Songname B', 'album': 'Album B', 'performer': "Performer B"} ,
{'artist': 'Artist C', 'title': 'Songname C', 'album': 'Album C', 'performer': "Performer C"} ,
]
'queue': [ ],
'roomCode': undefined,
'name': undefined
})
onMounted(() => {
window.addEventListener("resize", resizeBrowserHandler)
$(document).foundation();
$("#welcome").foundation("open")
if(useRoute().params.room) {
state.value.roomCode = useRoute().params.room
closeWelcome()
}
})
function setRoomCode(roomEvent) {
state.value.roomCode = roomEvent.target.value
}
function setName(nameEvent) {
state.value.name = nameEvent.target.value
}
function updateSearchTerm(val) {
state.value.search.searchTerm = val
@ -34,6 +49,23 @@ function search() {
socket.emit("search", {"query": state.value.search.searchTerm })
}
function append(entry) {
socket.emit("append", {"id": entry.id, "performer": state.value.name, "source": entry.source })
}
function closeWelcome() {
if(state.value.roomCode != undefined) {
socket.emit("register-web", {"room": state.value.roomCode}, (response) => {
if(response === true) {
$('#welcome').foundation("close")
router.push({name: "room", params: {room: state.value.roomCode}})
} else {
console.log("no such room")
}
})
}
}
socket.on("search-results", (results) => {
state.value.search.searchResults = results
})
@ -43,18 +75,46 @@ socket.on("connect", () =>
)
socket.on("state", (val) => {
console.log(val)
state.value.queue=val
})
</script>
<script>
</script>
<template>
<div class="page">
<div class="row" id="main-content">
<MobileLayout v-show="is_small" :state="state" @update:searchTerm="updateSearchTerm" />
<DesktopLayout v-show="!is_small" :state="state" @update:searchTerm="updateSearchTerm" @search="search"/>
<DesktopLayout v-show="!is_small" :state="state" @update:searchTerm="updateSearchTerm" @search="search" @append="append" />
<div class="reveal" id="welcome" data-reveal data-close-on-click="false">
<h1>Welcome to Syng</h1>
<p>
Please enter the room code and your name
</p>
<div class="grid-container">
<div class="grid-x grid-padding-x">
<div class="medium-6 cell">
<label>Room code
<input type="text" @input="setRoomCode" placeholder="XXXX">
</label>
</div>
<div class="medium-6 cell">
<label>Name
<input type="text" @input="setName" placeholder="Leave empty to be asked on append">
</label>
</div>
</div>
</div>
<button class="button" @click="closeWelcome" >Connect</button>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
</div>
<router-view></router-view>
</template>
<style scoped>

3
src/Main.vue Normal file
View file

@ -0,0 +1,3 @@
<template>
<router-view></router-view>
</template>

View file

@ -3,13 +3,13 @@ import SearchDesktop from './SearchDesktop.vue'
import QueueDesktop from './QueueDesktop.vue'
const props = defineProps(['state']);
const emit = defineEmits(['update:searchTerm', 'search'])
const emit = defineEmits(['update:searchTerm', 'search', 'append'])
</script>
<template>
<div class="splitter">
<SearchDesktop :search="state.search" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" />
<SearchDesktop :search="state.search" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" @append="(entry) => $emit('append', entry)" />
<QueueDesktop :queue="state.queue" />
<div class="comp-column" id="right-side">
<div class="header">Recent</div>

View file

@ -1,5 +1,6 @@
<script setup>
const props = defineProps(['result']);
const emits = defineEmits(['append'])
</script>
<template>
<li>
@ -7,13 +8,13 @@ const props = defineProps(['result']);
<div class="cell small-9">
<span class="artist">{{result.artist}}</span>
<span class="title">{{result.title}}</span><br />
<span class="album">{{resultalbum}}</span>
<span class="album">{{result.album}}</span>
</div>
<div class="cell small-3">
<button class="button alert fright">
<a class="button alert fright" :href="result.id" v-if="result.source == 'youtube'">
<font-awesome-icon icon="fa-brands fa-youtube" />
</button>
<button class="button fright">
</a>
<button class="button fright" @click="$emit('append')">
<font-awesome-icon icon="fa-solid fa-plus" />
</button>
</div>

View file

@ -3,7 +3,7 @@ import SearchResults from './SearchResults.vue'
import SearchBar from './SearchBar.vue'
const props = defineProps(['search']);
const emit = defineEmits(['update:searchTerm', 'search'])
const emit = defineEmits(['update:searchTerm', 'search', 'append'])
</script>
<template>
@ -11,7 +11,7 @@ const emit = defineEmits(['update:searchTerm', 'search'])
<div class="header">Search</div>
<div class="vsplit">
<SearchBar :searchTerm="search.searchTerm" @update:searchTerm="(val) => $emit('update:searchTerm', val)" @search="$emit('search')" />
<SearchResults :searchResults="search.searchResults" />
<SearchResults :searchResults="search.searchResults" @append="(entry) => $emit('append', entry)" />
</div>
</div>
</template>

View file

@ -1,12 +1,13 @@
<script setup>
import Result from './Result.vue'
const props = defineProps(['searchResults']);
const emits = defineEmits(['append'])
</script>
<template>
<div id="search-results" class="results">
<ul class="vertical menu">
<Result v-for="result in searchResults" :result="result" />
<Result v-for="result in searchResults" :result="result" @append="$emit('append', result)" />
</ul>
</div>
</template>

View file

@ -1,7 +1,9 @@
import { createApp } from 'vue'
import $ from 'jquery'
import { createRouter, createWebHistory } from 'vue-router'
import jquery from 'jquery'
import Foundation from 'foundation-sites'
import App from './App.vue'
import Main from './Main.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faMagnifyingGlass, faList, faHistory, faPlus, faStepForward, faTimes } from '@fortawesome/free-solid-svg-icons'
@ -9,7 +11,6 @@ import { faYoutube } from '@fortawesome/free-brands-svg-icons'
import 'foundation-sites/dist/css/foundation.min.css'
import './assets/main.css'
library.add(faMagnifyingGlass)
library.add(faList)
library.add(faPlus)
@ -18,8 +19,22 @@ library.add(faStepForward)
library.add(faYoutube)
library.add(faTimes)
createApp(App)
.component('font-awesome-icon', FontAwesomeIcon)
.mount('#app')
window.jQuery = jquery;
window.$ = jquery;
$(document).foundation();
Foundation.addToJquery($)
const routes = [
{ path: '/:room/', name: 'room', component: App},
{ path: '/', component: App}
]
const router = createRouter({
history: createWebHistory(),
routes}
)
app = createApp(Main)
app.component('font-awesome-icon', FontAwesomeIcon)
app.use(router)
app.mount('#app')