diff --git a/android/app/src/main/assets/public/blah/en-cat.json b/android/app/src/main/assets/public/blah/en-cat.json
index 16927f31..e2d7812c 100644
--- a/android/app/src/main/assets/public/blah/en-cat.json
+++ b/android/app/src/main/assets/public/blah/en-cat.json
@@ -194,5 +194,12 @@
"placeholder.type.text.emoji": "Type purr / meow...",
"action.cancel": "Cancel",
"title.crop.image": "Crop Image",
- "title.zoom": "Zoom"
+ "title.zoom": "Zoom",
+ "title.pin.message": "Pin",
+ "title.unpin.message": "Unpin",
+ "message.pinned.by": "{0} pinned a {1}.",
+ "message.unpinned.by": "{0} unpinned a {1}.",
+ "title.pinned.messages": "Pinned",
+ "error.pinned.messages.empty": "No pinned meows",
+ "title.message.lowercase": "meowsage"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/blah/en-us.json b/android/app/src/main/assets/public/blah/en-us.json
index dc3c41f2..21b5fcf2 100644
--- a/android/app/src/main/assets/public/blah/en-us.json
+++ b/android/app/src/main/assets/public/blah/en-us.json
@@ -194,5 +194,12 @@
"placeholder.type.text.emoji": "Type text / emoji...",
"action.cancel": "Cancel",
"title.crop.image": "Crop Image",
- "title.zoom": "Zoom"
+ "title.zoom": "Zoom",
+ "title.pin.message": "Pin",
+ "title.unpin.message": "Unpin",
+ "message.pinned.by": "{0} pinned a {1}.",
+ "message.unpinned.by": "{0} unpinned a {1}.",
+ "title.pinned.messages": "Pinned",
+ "error.pinned.messages.empty": "No pinned messages",
+ "title.message.lowercase": "message"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/blah/pl-pl.json b/android/app/src/main/assets/public/blah/pl-pl.json
index d59ae8b3..7ab7e4bf 100644
--- a/android/app/src/main/assets/public/blah/pl-pl.json
+++ b/android/app/src/main/assets/public/blah/pl-pl.json
@@ -194,5 +194,12 @@
"placeholder.type.text.emoji": "Wpisz tekst / emoji...",
"action.cancel": "Anuluj",
"title.crop.image": "Przytnij obraz",
- "title.zoom": "Przybliżenie"
+ "title.zoom": "Przybliżenie",
+ "title.pin.message": "Przypnij",
+ "title.unpin.message": "Odepnij",
+ "message.pinned.by": "{0} przypiął {1}.",
+ "message.unpinned.by": "{0} odpiął {1}.",
+ "title.pinned.messages": "Przypięte",
+ "error.pinned.messages.empty": "Brak przypiętych wiadomości",
+ "title.message.lowercase": "wiadomość"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/icons.js b/android/app/src/main/assets/public/icons.js
index 9d419cd5..06596908 100644
--- a/android/app/src/main/assets/public/icons.js
+++ b/android/app/src/main/assets/public/icons.js
@@ -16,7 +16,6 @@ const ICONS = {
_feather: function(content, props) {
return this._create(content, { viewBox: "0 0 24 24", width: "1.4rem", height: "1.4rem", fill: "none", stroke: "var(--text-color)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, props);
},
-
addChat: (props) => ICONS._material(``, props),
createGroup: (props) => ICONS._material(``, props),
createSpace: (props) => ICONS._material(``, props),
@@ -28,8 +27,8 @@ const ICONS = {
delete: (props) => ICONS._material(``, props),
menu: (props) => ICONS._material(``, props),
arrowBack: (props) => ICONS._material(``, props),
- pin: (props) => ICONS._material(``, props),
- call: (props) => ICONS._material(``, props),
+ pin: (props) => ICONS._material(``, props),
+ call: (props) => ICONS._material(``, props),
account: (props) => ICONS._material(``, props),
settings: (props) => ICONS._material(``, props),
profile: (props) => ICONS._material(``, props),
diff --git a/android/app/src/main/assets/public/main.js b/android/app/src/main/assets/public/main.js
index 21860dfc..5334dbdd 100644
--- a/android/app/src/main/assets/public/main.js
+++ b/android/app/src/main/assets/public/main.js
@@ -1350,7 +1350,14 @@ async function switchRoomContent(title, content, showRoomBar, icon = "", skipMob
var currentDetailsContentTitle = null;
var currentDetailsContentHtml = null;
-async function switchDetailsContent(title, content) {
+var savedDetailsHtml = null;
+var savedDetailsTitle = null;
+
+async function switchDetailsContent(title, content, showBack = false, backAction = "", saveCurrent = false) {
+ if (saveCurrent && currentDetailsContentTitle !== title) {
+ savedDetailsHtml = currentDetailsContentHtml;
+ savedDetailsTitle = currentDetailsContentTitle;
+ }
if (currentDetailsContentTitle === title && currentDetailsContentHtml === content) return;
currentDetailsContentTitle = title;
currentDetailsContentHtml = content;
@@ -1364,13 +1371,14 @@ async function switchDetailsContent(title, content) {
roomsTopBarTransition.style.opacity = "0";
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
- if (window.innerWidth > 55 * rem) {
+ if (window.innerWidth > 55 * rem || mainScreen.classList.contains('mobile-details')) {
await delay(200);
}
- let pinCallBtns = `${pinBtnHtml}${callBtnHtml}`;
- roomsTopBarTransition.innerHTML = `${processBlah(title)}
${pinCallBtns}`;
+ let pinCallBtns = showBack ? `${callBtnHtml}` : `${pinBtnHtml}${callBtnHtml}`;
+ let backBtn = showBack ? `` : "";
+ roomsTopBarTransition.innerHTML = `${backBtn}${processBlah(title)}${pinCallBtns}`;
let parser = new DOMParser();
let doc = parser.parseFromString(content, "text/html");
@@ -1495,7 +1503,7 @@ document.addEventListener("click", (e) => {
if (mainScreen && mainScreen.classList.contains('mobile-details')) {
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
if (window.innerWidth <= 55 * rem) {
- if (!roomDetailsBar.contains(e.target) && !e.target.closest('#room-topbar-clickable') && !e.target.closest('.profile-popup-container')) {
+ if (!roomDetailsBar.contains(e.target) && !e.target.closest('#room-topbar-clickable') && !e.target.closest('.profile-popup-container') && !e.target.closest('.room-action-pin')) {
mobileNavBack();
}
}
@@ -1513,6 +1521,21 @@ if (App) {
}
function popstate() {
+ if (fixedContextMenu && fixedContextMenu.classList.contains("show")) {
+ fixedContextMenu.classList.remove("show");
+ if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
+ if (typeof setActiveSidebarIndicator === "function" && typeof currentMainIndicator !== "undefined") {
+ setActiveSidebarIndicator(currentMainIndicator);
+ }
+ return;
+ }
+
+ let cropperPopup = document.getElementById("cropper-popup-container");
+ if (cropperPopup && cropperPopup.classList.contains("show")) {
+ cropperPopup.classList.remove("show");
+ return;
+ }
+
if (isProfileOpen) {
closeProfile();
return;
@@ -1582,7 +1605,17 @@ async function openProfile(accountId) {
let bannerUrl = `${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.banner`;
if (accountId === window.id && window.profileUpdateTimestamp) bannerUrl += `&t=${window.profileUpdateTimestamp}`;
- let bannerHtml = `
`;
+ let bannerHtml = `
`;
+ setTimeout(() => {
+ let bannerImg = document.querySelector("#profile-popup-inner .profile-banner");
+ if (bannerImg) {
+ bannerImg.addEventListener("error", function() {
+ let div = document.createElement("div");
+ div.className = "profile-banner";
+ this.parentNode.replaceChild(div, this);
+ });
+ }
+ }, 50);
let bio = await fetchAsync(`${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.bio`);
if (bio.startsWith("error:")) bio = "";
@@ -1624,7 +1657,8 @@ async function openProfile(accountId) {
}
if (hasDm) {
- actionBtnHtml = ``;
+ let safeName = encodeURIComponent(nameWithHost).replace(/'/g, "%27");
+ actionBtnHtml = ``;
} else {
let sentInvite = false;
let receivedInvite = false;
@@ -2141,8 +2175,10 @@ async function renderDms(res) {
let isRead = dmData.string3 === "true";
let nameStyle = isRead ? "opacity: 0.8;" : "opacity: 1;";
+ let safeTargetUsername = encodeURIComponent(targetUsername).replace(/'/g, "%27");
+
html += `
-