From ed87ba804321ee0055bfd947163512a8f54bda11 Mon Sep 17 00:00:00 2001
From: jomshir98 <jomshir98@protonmail.com>
Date: Fri, 9 Apr 2021 17:57:11 +0200
Subject: [PATCH 1/2] Quick search for room from friendlist

---
 .../Character/FriendList/FriendList.js        | 61 +++++++++++++------
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/BondageClub/Screens/Character/FriendList/FriendList.js b/BondageClub/Screens/Character/FriendList/FriendList.js
index db0e62257e..f8bcca7e5d 100644
--- a/BondageClub/Screens/Character/FriendList/FriendList.js
+++ b/BondageClub/Screens/Character/FriendList/FriendList.js
@@ -28,13 +28,12 @@ function FriendListLoad() {
 	FriendListConfirmDelete = [];
 	ElementCreateDiv("FriendList");
 	ElementPositionFix("FriendList", 36, 0, 70, 2000, 930);
-	ElementContent("FriendList", FriendListContent);
+	ElementContent("FriendList", "");
 	ServerSend("AccountQuery", { Query: "OnlineFriends" });
 }
 
-// 
 /**
- * Run the friend list screen - Draw the controls and print the result of the server query to the screen. 
+ * Run the friend list screen - Draw the controls and print the result of the server query to the screen.
  * This function is called dynamically on a regular basis. So don't do complex loops within
  * @returns {void} - Nothing
  */
@@ -62,7 +61,7 @@ function FriendListRun() {
 	DrawButton(1935, 5, 60, 60, "", "White", "Icons/Small/Exit.png");
 }
 
-/** 
+/**
  * Creates beep message menu
  * @param {number} MemberNumber Member number of target player
  * @param {FriendListBeepLogMessage} data Beep data of received beep
@@ -72,9 +71,9 @@ function FriendListBeep(MemberNumber, data = null) {
 		ElementCreateDiv("FriendListBeep");
 		ElementPositionFix("FriendListBeep", 36, 5, 75, 1985, 890);
 	}
-	const FriendListBeep = document.getElementById("FriendListBeep");
+	const FriendListBeepElement = document.getElementById("FriendListBeep");
 	FriendListBeepTarget = MemberNumber;
-	FriendListBeep.innerHTML = "";
+	FriendListBeepElement.innerHTML = "";
 	const dialog = document.createElement("div");
 	const user = document.createElement("div");
 	user.innerText = `${Player.FriendNames.get(MemberNumber)} [${MemberNumber}]`;
@@ -95,9 +94,14 @@ function FriendListBeep(MemberNumber, data = null) {
 		sendBtn.innerText = "Send";
 		sendBtn.onclick = FriendListBeepMenuSend;
 		footer.append(sendBtn);
+	} else {
+		const replyBtn = document.createElement("a");
+		replyBtn.innerText = "Reply";
+		replyBtn.onclick = () => FriendListBeep(data.MemberNumber);
+		footer.append(replyBtn);
 	}
 	dialog.append(data === null ? "Send Beep" : data.Sent ? "Sent Beep" : "Received Beep", user, messageArea, footer);
-	FriendListBeep.append(dialog);
+	FriendListBeepElement.append(dialog);
 }
 
 /**
@@ -143,7 +147,7 @@ function FriendListShowBeep(i) {
 	if (beep) {
 		FriendListBeep(beep.MemberNumber, beep);
 	}
-};
+}
 
 /**
  * Handles the click events in the friend list. Clicks are propagated to this function from CommonClick()
@@ -164,7 +168,7 @@ function FriendListClick() {
 }
 
 /**
- * This function is called, when the user exists the friend list. From here we either get back to the InformationSheet 
+ * This function is called, when the user exists the friend list. From here we either get back to the InformationSheet
  * or the ChatRoom serach, depending on the value of the global variable 'FriendListReturn'
  * @returns {void} - Nothing
  */
@@ -178,7 +182,17 @@ function FriendListExit() {
 	FriendListModeIndex = 0;
 }
 
-// 
+/**
+ * Exits the friendlist into `ChatSearch` screen, filling in the requested room name
+ * @param {string} room The room to search for
+ */
+function FriendListChatSearch(room) {
+	if (FriendListReturn !== "ChatSearch") return;
+	FriendListExit();
+	ElementValue("InputSearch", room);
+	ChatSearchQuery();
+}
+
 /**
  * Loads the friend list data into the HTML div element.
  * @param {Array.<*>} data - An array of data, we receive from the server
@@ -186,7 +200,7 @@ function FriendListExit() {
  * @param {number} data.MemberNumber - The ID of the player
  * @param {string} data.ChatRoomName - The name of the ChatRoom
  * @param {string} data.ChatRoomSpace - The space, where this room was created. Currently this can be the Asylum or the LARP arena
- * @param {string} data.Type - The relationship that exists between the player and the friend of the list. 
+ * @param {string} data.Type - The relationship that exists between the player and the friend of the list.
  * Currently, only "submissive" is supported
  * @returns {void} - Nothing
  */
