diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml new file mode 100644 index 0000000..46e088e --- /dev/null +++ b/.github/workflows/changelog-check.yml @@ -0,0 +1,19 @@ +name: Enforce Changelog Update +on: + pull_request: + types: [assigned, opened, synchronize, reopened, labeled, unlabeled] + branches: + - main +jobs: + build: + name: Check Actions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Changelog check + uses: Zomzog/changelog-checker@v1.1.0 + with: + fileName: CHANGELOG.md + noChangelogLabel: no changelog + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b46aeb..70072c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ ### Version 2.9.1 - added [nomination log indicator](https://fontawesome.com/icons/book-dead). When a nomination log [v] is available, the number of currently visible entries is displayed. Clicking the indicator can reveal/hide the nomination log. +- fix gamestate JSON not showing (custom) roles and failing to load states with custom scripts properly +- fix gamestate not stripping out special characters from role.id on load +- made character assignment modal a bit prettier +- got rid of the extra pixels on the Soldier icon +- fixed lengthy live session channel names not being correctly cut off +- hide player names in night order / character reference popup when town square is public +- fix (pre-)vote calculation being off by one if the nominee votes + +--- + +### Version 2.9.0 +- added support for assigning pronouns to players and display of the pronouns in a tooltip on the player name. +- added button to modals that allows the user to maximize them +- added Mephit and Snitch to roles.json ### Version 2.8.0 - added hands-off live session support for homebrew / custom characters again! diff --git a/package-lock.json b/package-lock.json index 6f53472..9b0464d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.8.0", + "version": "2.9.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -500,6 +500,15 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "cacache": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", @@ -525,6 +534,31 @@ "unique-filename": "^1.1.1" } }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true + }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", @@ -544,6 +578,32 @@ "path-exists": "^4.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "optional": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -605,6 +665,15 @@ "minipass": "^3.1.1" } }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "terser-webpack-plugin": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", @@ -620,6 +689,17 @@ "terser": "^4.6.12", "webpack-sources": "^1.4.3" } + }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.1.2", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", + "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + } } } }, @@ -3064,23 +3144,23 @@ "integrity": "sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg==" }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -8840,88 +8920,6 @@ } } }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.1.1", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.1.tgz", - "integrity": "sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==", - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "optional": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "optional": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "vue-style-loader": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", diff --git a/package.json b/package.json index 8eabedb..ffe66b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.8.0", + "version": "2.9.1", "description": "Blood on the Clocktower Town Square", "author": "Steffen Baumgart", "scripts": { diff --git a/src/assets/icons/soldier.png b/src/assets/icons/soldier.png index 0616697..4d6a463 100644 Binary files a/src/assets/icons/soldier.png and b/src/assets/icons/soldier.png differ diff --git a/src/components/Menu.vue b/src/components/Menu.vue index e8dcc56..40abc72 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -361,7 +361,7 @@ export default { top: 3px; text-align: right; padding-right: 50px; - z-index: 200; + z-index: 75; svg { filter: drop-shadow(0 0 5px rgba(0, 0, 0, 1)); diff --git a/src/components/Player.vue b/src/components/Player.vue index 4068144..5dab5f1 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -97,13 +97,16 @@ @click="updatePlayer('isVoteless', true)" title="Ghost vote" /> -
- {{ player.name }} + {{ player.name }} + +
+ {{ player.pronouns }} +
@@ -150,6 +153,15 @@ +
  • + Change Pronouns +
  • @@ -232,6 +244,15 @@ export default { }; }, methods: { + changePronouns() { + if (this.session.isSpectator && this.player.id !== this.session.playerId) + return; + const pronouns = prompt("Player pronouns", this.player.pronouns); + //Only update pronouns if not null (prompt was not cancelled) + if (pronouns !== null) { + this.updatePlayer("pronouns", pronouns, true); + } + }, toggleStatus() { if (this.grimoire.isPublic) { if (!this.player.isDead) { @@ -260,7 +281,12 @@ export default { this.updatePlayer("reminders", reminders, true); }, updatePlayer(property, value, closeMenu = false) { - if (this.session.isSpectator && property !== "reminders") return; + if ( + this.session.isSpectator && + property !== "reminders" && + property !== "pronouns" + ) + return; this.$store.commit("players/update", { player: this.player, property, @@ -629,25 +655,72 @@ li.move:not(.from) .player .overlay svg.move { /***** Player name *****/ .player > .name { - text-align: center; + right: 10%; + display: flex; + justify-content: center; font-size: 120%; line-height: 120%; cursor: pointer; white-space: nowrap; - width: 100%; + width: 120%; background: rgba(0, 0, 0, 0.5); border: 3px solid black; border-radius: 10px; top: 5px; box-shadow: 0 0 5px black; - text-overflow: ellipsis; - overflow: hidden; padding: 0 4px; + svg { + top: 3px; + margin-right: 2px; + } + + span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; + flex-grow: 1; + } + #townsquare:not(.spectator) &:hover, &.active { color: red; } + + &:hover .pronouns { + opacity: 1; + color: white; + } + + .pronouns { + display: flex; + position: absolute; + right: 110%; + max-width: 250px; + z-index: 25; + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; + border: 3px solid black; + filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5)); + align-items: center; + pointer-events: none; + opacity: 0; + transition: opacity 200ms ease-in-out; + padding: 0 4px; + bottom: -3px; + + &:before { + content: " "; + border: 10px solid transparent; + width: 0; + height: 0; + border-left-color: black; + position: absolute; + margin-left: 2px; + left: 100%; + } + } } .player.dead > .name { @@ -657,7 +730,7 @@ li.move:not(.from) .player .overlay svg.move { /***** Player menu *****/ .player > .menu { position: absolute; - left: 100%; + left: 110%; bottom: -5px; text-align: left; white-space: nowrap; diff --git a/src/components/TownSquare.vue b/src/components/TownSquare.vue index 684c386..3236102 100644 --- a/src/components/TownSquare.vue +++ b/src/components/TownSquare.vue @@ -264,7 +264,7 @@ export default { // open menu on the left .player > .menu { left: auto; - right: 100%; + right: 110%; margin-right: 15px; &:before { border-left-color: black; @@ -292,6 +292,16 @@ export default { left: 100%; } } + .pronouns { + left: 110%; + right: auto; + &:before { + border-left-color: transparent; + border-right-color: black; + left: auto; + right: 100%; + } + } } @else { // second half of players z-index: $i - 1; diff --git a/src/components/Vote.vue b/src/components/Vote.vue index 0c91994..4bdd242 100644 --- a/src/components/Vote.vue +++ b/src/components/Vote.vue @@ -10,17 +10,14 @@ {{ nominee.name }}!
    - - + + {{ voters.length }} vote{{ voters.length !== 1 ? "s" : "" }} + + in favor + + (majority is {{ Math.ceil(alive / 2) }}) + + (majority is {{ Math.ceil(players.length / 2) }})
    {{ voters.join(", ") }} @@ -170,7 +167,10 @@ export default { ...voters.slice(nomination + 1), ...voters.slice(0, nomination + 1) ]; - return reorder.slice(0, this.session.lockedVote - 1).filter(n => !!n); + return (this.session.lockedVote + ? reorder.slice(0, this.session.lockedVote - 1) + : reorder + ).filter(n => !!n); } }, data() { diff --git a/src/components/modals/EditionModal.vue b/src/components/modals/EditionModal.vue index c698b2f..2526778 100644 --- a/src/components/modals/EditionModal.vue +++ b/src/components/modals/EditionModal.vue @@ -163,19 +163,15 @@ export default { if (metaIndex > -1) { meta = roles.splice(metaIndex, 1).pop(); } - const customRoles = roles.map(role => { - role.id = role.id.toLocaleLowerCase().replace(/[^a-z0-9]/g, ""); - return role; - }); - this.$store.commit("setCustomRoles", customRoles); + this.$store.commit("setCustomRoles", roles); this.$store.commit( "setEdition", Object.assign({}, meta, { id: "custom" }) ); // check for fabled and set those too, if present - if (customRoles.some(({ id }) => this.$store.state.fabled.has(id))) { + if (roles.some(({ id }) => this.$store.state.fabled.has(id))) { const fabled = []; - customRoles.forEach(({ id }) => { + roles.forEach(({ id }) => { if (this.$store.state.fabled.has(id)) { fabled.push(this.$store.state.fabled.get(id)); } diff --git a/src/components/modals/GameStateModal.vue b/src/components/modals/GameStateModal.vue index 2e3d0dc..b7a7771 100644 --- a/src/components/modals/GameStateModal.vue +++ b/src/components/modals/GameStateModal.vue @@ -37,7 +37,9 @@ export default { edition: this.edition.isOfficial ? { id: this.edition.id } : this.edition, - roles: this.edition.isOfficial ? "" : this.$store.getters.customRoles, + roles: this.edition.isOfficial + ? "" + : this.$store.getters.customRolesStripped, fabled: this.players.fabled.map(({ id }) => id), players: this.players.players.map(player => ({ ...player, diff --git a/src/components/modals/Modal.vue b/src/components/modals/Modal.vue index f5f686f..f0390b8 100644 --- a/src/components/modals/Modal.vue +++ b/src/components/modals/Modal.vue @@ -3,13 +3,27 @@ @@ -17,6 +31,11 @@