mirror of https://github.com/bra1n/townsquare.git
replaced background image again
added session handling with persistence and urls
This commit is contained in:
parent
c8d71e7454
commit
4fd880961c
12
src/App.vue
12
src/App.vue
|
@ -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 |
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}?`
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue