show generic icons for custom roles and opt out players

This commit is contained in:
Steffen 2021-02-04 21:40:59 +01:00
parent d409186ff1
commit a5d6d593c8
9 changed files with 87 additions and 72 deletions

BIN
src/assets/icons/minion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -23,7 +23,7 @@
> >
<em>{{ nightOrder.get(player).first }}.</em> <em>{{ nightOrder.get(player).first }}.</em>
<span v-if="player.role.firstNightReminder">{{ <span v-if="player.role.firstNightReminder">{{
player.role.firstNightReminder | handleEmojis player.role.firstNightReminder
}}</span> }}</span>
</div> </div>
<div <div
@ -32,7 +32,7 @@
> >
<em>{{ nightOrder.get(player).other }}.</em> <em>{{ nightOrder.get(player).other }}.</em>
<span v-if="player.role.otherNightReminder">{{ <span v-if="player.role.otherNightReminder">{{
player.role.otherNightReminder | handleEmojis player.role.otherNightReminder
}}</span> }}</span>
</div> </div>
@ -165,8 +165,13 @@
<span <span
class="icon" class="icon"
:style="{ :style="{
backgroundImage: `url(${reminder.image || backgroundImage: `url(${
require('../assets/icons/' + reminder.role + '.png')})` reminder.image && grimoire.isImageOptIn
? reminder.image
: require('../assets/icons/' +
(reminder.imageAlt || reminder.role) +
'.png')
})`
}" }"
></span> ></span>
<span class="text">{{ reminder.name }}</span> <span class="text">{{ reminder.name }}</span>
@ -226,9 +231,6 @@ export default {
isSwap: false isSwap: false
}; };
}, },
filters: {
handleEmojis: text => text.replace(/:([^: ]+?):/g, "").replace(/ •/g, "\n•")
},
methods: { methods: {
toggleStatus() { toggleStatus() {
if (this.grimoire.isPublic) { if (this.grimoire.isPublic) {

View File

@ -4,8 +4,11 @@
class="icon" class="icon"
v-if="role.id" v-if="role.id"
:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${
require('../assets/icons/' + role.id + '.png')})` role.image && grimoire.isImageOptIn
? role.image
: require('../assets/icons/' + (role.imageAlt || role.id) + '.png')
})`
}" }"
></span> ></span>
<span <span
@ -47,6 +50,8 @@
</template> </template>
<script> <script>
import { mapState } from "vuex";
export default { export default {
name: "Token", name: "Token",
props: { props: {
@ -55,6 +60,9 @@ export default {
default: () => ({}) default: () => ({})
} }
}, },
computed: {
...mapState(["grimoire"])
},
data() { data() {
return {}; return {};
}, },

View File

@ -41,8 +41,13 @@
class="icon" class="icon"
v-if="role.id" v-if="role.id"
:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${
require('../../assets/icons/' + role.id + '.png')})` role.image && grimoire.isImageOptIn
? role.image
: require('../../assets/icons/' +
(role.imageAlt || role.id) +
'.png')
})`
}" }"
></span> ></span>
</li> </li>
@ -58,8 +63,13 @@
class="icon" class="icon"
v-if="role.id" v-if="role.id"
:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${
require('../../assets/icons/' + role.id + '.png')})` role.image && grimoire.isImageOptIn
? role.image
: require('../../assets/icons/' +
(role.imageAlt || role.id) +
'.png')
})`
}" }"
></span> ></span>
<span class="name"> <span class="name">

View File

@ -34,8 +34,13 @@
class="icon" class="icon"
v-if="role.id" v-if="role.id"
:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${
require('../../assets/icons/' + role.id + '.png')})` role.image && grimoire.isImageOptIn
? role.image
: require('../../assets/icons/' +
(role.imageAlt || role.id) +
'.png')
})`
}" }"
></span> ></span>
<span class="ability">{{ role.ability }}</span> <span class="ability">{{ role.ability }}</span>
@ -80,7 +85,7 @@ export default {
}); });
return players; return players;
}, },
...mapState(["roles", "modals", "edition"]), ...mapState(["roles", "modals", "edition", "grimoire"]),
...mapState("players", ["players"]) ...mapState("players", ["players"])
}, },
methods: { methods: {

View File

@ -15,8 +15,13 @@
<span <span
class="icon" class="icon"
:style="{ :style="{
backgroundImage: `url(${reminder.image || backgroundImage: `url(${
require('../../assets/icons/' + reminder.role + '.png')})` reminder.image && grimoire.isImageOptIn
? reminder.image
: require('../../assets/icons/' +
(reminder.imageAlt || reminder.role) +
'.png')
})`
}" }"
></span> ></span>
<span class="text">{{ reminder.name }}</span> <span class="text">{{ reminder.name }}</span>
@ -29,6 +34,18 @@
import Modal from "./Modal"; import Modal from "./Modal";
import { mapMutations, mapState } from "vuex"; import { mapMutations, mapState } from "vuex";
/**
* Helper function that maps a reminder name with a role-based object that provides necessary visual data.
* @param role The role for which the reminder should be generated
* @return {function(*): {image: string|string[]|string|*, role: *, name: *, imageAlt: string|*}}
*/
const mapReminder = ({ id, image, imageAlt }) => name => ({
role: id,
image,
imageAlt,
name
});
export default { export default {
components: { Modal }, components: { Modal },
props: ["playerIndex"], props: ["playerIndex"],
@ -39,61 +56,29 @@ export default {
this.$store.state.roles.forEach(role => { this.$store.state.roles.forEach(role => {
// add reminders from player roles // add reminders from player roles
if (players.some(p => p.role.id === role.id)) { if (players.some(p => p.role.id === role.id)) {
reminders = [ reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
...reminders,
...role.reminders.map(name => ({
role: role.id,
image: role.image,
name
}))
];
} }
// add reminders from bluff/other roles // add reminders from bluff/other roles
else if (bluffs.some(bluff => bluff.id === role.id)) { else if (bluffs.some(bluff => bluff.id === role.id)) {
reminders = [ reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
...reminders,
...role.reminders.map(name => ({
role: role.id,
image: role.image,
name
}))
];
} }
// add global reminders // add global reminders
if (role.remindersGlobal && role.remindersGlobal.length) { if (role.remindersGlobal && role.remindersGlobal.length) {
reminders = [ reminders = [
...reminders, ...reminders,
...role.remindersGlobal.map(name => ({ ...role.remindersGlobal.map(mapReminder(role))
role: role.id,
image: role.image,
name
}))
]; ];
} }
}); });
// add fabled reminders // add fabled reminders
this.$store.state.players.fabled.forEach(role => { this.$store.state.players.fabled.forEach(role => {
reminders = [ reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
...reminders,
...role.reminders.map(name => ({
role: role.id,
image: role.image,
name
}))
];
}); });
// add out of script traveler reminders // add out of script traveler reminders
this.$store.state.otherTravelers.forEach(role => { this.$store.state.otherTravelers.forEach(role => {
if (players.some(p => p.role.id === role.id)) { if (players.some(p => p.role.id === role.id)) {
reminders = [ reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
...reminders,
...role.reminders.map(name => ({
role: role.id,
image: role.image,
name
}))
];
} }
}); });
@ -102,7 +87,7 @@ export default {
reminders.push({ role: "custom", name: "Custom note" }); reminders.push({ role: "custom", name: "Custom note" });
return reminders; return reminders;
}, },
...mapState(["modals"]), ...mapState(["modals", "grimoire"]),
...mapState("players", ["players"]) ...mapState("players", ["players"])
}, },
methods: { methods: {

View File

@ -53,10 +53,11 @@ const toggle = key => ({ grimoire }, val) => {
}; };
// base definition for custom roles // base definition for custom roles
const imageBase =
"https://raw.githubusercontent.com/bra1n/townsquare/main/src/assets/icons/";
const customRole = { const customRole = {
id: "",
name: "",
image: "", image: "",
ability: "",
edition: "custom", edition: "custom",
firstNight: 0, firstNight: 0,
firstNightReminder: "", firstNightReminder: "",
@ -109,7 +110,11 @@ export default new Vuex.Store({
*/ */
customRolesStripped: ({ roles }) => { customRolesStripped: ({ roles }) => {
const customRoles = []; const customRoles = [];
const strippedProps = ["firstNightReminder", "otherNightReminder"] const strippedProps = [
"firstNightReminder",
"otherNightReminder",
"isCustom"
];
roles.forEach(role => { roles.forEach(role => {
if (!role.isCustom) { if (!role.isCustom) {
customRoles.push({ id: role.id }); customRoles.push({ id: role.id });
@ -120,7 +125,10 @@ export default new Vuex.Store({
continue; continue;
} }
const value = role[prop]; const value = role[prop];
if (prop !== "isCustom" && value !== customRole[prop]) { if (
Object.keys(customRole).includes(prop) &&
value !== customRole[prop]
) {
strippedRole[prop] = value; strippedRole[prop] = value;
} }
} }
@ -164,16 +172,16 @@ export default new Vuex.Store({
state.roles.get(role.id) || state.roles.get(role.id) ||
Object.assign({}, customRole, role) Object.assign({}, customRole, role)
) )
// default empty icons to good / evil / traveler // default empty icons and placeholders
.map(role => { .map(role => {
if (rolesJSONbyId.get(role.id)) return role; if (rolesJSONbyId.get(role.id)) return role;
if (role.team === "townsfolk" || role.team === "outsider") { role.imageAlt = // map team to generic icon
role.image = role.image || imageBase + "good.png"; {
} else if (role.team === "demon" || role.team === "minion") { townsfolk: "good",
role.image = role.image || imageBase + "evil.png"; outsider: "outsider",
} else { minion: "minion",
role.image = role.image || imageBase + "custom.png"; demon: "evil"
} }[role.team] || "custom";
return role; return role;
}) })
// filter out roles that don't match an existing role and also don't have name/ability/team // filter out roles that don't match an existing role and also don't have name/ability/team

View File

@ -115,10 +115,7 @@ module.exports = store => {
if (!payload.length) { if (!payload.length) {
localStorage.removeItem("roles"); localStorage.removeItem("roles");
} else { } else {
localStorage.setItem( localStorage.setItem("roles", JSON.stringify(payload));
"roles",
JSON.stringify(payload)
);
} }
break; break;
case "players/setBluff": case "players/setBluff":