replaced background image again

added session handling with persistence and urls
This commit is contained in:
Steffen 2020-05-12 20:48:00 +02:00
parent c8d71e7454
commit 4fd880961c
No known key found for this signature in database
GPG Key ID: 764D74E98267DFC6
9 changed files with 111 additions and 44 deletions

View File

@ -37,10 +37,10 @@ export default {
EditionModal,
RolesModal
},
computed: mapState({
grimoire: state => state.grimoire,
players: state => state.players.players
}),
computed: {
...mapState(["grimoire", "session"]),
...mapState("players", ["players"])
},
methods: {
takeScreenshot(dimensions) {
this.$refs.menu.takeScreenshot(dimensions);
@ -57,11 +57,11 @@ export default {
this.$refs.menu.randomizeSeatings();
break;
case "e":
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
this.$store.commit("toggleModal", "edition");
break;
case "c":
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
this.$store.commit("toggleModal", "roles");
break;
case "Escape":

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -1,9 +1,17 @@
<template>
<div id="controls">
<Screenshot ref="screenshot"></Screenshot>
<font-awesome-icon
@click="leaveSession"
icon="broadcast-tower"
v-if="session.sessionId"
v-bind:class="{ spectator: session.isSpectator }"
title="You're currently in a live game!"
/>
<font-awesome-icon
icon="camera"
@click="takeScreenshot()"
title="Take a screenshot"
v-bind:class="{ success: grimoire.isScreenshotSuccess }"
/>
<div class="menu" v-bind:class="{ open: grimoire.isMenuOpen }">
@ -37,22 +45,26 @@
<li @click="setBackground">
Background image
</li>
<li @click="hostSession" v-if="!grimoire.sessionId">
<li @click="hostSession" v-if="!session.sessionId">
Host Live Session
</li>
<li @click="joinSession" v-if="!grimoire.sessionId">
<li @click="joinSession" v-if="!session.sessionId">
Join Live Session
</li>
<li class="headline" v-if="grimoire.sessionId">
<li class="headline" v-if="session.sessionId">
<font-awesome-icon icon="broadcast-tower" />
{{ grimoire.isSpectator ? "Playing" : "Hosting" }}
{{ session.isSpectator ? "Playing" : "Hosting" }}
</li>
<li @click="leaveSession" v-if="grimoire.sessionId">
<em>{{ grimoire.sessionId }}</em>
<li v-if="session.sessionId" @click="copySessionUrl">
<em><font-awesome-icon icon="copy"/></em>
Copy player link
</li>
<li @click="leaveSession" v-if="session.sessionId">
<em>{{ session.sessionId }}</em>
Leave Session
</li>
<template v-if="!grimoire.isSpectator">
<template v-if="!session.isSpectator">
<!-- Users -->
<li class="headline">
<font-awesome-icon icon="users" />
@ -99,7 +111,7 @@ export default {
Screenshot
},
computed: {
...mapState(["grimoire"]),
...mapState(["grimoire", "session"]),
...mapState("players", ["players"])
},
methods: {
@ -115,49 +127,70 @@ export default {
},
hostSession() {
const sessionId = prompt(
"Enter a code for your session",
"Enter a channel number for your session",
Math.round(Math.random() * 10000)
);
if (sessionId) {
this.$store.commit("setSpectator", false);
this.$store.commit("setSessionId", sessionId.substr(0, 5));
this.$store.commit(
"setSessionId",
sessionId.replace(/[^0-9]/g, "").substr(0, 5)
);
this.copySessionUrl();
}
},
copySessionUrl() {
// check for clipboard permissions
navigator.permissions
.query({ name: "clipboard-write" })
.then(({ state }) => {
if (state === "granted" || state === "prompt") {
const url = window.location.href.split("#")[0];
const link = url + "#play/" + this.session.sessionId;
navigator.clipboard.writeText(link);
}
});
},
joinSession() {
const sessionId = prompt(
"Enter the code of the session you want to join"
"Enter the channel number of the session you want to join"
);
if (sessionId) {
this.$store.commit("setSpectator", true);
this.$store.commit("setSessionId", sessionId.substr(0, 5));
this.$store.commit(
"setSessionId",
sessionId.replace(/[^0-9]/g, "").substr(0, 5)
);
}
},
leaveSession() {
this.$store.commit("setSpectator", false);
this.$store.commit("setSessionId", "");
if (confirm("Are you sure you want to leave the active live game?")) {
this.$store.commit("setSpectator", false);
this.$store.commit("setSessionId", "");
}
},
addPlayer() {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
const name = prompt("Player name");
if (name) {
this.$store.commit("players/add", name);
}
},
randomizeSeatings() {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
if (confirm("Are you sure you want to randomize seatings?")) {
this.$store.dispatch("players/randomize");
}
},
clearPlayers() {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
if (confirm("Are you sure you want to remove all players?")) {
this.$store.commit("players/clear");
this.$store.commit("setBluff");
}
},
clearRoles() {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
if (confirm("Are you sure you want to remove all player roles?")) {
this.$store.dispatch("players/clearRoles");
this.$store.commit("setBluff");
@ -194,13 +227,13 @@ export default {
right: 3px;
top: 3px;
text-align: right;
padding-right: 50px;
#app.screenshot & {
display: none;
}
svg {
cursor: pointer;
filter: drop-shadow(0 0 5px rgba(0, 0, 0, 1));
&.success {
animation: greenToWhite 1s normal forwards;
@ -208,12 +241,17 @@ export default {
}
}
.fa-camera {
position: absolute;
right: 50px;
top: 10px;
> svg {
cursor: pointer;
z-index: 5;
}
> .fa-broadcast-tower {
color: $demon;
&.spectator {
color: $townsfolk;
}
}
}
.menu {
@ -221,12 +259,16 @@ export default {
transform-origin: 190px 22px;
transition: transform 500ms cubic-bezier(0.68, -0.55, 0.27, 1.55);
transform: rotate(-90deg);
position: absolute;
right: 0;
top: 0;
&.open {
transform: rotate(0deg);
}
> svg {
cursor: pointer;
background: rgba(0, 0, 0, 0.5);
border: 3px solid black;
width: 40px;

View File

@ -93,7 +93,7 @@ export default {
}
},
computed: {
...mapState(["grimoire"]),
...mapState(["grimoire", "session"]),
...mapGetters({ nightOrder: "players/nightOrder" })
},
data() {
@ -125,7 +125,7 @@ export default {
}
},
changeName() {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
const name = prompt("Player name", this.player.name) || this.player.name;
this.updatePlayer("name", name);
},
@ -135,7 +135,7 @@ export default {
this.updatePlayer("reminders", reminders);
},
updatePlayer(property, value) {
if (this.grimoire.isSpectator && property !== "reminders") return;
if (this.session.isSpectator && property !== "reminders") return;
this.$store.commit("players/update", {
player: this.player,
property,

View File

@ -4,7 +4,7 @@
class="square"
v-bind:class="{
public: grimoire.isPublic,
spectator: grimoire.isSpectator
spectator: session.isSpectator
}"
v-bind:style="{ zoom: grimoire.zoom }"
>
@ -54,7 +54,7 @@ export default {
ReminderModal
},
computed: {
...mapState(["grimoire", "roles"]),
...mapState(["grimoire", "roles", "session"]),
...mapState("players", ["players"])
},
data() {
@ -74,12 +74,12 @@ export default {
},
openRoleModal(playerIndex) {
const player = this.players[playerIndex];
if (this.grimoire.isSpectator && player.role.team === "traveler") return;
if (this.session.isSpectator && player.role.team === "traveler") return;
this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "role");
},
removePlayer(playerIndex) {
if (this.grimoire.isSpectator) return;
if (this.session.isSpectator) return;
if (
confirm(
`Do you really want to remove ${this.players[playerIndex].name}?`

View File

@ -19,7 +19,8 @@ import {
faSquare,
faRandom,
faPeopleArrows,
faBroadcastTower
faBroadcastTower,
faCopy
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
@ -40,7 +41,8 @@ library.add(
faSquare,
faRandom,
faPeopleArrows,
faBroadcastTower
faBroadcastTower,
faCopy
);
Vue.component("font-awesome-icon", FontAwesomeIcon);

View File

@ -34,7 +34,7 @@ export default new Vuex.Store({
isScreenshotSuccess: false,
zoom: 1,
background: "",
bluffs: [],
bluffs: []
},
session: {
sessionId: "",
@ -72,11 +72,11 @@ export default new Vuex.Store({
setBackground({ grimoire }, background) {
grimoire.background = background;
},
setSessionId({ grimoire }, sessionId) {
grimoire.sessionId = sessionId;
setSessionId({ session }, sessionId) {
session.sessionId = sessionId;
},
setSpectator({ grimoire }, spectator) {
grimoire.isSpectator = spectator;
setSpectator({ session }, spectator) {
session.isSpectator = spectator;
},
setBluff({ grimoire }, { index, role } = {}) {
if (index !== undefined) {

View File

@ -27,6 +27,11 @@ module.exports = store => {
}))
);
}
if (localStorage.getItem("session")) {
const [spectator, sessionId] = JSON.parse(localStorage.getItem("session"));
store.commit("setSpectator", spectator);
store.commit("setSessionId", sessionId);
}
// listen to mutations
store.subscribe(({ type, payload }, state) => {
@ -53,6 +58,16 @@ module.exports = store => {
JSON.stringify(state.grimoire.bluffs.map(({ id }) => id))
);
break;
case "setSessionId":
if (payload) {
localStorage.setItem(
"session",
JSON.stringify([state.session.isSpectator, payload])
);
} else {
localStorage.removeItem("session");
}
break;
case "players/add":
case "players/update":
case "players/remove":

View File

@ -79,7 +79,7 @@ class LiveSession {
* @param channel
*/
connect(channel) {
this.isSpectator = this.store.state.grimoire.isSpectator;
this.isSpectator = this.store.state.session.isSpectator;
this._open(channel);
}
@ -249,6 +249,7 @@ module.exports = store => {
if (payload) {
session.connect(payload);
} else {
window.location.hash = "";
session.disconnect();
}
break;
@ -264,4 +265,11 @@ module.exports = store => {
break;
}
});
// check for session Id in hash
const [command, param] = window.location.hash.substr(1).split("/");
if (command === "play") {
store.commit("setSpectator", true);
store.commit("setSessionId", param);
}
};