diff --git a/package-lock.json b/package-lock.json
index 7daaf92..c757fae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8578,6 +8578,11 @@
"resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw=="
},
+ "vuex": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.3.0.tgz",
+ "integrity": "sha512-1MfcBt+YFd20DPwKe0ThhYm1UEXZya4gVKUvCy7AtS11YAOUR+9a6u4fsv1Rr6ePZCDNxW/M1zuIaswp6nNv8Q=="
+ },
"watchpack": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz",
diff --git a/package.json b/package.json
index d21aac8..c4f1b86 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"sass": "^1.26.3",
"sass-loader": "^8.0.2",
"vue": "^2.3.3",
- "vue-template-compiler": "^2.6.11"
+ "vue-template-compiler": "^2.6.11",
+ "vuex": "^3.3.0"
},
"devDependencies": {
"@vue/cli-plugin-eslint": "^4.3.1",
diff --git a/src/App.vue b/src/App.vue
index a89f9c3..d160639 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -3,15 +3,19 @@
id="app"
@keyup="keyup"
tabindex="-1"
- v-bind:class="{ screenshot: isScreenshot }"
- v-bind:style="{ backgroundImage: background ? `url('${background}')` : '' }"
+ v-bind:class="{ screenshot: grimoire.isScreenshot }"
+ v-bind:style="{
+ backgroundImage: grimoire.background
+ ? `url('${grimoire.background}')`
+ : ''
+ }"
>
Welcome to the (unofficial)
Virtual Blood on the Clocktower Town Square!
Please add more players through the
-
+
Menu
on the top right or by pressing [A].
@@ -24,252 +28,62 @@
v-if="players.length"
>
-
- Select an edition:
-
- -
- {{ edition.name }}
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/components/Menu.vue b/src/components/Menu.vue
new file mode 100644
index 0000000..37c44fe
--- /dev/null
+++ b/src/components/Menu.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RoleSelectionModal.vue b/src/components/RoleSelectionModal.vue
index d623351..26d9822 100644
--- a/src/components/RoleSelectionModal.vue
+++ b/src/components/RoleSelectionModal.vue
@@ -1,8 +1,8 @@
Select the characters for {{ nontravelerPlayers }} players:
@@ -51,6 +51,7 @@
import Modal from "./Modal";
import gameJSON from "./../game";
import Token from "./Token";
+import { mapMutations, mapState } from "vuex";
const randomElement = arr => arr[Math.floor(Math.random() * arr.length)];
@@ -63,14 +64,6 @@ export default {
players: {
type: Array,
required: true
- },
- roles: {
- type: Map,
- required: true
- },
- isOpen: {
- type: Boolean,
- required: true
}
},
data: function() {
@@ -96,12 +89,10 @@ export default {
return Object.values(this.roleSelection).some(roles =>
roles.some(role => role.selected && role.setup)
);
- }
+ },
+ ...mapState(["roles", "modals"])
},
methods: {
- close() {
- this.$emit("close");
- },
selectRandomRoles() {
this.roleSelection = {};
this.roles.forEach(role => {
@@ -141,7 +132,8 @@ export default {
});
this.close();
}
- }
+ },
+ ...mapMutations(["toggleModal"])
},
mounted: function() {
if (!Object.keys(this.roleSelection).length) {
diff --git a/src/components/Screenshot.vue b/src/components/Screenshot.vue
index 8fa68aa..15c80c4 100644
--- a/src/components/Screenshot.vue
+++ b/src/components/Screenshot.vue
@@ -13,9 +13,10 @@ export default {
};
},
methods: {
- async capture({ x = 0, y = 0, width = 0, height = 0 }, zoom = 1) {
+ async capture({ x = 0, y = 0, width = 0, height = 0 }) {
const canvas = this.$refs.canvas;
const video = this.$refs.video;
+ const zoom = this.$store.state.grimoire.zoom;
// start capturing
if (!this.stream || !this.stream.active) {
alert(
@@ -30,7 +31,7 @@ export default {
audio: false
});
} catch (err) {
- this.$emit("error", err);
+ this.$store.commit("updateScreenshot", false);
}
}
// get screenshot
@@ -57,9 +58,9 @@ export default {
// eslint-disable-next-line no-undef
const item = new ClipboardItem({ "image/png": blob });
navigator.clipboard.write([item]);
- this.$emit("success");
+ this.$store.commit("updateScreenshot", true);
} catch (err) {
- this.$emit("error", err);
+ this.$store.commit("updateScreenshot", false);
}
});
}, 100);
diff --git a/src/main.js b/src/main.js
index 5b24f4b..dba9a27 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,5 +1,6 @@
import Vue from "vue";
import App from "./App";
+import store from "./store";
import { library } from "@fortawesome/fontawesome-svg-core";
import {
faBookOpen,
@@ -45,5 +46,6 @@ Vue.component("font-awesome-icon", FontAwesomeIcon);
Vue.config.productionTip = false;
new Vue({
- render: h => h(App)
+ render: h => h(App),
+ store
}).$mount("#app");
diff --git a/src/store/index.js b/src/store/index.js
new file mode 100644
index 0000000..0016e55
--- /dev/null
+++ b/src/store/index.js
@@ -0,0 +1,73 @@
+import Vue from "vue";
+import Vuex from "vuex";
+import editionJSON from "../editions.json";
+import rolesJSON from "../roles.json";
+
+Vue.use(Vuex);
+
+const getRolesByEdition = (edition = "tb") => {
+ const selectedEdition = editionJSON.find(({ id }) => id === edition);
+ return new Map(
+ rolesJSON
+ .filter(
+ r => r.edition === edition || selectedEdition.roles.includes(r.id)
+ )
+ .sort((a, b) => b.team.localeCompare(a.team))
+ .map(role => [role.id, role])
+ );
+};
+
+export default new Vuex.Store({
+ state: {
+ grimoire: {
+ isNightOrder: true,
+ isPublic: true,
+ isScreenshot: false,
+ isScreenshotSuccess: false,
+ zoom: 1,
+ background: ""
+ },
+ modals: {
+ edition: false,
+ roles: false
+ },
+ edition: "tb",
+ roles: getRolesByEdition(),
+ players: []
+ },
+ mutations: {
+ toggleGrimoire({ grimoire }) {
+ grimoire.isPublic = !grimoire.isPublic;
+ grimoire.isControlOpen = !grimoire.isPublic;
+ },
+ showGrimoire({ grimoire }) {
+ grimoire.isPublic = false;
+ },
+ toggleNightOrder({ grimoire }) {
+ grimoire.isNightOrder = !grimoire.isNightOrder;
+ },
+ updateZoom({ grimoire }, by = 0) {
+ grimoire.zoom += by;
+ },
+ setBackground({ grimoire }, background) {
+ grimoire.background = background;
+ },
+ toggleModal({ modals }, name) {
+ modals[name] = !modals[name];
+ },
+ updateScreenshot({ grimoire }, status) {
+ if (status !== true && status !== false) {
+ grimoire.isScreenshotSuccess = false;
+ grimoire.isScreenshot = true;
+ } else {
+ grimoire.isScreenshotSuccess = status;
+ grimoire.isScreenshot = false;
+ }
+ },
+ setEdition(state, edition) {
+ state.edition = edition;
+ state.modals.edition = false;
+ state.roles = getRolesByEdition(edition);
+ }
+ }
+});