townsquare/src/components/Menu.vue

289 lines
7.0 KiB
Vue
Raw Normal View History

2020-05-02 19:11:20 +00:00
<template>
<div id="controls">
<Screenshot ref="screenshot"></Screenshot>
<font-awesome-icon
icon="camera"
@click="takeScreenshot()"
v-bind:class="{ success: grimoire.isScreenshotSuccess }"
/>
2020-05-02 19:33:44 +00:00
<div class="menu" v-bind:class="{ open: grimoire.isMenuOpen }">
<font-awesome-icon icon="cog" @click="toggleMenu" />
2020-05-02 19:11:20 +00:00
<ul>
<!-- Grimoire -->
<li class="headline">
<font-awesome-icon icon="book-open" />
Grimoire
</li>
<li @click="toggleGrimoire" v-if="players.length">
<em>[G]</em>
<template v-if="!grimoire.isPublic">Hide</template>
<template v-if="grimoire.isPublic">Show</template>
</li>
<li @click="toggleNightOrder" v-if="players.length">
<em
><font-awesome-icon
:icon="['fas', grimoire.isNightOrder ? 'check-square' : 'square']"
/></em>
Night order
</li>
<li v-if="players.length">
<em>
<font-awesome-icon @click="updateZoom(-0.1)" icon="search-minus" />
{{ Math.round(grimoire.zoom * 100) }}%
<font-awesome-icon @click="updateZoom(0.1)" icon="search-plus" />
</em>
Zoom
</li>
<li @click="setBackground">
Background image
</li>
2020-05-08 17:33:29 +00:00
<li @click="hostSession" v-if="!grimoire.sessionId">
Host Live Session
</li>
<li @click="joinSession" v-if="!grimoire.sessionId">
Join Live Session
</li>
<li class="headline" v-if="grimoire.sessionId">
<font-awesome-icon icon="broadcast-tower" />
2020-05-09 19:56:51 +00:00
{{ grimoire.isSpectator ? "Playing" : "Hosting" }}
</li>
2020-05-08 17:33:29 +00:00
<li @click="leaveSession" v-if="grimoire.sessionId">
<em>{{ grimoire.sessionId }}</em>
2020-05-08 17:33:29 +00:00
Leave Session
</li>
2020-05-02 19:11:20 +00:00
<template v-if="!grimoire.isSpectator">
<!-- Users -->
<li class="headline">
<font-awesome-icon icon="users" />
Players
</li>
2020-05-09 19:48:16 +00:00
<li @click="addPlayer" v-if="players.length < 20">
<em>[A]</em> Add
</li>
<li @click="randomizeSeatings" v-if="players.length > 2">
<em>[R]</em> Randomize
</li>
<li @click="clearPlayers" v-if="players.length">
Remove all
</li>
2020-05-02 19:11:20 +00:00
<!-- Characters -->
<li class="headline">
<font-awesome-icon icon="theater-masks" />
Characters
</li>
<li @click="toggleModal('edition')">
<em>[E]</em>
Select Edition
</li>
<li @click="toggleModal('roles')" v-if="players.length > 4">
<em>[C]</em>
Choose & Assign
</li>
<li @click="clearRoles" v-if="players.length">
Remove all
</li>
</template>
2020-05-02 19:11:20 +00:00
</ul>
</div>
</div>
</template>
<script>
import { mapMutations, mapState } from "vuex";
import Screenshot from "./Screenshot";
export default {
components: {
Screenshot
},
2020-05-08 17:33:29 +00:00
computed: {
...mapState(["grimoire"]),
...mapState("players", ["players"])
},
2020-05-02 19:11:20 +00:00
methods: {
takeScreenshot(dimensions = {}) {
this.$store.commit("updateScreenshot");
this.$refs.screenshot.capture(dimensions);
},
setBackground() {
this.$store.commit(
"setBackground",
prompt("Enter custom background URL")
);
},
2020-05-08 17:33:29 +00:00
hostSession() {
const sessionId = prompt(
"Enter a code for your session",
2020-05-09 19:56:51 +00:00
Math.round(Math.random() * 10000)
2020-05-08 17:33:29 +00:00
);
if (sessionId) {
this.$store.commit("setSpectator", false);
this.$store.commit("setSessionId", sessionId.substr(0, 5));
2020-05-08 17:33:29 +00:00
}
},
joinSession() {
const sessionId = prompt(
"Enter the code of the session you want to join"
);
if (sessionId) {
this.$store.commit("setSpectator", true);
this.$store.commit("setSessionId", sessionId.substr(0, 5));
2020-05-08 17:33:29 +00:00
}
},
leaveSession() {
this.$store.commit("setSpectator", false);
2020-05-08 17:33:29 +00:00
this.$store.commit("setSessionId", "");
},
2020-05-02 19:11:20 +00:00
addPlayer() {
if (this.grimoire.isSpectator) return;
2020-05-02 19:11:20 +00:00
const name = prompt("Player name");
if (name) {
2020-05-03 21:05:17 +00:00
this.$store.commit("players/add", name);
2020-05-02 19:11:20 +00:00
}
},
randomizeSeatings() {
if (this.grimoire.isSpectator) return;
2020-05-02 19:11:20 +00:00
if (confirm("Are you sure you want to randomize seatings?")) {
2020-05-03 21:05:17 +00:00
this.$store.dispatch("players/randomize");
2020-05-02 19:11:20 +00:00
}
},
clearPlayers() {
if (this.grimoire.isSpectator) return;
2020-05-02 19:11:20 +00:00
if (confirm("Are you sure you want to remove all players?")) {
2020-05-03 21:05:17 +00:00
this.$store.commit("players/clear");
2020-05-02 19:11:20 +00:00
}
},
clearRoles() {
if (this.grimoire.isSpectator) return;
2020-05-02 19:11:20 +00:00
this.$store.commit("showGrimoire");
if (confirm("Are you sure you want to remove all player roles?")) {
2020-05-03 21:05:17 +00:00
this.$store.dispatch("players/clearRoles");
2020-05-02 19:11:20 +00:00
}
},
...mapMutations([
"toggleGrimoire",
2020-05-02 19:33:44 +00:00
"toggleMenu",
2020-05-02 19:11:20 +00:00
"toggleNightOrder",
"updateScreenshot",
"updateZoom",
"toggleModal"
])
}
};
</script>
<style scoped lang="scss">
@import "../vars.scss";
2020-05-02 19:33:44 +00:00
// success animation
@keyframes greenToWhite {
from {
color: green;
}
to {
color: white;
}
}
2020-05-02 19:11:20 +00:00
// Controls
#controls {
position: absolute;
right: 3px;
top: 3px;
text-align: right;
#app.screenshot & {
display: none;
}
svg {
cursor: pointer;
filter: drop-shadow(0 0 5px rgba(0, 0, 0, 1));
&.success {
animation: greenToWhite 1s normal forwards;
animation-iteration-count: 1;
}
}
.fa-camera {
position: absolute;
right: 50px;
top: 10px;
z-index: 5;
}
}
.menu {
width: 210px;
transform-origin: 190px 22px;
transition: transform 500ms cubic-bezier(0.68, -0.55, 0.27, 1.55);
transform: rotate(-90deg);
&.open {
transform: rotate(0deg);
}
> svg {
background: rgba(0, 0, 0, 0.5);
border: 3px solid black;
width: 40px;
height: 50px;
margin-bottom: -8px;
border-bottom: 0;
border-radius: 10px 10px 0 0;
padding: 5px 5px 15px;
}
ul {
display: flex;
list-style-type: none;
padding: 0;
margin: 0;
flex-direction: column;
overflow: hidden;
box-shadow: 0 0 10px black;
border: 3px solid black;
border-radius: 10px 0 10px 10px;
li {
padding: 2px 10px;
color: white;
text-align: left;
background: rgba(0, 0, 0, 0.7);
&:last-child {
margin-bottom: 0;
}
&:not(.headline):hover {
cursor: pointer;
color: red;
}
em {
float: right;
font-style: normal;
margin-left: 10px;
font-size: 80%;
line-height: 31px;
}
}
.headline {
padding: 5px 10px;
text-align: center;
font-weight: bold;
background: linear-gradient(
to right,
2020-05-04 21:05:36 +00:00
$townsfolk 0%,
2020-05-02 19:11:20 +00:00
rgba(0, 0, 0, 0.5) 20%,
rgba(0, 0, 0, 0.5) 80%,
2020-05-04 21:05:36 +00:00
$demon 100%
2020-05-02 19:11:20 +00:00
);
}
}
}
</style>