koin.js 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +109 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -2
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +13 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -5640,10 +5640,45 @@ function getCore2(system) {
|
|
|
5640
5640
|
return getCore(system);
|
|
5641
5641
|
}
|
|
5642
5642
|
|
|
5643
|
+
// src/lib/rom-cache.ts
|
|
5644
|
+
var CACHE_NAME = "koin-rom-cache-v1";
|
|
5645
|
+
async function getCachedRom(romId) {
|
|
5646
|
+
if (typeof caches === "undefined") return null;
|
|
5647
|
+
try {
|
|
5648
|
+
const cache = await caches.open(CACHE_NAME);
|
|
5649
|
+
const response = await cache.match(romId);
|
|
5650
|
+
if (response) {
|
|
5651
|
+
console.log(`[Cache] Hit for ROM ${romId}`);
|
|
5652
|
+
return await response.blob();
|
|
5653
|
+
}
|
|
5654
|
+
} catch (e) {
|
|
5655
|
+
console.warn("[Cache] Read failed:", e);
|
|
5656
|
+
}
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5659
|
+
async function fetchAndCacheRom(romId, url) {
|
|
5660
|
+
const response = await fetch(url);
|
|
5661
|
+
if (!response.ok) {
|
|
5662
|
+
throw new Error(`Failed to fetch ROM: ${response.statusText}`);
|
|
5663
|
+
}
|
|
5664
|
+
const blob = await response.blob();
|
|
5665
|
+
if (typeof caches !== "undefined") {
|
|
5666
|
+
try {
|
|
5667
|
+
const cache = await caches.open(CACHE_NAME);
|
|
5668
|
+
await cache.put(romId, new Response(blob));
|
|
5669
|
+
console.log(`[Cache] Cached ROM ${romId}`);
|
|
5670
|
+
} catch (e) {
|
|
5671
|
+
console.warn("[Cache] Write failed:", e);
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5674
|
+
return blob;
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5643
5677
|
// src/hooks/emulator/useEmulatorCore.ts
|
|
5644
5678
|
function useEmulatorCore({
|
|
5645
5679
|
system,
|
|
5646
5680
|
romUrl,
|
|
5681
|
+
romId,
|
|
5647
5682
|
core: coreOverride,
|
|
5648
5683
|
biosUrl,
|
|
5649
5684
|
initialState,
|
|
@@ -5725,7 +5760,25 @@ function useEmulatorCore({
|
|
|
5725
5760
|
setError(null);
|
|
5726
5761
|
const core = coreOverride || getCore2(system);
|
|
5727
5762
|
let romOption = romUrl;
|
|
5728
|
-
if (
|
|
5763
|
+
if (romId) {
|
|
5764
|
+
try {
|
|
5765
|
+
let blob = await getCachedRom(romId);
|
|
5766
|
+
if (!blob) {
|
|
5767
|
+
console.log(`[Nostalgist] Fetching and caching ROM ${romId}`);
|
|
5768
|
+
blob = await fetchAndCacheRom(romId, romUrl);
|
|
5769
|
+
} else {
|
|
5770
|
+
console.log(`[Nostalgist] Loaded ROM ${romId} from cache`);
|
|
5771
|
+
}
|
|
5772
|
+
if (blob) {
|
|
5773
|
+
romOption = {
|
|
5774
|
+
fileName: romFileName || "rom.bin",
|
|
5775
|
+
fileContent: blob
|
|
5776
|
+
};
|
|
5777
|
+
}
|
|
5778
|
+
} catch (err) {
|
|
5779
|
+
console.error("[Nostalgist] Cache/Fetch error, falling back to direct URL:", err);
|
|
5780
|
+
}
|
|
5781
|
+
} else if (romFileName) {
|
|
5729
5782
|
romOption = { fileName: romFileName, fileContent: romUrl };
|
|
5730
5783
|
}
|
|
5731
5784
|
const inputConfig = buildRetroArchConfig({
|
|
@@ -6392,7 +6445,8 @@ var useNostalgist = ({
|
|
|
6392
6445
|
onError,
|
|
6393
6446
|
initialVolume = 100,
|
|
6394
6447
|
romFileName,
|
|
6395
|
-
shader
|
|
6448
|
+
shader,
|
|
6449
|
+
romId
|
|
6396
6450
|
}) => {
|
|
6397
6451
|
const isHeavySystem = useMemo(() => {
|
|
6398
6452
|
return PERFORMANCE_TIER_2_SYSTEMS.has(system.toUpperCase());
|
|
@@ -6420,6 +6474,7 @@ var useNostalgist = ({
|
|
|
6420
6474
|
} = useEmulatorCore({
|
|
6421
6475
|
system,
|
|
6422
6476
|
romUrl,
|
|
6477
|
+
romId,
|
|
6423
6478
|
core,
|
|
6424
6479
|
biosUrl,
|
|
6425
6480
|
initialState,
|
|
@@ -6613,6 +6668,7 @@ function useControls(system, onNotify) {
|
|
|
6613
6668
|
function useGameSession(props) {
|
|
6614
6669
|
const {
|
|
6615
6670
|
romUrl,
|
|
6671
|
+
romId,
|
|
6616
6672
|
romFileName,
|
|
6617
6673
|
system,
|
|
6618
6674
|
core,
|
|
@@ -6661,6 +6717,7 @@ function useGameSession(props) {
|
|
|
6661
6717
|
const nostalgist = useNostalgist({
|
|
6662
6718
|
system,
|
|
6663
6719
|
romUrl,
|
|
6720
|
+
romId,
|
|
6664
6721
|
romFileName,
|
|
6665
6722
|
core,
|
|
6666
6723
|
biosUrl,
|
|
@@ -7434,8 +7491,39 @@ function usePlayerPersistence(onSettingsChange) {
|
|
|
7434
7491
|
updateSettings
|
|
7435
7492
|
};
|
|
7436
7493
|
}
|
|
7494
|
+
|
|
7495
|
+
// src/lib/telemetry.ts
|
|
7496
|
+
var sendTelemetry = (eventName, params = {}) => {
|
|
7497
|
+
if (typeof window === "undefined") return;
|
|
7498
|
+
try {
|
|
7499
|
+
fetch("https://koin.theretrosaga.com/api/telemetry", {
|
|
7500
|
+
method: "POST",
|
|
7501
|
+
headers: {
|
|
7502
|
+
"Content-Type": "application/json"
|
|
7503
|
+
},
|
|
7504
|
+
body: JSON.stringify({
|
|
7505
|
+
event_name: eventName,
|
|
7506
|
+
params: {
|
|
7507
|
+
...params,
|
|
7508
|
+
url: window.location.href,
|
|
7509
|
+
referrer: document.referrer,
|
|
7510
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
7511
|
+
}
|
|
7512
|
+
})
|
|
7513
|
+
}).catch(() => {
|
|
7514
|
+
});
|
|
7515
|
+
} catch (e) {
|
|
7516
|
+
}
|
|
7517
|
+
};
|
|
7437
7518
|
var GamePlayer = memo(function GamePlayer2(props) {
|
|
7438
7519
|
const { settings, updateSettings, isLoaded: settingsLoaded } = usePlayerPersistence();
|
|
7520
|
+
useEffect(() => {
|
|
7521
|
+
sendTelemetry("game_start", {
|
|
7522
|
+
system: props.system,
|
|
7523
|
+
core: props.core,
|
|
7524
|
+
game: props.title || "unknown"
|
|
7525
|
+
});
|
|
7526
|
+
}, [props.system, props.core, props.title]);
|
|
7439
7527
|
const [biosModalOpen, setBiosModalOpen] = useState(false);
|
|
7440
7528
|
const [showShortcutsModal, setShowShortcutsModal] = useState(false);
|
|
7441
7529
|
const effectiveShader = props.shader !== void 0 ? props.shader : settings.shader;
|
|
@@ -7533,6 +7621,13 @@ var GamePlayer = memo(function GamePlayer2(props) {
|
|
|
7533
7621
|
status,
|
|
7534
7622
|
isPerformanceMode
|
|
7535
7623
|
} = nostalgist;
|
|
7624
|
+
useEffect(() => {
|
|
7625
|
+
if (status === "running") {
|
|
7626
|
+
console.log("[Koin Debug] Status:", status);
|
|
7627
|
+
console.log("[Koin Debug] isPerformanceMode:", isPerformanceMode);
|
|
7628
|
+
console.log("[Koin Debug] crossOriginIsolated:", typeof window !== "undefined" ? window.crossOriginIsolated : "N/A");
|
|
7629
|
+
}
|
|
7630
|
+
}, [status, isPerformanceMode]);
|
|
7536
7631
|
useEffect(() => {
|
|
7537
7632
|
if (settingsLoaded) {
|
|
7538
7633
|
setVolume(settings.volume);
|
|
@@ -7726,6 +7821,18 @@ var GamePlayer = memo(function GamePlayer2(props) {
|
|
|
7726
7821
|
]
|
|
7727
7822
|
}
|
|
7728
7823
|
),
|
|
7824
|
+
!isPerformanceMode && (status === "running" || status === "paused") && /* @__PURE__ */ jsx(
|
|
7825
|
+
"div",
|
|
7826
|
+
{
|
|
7827
|
+
className: "bg-red-900/80 backdrop-blur-md px-2 py-1 rounded border border-red-500/50 flex items-center gap-1.5",
|
|
7828
|
+
title: "Standard Mode (Single Threaded)",
|
|
7829
|
+
children: /* @__PURE__ */ jsxs("span", { className: "text-[10px] uppercase font-bold tracking-wider text-red-200", children: [
|
|
7830
|
+
"Standard (",
|
|
7831
|
+
typeof window !== "undefined" && window.crossOriginIsolated ? "Isolated" : "Not Isolated",
|
|
7832
|
+
")"
|
|
7833
|
+
] })
|
|
7834
|
+
}
|
|
7835
|
+
),
|
|
7729
7836
|
settings.showInputDisplay && (status === "running" || status === "paused") && /* @__PURE__ */ jsx(
|
|
7730
7837
|
InputDisplay_default,
|
|
7731
7838
|
{
|