@momoyu-ink/kit 0.5.0 → 0.5.1
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/lib.cjs +138 -31
- package/dist/lib.d.mts +1 -0
- package/dist/lib.d.ts +1 -0
- package/dist/lib.mjs +138 -31
- package/package.json +1 -1
package/dist/lib.cjs
CHANGED
|
@@ -855,6 +855,138 @@ function useFadeOut(outTime, pause = false, onFinished) {
|
|
|
855
855
|
|
|
856
856
|
// src/hooks/useScenario.ts
|
|
857
857
|
var import_react4 = require("react");
|
|
858
|
+
var currentScenarioSession = null;
|
|
859
|
+
var scenarioSessionId = 0;
|
|
860
|
+
var scenarioLifecycleQueue = Promise.resolve();
|
|
861
|
+
function normalizeStories(stories) {
|
|
862
|
+
return stories.filter((story) => Boolean(story));
|
|
863
|
+
}
|
|
864
|
+
function createScenarioSessionKey(config) {
|
|
865
|
+
return JSON.stringify({
|
|
866
|
+
stories: config.stories,
|
|
867
|
+
startName: config.startName ?? null,
|
|
868
|
+
entryName: config.entryName ?? null,
|
|
869
|
+
goNextOnLoad: config.goNextOnLoad
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
function isCurrentScenarioSession(session) {
|
|
873
|
+
return currentScenarioSession?.id === session.id && !session.disposed;
|
|
874
|
+
}
|
|
875
|
+
function enqueueScenarioLifecycleTask(task) {
|
|
876
|
+
const nextTask = scenarioLifecycleQueue.then(task, task);
|
|
877
|
+
scenarioLifecycleQueue = nextTask.catch(() => {
|
|
878
|
+
});
|
|
879
|
+
return nextTask;
|
|
880
|
+
}
|
|
881
|
+
function clearScenarioDisposeTimer(session) {
|
|
882
|
+
if (session.disposeTimer !== null) {
|
|
883
|
+
clearTimeout(session.disposeTimer);
|
|
884
|
+
session.disposeTimer = null;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
async function terminateCurrentScenario() {
|
|
888
|
+
try {
|
|
889
|
+
await executePluginCommand("scenario", {
|
|
890
|
+
subCommand: "terminateStory"
|
|
891
|
+
});
|
|
892
|
+
} catch (error) {
|
|
893
|
+
console.error("Failed to terminate scenario:", error);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
async function startScenarioSession(session, config) {
|
|
897
|
+
for (const story of config.stories) {
|
|
898
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
899
|
+
try {
|
|
900
|
+
await executePluginCommand("scenario", {
|
|
901
|
+
subCommand: "addStory",
|
|
902
|
+
name: story
|
|
903
|
+
});
|
|
904
|
+
} catch (error) {
|
|
905
|
+
console.error("Failed to load scenario:", error);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
909
|
+
try {
|
|
910
|
+
if (config.startName) {
|
|
911
|
+
await executePluginCommand("scenario", {
|
|
912
|
+
subCommand: "startStory",
|
|
913
|
+
name: config.startName,
|
|
914
|
+
entry: config.entryName
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
918
|
+
if (config.goNextOnLoad) {
|
|
919
|
+
await nextLine();
|
|
920
|
+
}
|
|
921
|
+
} catch (error) {
|
|
922
|
+
console.error(`Failed to start scenario ${config.startName}:`, error);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function ensureScenarioSessionStarted(session, config) {
|
|
926
|
+
if (session.started || session.startPromise !== null) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
const startPromise = enqueueScenarioLifecycleTask(async () => {
|
|
930
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
931
|
+
await startScenarioSession(session, config);
|
|
932
|
+
if (isCurrentScenarioSession(session)) {
|
|
933
|
+
session.started = true;
|
|
934
|
+
}
|
|
935
|
+
});
|
|
936
|
+
session.startPromise = startPromise;
|
|
937
|
+
void startPromise.finally(() => {
|
|
938
|
+
if (session.startPromise === startPromise) {
|
|
939
|
+
session.startPromise = null;
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
function disposeScenarioSession(session, delayMs) {
|
|
944
|
+
clearScenarioDisposeTimer(session);
|
|
945
|
+
session.disposeTimer = setTimeout(() => {
|
|
946
|
+
if (!isCurrentScenarioSession(session) || session.refCount > 0) {
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
session.disposeTimer = null;
|
|
950
|
+
session.disposed = true;
|
|
951
|
+
currentScenarioSession = null;
|
|
952
|
+
void enqueueScenarioLifecycleTask(terminateCurrentScenario);
|
|
953
|
+
}, delayMs);
|
|
954
|
+
}
|
|
955
|
+
function acquireScenarioSession(config) {
|
|
956
|
+
const key = createScenarioSessionKey(config);
|
|
957
|
+
if (currentScenarioSession !== null && currentScenarioSession.key !== key) {
|
|
958
|
+
const previousSession = currentScenarioSession;
|
|
959
|
+
clearScenarioDisposeTimer(previousSession);
|
|
960
|
+
previousSession.disposed = true;
|
|
961
|
+
currentScenarioSession = null;
|
|
962
|
+
void enqueueScenarioLifecycleTask(terminateCurrentScenario);
|
|
963
|
+
}
|
|
964
|
+
if (currentScenarioSession === null) {
|
|
965
|
+
currentScenarioSession = {
|
|
966
|
+
id: ++scenarioSessionId,
|
|
967
|
+
key,
|
|
968
|
+
refCount: 0,
|
|
969
|
+
started: false,
|
|
970
|
+
startPromise: null,
|
|
971
|
+
disposeTimer: null,
|
|
972
|
+
disposed: false
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
clearScenarioDisposeTimer(currentScenarioSession);
|
|
976
|
+
currentScenarioSession.refCount += 1;
|
|
977
|
+
ensureScenarioSessionStarted(currentScenarioSession, config);
|
|
978
|
+
return currentScenarioSession;
|
|
979
|
+
}
|
|
980
|
+
function releaseScenarioSession(session) {
|
|
981
|
+
if (!isCurrentScenarioSession(session)) {
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
session.refCount = Math.max(0, session.refCount - 1);
|
|
985
|
+
if (session.refCount > 0) {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
disposeScenarioSession(session, 0);
|
|
989
|
+
}
|
|
858
990
|
function nextLine() {
|
|
859
991
|
return executePluginCommand("scenario", { subCommand: "nextLine" });
|
|
860
992
|
}
|
|
@@ -863,39 +995,14 @@ function setWaiting(time, skippable) {
|
|
|
863
995
|
}
|
|
864
996
|
function useScenario(stories, startName, entryName, goNextOnLoad = false) {
|
|
865
997
|
(0, import_react4.useEffect)(() => {
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
subCommand: "addStory",
|
|
872
|
-
name: story
|
|
873
|
-
});
|
|
874
|
-
} catch (error) {
|
|
875
|
-
console.error(`Failed to load scenario:`, error);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
void loadScenario().then(async () => {
|
|
880
|
-
try {
|
|
881
|
-
if (startName) {
|
|
882
|
-
await executePluginCommand("scenario", {
|
|
883
|
-
subCommand: "startStory",
|
|
884
|
-
name: startName,
|
|
885
|
-
entry: entryName
|
|
886
|
-
});
|
|
887
|
-
}
|
|
888
|
-
if (goNextOnLoad) {
|
|
889
|
-
await nextLine();
|
|
890
|
-
}
|
|
891
|
-
} catch (error) {
|
|
892
|
-
console.error(`Failed to start scenario ${startName}:`, error);
|
|
893
|
-
}
|
|
998
|
+
const session = acquireScenarioSession({
|
|
999
|
+
stories: normalizeStories(stories),
|
|
1000
|
+
startName,
|
|
1001
|
+
entryName,
|
|
1002
|
+
goNextOnLoad
|
|
894
1003
|
});
|
|
895
1004
|
return () => {
|
|
896
|
-
|
|
897
|
-
subCommand: "terminateStory"
|
|
898
|
-
});
|
|
1005
|
+
releaseScenarioSession(session);
|
|
899
1006
|
};
|
|
900
1007
|
}, [stories, startName, entryName, goNextOnLoad]);
|
|
901
1008
|
}
|
package/dist/lib.d.mts
CHANGED
|
@@ -516,6 +516,7 @@ declare function nextLine(): any;
|
|
|
516
516
|
declare function setWaiting(time: number, skippable: boolean): void;
|
|
517
517
|
/**
|
|
518
518
|
* Custom hook to manage scenario lifecycle (load, start, terminate).
|
|
519
|
+
* The underlying session is resilient to transient remounts such as Fast Refresh.
|
|
519
520
|
*
|
|
520
521
|
* @param {string[]} stories - An array of story names to load.
|
|
521
522
|
* @param {string} [startName] - The name of the story to start.
|
package/dist/lib.d.ts
CHANGED
|
@@ -516,6 +516,7 @@ declare function nextLine(): any;
|
|
|
516
516
|
declare function setWaiting(time: number, skippable: boolean): void;
|
|
517
517
|
/**
|
|
518
518
|
* Custom hook to manage scenario lifecycle (load, start, terminate).
|
|
519
|
+
* The underlying session is resilient to transient remounts such as Fast Refresh.
|
|
519
520
|
*
|
|
520
521
|
* @param {string[]} stories - An array of story names to load.
|
|
521
522
|
* @param {string} [startName] - The name of the story to start.
|
package/dist/lib.mjs
CHANGED
|
@@ -843,6 +843,138 @@ function useFadeOut(outTime, pause = false, onFinished) {
|
|
|
843
843
|
|
|
844
844
|
// src/hooks/useScenario.ts
|
|
845
845
|
import { useEffect } from "react";
|
|
846
|
+
var currentScenarioSession = null;
|
|
847
|
+
var scenarioSessionId = 0;
|
|
848
|
+
var scenarioLifecycleQueue = Promise.resolve();
|
|
849
|
+
function normalizeStories(stories) {
|
|
850
|
+
return stories.filter((story) => Boolean(story));
|
|
851
|
+
}
|
|
852
|
+
function createScenarioSessionKey(config) {
|
|
853
|
+
return JSON.stringify({
|
|
854
|
+
stories: config.stories,
|
|
855
|
+
startName: config.startName ?? null,
|
|
856
|
+
entryName: config.entryName ?? null,
|
|
857
|
+
goNextOnLoad: config.goNextOnLoad
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
function isCurrentScenarioSession(session) {
|
|
861
|
+
return currentScenarioSession?.id === session.id && !session.disposed;
|
|
862
|
+
}
|
|
863
|
+
function enqueueScenarioLifecycleTask(task) {
|
|
864
|
+
const nextTask = scenarioLifecycleQueue.then(task, task);
|
|
865
|
+
scenarioLifecycleQueue = nextTask.catch(() => {
|
|
866
|
+
});
|
|
867
|
+
return nextTask;
|
|
868
|
+
}
|
|
869
|
+
function clearScenarioDisposeTimer(session) {
|
|
870
|
+
if (session.disposeTimer !== null) {
|
|
871
|
+
clearTimeout(session.disposeTimer);
|
|
872
|
+
session.disposeTimer = null;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
async function terminateCurrentScenario() {
|
|
876
|
+
try {
|
|
877
|
+
await executePluginCommand("scenario", {
|
|
878
|
+
subCommand: "terminateStory"
|
|
879
|
+
});
|
|
880
|
+
} catch (error) {
|
|
881
|
+
console.error("Failed to terminate scenario:", error);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
async function startScenarioSession(session, config) {
|
|
885
|
+
for (const story of config.stories) {
|
|
886
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
887
|
+
try {
|
|
888
|
+
await executePluginCommand("scenario", {
|
|
889
|
+
subCommand: "addStory",
|
|
890
|
+
name: story
|
|
891
|
+
});
|
|
892
|
+
} catch (error) {
|
|
893
|
+
console.error("Failed to load scenario:", error);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
897
|
+
try {
|
|
898
|
+
if (config.startName) {
|
|
899
|
+
await executePluginCommand("scenario", {
|
|
900
|
+
subCommand: "startStory",
|
|
901
|
+
name: config.startName,
|
|
902
|
+
entry: config.entryName
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
906
|
+
if (config.goNextOnLoad) {
|
|
907
|
+
await nextLine();
|
|
908
|
+
}
|
|
909
|
+
} catch (error) {
|
|
910
|
+
console.error(`Failed to start scenario ${config.startName}:`, error);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function ensureScenarioSessionStarted(session, config) {
|
|
914
|
+
if (session.started || session.startPromise !== null) {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const startPromise = enqueueScenarioLifecycleTask(async () => {
|
|
918
|
+
if (!isCurrentScenarioSession(session)) return;
|
|
919
|
+
await startScenarioSession(session, config);
|
|
920
|
+
if (isCurrentScenarioSession(session)) {
|
|
921
|
+
session.started = true;
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
session.startPromise = startPromise;
|
|
925
|
+
void startPromise.finally(() => {
|
|
926
|
+
if (session.startPromise === startPromise) {
|
|
927
|
+
session.startPromise = null;
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
function disposeScenarioSession(session, delayMs) {
|
|
932
|
+
clearScenarioDisposeTimer(session);
|
|
933
|
+
session.disposeTimer = setTimeout(() => {
|
|
934
|
+
if (!isCurrentScenarioSession(session) || session.refCount > 0) {
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
session.disposeTimer = null;
|
|
938
|
+
session.disposed = true;
|
|
939
|
+
currentScenarioSession = null;
|
|
940
|
+
void enqueueScenarioLifecycleTask(terminateCurrentScenario);
|
|
941
|
+
}, delayMs);
|
|
942
|
+
}
|
|
943
|
+
function acquireScenarioSession(config) {
|
|
944
|
+
const key = createScenarioSessionKey(config);
|
|
945
|
+
if (currentScenarioSession !== null && currentScenarioSession.key !== key) {
|
|
946
|
+
const previousSession = currentScenarioSession;
|
|
947
|
+
clearScenarioDisposeTimer(previousSession);
|
|
948
|
+
previousSession.disposed = true;
|
|
949
|
+
currentScenarioSession = null;
|
|
950
|
+
void enqueueScenarioLifecycleTask(terminateCurrentScenario);
|
|
951
|
+
}
|
|
952
|
+
if (currentScenarioSession === null) {
|
|
953
|
+
currentScenarioSession = {
|
|
954
|
+
id: ++scenarioSessionId,
|
|
955
|
+
key,
|
|
956
|
+
refCount: 0,
|
|
957
|
+
started: false,
|
|
958
|
+
startPromise: null,
|
|
959
|
+
disposeTimer: null,
|
|
960
|
+
disposed: false
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
clearScenarioDisposeTimer(currentScenarioSession);
|
|
964
|
+
currentScenarioSession.refCount += 1;
|
|
965
|
+
ensureScenarioSessionStarted(currentScenarioSession, config);
|
|
966
|
+
return currentScenarioSession;
|
|
967
|
+
}
|
|
968
|
+
function releaseScenarioSession(session) {
|
|
969
|
+
if (!isCurrentScenarioSession(session)) {
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
session.refCount = Math.max(0, session.refCount - 1);
|
|
973
|
+
if (session.refCount > 0) {
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
disposeScenarioSession(session, 0);
|
|
977
|
+
}
|
|
846
978
|
function nextLine() {
|
|
847
979
|
return executePluginCommand("scenario", { subCommand: "nextLine" });
|
|
848
980
|
}
|
|
@@ -851,39 +983,14 @@ function setWaiting(time, skippable) {
|
|
|
851
983
|
}
|
|
852
984
|
function useScenario(stories, startName, entryName, goNextOnLoad = false) {
|
|
853
985
|
useEffect(() => {
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
subCommand: "addStory",
|
|
860
|
-
name: story
|
|
861
|
-
});
|
|
862
|
-
} catch (error) {
|
|
863
|
-
console.error(`Failed to load scenario:`, error);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
};
|
|
867
|
-
void loadScenario().then(async () => {
|
|
868
|
-
try {
|
|
869
|
-
if (startName) {
|
|
870
|
-
await executePluginCommand("scenario", {
|
|
871
|
-
subCommand: "startStory",
|
|
872
|
-
name: startName,
|
|
873
|
-
entry: entryName
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
if (goNextOnLoad) {
|
|
877
|
-
await nextLine();
|
|
878
|
-
}
|
|
879
|
-
} catch (error) {
|
|
880
|
-
console.error(`Failed to start scenario ${startName}:`, error);
|
|
881
|
-
}
|
|
986
|
+
const session = acquireScenarioSession({
|
|
987
|
+
stories: normalizeStories(stories),
|
|
988
|
+
startName,
|
|
989
|
+
entryName,
|
|
990
|
+
goNextOnLoad
|
|
882
991
|
});
|
|
883
992
|
return () => {
|
|
884
|
-
|
|
885
|
-
subCommand: "terminateStory"
|
|
886
|
-
});
|
|
993
|
+
releaseScenarioSession(session);
|
|
887
994
|
};
|
|
888
995
|
}, [stories, startName, entryName, goNextOnLoad]);
|
|
889
996
|
}
|