mirror of
				https://github.com/bra1n/townsquare.git
				synced 2025-10-21 16:55:12 +00:00 
			
		
		
		
	Merge pull request #107 from davotronic5000/#43_gender_pronouns
#43 gender pronouns
This commit is contained in:
		
						commit
						2b2500a6c6
					
				
					 6 changed files with 144 additions and 12 deletions
				
			
		|  | @ -1,5 +1,9 @@ | ||||||
| # Release Notes | # Release Notes | ||||||
| 
 | 
 | ||||||
|  | ### Version 2.9.0 | ||||||
|  | - added support for assigning pronouns to players and display of the pronouns in a tooltip on the player name. | ||||||
|  | 
 | ||||||
|  | --- | ||||||
| ### Version 2.8.0 | ### Version 2.8.0 | ||||||
| - added hands-off live session support for homebrew / custom characters again! | - added hands-off live session support for homebrew / custom characters again! | ||||||
| - added custom image opt-in that will prevent any (potentially malicious / harmful) images from loading until a player manually allows them to | - added custom image opt-in that will prevent any (potentially malicious / harmful) images from loading until a player manually allows them to | ||||||
|  |  | ||||||
|  | @ -97,13 +97,16 @@ | ||||||
|         @click="updatePlayer('isVoteless', true)" |         @click="updatePlayer('isVoteless', true)" | ||||||
|         title="Ghost vote" |         title="Ghost vote" | ||||||
|       /> |       /> | ||||||
| 
 |  | ||||||
