2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-12-10 13:17:48 +00:00

chore: track loaded zones in ui

This commit is contained in:
Jan Laupetin
2025-10-11 16:25:14 +01:00
parent 7cefaee41c
commit 49f2000bad
12 changed files with 166 additions and 31 deletions

View File

@@ -1,12 +1,42 @@
#include "FastFileContext.h" #include "FastFileContext.h"
#include "Web/Binds/FastFileBinds.h"
#include "Web/UiCommunication.h"
#include "ZoneLoading.h" #include "ZoneLoading.h"
void FastFileContext::Destroy()
{
// Unload all zones
m_loaded_zones.clear();
}
result::Expected<Zone*, std::string> FastFileContext::LoadFastFile(const std::string& path) result::Expected<Zone*, std::string> FastFileContext::LoadFastFile(const std::string& path)
{ {
auto zone = ZoneLoading::LoadZone(path); auto zone = ZoneLoading::LoadZone(path);
if (!zone) if (!zone)
return result::Unexpected(std::move(zone.error())); return result::Unexpected(std::move(zone.error()));
return m_loaded_zones.emplace_back(std::move(*zone)).get(); auto* result = m_loaded_zones.emplace_back(std::move(*zone)).get();
ui::NotifyZoneLoaded(result->m_name, path);
return result;
}
result::Expected<NoResult, std::string> FastFileContext::UnloadZone(const std::string& zoneName)
{
const auto existingZone = std::ranges::find_if(m_loaded_zones,
[&zoneName](const std::unique_ptr<Zone>& zone)
{
return zone->m_name == zoneName;
});
if (existingZone != m_loaded_zones.end())
{
m_loaded_zones.erase(existingZone);
ui::NotifyZoneUnloaded(zoneName);
return NoResult();
}
return result::Unexpected(std::format("No zone with name {} loaded", zoneName));
} }

View File

@@ -9,7 +9,10 @@
class FastFileContext class FastFileContext
{ {
public: public:
void Destroy();
result::Expected<Zone*, std::string> LoadFastFile(const std::string& path); result::Expected<Zone*, std::string> LoadFastFile(const std::string& path);
result::Expected<NoResult, std::string> UnloadZone(const std::string& zoneName);
std::vector<std::unique_ptr<Zone>> m_loaded_zones; std::vector<std::unique_ptr<Zone>> m_loaded_zones;
}; };

View File

@@ -13,5 +13,6 @@ void ModManContext::Startup()
void ModManContext::Destroy() void ModManContext::Destroy()
{ {
m_fast_file.Destroy();
m_db_thread.Terminate(); m_db_thread.Terminate();
} }

View File

@@ -8,6 +8,6 @@ namespace ui
void RegisterAllBinds(webview::webview& wv) void RegisterAllBinds(webview::webview& wv)
{ {
RegisterDialogHandlerBinds(wv); RegisterDialogHandlerBinds(wv);
RegisterFastFileBinds(wv); RegisterZoneBinds(wv);
} }
} // namespace ui } // namespace ui

View File

