mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-25 15:20:24 +00:00
Discord(et al.) embedded URLs (#2740)
## Description: Changes URL embeds within other platforms, e.g. Discord, WhatsApp & X. Updates game URLs to `/game/<code>` instead of `/#join=<code>` (required for embedded URLs). An added benefit of this is that you would be able to change a url from `openfront.io/game/RQDUy8nP?replay` to `api.openfront.io/game/RQDUy8nP?replay` (add api. In front) and be in the right place for the API data. Updates URLs when joining/leaving private lobbies Appends a random string to the end of the URL when inside a private lobby and options change - this is to force discord to update the embedded details. Updates URL in different game states to ?lobby / ?live and ?replay. These do nothing other than being used as a _cache-busting_ solution. ----------------------------------------------- ### **Lobby Info** Discord: <img width="556" height="487" alt="image" src="https://github.com/user-attachments/assets/efd4a06d-506c-4036-9403-ee7c9a669e21" /> WhatsApp: <img width="353" height="339" alt="image" src="https://github.com/user-attachments/assets/3b2d0c69-988c-424f-9dee-f4e6a6868f6b" /> x.com: <img width="588" height="325" alt="image" src="https://github.com/user-attachments/assets/d9e78169-20be-4a3e-8df4-8ad41d08a750" /> ------------------------- ### **Game Win Details** Discord: <img width="506" height="468" alt="image" src="https://github.com/user-attachments/assets/69947774-c943-4a50-b470-5634ed3bf3d7" /> WhatsApp: <img width="770" height="132" alt="image" src="https://github.com/user-attachments/assets/eec28bf8-bf64-4ab8-954e-03dfdd1aae40" /> x.com <img width="584" height="350" alt="image" src="https://github.com/user-attachments/assets/168063e2-b707-422b-b7a1-0025f3ebeb92" /> ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: w.o.n
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
GameConfig,
|
||||
GameInfo,
|
||||
TeamCountConfig,
|
||||
isValidGameID,
|
||||
} from "../core/Schemas";
|
||||
import { generateID } from "../core/Util";
|
||||
import "./components/baseComponents/Modal";
|
||||
@@ -61,6 +62,7 @@ export class HostLobbyModal extends BaseModal {
|
||||
@state() private compactMap: boolean = false;
|
||||
@state() private lobbyId = "";
|
||||
@state() private copySuccess = false;
|
||||
@state() private lobbyUrlSuffix = "";
|
||||
@state() private clients: ClientInfo[] = [];
|
||||
@state() private useRandomMap: boolean = false;
|
||||
@state() private disabledUnits: UnitType[] = [];
|
||||
@@ -74,6 +76,8 @@ export class HostLobbyModal extends BaseModal {
|
||||
private userSettings: UserSettings = new UserSettings();
|
||||
private mapLoader = terrainMapFileLoader;
|
||||
|
||||
private leaveLobbyOnClose = true;
|
||||
|
||||
private renderOptionToggle(
|
||||
labelKey: string,
|
||||
checked: boolean,
|
||||
@@ -100,6 +104,28 @@ export class HostLobbyModal extends BaseModal {
|
||||
`;
|
||||
}
|
||||
|
||||
private getRandomString(): string {
|
||||
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
return Array.from(
|
||||
{ length: 5 },
|
||||
() => chars[Math.floor(Math.random() * chars.length)],
|
||||
).join("");
|
||||
}
|
||||
|
||||
private async buildLobbyUrl(): Promise<string> {
|
||||
const config = await getServerConfigFromClient();
|
||||
return `${window.location.origin}/${config.workerPath(this.lobbyId)}/game/${this.lobbyId}?lobby&s=${encodeURIComponent(this.lobbyUrlSuffix)}`;
|
||||
}
|
||||
|
||||
private async constructUrl(): Promise<string> {
|
||||
this.lobbyUrlSuffix = this.getRandomString();
|
||||
return await this.buildLobbyUrl();
|
||||
}
|
||||
|
||||
private updateHistory(url: string): void {
|
||||
history.replaceState(null, "", url);
|
||||
}
|
||||
|
||||
render() {
|
||||
const content = html`
|
||||
<div
|
||||
@@ -109,7 +135,7 @@ export class HostLobbyModal extends BaseModal {
|
||||
${modalHeader({
|
||||
title: translateText("host_modal.title"),
|
||||
onBack: () => {
|
||||
this.leaveLobby();
|
||||
this.leaveLobbyOnClose = true;
|
||||
this.close();
|
||||
},
|
||||
ariaLabel: translateText("common.back"),
|
||||
@@ -821,9 +847,14 @@ export class HostLobbyModal extends BaseModal {
|
||||
);
|
||||
|
||||
createLobby(this.lobbyCreatorClientID)
|
||||
.then((lobby) => {
|
||||
.then(async (lobby) => {
|
||||
this.lobbyId = lobby.gameID;
|
||||
if (!isValidGameID(this.lobbyId)) {
|
||||
throw new Error(`Invalid lobby ID format: ${this.lobbyId}`);
|
||||
}
|
||||
crazyGamesSDK.showInviteButton(this.lobbyId);
|
||||
const url = await this.constructUrl();
|
||||
this.updateHistory(url);
|
||||
})
|
||||
.then(() => {
|
||||
this.dispatchEvent(
|
||||
@@ -895,6 +926,10 @@ export class HostLobbyModal extends BaseModal {
|
||||
|
||||
protected onClose(): void {
|
||||
console.log("Closing host lobby modal");
|
||||
if (this.leaveLobbyOnClose) {
|
||||
this.leaveLobby();
|
||||
this.updateHistory("/"); // Reset URL to base
|
||||
}
|
||||
crazyGamesSDK.hideInviteButton();
|
||||
|
||||
// Clean up timers and resources
|
||||
@@ -933,6 +968,8 @@ export class HostLobbyModal extends BaseModal {
|
||||
this.lobbyCreatorClientID = "";
|
||||
this.lobbyIdVisible = true;
|
||||
this.nationCount = 0;
|
||||
|
||||
this.leaveLobbyOnClose = true;
|
||||
}
|
||||
|
||||
private async handleSelectRandomMap() {
|
||||
@@ -1075,6 +1112,8 @@ export class HostLobbyModal extends BaseModal {
|
||||
const spawnImmunityTicks = this.spawnImmunityDurationMinutes
|
||||
? this.spawnImmunityDurationMinutes * 60 * 10
|
||||
: 0;
|
||||
const url = await this.constructUrl();
|
||||
this.updateHistory(url);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("update-game-config", {
|
||||
detail: {
|
||||
@@ -1134,6 +1173,10 @@ export class HostLobbyModal extends BaseModal {
|
||||
console.log(
|
||||
`Starting private game with map: ${GameMapType[this.selectedMap as keyof typeof GameMapType]} ${this.useRandomMap ? " (Randomly selected)" : ""}`,
|
||||
);
|
||||
|
||||
// If the modal closes as part of starting the game, do not leave the lobby
|
||||
this.leaveLobbyOnClose = false;
|
||||
|
||||
const config = await getServerConfigFromClient();
|
||||
const response = await fetch(
|
||||
`${window.location.origin}/${config.workerPath(this.lobbyId)}/api/start_game/${this.lobbyId}`,
|
||||
@@ -1144,12 +1187,17 @@ export class HostLobbyModal extends BaseModal {
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
this.leaveLobbyOnClose = true;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private async copyToClipboard() {
|
||||
const url = await this.buildLobbyUrl();
|
||||
await copyToClipboard(
|
||||
`${location.origin}/#join=${this.lobbyId}`,
|
||||
url,
|
||||
() => (this.copySuccess = true),
|
||||
() => (this.copySuccess = false),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user