From fd49717b9c986b6497f604a23cb6fce0911e82b1 Mon Sep 17 00:00:00 2001 From: Nathaniel Mitchell Date: Thu, 17 Sep 2026 11:09:07 -0400 Subject: [PATCH] Custom Lobby view updates (#719) This PR combines updates to multiple components to implement a significant feature update to Custom Lobbies, rendering them mostly functional. Two notable exceptions: 1. Voting is not implemented even though the server triggers it. As a result, votes will silently tick down in the background until they fail to pass (assuming they do not auto-succeed). The recommended workaround for now is to enable Boss mode. 2. This PR does not properly set start-polys. Selecting a polygon preset will reduce them to boxes after submission to the server. --- lang/dev/lobby.json | 22 +- lang/en/lobby.json | 22 +- src/main/game/battle/battle-types.ts | 6 +- src/main/model/start-script.ts | 18 +- src/main/utils/start-script-converter.ts | 2 +- src/renderer/assets/languages/cs.json | 22 +- src/renderer/assets/languages/de.json | 22 +- src/renderer/assets/languages/dev.json | 22 +- src/renderer/assets/languages/en.json | 22 +- src/renderer/assets/languages/fr.json | 22 +- src/renderer/assets/languages/ru.json | 22 +- src/renderer/assets/languages/zh.json | 22 +- .../components/battle/AddBotModal.vue | 4 +- .../components/battle/BotParticipant.vue | 2 +- src/renderer/components/battle/HostBattle.vue | 625 ++++++++++++++---- .../components/battle/LuaOptionsModal.vue | 11 +- .../components/battle/MapOptionsModal.vue | 119 ++-- .../battle/OfflineBattleComponent.vue | 13 +- src/renderer/components/battle/Playerlist.vue | 123 +++- .../battle/SpectatorParticipant.vue | 96 +-- .../components/battle/SpectatorsComponent.vue | 127 +++- .../components/battle/TeamComponent.vue | 18 +- .../PartyChat.vue => common/ChatPanel.vue} | 38 +- .../components/common/ContextMenu.vue | 5 +- .../lobbies/LobbyBotParticipant.vue | 183 +++++ .../components/lobbies/LobbyParticipant.vue | 139 ++++ .../components/lobbies/LobbyTeamComponent.vue | 299 +++++++++ src/renderer/components/lobbies/ffa.vue | 45 ++ .../components/lobbies/lobby.types.ts | 26 + src/renderer/components/lobbies/raptors.vue | 11 + .../components/lobbies/scavengers.vue | 11 + src/renderer/components/lobbies/standard.vue | 56 ++ .../maps/EditableMapBattlePreview.vue | 48 ++ .../components/maps/MapBattlePreview.vue | 108 +-- .../maps/MapBattlePreviewStartBox.vue | 80 ++- .../composables/useImageBlobUrlCache.ts | 18 +- .../composables/useLobbySettingsDraft.ts | 420 ++++++++++++ src/renderer/store/battle.store.ts | 53 +- src/renderer/store/lobby.store.ts | 27 +- src/renderer/utils/battle-map-options.ts | 28 + src/renderer/utils/deep-toraw.ts | 6 + src/renderer/views/play/customLobbies.vue | 121 ++-- src/renderer/views/play/lobby.vue | 205 +++++- src/renderer/views/profile/party.vue | 4 +- .../unit/main/start-script-converter.spec.ts | 12 +- tests/unit/renderer/app-component.spec.ts | 1 + .../unit/renderer/battle-start-boxes.spec.ts | 13 + .../unit/renderer/chat-offline-input.spec.ts | 7 +- .../renderer/lobby-settings-draft.spec.ts | 427 ++++++++++++ vite.renderer.config.mts | 2 +- 50 files changed, 3182 insertions(+), 573 deletions(-) rename src/renderer/components/{party/PartyChat.vue => common/ChatPanel.vue} (75%) create mode 100644 src/renderer/components/lobbies/LobbyBotParticipant.vue create mode 100644 src/renderer/components/lobbies/LobbyParticipant.vue create mode 100644 src/renderer/components/lobbies/LobbyTeamComponent.vue create mode 100644 src/renderer/components/lobbies/ffa.vue create mode 100644 src/renderer/components/lobbies/lobby.types.ts create mode 100644 src/renderer/components/lobbies/raptors.vue create mode 100644 src/renderer/components/lobbies/scavengers.vue create mode 100644 src/renderer/components/lobbies/standard.vue create mode 100644 src/renderer/components/maps/EditableMapBattlePreview.vue create mode 100644 src/renderer/composables/useLobbySettingsDraft.ts create mode 100644 src/renderer/utils/battle-map-options.ts create mode 100644 tests/unit/renderer/lobby-settings-draft.spec.ts diff --git a/lang/dev/lobby.json b/lang/dev/lobby.json index d6114175d..a9427da00 100644 --- a/lang/dev/lobby.json +++ b/lang/dev/lobby.json @@ -193,6 +193,13 @@ "players": "Plyreas", "runningFor": "Rnuinng for", "join": "Jion" + }, + "lobby": { + "title": "Lbboy", + "gameVersion": "Gmae Vosiren", + "engineVersion": "Egnnie Vosiren", + "maps": "Maps", + "map": "Map" } } }, @@ -292,7 +299,8 @@ "message": "Msaesge", "userID": "User {id}", "userIDPlaceholder": "32452", - "send": "Sned" + "send": "Sned", + "noMessages": "No maegesss in tihs caht htoisry." }, "settings": { "title": "seinttgs", @@ -482,7 +490,14 @@ "startBoxes3": "AylmaeTls whoutit one are full-map sbrxoteats.", "allyTeamCount": "AyaeTllm Cunot: ", "teamsPerAllyTeam": "Tmaes per AyaeTllm: ", - "map": "Map" + "map": "Map", + "areBossesEnabled": "Eblnae Bosses? Tihs caonnt be cngeahd letar.", + "conflictWarning": "Seevrr cngaehs cilnocft wtih your lcoal dafrt.", + "useServer": "Use sveerr", + "keepMine": "Keep mine", + "lobbyNameChanged": "Lbboy name cngeahd on the sveerr.", + "mapNameChanged": "Map cngeahd on the sveerr.", + "allyTeamConfigChanged": "Team stuep cngeahd on the sveerr." }, "votePanel": { "vote": "Vtoe:", @@ -520,7 +535,8 @@ "spectatorsComponent": { "spectators": "Setptacros", "memberCount": "0 Mrembes | 1 Meembr | {n} Mrembes", - "join": "Jion" + "join": "Jion", + "queue": "Quuee" }, "battlePreview": { "preview": "Pevierw", diff --git a/lang/en/lobby.json b/lang/en/lobby.json index 202e1d35c..0c12d0a49 100644 --- a/lang/en/lobby.json +++ b/lang/en/lobby.json @@ -193,6 +193,13 @@ "players": "Players", "runningFor": "Running for", "join": "Join" + }, + "lobby": { + "title": "Lobby", + "gameVersion": "Game Version", + "engineVersion": "Engine Version", + "maps": "Maps", + "map": "Map" } } }, @@ -292,7 +299,8 @@ "message": "Message", "userID": "User {id}", "userIDPlaceholder": "32452", - "send": "Send" + "send": "Send", + "noMessages": "No messages in this chat history." }, "settings": { "title": "settings", @@ -482,7 +490,14 @@ "startBoxes3": "AllyTeams without one are full-map startboxes.", "allyTeamCount": "AllyTeam Count: ", "teamsPerAllyTeam": "Teams per AllyTeam: ", - "map": "Map" + "map": "Map", + "areBossesEnabled": "Enable Bosses? This cannot be changed later.", + "conflictWarning": "Server changes conflict with your local draft.", + "useServer": "Use server", + "keepMine": "Keep mine", + "lobbyNameChanged": "Lobby name changed on the server.", + "mapNameChanged": "Map changed on the server.", + "allyTeamConfigChanged": "Team setup changed on the server." }, "votePanel": { "vote": "Vote:", @@ -520,7 +535,8 @@ "spectatorsComponent": { "spectators": "Spectators", "memberCount": "0 Members | 1 Member | {n} Members", - "join": "Join" + "join": "Join", + "queue": "Queue" }, "battlePreview": { "preview": "Preview", diff --git a/src/main/game/battle/battle-types.ts b/src/main/game/battle/battle-types.ts index 3a7a65731..c9d411c26 100644 --- a/src/main/game/battle/battle-types.ts +++ b/src/main/game/battle/battle-types.ts @@ -109,7 +109,7 @@ export type Restriction = { }; export type Player = { - id: number; + id: string; name: string; user: User; contentSyncState: { @@ -128,8 +128,8 @@ export type Player = { }; export type Bot = { - id: number; - host: number; + id: string; + host: string; aiShortName: string; name: string; aiOptions: Record; diff --git a/src/main/model/start-script.ts b/src/main/model/start-script.ts index 801298fe8..a9c887740 100644 --- a/src/main/model/start-script.ts +++ b/src/main/model/start-script.ts @@ -62,7 +62,7 @@ export interface Restriction { } export interface AllyTeam { - id: number; + id: string; numallies?: number; startrecttop?: number; startrectleft?: number; @@ -71,9 +71,9 @@ export interface AllyTeam { } export interface Team { - id: number; - allyteam: number; - teamleader: number; + id: string; + allyteam: string; + teamleader: string; rgbcolor?: string; side?: string; handicap?: number; @@ -85,9 +85,9 @@ export interface Team { } export interface Player { - id: number; + id: string; name: string; - team?: number; + team?: string; password?: string; spectator?: number; isfromdemo?: number; @@ -97,10 +97,10 @@ export interface Player { } export interface Bot { - id: number; - team: number; + id: string; + team: string; shortname: string; - host: number; + host: string; name?: string; version?: string; options?: { diff --git a/src/main/utils/start-script-converter.ts b/src/main/utils/start-script-converter.ts index 89b5e6a61..04aebe5f9 100644 --- a/src/main/utils/start-script-converter.ts +++ b/src/main/utils/start-script-converter.ts @@ -77,7 +77,7 @@ class StartScriptConverter { const bots: Bot[] = []; Object.entries(battle.teams).forEach((entry) => { - const teamId = Number(entry[0]); + const teamId = entry[0]; const team = entry[1]; const allyTeam: AllyTeam = { id: teamId, diff --git a/src/renderer/assets/languages/cs.json b/src/renderer/assets/languages/cs.json index 5cd84524f..ba2b43077 100644 --- a/src/renderer/assets/languages/cs.json +++ b/src/renderer/assets/languages/cs.json @@ -2176,6 +2176,13 @@ "players": null, "runningFor": null, "join": null + }, + "lobby": { + "title": null, + "gameVersion": null, + "engineVersion": null, + "maps": null, + "map": null } } }, @@ -2275,7 +2282,8 @@ "message": null, "userID": null, "userIDPlaceholder": null, - "send": null + "send": null, + "noMessages": null }, "settings": { "title": null, @@ -2465,7 +2473,14 @@ "startBoxes3": null, "allyTeamCount": null, "teamsPerAllyTeam": null, - "map": null + "map": null, + "areBossesEnabled": null, + "conflictWarning": null, + "useServer": null, + "keepMine": null, + "lobbyNameChanged": null, + "mapNameChanged": null, + "allyTeamConfigChanged": null }, "votePanel": { "vote": null, @@ -2503,7 +2518,8 @@ "spectatorsComponent": { "spectators": null, "memberCount": null, - "join": null + "join": null, + "queue": null }, "battlePreview": { "preview": null, diff --git a/src/renderer/assets/languages/de.json b/src/renderer/assets/languages/de.json index 154b115bd..6b811c36c 100644 --- a/src/renderer/assets/languages/de.json +++ b/src/renderer/assets/languages/de.json @@ -2047,6 +2047,13 @@ "players": null, "runningFor": null, "join": null + }, + "lobby": { + "title": null, + "gameVersion": null, + "engineVersion": null, + "maps": null, + "map": null } } }, @@ -2146,7 +2153,8 @@ "message": null, "userID": null, "userIDPlaceholder": null, - "send": null + "send": null, + "noMessages": null }, "settings": { "title": null, @@ -2336,7 +2344,14 @@ "startBoxes3": null, "allyTeamCount": null, "teamsPerAllyTeam": null, - "map": null + "map": null, + "areBossesEnabled": null, + "conflictWarning": null, + "useServer": null, + "keepMine": null, + "lobbyNameChanged": null, + "mapNameChanged": null, + "allyTeamConfigChanged": null }, "votePanel": { "vote": null, @@ -2374,7 +2389,8 @@ "spectatorsComponent": { "spectators": null, "memberCount": null, - "join": null + "join": null, + "queue": null }, "battlePreview": { "preview": null, diff --git a/src/renderer/assets/languages/dev.json b/src/renderer/assets/languages/dev.json index e4102426a..47c896223 100644 --- a/src/renderer/assets/languages/dev.json +++ b/src/renderer/assets/languages/dev.json @@ -193,6 +193,13 @@ "players": "Plyreas", "runningFor": "Rnuinng for", "join": "Jion" + }, + "lobby": { + "title": "Lbboy", + "gameVersion": "Gmae Vosiren", + "engineVersion": "Egnnie Vosiren", + "maps": "Maps", + "map": "Map" } } }, @@ -292,7 +299,8 @@ "message": "Msaesge", "userID": "User {id}", "userIDPlaceholder": "32452", - "send": "Sned" + "send": "Sned", + "noMessages": "No maegesss in tihs caht htoisry." }, "settings": { "title": "seinttgs", @@ -482,7 +490,14 @@ "startBoxes3": "AylmaeTls whoutit one are full-map sbrxoteats.", "allyTeamCount": "AyaeTllm Cunot: ", "teamsPerAllyTeam": "Tmaes per AyaeTllm: ", - "map": "Map" + "map": "Map", + "areBossesEnabled": "Eblnae Bosses? Tihs caonnt be cngeahd letar.", + "conflictWarning": "Seevrr cngaehs cilnocft wtih your lcoal dafrt.", + "useServer": "Use sveerr", + "keepMine": "Keep mine", + "lobbyNameChanged": "Lbboy name cngeahd on the sveerr.", + "mapNameChanged": "Map cngeahd on the sveerr.", + "allyTeamConfigChanged": "Team stuep cngeahd on the sveerr." }, "votePanel": { "vote": "Vtoe:", @@ -520,7 +535,8 @@ "spectatorsComponent": { "spectators": "Setptacros", "memberCount": "0 Mrembes | 1 Meembr | {n} Mrembes", - "join": "Jion" + "join": "Jion", + "queue": "Quuee" }, "battlePreview": { "preview": "Pevierw", diff --git a/src/renderer/assets/languages/en.json b/src/renderer/assets/languages/en.json index 91ac4832d..4a626fc6e 100644 --- a/src/renderer/assets/languages/en.json +++ b/src/renderer/assets/languages/en.json @@ -2024,6 +2024,13 @@ "players": "Players", "runningFor": "Running for", "join": "Join" + }, + "lobby": { + "title": "Lobby", + "gameVersion": "Game Version", + "engineVersion": "Engine Version", + "maps": "Maps", + "map": "Map" } } }, @@ -2123,7 +2130,8 @@ "message": "Message", "userID": "User {id}", "userIDPlaceholder": "32452", - "send": "Send" + "send": "Send", + "noMessages": "No messages in this chat history." }, "settings": { "title": "settings", @@ -2313,7 +2321,14 @@ "startBoxes3": "AllyTeams without one are full-map startboxes.", "allyTeamCount": "AllyTeam Count: ", "teamsPerAllyTeam": "Teams per AllyTeam: ", - "map": "Map" + "map": "Map", + "areBossesEnabled": "Enable Bosses? This cannot be changed later.", + "conflictWarning": "Server changes conflict with your local draft.", + "useServer": "Use server", + "keepMine": "Keep mine", + "lobbyNameChanged": "Lobby name changed on the server.", + "mapNameChanged": "Map changed on the server.", + "allyTeamConfigChanged": "Team setup changed on the server." }, "votePanel": { "vote": "Vote:", @@ -2351,7 +2366,8 @@ "spectatorsComponent": { "spectators": "Spectators", "memberCount": "0 Members | 1 Member | {n} Members", - "join": "Join" + "join": "Join", + "queue": "Queue" }, "battlePreview": { "preview": "Preview", diff --git a/src/renderer/assets/languages/fr.json b/src/renderer/assets/languages/fr.json index 518283d3b..097e8050b 100644 --- a/src/renderer/assets/languages/fr.json +++ b/src/renderer/assets/languages/fr.json @@ -4029,6 +4029,13 @@ "players": null, "runningFor": null, "join": null + }, + "lobby": { + "title": null, + "gameVersion": null, + "engineVersion": null, + "maps": null, + "map": null } } }, @@ -4128,7 +4135,8 @@ "message": null, "userID": null, "userIDPlaceholder": null, - "send": null + "send": null, + "noMessages": null }, "settings": { "title": null, @@ -4318,7 +4326,14 @@ "startBoxes3": null, "allyTeamCount": null, "teamsPerAllyTeam": null, - "map": null + "map": null, + "areBossesEnabled": null, + "conflictWarning": null, + "useServer": null, + "keepMine": null, + "lobbyNameChanged": null, + "mapNameChanged": null, + "allyTeamConfigChanged": null }, "votePanel": { "vote": null, @@ -4356,7 +4371,8 @@ "spectatorsComponent": { "spectators": null, "memberCount": null, - "join": null + "join": null, + "queue": null }, "battlePreview": { "preview": null, diff --git a/src/renderer/assets/languages/ru.json b/src/renderer/assets/languages/ru.json index 5f1699f96..f761bd735 100644 --- a/src/renderer/assets/languages/ru.json +++ b/src/renderer/assets/languages/ru.json @@ -3998,6 +3998,13 @@ "players": null, "runningFor": null, "join": null + }, + "lobby": { + "title": null, + "gameVersion": null, + "engineVersion": null, + "maps": null, + "map": null } } }, @@ -4097,7 +4104,8 @@ "message": null, "userID": null, "userIDPlaceholder": null, - "send": null + "send": null, + "noMessages": null }, "settings": { "title": null, @@ -4287,7 +4295,14 @@ "startBoxes3": null, "allyTeamCount": null, "teamsPerAllyTeam": null, - "map": null + "map": null, + "areBossesEnabled": null, + "conflictWarning": null, + "useServer": null, + "keepMine": null, + "lobbyNameChanged": null, + "mapNameChanged": null, + "allyTeamConfigChanged": null }, "votePanel": { "vote": null, @@ -4325,7 +4340,8 @@ "spectatorsComponent": { "spectators": null, "memberCount": null, - "join": null + "join": null, + "queue": null }, "battlePreview": { "preview": null, diff --git a/src/renderer/assets/languages/zh.json b/src/renderer/assets/languages/zh.json index 9e400f7ad..6f7d30d77 100644 --- a/src/renderer/assets/languages/zh.json +++ b/src/renderer/assets/languages/zh.json @@ -4140,6 +4140,13 @@ "players": null, "runningFor": null, "join": null + }, + "lobby": { + "title": null, + "gameVersion": null, + "engineVersion": null, + "maps": null, + "map": null } } }, @@ -4239,7 +4246,8 @@ "message": null, "userID": null, "userIDPlaceholder": null, - "send": null + "send": null, + "noMessages": null }, "settings": { "title": null, @@ -4429,7 +4437,14 @@ "startBoxes3": null, "allyTeamCount": null, "teamsPerAllyTeam": null, - "map": null + "map": null, + "areBossesEnabled": null, + "conflictWarning": null, + "useServer": null, + "keepMine": null, + "lobbyNameChanged": null, + "mapNameChanged": null, + "allyTeamConfigChanged": null }, "votePanel": { "vote": null, @@ -4467,7 +4482,8 @@ "spectatorsComponent": { "spectators": null, "memberCount": null, - "join": null + "join": null, + "queue": null }, "battlePreview": { "preview": null, diff --git a/src/renderer/components/battle/AddBotModal.vue b/src/renderer/components/battle/AddBotModal.vue index 9ce18fbee..cb9d8792b 100644 --- a/src/renderer/components/battle/AddBotModal.vue +++ b/src/renderer/components/battle/AddBotModal.vue @@ -46,11 +46,11 @@ const { t } = useTypedI18n(); const props = defineProps<{ engineVersion: string; gameVersion: string; - teamId: number; + teamId: string; }>(); const emit = defineEmits<{ - (event: "bot-selected", ai: EngineAI | GameAI, teamId: number): void; + (event: "bot-selected", ai: EngineAI | GameAI, teamId: string): void; }>(); function addBot(ai: EngineAI | GameAI) { diff --git a/src/renderer/components/battle/BotParticipant.vue b/src/renderer/components/battle/BotParticipant.vue index fc4c24291..e9cdd54c8 100644 --- a/src/renderer/components/battle/BotParticipant.vue +++ b/src/renderer/components/battle/BotParticipant.vue @@ -47,7 +47,7 @@ const { t } = useTypedI18n(); const props = defineProps<{ bot: Bot; - teamId: number; + teamId: string; }>(); const botOptions: Ref = ref([]); diff --git a/src/renderer/components/battle/HostBattle.vue b/src/renderer/components/battle/HostBattle.vue index ef5ce2d85..6d220e8f3 100644 --- a/src/renderer/components/battle/HostBattle.vue +++ b/src/renderer/components/battle/HostBattle.vue @@ -5,221 +5,553 @@ SPDX-License-Identifier: MIT --> diff --git a/src/renderer/components/battle/LuaOptionsModal.vue b/src/renderer/components/battle/LuaOptionsModal.vue index dee794cd4..d9bb1ff3f 100644 --- a/src/renderer/components/battle/LuaOptionsModal.vue +++ b/src/renderer/components/battle/LuaOptionsModal.vue @@ -78,7 +78,7 @@ SPDX-License-Identifier: MIT - + diff --git a/src/renderer/components/battle/SpectatorsComponent.vue b/src/renderer/components/battle/SpectatorsComponent.vue index 814ce0d1a..375609185 100644 --- a/src/renderer/components/battle/SpectatorsComponent.vue +++ b/src/renderer/components/battle/SpectatorsComponent.vue @@ -3,7 +3,6 @@ SPDX-FileCopyrightText: 2025 The BAR Lobby Authors SPDX-License-Identifier: MIT --> - diff --git a/src/renderer/components/battle/TeamComponent.vue b/src/renderer/components/battle/TeamComponent.vue index 189f2712d..235e5d123 100644 --- a/src/renderer/components/battle/TeamComponent.vue +++ b/src/renderer/components/battle/TeamComponent.vue @@ -66,7 +66,7 @@ import { battleActions, battleWithMetadataStore } from "@renderer/store/battle.s const { t } = useTypedI18n(); const props = defineProps<{ - teamId: number; + teamId: string; }>(); const title = computed(() => @@ -86,11 +86,11 @@ const maxPlayersPerTeam = computed(() => { return battleActions.getMaxPlayersPerTeam(); }); -function isRaptorTeam(teamId: number) { - return battleWithMetadataStore.teams[teamId].participants.some((member) => isBot(member) && isRaptor(member)); +function isRaptorTeam(teamId: string) { + return battleWithMetadataStore.teams[Number(teamId)].participants.some((member) => isBot(member) && isRaptor(member)); } -function isScavengerTeam(teamId: number) { - return battleWithMetadataStore.teams[teamId]?.participants.some((member) => isBot(member) && isScavenger(member)); +function isScavengerTeam(teamId: string) { + return battleWithMetadataStore.teams[Number(teamId)]?.participants.some((member) => isBot(member) && isScavenger(member)); } function getAmountOfJoinButtons(maxPlayersPerTeam: number | undefined, memberCount: number) { @@ -110,11 +110,11 @@ function getAmountOfJoinButtons(maxPlayersPerTeam: number | undefined, memberCou // }); const emit = defineEmits(["addBotClicked", "onJoinClicked", "onDragStart", "onDragEnd", "onDragEnter", "onDrop"]); -function addBotClicked(teamId: number) { +function addBotClicked(teamId: string) { emit("addBotClicked", teamId); } -function onJoinClicked(teamId: number) { +function onJoinClicked(teamId: string) { emit("onJoinClicked", teamId); } @@ -127,12 +127,12 @@ function onDragEnd() { emit("onDragEnd"); } -function onDragEnter(event: DragEvent, teamId: number) { +function onDragEnter(event: DragEvent, teamId: string) { if (isRaptorTeam(props.teamId) || isScavengerTeam(props.teamId)) return; emit("onDragEnter", event, teamId); } -function onDrop(event: DragEvent, teamId: number) { +function onDrop(event: DragEvent, teamId: string) { if (isRaptorTeam(props.teamId) || isScavengerTeam(props.teamId)) return; emit("onDrop", event, teamId); } diff --git a/src/renderer/components/party/PartyChat.vue b/src/renderer/components/common/ChatPanel.vue similarity index 75% rename from src/renderer/components/party/PartyChat.vue rename to src/renderer/components/common/ChatPanel.vue index be22aee8b..3f6827817 100644 --- a/src/renderer/components/party/PartyChat.vue +++ b/src/renderer/components/common/ChatPanel.vue @@ -8,9 +8,10 @@ SPDX-License-Identifier: MIT
-
+
{{ t("lobby.navbar.messages.noMessages") }}
+
- +
@@ -38,10 +39,9 @@ SPDX-License-Identifier: MIT + + diff --git a/src/renderer/components/lobbies/LobbyParticipant.vue b/src/renderer/components/lobbies/LobbyParticipant.vue new file mode 100644 index 000000000..c29d02ed7 --- /dev/null +++ b/src/renderer/components/lobbies/LobbyParticipant.vue @@ -0,0 +1,139 @@ + + + + + + + diff --git a/src/renderer/components/lobbies/LobbyTeamComponent.vue b/src/renderer/components/lobbies/LobbyTeamComponent.vue new file mode 100644 index 000000000..f2de7285b --- /dev/null +++ b/src/renderer/components/lobbies/LobbyTeamComponent.vue @@ -0,0 +1,299 @@ + + + + + + + diff --git a/src/renderer/components/lobbies/ffa.vue b/src/renderer/components/lobbies/ffa.vue new file mode 100644 index 000000000..2c53a5016 --- /dev/null +++ b/src/renderer/components/lobbies/ffa.vue @@ -0,0 +1,45 @@ + + + + + + + diff --git a/src/renderer/components/lobbies/lobby.types.ts b/src/renderer/components/lobbies/lobby.types.ts new file mode 100644 index 000000000..00fe90896 --- /dev/null +++ b/src/renderer/components/lobbies/lobby.types.ts @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2026 The BAR Lobby Authors +// +// SPDX-License-Identifier: MIT + +// This is not defined in the protocol as type/interface, but it's consistent for type "player" so we are just going to define it ourselves. +import type { UserId } from "tachyon-protocol/types"; + +export interface Member { + id: UserId; + allyTeam: string; + team: string; + player: string; +} +export interface LobbyBot { + id: string; + hostUserId: string; + allyTeam: string; + team: string; + player: string; + name?: string; + shortName?: string; + version?: string | null; + options?: { + [k: string]: string; + }; +} diff --git a/src/renderer/components/lobbies/raptors.vue b/src/renderer/components/lobbies/raptors.vue new file mode 100644 index 000000000..71fa2798c --- /dev/null +++ b/src/renderer/components/lobbies/raptors.vue @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/renderer/components/lobbies/scavengers.vue b/src/renderer/components/lobbies/scavengers.vue new file mode 100644 index 000000000..a4c862af4 --- /dev/null +++ b/src/renderer/components/lobbies/scavengers.vue @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/renderer/components/lobbies/standard.vue b/src/renderer/components/lobbies/standard.vue new file mode 100644 index 000000000..b305a6313 --- /dev/null +++ b/src/renderer/components/lobbies/standard.vue @@ -0,0 +1,56 @@ + + + + + + + + + diff --git a/src/renderer/components/maps/EditableMapBattlePreview.vue b/src/renderer/components/maps/EditableMapBattlePreview.vue new file mode 100644 index 000000000..66ff71bea --- /dev/null +++ b/src/renderer/components/maps/EditableMapBattlePreview.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/renderer/components/maps/MapBattlePreview.vue b/src/renderer/components/maps/MapBattlePreview.vue index ef023b0c4..8e66e1bef 100644 --- a/src/renderer/components/maps/MapBattlePreview.vue +++ b/src/renderer/components/maps/MapBattlePreview.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT diff --git a/src/renderer/views/profile/party.vue b/src/renderer/views/profile/party.vue index 01439a184..a02358e45 100644 --- a/src/renderer/views/profile/party.vue +++ b/src/renderer/views/profile/party.vue @@ -155,7 +155,7 @@ SPDX-License-Identifier: MIT

{{ matchmakingStore.errorMessage }}

- +
@@ -207,7 +207,7 @@ SPDX-License-Identifier: MIT import { useTypedI18n } from "@renderer/i18n"; import { partyStore, PlayersPartyState, party } from "@renderer/store/party.store"; import { computed, ref, watch, toRaw } from "vue"; -import PartyChat from "@renderer/components/party/PartyChat.vue"; +import ChatPanel from "@renderer/components/common/ChatPanel.vue"; import Panel from "@renderer/components/common/Panel.vue"; import { PartyId } from "tachyon-protocol/types"; import Button from "@renderer/components/controls/Button.vue"; diff --git a/tests/unit/main/start-script-converter.spec.ts b/tests/unit/main/start-script-converter.spec.ts index fc33902f9..75e5c04b3 100644 --- a/tests/unit/main/start-script-converter.spec.ts +++ b/tests/unit/main/start-script-converter.spec.ts @@ -39,8 +39,8 @@ function twoTeamBattle(mapOptions: Record): BattleWithMetadata return { isOnline: false, spectators: [], - me: { id: 0, user: { username: "p1", userId: 1 } }, - teams: [{ participants: [{ id: 0, user: { username: "p1", userId: 1 } }] }, { participants: [{ id: 1, user: { username: "p2", userId: 2 } }] }], + me: { id: "0", user: { username: "p1", userId: "1" } }, + teams: [{ participants: [{ id: "0", user: { username: "p1", userId: "1" } }] }, { participants: [{ id: "1", user: { username: "p2", userId: "2" } }] }], battleOptions: { gameVersion: "test", gameMode: { id: GameModeID.CLASSIC, label: "Classic", options: {} }, @@ -65,8 +65,8 @@ describe("start script bot factions", () => { const battle = twoTeamBattle({ startPosType: StartPosType.Fixed }); battle.teams[1].participants = [ { - id: 1, - host: 0, + id: "1", + host: "0", aiShortName: "BARb", name: "Armada bot", aiOptions: {}, @@ -83,8 +83,8 @@ describe("start script bot factions", () => { const battle = twoTeamBattle({ startPosType: StartPosType.Fixed }); battle.teams[1].participants = [ { - id: 1, - host: 0, + id: "1", + host: "0", aiShortName: "BARb", name: "Default bot", aiOptions: {}, diff --git a/tests/unit/renderer/app-component.spec.ts b/tests/unit/renderer/app-component.spec.ts index 43ab44dd0..6122e0d4a 100644 --- a/tests/unit/renderer/app-component.spec.ts +++ b/tests/unit/renderer/app-component.spec.ts @@ -20,6 +20,7 @@ vi.mock("@renderer/store/settings.store", () => ({ devMode: false, }, })); +vi.mock("@renderer/router", () => ({ router: { currentRoute: { value: { path: "/" } }, push: vi.fn(), replace: vi.fn() } })); vi.mock("@renderer/store/infos.store", () => ({ infosStore: { diff --git a/tests/unit/renderer/battle-start-boxes.spec.ts b/tests/unit/renderer/battle-start-boxes.spec.ts index 251c927ce..9fe025047 100644 --- a/tests/unit/renderer/battle-start-boxes.spec.ts +++ b/tests/unit/renderer/battle-start-boxes.spec.ts @@ -4,6 +4,7 @@ import { MapData } from "@main/content/maps/map-data"; import { StartPosType } from "@main/game/battle/battle-types"; +import { getCurrentStartBoxes } from "@renderer/utils/battle-map-options"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { nextTick } from "vue"; @@ -96,4 +97,16 @@ describe("getCurrentStartBoxes", () => { expect(battleStore.battleOptions.mapOptions.startBoxesIndex).toBe(0); }); + + it("resolves boxes without depending on the battle store", () => { + expect( + getCurrentStartBoxes(mapWith(twoBoxPreset), { + startPosType: StartPosType.Boxes, + startBoxesIndex: 0, + }) + ).toEqual([ + { left: 0, top: 0, right: 0.2, bottom: 1 }, + { left: 0.8, top: 0, right: 1, bottom: 1 }, + ]); + }); }); diff --git a/tests/unit/renderer/chat-offline-input.spec.ts b/tests/unit/renderer/chat-offline-input.spec.ts index b3260c53c..0946dd50f 100644 --- a/tests/unit/renderer/chat-offline-input.spec.ts +++ b/tests/unit/renderer/chat-offline-input.spec.ts @@ -10,7 +10,7 @@ const requestSend = vi.hoisted(() => vi.fn()); vi.mock("@renderer/store/chat.store", () => ({ chat: { requestSend, clearUserChat: vi.fn() }, - chatStore: { partyChat: [], userChats: new Map() }, + chatStore: { partyChats: new Map(), lobbyChats: new Map(), userChats: new Map() }, })); vi.mock("@renderer/store/tachyon.store", () => ({ tachyonStore: { isConnected: false } })); @@ -23,10 +23,11 @@ vi.mock("@renderer/composables/useDexieLiveQuery", () => ({ vi.mock("@renderer/store/db", () => ({ db: { users: { each: vi.fn(), filter: () => ({ each: vi.fn() }) } } })); const { tachyonStore } = await import("@renderer/store/tachyon.store"); -const PartyChat = (await import("@renderer/components/party/PartyChat.vue")).default; +const ChatPanel = (await import("@renderer/components/common/ChatPanel.vue")).default; const mountChat = () => - mount(PartyChat, { + mount(ChatPanel, { + props: { type: "party", id: "party1" }, global: { plugins: [PrimeVue], directives: { "in-view": {} }, diff --git a/tests/unit/renderer/lobby-settings-draft.spec.ts b/tests/unit/renderer/lobby-settings-draft.spec.ts new file mode 100644 index 000000000..d057ee6b1 --- /dev/null +++ b/tests/unit/renderer/lobby-settings-draft.spec.ts @@ -0,0 +1,427 @@ +// SPDX-FileCopyrightText: 2026 The BAR Lobby Authors +// +// SPDX-License-Identifier: MIT + +import { StartPosType } from "@main/game/battle/battle-types"; +import { MapData } from "@main/content/maps/map-data"; +import { createLobbySettingsDraft, useLobbySettingsDraft } from "@renderer/composables/useLobbySettingsDraft"; +import { Lobby } from "@renderer/model/lobby"; +import { getCurrentStartBoxes } from "@renderer/utils/battle-map-options"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { reactive, toRaw } from "vue"; + +const map = { springName: "Test Map" } as MapData; +const boxes = [ + { top: 0, bottom: 1, left: 0, right: 0.25 }, + { top: 0, bottom: 1, left: 0.75, right: 1 }, +]; +const mapOptions = { startPosType: StartPosType.Boxes, startBoxesIndex: undefined }; + +function createLobby(mapName = "Test Map") { + return { + id: "lobby-1", + name: "Existing Lobby", + mapName, + engineVersion: "test-engine", + gameVersion: "test-game", + gameOptions: {}, + allyTeamConfig: { + "0": { maxTeams: 1, startBox: boxes[0], teams: { "0": { maxPlayers: 1 } } }, + "1": { maxTeams: 1, startBox: boxes[1], teams: { "0": { maxPlayers: 1 } } }, + }, + areBossesEnabled: false, + bosses: {}, + players: {}, + spectators: {}, + bots: {}, + maxPlayerCount: 2, + playerCount: 0, + spectatorCount: 0, + playerQueue: new Map(), + botCount: 0, + } satisfies Lobby; +} + +function expectBoxesInSync(settingsDraft: ReturnType) { + const currentDraft = settingsDraft.draft.value; + expect(currentDraft).toBeDefined(); + expect(getCurrentStartBoxes(currentDraft?.map, currentDraft!.mapOptions)).toEqual(currentDraft!.allyTeamConfig.map((allyTeam) => allyTeam.startBox)); +} + +describe("useLobbySettingsDraft", () => { + afterEach(() => vi.restoreAllMocks()); + + it("creates an isolated complete create payload", () => { + const initial = createLobbySettingsDraft("New Lobby", map, mapOptions, 2, 1, boxes); + const draft = useLobbySettingsDraft(); + + draft.openCreate(initial); + initial.name = "Changed outside draft"; + + expect(draft.createPayload()).toEqual({ + name: "New Lobby", + mapName: "Test Map", + areBossesEnabled: false, + allyTeamConfig: [ + { maxTeams: 1, startBox: boxes[0], teams: [{ maxPlayers: 1 }] }, + { maxTeams: 1, startBox: boxes[1], teams: [{ maxPlayers: 1 }] }, + ], + }); + expectBoxesInSync(draft); + }); + + it("creates a dirty-only update payload", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.updateDraft({ name: "Renamed Lobby" }); + + expect(draft.updatePayload()).toEqual({ name: "Renamed Lobby" }); + expect(draft.dirtyFields.value).toEqual(new Set(["name"])); + }); + + it("creates no update payload when the draft is unchanged", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + + expect(draft.dirtyFields.value).toEqual(new Set()); + expect(draft.updatePayload()).toEqual({}); + }); + + it("includes map and ally-team changes in the same update payload", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.setMap({ springName: "Updated Map" } as MapData); + draft.setTeamCounts(3, 1); + + const payload = draft.updatePayload(); + + expect(payload.mapName).toBe("Updated Map"); + expect(payload.allyTeamConfig).toHaveLength(3); + expect(draft.dirtyFields.value).toEqual(new Set(["mapName", "allyTeamConfig"])); + }); + + it("purges the session state", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.purge(); + + expect(draft.draft.value).toBeUndefined(); + expect(draft.base.value).toBeUndefined(); + expect(draft.dirtyFields.value.size).toBe(0); + }); + + it("preserves a local edit and reports a same-field server conflict", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.updateDraft({ name: "Local Name" }); + + const server = { ...draft.base.value!, name: "Server Name" }; + draft.syncFromServer(server); + + expect(draft.conflicts).toHaveLength(1); + expect(draft.draft.value?.name).toBe("Local Name"); + expect(draft.base.value?.name).toBe("Server Name"); + + draft.useServer("name"); + expect(draft.draft.value?.name).toBe("Server Name"); + expect(draft.conflicts).toHaveLength(0); + }); + + it("applies the server map when resolving a map-name conflict", () => { + const draft = useLobbySettingsDraft(); + const localMap = { springName: "Local Map" } as MapData; + const serverMap = { springName: "Server Map" } as MapData; + draft.openUpdate(createLobby(), map); + draft.setMap(localMap); + + draft.syncFromLobby(createLobby("Server Map"), serverMap); + draft.useServer("mapName"); + + expect(draft.draft.value?.mapName).toBe("Server Map"); + expect(draft.draft.value?.map).toEqual(serverMap); + expect(draft.conflicts.some((conflict) => conflict.field === "mapName")).toBe(false); + expectBoxesInSync(draft); + }); + + it("rebases clean server updates without creating conflicts", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + + const server = { ...draft.base.value!, name: "Server Name" }; + draft.syncFromServer(server); + draft.syncFromServer({ ...server, name: "Server Name 2" }); + + expect(draft.draft.value?.name).toBe("Server Name 2"); + expect(draft.conflicts).toHaveLength(0); + }); + + it("does not duplicate a conflict when the same server update repeats", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.updateDraft({ name: "Local Name" }); + + const server = { ...draft.base.value!, name: "Server Name" }; + draft.syncFromServer(server); + draft.syncFromServer(server); + + expect(draft.conflicts).toHaveLength(1); + }); + + it("clones reactive map options without throwing", () => { + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("New Lobby", map, mapOptions, 2, 1, boxes)); + + const reactiveMapOptions = reactive({ + ...mapOptions, + customStartBoxes: boxes, + }); + + expect(() => draft.setMapOptions(reactiveMapOptions)).not.toThrow(); + expect(draft.draft.value?.mapOptions.customStartBoxes).toEqual(boxes); + }); + + it("updates preview and payload boxes atomically for custom edits", () => { + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("New Lobby", map, mapOptions, 2, 1, boxes)); + const editedBoxes = [ + { ...boxes[0], right: 0.4 }, + { ...boxes[1], left: 0.6 }, + ]; + + draft.setCustomStartBoxes(editedBoxes); + + expectBoxesInSync(draft); + expect(draft.createPayload().allyTeamConfig.map((allyTeam) => allyTeam.startBox)).toEqual(editedBoxes); + }); + + it("preserves a map preview Blob when opening a create draft", () => { + const preview = new Blob(["preview"], { type: "image/webp" }); + const draft = useLobbySettingsDraft(); + const mapWithPreview = { springName: "Test Map", images: { preview: "preview" }, imagesBlob: { preview } } as MapData; + + draft.openCreate(createLobbySettingsDraft("New Lobby", mapWithPreview, mapOptions, 2, 1, boxes)); + + const clonedPreview = draft.draft.value?.map?.imagesBlob?.preview; + expect(clonedPreview).toBeDefined(); + expect(toRaw(clonedPreview)).toBe(preview); + }); + + it("adds a visible custom start box when the team count grows", () => { + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("New Lobby", map, { ...mapOptions, customStartBoxes: boxes }, 2, 1, boxes)); + vi.spyOn(Math, "random").mockReturnValue(0); + + draft.setTeamCounts(3, 1); + + const customStartBoxes = draft.draft.value?.mapOptions.customStartBoxes; + const previousBox = customStartBoxes?.[1]; + const addedBox = customStartBoxes?.[2]; + expect(customStartBoxes).toHaveLength(3); + expect(addedBox).not.toEqual(previousBox); + expect(addedBox!.right - addedBox!.left).toBeCloseTo(previousBox!.right - previousBox!.left); + expect(addedBox!.bottom - addedBox!.top).toBeCloseTo(previousBox!.bottom - previousBox!.top); + expect(Math.min(addedBox!.top, addedBox!.left)).toBeGreaterThanOrEqual(0); + expect(Math.max(addedBox!.bottom, addedBox!.right)).toBeLessThanOrEqual(1); + expect(draft.draft.value?.allyTeamConfig).toHaveLength(3); + expectBoxesInSync(draft); + }); + + it("sizes ally teams from a selected preset's startbox count", () => { + const presetMap = { + springName: "Preset Map", + startboxesSet: [ + { + maxPlayersPerStartbox: 1, + startboxes: [ + { + poly: [ + { x: 0, y: 0 }, + { x: 40, y: 200 }, + ], + }, + { + poly: [ + { x: 80, y: 0 }, + { x: 120, y: 200 }, + ], + }, + { + poly: [ + { x: 160, y: 0 }, + { x: 200, y: 200 }, + ], + }, + ], + }, + ], + } as MapData; + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("Preset Lobby", presetMap, { startPosType: StartPosType.Boxes, startBoxesIndex: 0 }, 2, 1, boxes)); + + draft.setTeamCounts(3, 1); + + expect(draft.draft.value?.allyTeamConfig).toHaveLength(3); + expectBoxesInSync(draft); + }); + + it("synchronizes ally teams when selecting a preset", () => { + const presetMap = { + springName: "Preset Map", + startboxesSet: [ + { + maxPlayersPerStartbox: 1, + startboxes: [ + { + poly: [ + { x: 0, y: 0 }, + { x: 50, y: 200 }, + ], + }, + { + poly: [ + { x: 150, y: 0 }, + { x: 200, y: 200 }, + ], + }, + ], + }, + ], + } as MapData; + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("Preset Lobby", presetMap, mapOptions, 2, 1, boxes)); + + draft.setMapOptions({ startPosType: StartPosType.Boxes, startBoxesIndex: 0 }); + + expect(draft.draft.value?.mapOptions.startBoxesIndex).toBe(0); + expectBoxesInSync(draft); + }); + + it("materializes an initial preset when its box count differs from the requested team count", () => { + const presetMap = { + springName: "Large Preset Map", + startboxesSet: [ + { + maxPlayersPerStartbox: 1, + startboxes: [ + { + poly: [ + { x: 0, y: 0 }, + { x: 40, y: 200 }, + ], + }, + { + poly: [ + { x: 50, y: 0 }, + { x: 90, y: 200 }, + ], + }, + { + poly: [ + { x: 110, y: 0 }, + { x: 150, y: 200 }, + ], + }, + { + poly: [ + { x: 160, y: 0 }, + { x: 200, y: 200 }, + ], + }, + ], + }, + ], + } as MapData; + const presetOptions = { startPosType: StartPosType.Boxes, startBoxesIndex: 0 }; + const presetBoxes = getCurrentStartBoxes(presetMap, presetOptions); + const draft = useLobbySettingsDraft(); + + draft.openCreate(createLobbySettingsDraft("Two Team Lobby", presetMap, presetOptions, 2, 1, presetBoxes)); + + expect(draft.draft.value?.mapOptions.startBoxesIndex).toBeUndefined(); + expect(draft.draft.value?.mapOptions.customStartBoxes).toHaveLength(2); + expectBoxesInSync(draft); + }); + + it("replaces old boxes when the map changes", () => { + const nextMap = { + springName: "Next Map", + startboxesSet: [ + { + maxPlayersPerStartbox: 1, + startboxes: [ + { + poly: [ + { x: 0, y: 0 }, + { x: 80, y: 80 }, + ], + }, + { + poly: [ + { x: 120, y: 120 }, + { x: 200, y: 200 }, + ], + }, + ], + }, + ], + } as MapData; + const draft = useLobbySettingsDraft(); + draft.openCreate(createLobbySettingsDraft("New Lobby", map, mapOptions, 2, 1, boxes)); + + draft.setMap(nextMap); + + expect(draft.draft.value?.mapName).toBe("Next Map"); + expect(draft.draft.value?.allyTeamConfig.map((allyTeam) => allyTeam.startBox)).not.toEqual(boxes); + expectBoxesInSync(draft); + }); + + it("updates preview boxes after accepting a clean server team update", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + const serverBoxes = [ + { ...boxes[0], right: 0.35 }, + { ...boxes[1], left: 0.65 }, + ]; + const server = { + ...draft.base.value!, + allyTeamConfig: draft.base.value!.allyTeamConfig.map((allyTeam, index) => ({ + ...allyTeam, + startBox: serverBoxes[index], + })), + }; + + draft.syncFromServer(server); + + expectBoxesInSync(draft); + expect(draft.draft.value?.mapOptions.customStartBoxes).toEqual(serverBoxes); + }); + + it("updates preview boxes when resolving a team conflict with the server", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.setCustomStartBoxes([{ ...boxes[0], right: 0.4 }, boxes[1]]); + const server = { + ...draft.base.value!, + allyTeamConfig: draft.base.value!.allyTeamConfig.map((allyTeam, index) => ({ + ...allyTeam, + startBox: index === 0 ? { ...boxes[0], right: 0.3 } : allyTeam.startBox, + })), + }; + draft.syncFromServer(server); + + draft.useServer("allyTeamConfig"); + + expectBoxesInSync(draft); + expect(draft.draft.value?.allyTeamConfig).toEqual(server.allyTeamConfig); + }); + + it("preserves a non-box start mode during unrelated server updates", () => { + const draft = useLobbySettingsDraft(); + draft.openUpdate(createLobby(), map); + draft.setMapOptions({ startPosType: StartPosType.Fixed, fixedPositionsIndex: 0 }); + + draft.syncFromServer({ ...draft.base.value!, name: "Server Name" }); + + expect(draft.draft.value?.mapOptions.startPosType).toBe(StartPosType.Fixed); + }); +}); diff --git a/vite.renderer.config.mts b/vite.renderer.config.mts index 0ff566749..99b0bf799 100644 --- a/vite.renderer.config.mts +++ b/vite.renderer.config.mts @@ -19,7 +19,7 @@ export default defineConfig({ sourcemap: true, }, optimizeDeps: { - force: true, + // force: true, entries: ["src/renderer/**/*.vue", "src/renderer/**/*.ts", "src/renderer/**/*.js"], esbuildOptions: { target: "esnext",