@@ -219,9 +233,9 @@ function FriendListLoadFriendList(data) {
 		}
 		if (Player.SubmissivesList.has(friend.MemberNumber) != (friend.Type == "Submissive")) {
 			if (friend.Type == "Submissive") {
-				Player.SubmissivesList.add(friend.MemberNumber)
+				Player.SubmissivesList.add(friend.MemberNumber);
 			} else {
-				Player.SubmissivesList.delete(friend.MemberNumber)
+				Player.SubmissivesList.delete(friend.MemberNumber);
 			}
 			infoChanged = true;
 		}
@@ -238,7 +252,12 @@ function FriendListLoadFriendList(data) {
 			if (friend.ChatRoomName.startsWith("-")) {
 				FriendListContent += `<div class='FriendListTextColumn'> ${friend.ChatRoomName.replace("-Private-", PrivateRoomCaption)} </div>`;
 			} else {
-				FriendListContent += `<div class='FriendListTextColumn'> ${friend.ChatRoomSpace ? friend.ChatRoomSpace.replace("Asylum", SpaceAsylumCaption) + " - " : ''} ${friend.ChatRoomName} </div>`;
+				const Caption = `${friend.ChatRoomSpace ? friend.ChatRoomSpace.replace("Asylum", SpaceAsylumCaption) + " - " : ''} ${friend.ChatRoomName}`;
+				if (FriendListReturn === "ChatSearch" && ChatRoomSpace === (friend.ChatRoomSpace || "")) {
+					FriendListContent += `<div class='FriendListLinkColumn' onClick='FriendListChatSearch("${friend.ChatRoomName}")'> ${Caption} </div>`;
+				} else {
+					FriendListContent += `<div class='FriendListTextColumn'> ${Caption} </div>`;
+				}
 			}
 			FriendListContent += `<div class='FriendListLinkColumn' onClick='FriendListBeep(${friend.MemberNumber})'> ${BeepCaption} </div>`;
 			FriendListContent += "</div>";
@@ -250,12 +269,14 @@ function FriendListLoadFriendList(data) {
 			FriendListContent += `<div class='FriendListRow'>`;
 			FriendListContent += `<div class='FriendListTextColumn FriendListFirstColumn'> ${B.MemberName}</div>`;
 			FriendListContent += `<div class='FriendListTextColumn'>${B.MemberNumber != null ? B.MemberNumber : "-"}</div>`;
-			FriendListContent +=
-				"<div class='FriendListTextColumn'>" +
-				(B.ChatRoomName == null ? "-" : (B.ChatRoomSpace ? B.ChatRoomSpace.replace("Asylum", SpaceAsylumCaption) + " - " : "") + B.ChatRoomName.replace("-Private-", PrivateRoomCaption)) +
-				"</div>";
+			const Caption = (B.ChatRoomName == null ? "-" : (B.ChatRoomSpace ? B.ChatRoomSpace.replace("Asylum", SpaceAsylumCaption) + " - " : "") + B.ChatRoomName.replace("-Private-", PrivateRoomCaption));
+			if (FriendListReturn === "ChatSearch" && ChatRoomSpace === (B.ChatRoomSpace || "") && !B.ChatRoomName.startsWith("-")) {
+				FriendListContent += `<div class='FriendListLinkColumn' onClick='FriendListChatSearch("${B.ChatRoomName}")'> ${Caption} </div>`;
+			} else {
+				FriendListContent += `<div class='FriendListTextColumn'> ${Caption} </div>`;
+			}
 			if (B.Message) {
-				FriendListContent += `<div class='FriendListLinkColumn' onclick="FriendListShowBeep(${i})">${B.Sent ? SentCaption : ReceivedCaption} ${TimerHourToString(B.Time)} (Mail)</div>`;
+				FriendListContent += `<div class='FriendListLinkColumn' onclick="FriendListShowBeep(${i})">${B.Sent ? SentCaption : ReceivedCaption} ${TimerHourToString(B.Time)} ${MailCaption}</div>`;
 			} else {
 				FriendListContent += `<div class='FriendListTextColumn'>${B.Sent ? SentCaption : ReceivedCaption} ${TimerHourToString(B.Time)}</div>`;
 			}
@@ -290,7 +311,7 @@ function FriendListLoadFriendList(data) {
 }
 
 /**
- * When the user wants to delete someone from her friend list this must be confirmed. 
+ * When the user wants to delete someone from her friend list this must be confirmed.
  * This function either displays the confirm message or deletes the friend from the player's friendlist
  * @param {number} MemberNumber - The member to delete from the friendlist
  * @returns {void} - Nothing
-- 
GitLab


From 21aa0169997ae4bba2393dc1ce8be8ebe8127dcb Mon Sep 17 00:00:00 2001
From: jomshir98 <jomshir98@protonmail.com>
Date: Fri, 9 Apr 2021 18:08:34 +0200
Subject: [PATCH 2/2] Fixes

---
 .../Character/FriendList/FriendList.js        | 32 +++++++++++++------
 BondageClub/Scripts/Timer.js                  |  2 +-
 2 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/BondageClub/Screens/Character/FriendList/FriendList.js b/BondageClub/Screens/Character/FriendList/FriendList.js
index f8bcca7e5d..edc2a48aa6 100644
--- a/BondageClub/Screens/Character/FriendList/FriendList.js
+++ b/BondageClub/Screens/Character/FriendList/FriendList.js
@@ -12,9 +12,10 @@ let FriendListBeepTarget = null;
 
 /**
  * @typedef {Object} FriendListBeepLogMessage
- * @property {number} MemberNumber
+ * @property {number} [MemberNumber]
  * @property {string} MemberName
  * @property {string|null} ChatRoomName
+ * @property {string|null} [ChatRoomSpace]
  * @property {boolean} Sent
  * @property {Date} Time
  * @property {string} [Message]
@@ -117,7 +118,7 @@ function FriendListBeepMenuClose() {
  */
 function FriendListBeepMenuSend() {
 	if (FriendListBeepTarget !== null) {
-		const textarea = document.getElementById("FriendListBeepTextArea");
+		const textarea = /** @type {HTMLTextAreaElement} */ (document.getElementById("FriendListBeepTextArea"));
 		if (textarea) {
 			const msg = textarea.value;
 			if (msg) {
@@ -195,12 +196,23 @@ function FriendListChatSearch(room) {
 
 /**
  * Loads the friend list data into the HTML div element.
- * @param {Array.<*>} data - An array of data, we receive from the server
- * @param {string} data.MemberName - The name of the player
- * @param {number} data.MemberNumber - The ID of the player
- * @param {string} data.ChatRoomName - The name of the ChatRoom
- * @param {string} data.ChatRoomSpace - The space, where this room was created. Currently this can be the Asylum or the LARP arena
- * @param {string} data.Type - The relationship that exists between the player and the friend of the list.
+ * @param {{
+ * MemberName: string;
+ * MemberNumber: number;
+ * ChatRoomName: string | null;
+ * ChatRoomSpace: string | null;
+ * Type: "Submissive" | "Friend";
+ * }[]} data - An array of data, we receive from the server
+ *
+ * `data.MemberName` - The name of the player
+ *
+ * `data.MemberNumber` - The ID of the player
+ *
+ * `data.ChatRoomName` - The name of the ChatRoom
+ *
+ * `data.ChatRoomSpace` - The space, where this room was created. Currently this can be the Asylum or the LARP arena
+ *
+ * `data.Type` - The relationship that exists between the player and the friend of the list.
  * Currently, only "submissive" is supported
  * @returns {void} - Nothing
  */
@@ -244,7 +256,7 @@ function FriendListLoadFriendList(data) {
 
 	if (mode === "Friends") {
 		// In Friend List mode, we show the friend list and allow doing beeps
-		for (const friend of data.sort((a, b) => a.MemberName.localeCompare(b))) {
+		for (const friend of data.sort((a, b) => a.MemberName.localeCompare(b.MemberName))) {
 			FriendListContent += "<div class='FriendListRow'>";
 			FriendListContent += `<div class='FriendListTextColumn FriendListFirstColumn'> ${friend.MemberName} </div>`;
 			FriendListContent += `<div class='FriendListTextColumn'> ${friend.MemberNumber} </div>`;
@@ -270,7 +282,7 @@ function FriendListLoadFriendList(data) {
 			FriendListContent += `<div class='FriendListTextColumn FriendListFirstColumn'> ${B.MemberName}</div>`;
 			FriendListContent += `<div class='FriendListTextColumn'>${B.MemberNumber != null ? B.MemberNumber : "-"}</div>`;
 			const Caption = (B.ChatRoomName == null ? "-" : (B.ChatRoomSpace ? B.ChatRoomSpace.replace("Asylum", SpaceAsylumCaption) + " - " : "") + B.ChatRoomName.replace("-Private-", PrivateRoomCaption));
-			if (FriendListReturn === "ChatSearch" && ChatRoomSpace === (B.ChatRoomSpace || "") && !B.ChatRoomName.startsWith("-")) {
+			if (FriendListReturn === "ChatSearch" && B.ChatRoomSpace !== undefined && ChatRoomSpace === (B.ChatRoomSpace || "") && !B.ChatRoomName.startsWith("-")) {
 				FriendListContent += `<div class='FriendListLinkColumn' onClick='FriendListChatSearch("${B.ChatRoomName}")'> ${Caption} </div>`;
 			} else {
 				FriendListContent += `<div class='FriendListTextColumn'> ${Caption} </div>`;
diff --git a/BondageClub/Scripts/Timer.js b/BondageClub/Scripts/Timer.js
index 33a0ead8a1..4d489e76a6 100644
--- a/BondageClub/Scripts/Timer.js
+++ b/BondageClub/Scripts/Timer.js
@@ -33,7 +33,7 @@ function TimerToString(T) {
 
 /**
  * Returns a string of the time remaining on a given timer (Hours and minutes only)
- * @param {number} T - Time to convert to a string in ms 
+ * @param {Date} T - Time to convert to a string in ms 
  * @returns {string} - The time string in the HH:MM format
  */
 function TimerHourToString(T) {
-- 
GitLab