@@ -3,8 +3,27 @@
#include "Context/ModManContext.h" #include "Context/ModManContext.h"
#include "Web/UiCommunication.h" #include "Web/UiCommunication.h"
#include "Json/JsonExtension.h"
namespace namespace
{ {
class ZoneLoadedDto
{
public:
std::string zoneName;
std::string filePath;
};
NLOHMANN_DEFINE_TYPE_EXTENSION(ZoneLoadedDto, zoneName, filePath);
class ZoneUnloadedDto
{
public:
std::string zoneName;
};
NLOHMANN_DEFINE_TYPE_EXTENSION(ZoneUnloadedDto, zoneName);
void LoadFastFile(webview::webview& wv, std::string id, std::string path) // NOLINT(performance-unnecessary-value-param) Copy is made for thread safety void LoadFastFile(webview::webview& wv, std::string id, std::string path) // NOLINT(performance-unnecessary-value-param) Copy is made for thread safety
{ {
ModManContext::Get().m_db_thread.Dispatch( ModManContext::Get().m_db_thread.Dispatch(
@@ -24,11 +43,47 @@ namespace
} }
}); });
} }
void UnloadZone(webview::webview& wv, std::string id, std::string zoneName) // NOLINT(performance-unnecessary-value-param) Copy is made for thread safety
{
ModManContext::Get().m_db_thread.Dispatch(
[&wv, id, zoneName]
{
auto result = ModManContext::Get().m_fast_file.UnloadZone(zoneName);
if (result)
{
con::debug("Unloaded zone \"{}\"", zoneName);
ui::PromiseResolve(wv, id, true);
}
else
{
con::warn("Failed unloading zone {}: {}", zoneName, result.error());
ui::PromiseReject(wv, id, std::move(result).error());
}
});
}
} // namespace } // namespace
namespace ui namespace ui
{ {
void RegisterFastFileBinds(webview::webview& wv) void NotifyZoneLoaded(std::string zoneName, std::string fastFilePath)
{
const ZoneLoadedDto dto{
.zoneName = std::move(zoneName),
.filePath = std::move(fastFilePath),
};
Notify(*ModManContext::Get().m_main_webview, "zoneLoaded", dto);
}
void NotifyZoneUnloaded(std::string zoneName)
{
const ZoneUnloadedDto dto{
.zoneName = std::move(zoneName),
};
Notify(*ModManContext::Get().m_main_webview, "zoneUnloaded", dto);
}
void RegisterZoneBinds(webview::webview& wv)
{ {
BindAsync<std::string>(wv, BindAsync<std::string>(wv,
"loadFastFile", "loadFastFile",
@@ -36,5 +91,12 @@ namespace ui
{ {
LoadFastFile(wv, id, std::move(path)); LoadFastFile(wv, id, std::move(path));
}); });
BindAsync<std::string>(wv,
"unloadZone",
[&wv](const std::string& id, std::string zoneName)
{
UnloadZone(wv, id, std::move(zoneName));
});
} }
} // namespace ui } // namespace ui

View File

@@ -4,5 +4,8 @@
namespace ui namespace ui
{ {
void RegisterFastFileBinds(webview::webview& wv); void NotifyZoneLoaded(std::string zoneName, std::string fastFilePath);
} void NotifyZoneUnloaded(std::string zoneName);
void RegisterZoneBinds(webview::webview& wv);
} // namespace ui

View File

@@ -1,7 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { webviewBinds } from "./native"; import { webviewBinds } from "@/native";
import { useZoneStore } from "@/stores/ZoneStore";
const zoneStore = useZoneStore();
const lastPath = ref(""); const lastPath = ref("");
const loadingFastFile = ref(false); const loadingFastFile = ref(false);
@@ -11,12 +13,19 @@ async function onOpenFastfileClick() {
loadingFastFile.value = true; loadingFastFile.value = true;
webviewBinds.loadFastFile(lastPath.value) webviewBinds
.catch((e: string) => { .loadFastFile(lastPath.value)
console.error("Failed to load fastfile:", e); .catch((e: string) => {
}) console.error("Failed to load fastfile:", e);
.finally(() => { })
loadingFastFile.value = false; .finally(() => {
loadingFastFile.value = false;
});
}
function onUnloadClicked(zoneName: string) {
webviewBinds.unloadZone(zoneName).catch((e: string) => {
console.error("Failed to unload zone:", e);
}); });
} }
</script> </script>
@@ -28,9 +37,15 @@ async function onOpenFastfileClick() {
<p> <p>
<button @click="onOpenFastfileClick">Open fastfile</button> <button @click="onOpenFastfileClick">Open fastfile</button>
<span>The last path: {{ lastPath }}</span>
<span>Loading: {{ loadingFastFile }}</span> <span>Loading: {{ loadingFastFile }}</span>
</p> </p>
<div>
<h3>Loaded zones:</h3>
<div v-for="zone in zoneStore.loadedZones" :key="zone">
<span>{{ zone }}</span>
<button @click="onUnloadClicked(zone)">Unload</button>
</div>
</div>
</main> </main>
</template> </template>

View File

@@ -1,3 +1,18 @@
export interface ZoneLoadedDto {
zoneName: string;
filePath: string;
}
export interface ZoneUnloadedDto {
zoneName: string;
}
export interface FastFileBinds { export interface FastFileBinds {
loadFastFile(path: string): Promise<void>; loadFastFile(path: string): Promise<void>;
unloadZone(zoneName: string): Promise<void>;
}
export interface FastFileEventMap {
zoneLoaded: ZoneLoadedDto;
zoneUnloaded: ZoneUnloadedDto;
} }

View File

@@ -1,12 +1,9 @@
import type { DialogBinds } from "./DialogBinds"; import type { DialogBinds } from "./DialogBinds";
import type { FastFileBinds } from "./FastFileBinds"; import type { FastFileBinds, FastFileEventMap } from "./FastFileBinds";
export type NativeMethods = DialogBinds & FastFileBinds; export type NativeMethods = DialogBinds & FastFileBinds;
interface NativeEventMap { type NativeEventMap = FastFileEventMap;
}
type WebViewExtensions = { type WebViewExtensions = {
webviewBinds: NativeMethods; webviewBinds: NativeMethods;

View File

@@ -0,0 +1,20 @@
import { readonly, ref } from "vue";
import { defineStore } from "pinia";
import { webviewAddEventListener } from "@/native";
export const useZoneStore = defineStore("zone", () => {
const loadedZones = ref<string[]>([]);
webviewAddEventListener("zoneLoaded", (dto) => {
loadedZones.value.push(dto.zoneName);
});
webviewAddEventListener("zoneUnloaded", (dto) => {
const index = loadedZones.value.indexOf(dto.zoneName);
if (index >= 0) {
loadedZones.value.splice(index, 1);
}
});
return { loadedZones: readonly(loadedZones) };
});

View File

@@ -1,12 +0,0 @@
import { ref, computed } from "vue";
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", () => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
});

View File

@@ -8,7 +8,8 @@ Zone::Zone(std::string name, const zone_priority_t priority, GameId gameId)
m_language(GameLanguage::LANGUAGE_NONE), m_language(GameLanguage::LANGUAGE_NONE),
m_game_id(gameId), m_game_id(gameId),
m_pools(ZoneAssetPools::CreateForGame(gameId, this, priority)), m_pools(ZoneAssetPools::CreateForGame(gameId, this, priority)),
m_memory(std::make_unique<ZoneMemory>()) m_memory(std::make_unique<ZoneMemory>()),
m_registered(false)
{ {
} }