added swapping, fixed some bugs

This commit is contained in:
Steffen 2020-05-12 22:22:36 +02:00
parent 4fd880961c
commit ddb4105c89
No known key found for this signature in database
GPG Key ID: 764D74E98267DFC6
8 changed files with 190 additions and 48 deletions

View File

@ -244,6 +244,8 @@ export default {
> svg {
cursor: pointer;
z-index: 5;
margin-top: 10px;
margin-left: 10px;
}
> .fa-broadcast-tower {

View File

@ -33,6 +33,19 @@
<Token :role="player.role" @set-role="$emit('set-role')" />
<font-awesome-icon
icon="times-circle"
class="cancel"
title="Cancel"
@click="doSwap(true)"
/>
<font-awesome-icon
icon="exchange-alt"
class="swap"
@click="doSwap()"
title="Swap seats with this player"
/>
<font-awesome-icon
icon="vote-yea"
class="vote"
@ -41,18 +54,40 @@
title="Ghost vote"
/>
<div class="name" @click="changeName">
<span class="screenshot" @click.stop="takeScreenshot">
<font-awesome-icon icon="camera" />
</span>
<span class="name">
{{ player.name }}
</span>
<span class="remove" @click.stop="$emit('remove-player')">
<font-awesome-icon icon="times-circle" />
</span>
<div
class="name"
@click="isMenuOpen = !isMenuOpen"
v-bind:class="{ active: isMenuOpen }"
>
{{ player.name }}
</div>
<transition name="fold">
<ul class="menu" v-if="isMenuOpen && !session.isSpectator">
<li @click="changeName">
<font-awesome-icon icon="user-edit" />
Rename
</li>
<!--<li @click="nomination">
<font-awesome-icon icon="hand-point-right" />
Nomination
</li>-->
<li @click="initSwap">
<font-awesome-icon icon="exchange-alt" />
Swap seats
</li>
<li @click="takeScreenshot">
<font-awesome-icon icon="camera" />
Screenshot
</li>
<li @click="$emit('remove-player')">
<font-awesome-icon icon="times-circle" />
Remove
</li>
</ul>
</transition>
</div>
<template v-if="player.reminders">
<div
class="reminder"
@ -97,7 +132,10 @@ export default {
...mapGetters({ nightOrder: "players/nightOrder" })
},
data() {
return {};
return {
isMenuOpen: false,
isSwap: false
};
},
filters: {
handleEmojis: text => text.replace(/:([^: ]+?):/g, "").replace(/ •/g, "\n•")
@ -106,6 +144,7 @@ export default {
takeScreenshot() {
const { width, height, x, y } = this.$refs.player.getBoundingClientRect();
this.$emit("screenshot", { width, height, x, y });
this.isMenuOpen = false;
},
toggleStatus() {
if (this.grimoire.isPublic) {
@ -128,6 +167,7 @@ export default {
if (this.session.isSpectator) return;
const name = prompt("Player name", this.player.name) || this.player.name;
this.updatePlayer("name", name);
this.isMenuOpen = false;
},
removeReminder(reminder) {
const reminders = [...this.player.reminders];
@ -141,6 +181,13 @@ export default {
property,
value
});
},
initSwap() {
this.isMenuOpen = false;
this.$emit("swap-seats");
},
doSwap(cancel) {
this.$emit("swap-seats", cancel ? false : this.player);
}
}
};
@ -149,6 +196,17 @@ export default {
<style lang="scss">
@import "../vars.scss";
.fold-enter-active,
.fold-leave-active {
transition: transform 250ms ease-in-out;
transform-origin: left center;
transform: perspective(200px);
}
.fold-enter,
.fold-leave-to {
transform: perspective(200px) rotateY(90deg);
}
/***** Player token *****/
.circle .player {
margin-bottom: 10px;
@ -284,6 +342,40 @@ export default {
transform: perspective(400px) rotateY(-180deg);
}
/****** Player choice icons *******/
.player > svg {
position: absolute;
filter: drop-shadow(0 0 3px black);
z-index: 2;
cursor: pointer;
&.swap,
&.cancel {
top: 9%;
left: 20%;
width: 60%;
height: 60%;
opacity: 0;
pointer-events: none;
transition: all 250ms;
transform: scale(0.2);
&:hover {
color: red;
}
}
}
li.swap-from .player > svg.cancel {
opacity: 1;
transform: scale(1);
pointer-events: all;
}
li.swap:not(.swap-from) .player > svg.swap {
opacity: 1;
transform: scale(1);
pointer-events: all;
}
/****** Vote icon ********/
.player .vote {
position: absolute;
@ -314,37 +406,12 @@ export default {
border-radius: 10px;
top: 5px;
box-shadow: 0 0 5px black;
text-overflow: ellipsis;
overflow: hidden;
span.screenshot,
span.remove {
display: none;
position: absolute;
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5));
#app.screenshot & {
display: none;
}
}
span.screenshot {
right: 100%;
}
span.remove {
left: 100%;
}
span.name {
flex-shrink: 1;
text-overflow: ellipsis;
overflow: hidden;
}
#townsquare:not(.spectator) &:hover {
#townsquare:not(.spectator) &:hover,
&.active {
color: red;
span {
display: block;
color: white;
&:hover {
color: red;
}
}
}
}
@ -352,11 +419,47 @@ export default {
opacity: 0.5;
}
/***** Player menu *****/
.player > .menu {
position: absolute;
left: 100%;
bottom: 0;
text-align: left;
white-space: nowrap;
background: rgba(0, 0, 0, 0.5);
padding: 0 5px;
border-radius: 5px;
border: 3px solid black;
margin-left: 15px;
cursor: pointer;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
&:before {
content: " ";
width: 0;
height: 0;
position: absolute;
border: 10px solid transparent;
border-right-color: black;
right: 100%;
bottom: 7px;
margin-right: 2px;
}
li:hover {
color: red;
}
svg {
margin-right: 2px;
}
}
/***** Ability text *****/
#townsquare.public .ability {
display: none;
}
.circle .player:hover .ability {
.circle .player .shroud:hover ~ .token .ability,
.circle .player .token:hover .ability {
opacity: 1;
}
@ -370,7 +473,7 @@ export default {
opacity: 1;
transition: opacity 200ms;
display: flex;
top: -16px;
top: -20px;
align-items: center;
pointer-events: none;

View File

@ -16,7 +16,12 @@
@add-reminder="openReminderModal(index)"
@set-role="openRoleModal(index)"
@remove-player="removePlayer(index)"
@swap-seats="swapSeats(index, $event)"
@screenshot="$emit('screenshot', $event)"
v-bind:class="{
'swap-from': swapFrom === index,
swap: swapFrom > -1
}"
></Player>
</ul>
@ -60,7 +65,8 @@ export default {
data() {
return {
selectedPlayer: 0,
bluffs: 3
bluffs: 3,
swapFrom: -1
};
},
methods: {
@ -87,6 +93,19 @@ export default {
) {
this.$store.commit("players/remove", playerIndex);
}
},
swapSeats(from, to) {
if (to === undefined) {
this.swapFrom = from;
} else if (to === false) {
this.swapFrom = -1;
} else {
this.$store.commit("players/swap", [
this.swapFrom,
this.players.indexOf(to)
]);
this.swapFrom = -1;
}
}
}
};
@ -100,7 +119,7 @@ export default {
list-style: none;
margin: 0;
li {
> li {
position: absolute;
top: 0;
left: 50%;
@ -169,7 +188,7 @@ export default {
}
@for $i from 1 through 20 {
.circle.size-#{$i} li {
.circle.size-#{$i} > li {
@include on-circle($item-count: $i);
}
}

View File

@ -5,7 +5,11 @@
>
<h3>
Choose a new character for
{{ playerIndex >= 0 ? players[playerIndex].name : "bluffing" }}
{{
playerIndex >= 0 && players.length
? players[playerIndex].name
: "bluffing"
}}
</h3>
<ul class="tokens">
<li

View File

@ -12,6 +12,7 @@ import {
faTheaterMasks,
faTimesCircle,
faUser,
faUserEdit,
faUserFriends,
faUsers,
faVoteYea,
@ -20,7 +21,9 @@ import {
faRandom,
faPeopleArrows,
faBroadcastTower,
faCopy
faCopy,
faExchangeAlt,
faHandPointRight
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
@ -34,6 +37,7 @@ library.add(
faTheaterMasks,
faTimesCircle,
faUser,
faUserEdit,
faUserFriends,
faUsers,
faVoteYea,
@ -42,7 +46,9 @@ library.add(
faRandom,
faPeopleArrows,
faBroadcastTower,
faCopy
faCopy,
faExchangeAlt,
faHandPointRight
);
Vue.component("font-awesome-icon", FontAwesomeIcon);

View File

@ -78,6 +78,12 @@ const mutations = {
},
remove(state, index) {
state.players.splice(index, 1);
},
swap(state, [from, to]) {
[state.players[from], state.players[to]] = [
state.players[to],
state.players[from]
];
}
};

View File

@ -73,6 +73,7 @@ module.exports = store => {
case "players/remove":
case "players/clear":
case "players/set":
case "players/swap":
if (state.players.players.length) {
localStorage.setItem(
"players",

View File

@ -254,6 +254,7 @@ module.exports = store => {
}
break;
case "players/set":
case "players/swap":
case "players/clear":
case "players/remove":
case "players/add":