|       <div |       <div | ||||||
|         class="name" |         class="name" | ||||||
|         @click="isMenuOpen = !isMenuOpen" |         @click="isMenuOpen = !isMenuOpen" | ||||||
|         :class="{ active: isMenuOpen }" |         :class="{ active: isMenuOpen }" | ||||||
|       > |       > | ||||||
|         {{ player.name }} |         <span>{{ player.name }}</span> | ||||||
|  |         <font-awesome-icon icon="venus-mars" v-if="player.pronouns" /> | ||||||
|  |         <div class="pronouns" v-if="player.pronouns"> | ||||||
|  |           <span>{{ player.pronouns }}</span> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|       <transition name="fold"> |       <transition name="fold"> | ||||||
|  | @ -150,6 +153,15 @@ | ||||||
|             </template> |             </template> | ||||||
|             <template v-else> Seat occupied</template> |             <template v-else> Seat occupied</template> | ||||||
|           </li> |           </li> | ||||||
|  |           <li | ||||||
|  |             @click="changePronouns" | ||||||
|  |             v-if=" | ||||||
|  |               !session.isSpectator || | ||||||
|  |                 (session.isSpectator && player.id === session.playerId) | ||||||
|  |             " | ||||||
|  |           > | ||||||
|  |             <font-awesome-icon icon="venus-mars" />Change Pronouns | ||||||
|  |           </li> | ||||||
|         </ul> |         </ul> | ||||||
|       </transition> |       </transition> | ||||||
|     </div> |     </div> | ||||||
|  | @ -232,6 +244,15 @@ export default { | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   methods: { |   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() { |     toggleStatus() { | ||||||
|       if (this.grimoire.isPublic) { |       if (this.grimoire.isPublic) { | ||||||
|         if (!this.player.isDead) { |         if (!this.player.isDead) { | ||||||
|  | @ -260,7 +281,12 @@ export default { | ||||||
|       this.updatePlayer("reminders", reminders, true); |       this.updatePlayer("reminders", reminders, true); | ||||||
|     }, |     }, | ||||||
|     updatePlayer(property, value, closeMenu = false) { |     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", { |       this.$store.commit("players/update", { | ||||||
|         player: this.player, |         player: this.player, | ||||||
|         property, |         property, | ||||||
|  | @ -629,25 +655,72 @@ li.move:not(.from) .player .overlay svg.move { | ||||||
| 
 | 
 | ||||||
| /***** Player name *****/ | /***** Player name *****/ | ||||||
| .player > .name { | .player > .name { | ||||||
|   text-align: center; |   right: 10%; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|   font-size: 120%; |   font-size: 120%; | ||||||
|   line-height: 120%; |   line-height: 120%; | ||||||
|   cursor: pointer; |   cursor: pointer; | ||||||
|   white-space: nowrap; |   white-space: nowrap; | ||||||
|   width: 100%; |   width: 120%; | ||||||
|   background: rgba(0, 0, 0, 0.5); |   background: rgba(0, 0, 0, 0.5); | ||||||
|   border: 3px solid black; |   border: 3px solid black; | ||||||
|   border-radius: 10px; |   border-radius: 10px; | ||||||
|   top: 5px; |   top: 5px; | ||||||
|   box-shadow: 0 0 5px black; |   box-shadow: 0 0 5px black; | ||||||
|   text-overflow: ellipsis; |  | ||||||
|   overflow: hidden; |  | ||||||
|   padding: 0 4px; |   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, |   #townsquare:not(.spectator) &:hover, | ||||||
|   &.active { |   &.active { | ||||||
|     color: red; |     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 { | .player.dead > .name { | ||||||
|  | @ -657,7 +730,7 @@ li.move:not(.from) .player .overlay svg.move { | ||||||
| /***** Player menu *****/ | /***** Player menu *****/ | ||||||
| .player > .menu { | .player > .menu { | ||||||
|   position: absolute; |   position: absolute; | ||||||
|   left: 100%; |   left: 110%; | ||||||
|   bottom: -5px; |   bottom: -5px; | ||||||
|   text-align: left; |   text-align: left; | ||||||
|   white-space: nowrap; |   white-space: nowrap; | ||||||
|  |  | ||||||
|  | @ -264,7 +264,7 @@ export default { | ||||||
|         // open menu on the left |         // open menu on the left | ||||||
|         .player > .menu { |         .player > .menu { | ||||||
|           left: auto; |           left: auto; | ||||||
|           right: 100%; |           right: 110%; | ||||||
|           margin-right: 15px; |           margin-right: 15px; | ||||||
|           &:before { |           &:before { | ||||||
|             border-left-color: black; |             border-left-color: black; | ||||||
|  | @ -292,6 +292,16 @@ export default { | ||||||
|             left: 100%; |             left: 100%; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |         .pronouns { | ||||||
|  |           left: 110%; | ||||||
|  |           right: auto; | ||||||
|  |           &:before { | ||||||
|  |             border-left-color: transparent; | ||||||
|  |             border-right-color: black; | ||||||
|  |             left: auto; | ||||||
|  |             right: 100%; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } @else { |       } @else { | ||||||
|         // second half of players |         // second half of players | ||||||
|         z-index: $i - 1; |         z-index: $i - 1; | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ const faIcons = [ | ||||||
|   "UserEdit", |   "UserEdit", | ||||||
|   "UserFriends", |   "UserFriends", | ||||||
|   "Users", |   "Users", | ||||||
|  |   "VenusMars", | ||||||
|   "VolumeUp", |   "VolumeUp", | ||||||
|   "VolumeMute", |   "VolumeMute", | ||||||
|   "VoteYea", |   "VoteYea", | ||||||
|  |  | ||||||
|  | @ -4,7 +4,8 @@ const NEWPLAYER = { | ||||||
|   role: {}, |   role: {}, | ||||||
|   reminders: [], |   reminders: [], | ||||||
|   isVoteless: false, |   isVoteless: false, | ||||||
|   isDead: false |   isDead: false, | ||||||
|  |   pronouns: "" | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const state = () => ({ | const state = () => ({ | ||||||
|  |  | ||||||
|  | @ -189,6 +189,9 @@ class LiveSession { | ||||||
|       case "bye": |       case "bye": | ||||||
|         this._handleBye(params); |         this._handleBye(params); | ||||||
|         break; |         break; | ||||||
|  |       case "pronouns": | ||||||
|  |         this._updatePlayerPronouns(params); | ||||||
|  |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -244,6 +247,7 @@ class LiveSession { | ||||||
|       id: player.id, |       id: player.id, | ||||||
|       isDead: player.isDead, |       isDead: player.isDead, | ||||||
|       isVoteless: player.isVoteless, |       isVoteless: player.isVoteless, | ||||||
|  |       pronouns: player.pronouns, | ||||||
|       ...(player.role && player.role.team === "traveler" |       ...(player.role && player.role.team === "traveler" | ||||||
|         ? { roleId: player.role.id } |         ? { roleId: player.role.id } | ||||||
|         : {}) |         : {}) | ||||||
|  | @ -304,7 +308,7 @@ class LiveSession { | ||||||
|       const player = players[x]; |       const player = players[x]; | ||||||
|       const { roleId } = state; |       const { roleId } = state; | ||||||
|       // update relevant properties
 |       // update relevant properties
 | ||||||
|       ["name", "id", "isDead", "isVoteless"].forEach(property => { |       ["name", "id", "isDead", "isVoteless", "pronouns"].forEach(property => { | ||||||
|         const value = state[property]; |         const value = state[property]; | ||||||
|         if (player[property] !== value) { |         if (player[property] !== value) { | ||||||
|           this._store.commit("players/update", { player, property, value }); |           this._store.commit("players/update", { player, property, value }); | ||||||
|  | @ -481,6 +485,41 @@ class LiveSession { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /** | ||||||
|  |    * Publish a player pronouns update | ||||||
|  |    * @param player | ||||||
|  |    * @param value | ||||||
|  |    */ | ||||||
|  |   sendPlayerPronouns({ player, value }) { | ||||||
|  |     //send pronoun only for the seated player or storyteller
 | ||||||
|  |     if (this._isSpectator && this._store.state.session.playerId !== player.id) | ||||||
|  |       return; | ||||||
|  |     const index = this._store.state.players.players.indexOf(player); | ||||||
|  |     this._send("pronouns", [index, value, !this._isSpectator]); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Update a pronouns based on incoming data. Player only. | ||||||
|  |    * @param index | ||||||
|  |    * @param value | ||||||
|  |    * @param fromSt | ||||||
|  |    * @private | ||||||
|  |    */ | ||||||
|  |   _updatePlayerPronouns([index, value, fromST]) { | ||||||
|  |     const player = this._store.state.players.players[index]; | ||||||
|  |     if ( | ||||||
|  |       player && | ||||||
|  |       (fromST || this._store.state.session.playerId !== player.id) && | ||||||
|  |       player.pronouns !== value | ||||||
|  |     ) { | ||||||
|  |       this._store.commit("players/update", { | ||||||
|  |         player, | ||||||
|  |         property: "pronouns", | ||||||
|  |         value | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   /** |   /** | ||||||
|    * Handle a ping message by another player / storyteller |    * Handle a ping message by another player / storyteller | ||||||
|    * @param playerIdOrCount |    * @param playerIdOrCount | ||||||
|  | @ -810,7 +849,11 @@ export default store => { | ||||||
|         session.sendGamestate("", true); |         session.sendGamestate("", true); | ||||||
|         break; |         break; | ||||||
|       case "players/update": |       case "players/update": | ||||||
|  |         if (payload.property === "pronouns") { | ||||||
|  |           session.sendPlayerPronouns(payload); | ||||||
|  |         } else { | ||||||
|           session.sendPlayer(payload); |           session.sendPlayer(payload); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue