refactor: establish standalone application boundary
This commit is contained in:
@@ -1,9 +1,95 @@
|
||||
const HEART_BREATH_INHALE_MS = 3_000;
|
||||
const HEART_BREATH_HOLD_MS = 2_000;
|
||||
const HEART_BREATH_EXHALE_MS = 4_000;
|
||||
const HEART_BREATH_PREPARE_MS = 1_000;
|
||||
const HEART_BREATH_CYCLE_MS = HEART_BREATH_INHALE_MS + HEART_BREATH_HOLD_MS + HEART_BREATH_EXHALE_MS;
|
||||
const HEART_BREATH_ACTIVE_MS = HEART_BREATH_CYCLE_MS * 5;
|
||||
const HEART_BREATH_TOTAL_MS = HEART_BREATH_PREPARE_MS + HEART_BREATH_ACTIVE_MS;
|
||||
|
||||
let qiFieldAnimationFrame = 0;
|
||||
let qiFieldSoloElement = "";
|
||||
let heavenPerformanceToken = 0;
|
||||
let heavenReadingAnimation = null;
|
||||
let heartHoldTimer = null;
|
||||
let heartHoldTriggered = false;
|
||||
let heartHoldStartedAt = 0;
|
||||
let heartHoldAnimationFrame = 0;
|
||||
let heartCastingBusy = false;
|
||||
let heartDustAnimationFrame = 0;
|
||||
let heartDustParticles = [];
|
||||
let heartIncenseAnimation = null;
|
||||
const heartCoinRotations = [0, 0, 0];
|
||||
|
||||
let heavenResizeTimer = null;
|
||||
|
||||
const heartSound = {
|
||||
enabled: false,
|
||||
context: null,
|
||||
ensure() {
|
||||
if (!this.context) {
|
||||
const AudioContextClass = window.AudioContext || window.webkitAudioContext;
|
||||
if (!AudioContextClass) return null;
|
||||
this.context = new AudioContextClass();
|
||||
}
|
||||
if (this.context.state === "suspended") this.context.resume();
|
||||
return this.context;
|
||||
},
|
||||
tone(frequency, duration, gain, type = "sine", delay = 0) {
|
||||
if (!this.enabled) return;
|
||||
const context = this.ensure();
|
||||
if (!context) return;
|
||||
const start = context.currentTime + delay;
|
||||
const oscillator = context.createOscillator();
|
||||
const volume = context.createGain();
|
||||
oscillator.type = type;
|
||||
oscillator.frequency.value = frequency;
|
||||
volume.gain.setValueAtTime(0.0001, start);
|
||||
volume.gain.linearRampToValueAtTime(gain, start + 0.015);
|
||||
volume.gain.exponentialRampToValueAtTime(0.0001, start + duration);
|
||||
oscillator.connect(volume).connect(context.destination);
|
||||
oscillator.start(start);
|
||||
oscillator.stop(start + duration + 0.05);
|
||||
},
|
||||
chime(frequency = 640) {
|
||||
this.tone(frequency, 4.8, 0.12);
|
||||
this.tone(frequency * 2.02, 3.6, 0.045);
|
||||
this.tone(frequency * 3.96, 2.2, 0.018);
|
||||
},
|
||||
coin(delay = 0) {
|
||||
this.tone(2350 + Math.random() * 260, 0.28, 0.055, "triangle", delay);
|
||||
this.tone(3250 + Math.random() * 260, 0.18, 0.025, "triangle", delay + 0.01);
|
||||
},
|
||||
};
|
||||
|
||||
const HEART_WHISPERS = [
|
||||
["应无所住,而生其心", 10, 12, 0],
|
||||
["不是风动,不是幡动,仁者心动", 89, 8, 1],
|
||||
["菩提本无树,明镜亦非台", 16, 52, 2],
|
||||
["本来无一物,何处惹尘埃", 84, 54, 3],
|
||||
["心外无物,心外无理", 22, 18, 4],
|
||||
["知行合一", 78, 30, 5],
|
||||
["此心光明,亦复何言", 90, 60, 6],
|
||||
];
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
clearTimeout(heavenResizeTimer);
|
||||
heavenResizeTimer = setTimeout(() => {
|
||||
if (state.activeView !== "heavenView") return;
|
||||
if (state.heavenPanel === "fortune" && state.heavenSetup?.field) {
|
||||
renderQiFieldCanvas(state.heavenSetup.field.balance || [], { intro: false });
|
||||
drawQiUseConnections(false);
|
||||
}
|
||||
if (state.heavenPanel === "heart") startHeartDust();
|
||||
}, 120);
|
||||
});
|
||||
|
||||
|
||||
window.XiaobaiPageModules.register("heaven", ["heavenView"], {
|
||||
bind: bindHeavenEvents,
|
||||
enter: ["loadHeaven"],
|
||||
leave: ["stopHeaven"],
|
||||
});
|
||||
|
||||
/* PRESERVATION-SOURCE-BEGIN app.js:4828-6667 */
|
||||
async function loadHeavenSetup(force = false, sector = "", stockCode = "") {
|
||||
const calendarDate = document.querySelector("#qiObservationDate")?.value || elements.tradeDate.value;
|
||||
const requestedDate = calendarDate.replaceAll("-", "");
|
||||
@@ -1827,4 +1913,53 @@ function capitalize(value) {
|
||||
|
||||
const LINE_POSITIONS_CLIENT = ["初爻", "二爻", "三爻", "四爻", "五爻", "上爻"];
|
||||
|
||||
/* PRESERVATION-SOURCE-END app.js:4828-6667 */
|
||||
|
||||
function bindHeavenEvents() {
|
||||
document.querySelectorAll("[data-heaven-panel]").forEach((button) => {
|
||||
button.addEventListener("click", () => selectHeavenPanel(button.dataset.heavenPanel, true));
|
||||
});
|
||||
document.querySelector("#loadHeavenSelectionButton").addEventListener("click", loadHeavenSelection);
|
||||
document.querySelector("#heavenCalibrationForm").addEventListener("submit", applyHeavenCalibration);
|
||||
document.querySelector("#resetHeavenCalibrationButton").addEventListener("click", resetHeavenCalibration);
|
||||
document.querySelector("#heavenStockInput").addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
loadHeavenSelection();
|
||||
}
|
||||
});
|
||||
document.querySelector("#interpretTrendButton").addEventListener("click", () => interpretHeaven("trend"));
|
||||
document.querySelector("#interpretFortuneButton").addEventListener("click", () => interpretHeaven("fortune"));
|
||||
document.querySelector("#historyTrendButton").addEventListener("click", () => openHeavenHistory("trend"));
|
||||
document.querySelector("#historyFortuneButton").addEventListener("click", () => openHeavenHistory("fortune"));
|
||||
document.querySelector("#qiObservationDate").addEventListener("change", () => {
|
||||
state.personalField = null;
|
||||
state.heavenManualData = null;
|
||||
state.heavenInterpretations.fortune = "";
|
||||
loadHeavenSetup(
|
||||
true,
|
||||
"",
|
||||
document.querySelector("#heavenStockInput").value.trim(),
|
||||
);
|
||||
});
|
||||
document.querySelector("#openPersonalSettingsButton").addEventListener("click", () => openSettings("profile"));
|
||||
document.querySelector("#sectorPhaseForm").addEventListener("submit", saveSectorPhaseOverride);
|
||||
document.querySelector("#startBreathingButton").addEventListener("click", startHeartBreathing);
|
||||
document.querySelector("#beginCastingButton").addEventListener("click", beginHeartCasting);
|
||||
document.querySelector("#heartSoundToggle").addEventListener("click", toggleHeartSound);
|
||||
document.querySelector("#historyHeartButton").addEventListener("click", () => openHeavenHistory("heart"));
|
||||
initializeHeartCoinHold();
|
||||
initializeHeartLineInspection();
|
||||
document.querySelector("#interpretHeartButton").addEventListener("click", () => interpretHeaven("heart"));
|
||||
document.querySelector("#viewHeartReadingButton").addEventListener("click", () => openHeavenReading("heart"));
|
||||
document.querySelector("#restartHeartButton").addEventListener("click", resetHeartRitual);
|
||||
document.querySelector("#closeHeavenReadingDialog").addEventListener("click", () => elements.heavenReadingDialog.close());
|
||||
elements.heavenReadingDialog.addEventListener("close", stopHeavenReadingAnimation);
|
||||
document.querySelectorAll("[data-heaven-reading-tab]").forEach((button) => {
|
||||
button.addEventListener("click", () => selectHeavenReadingTab(button.dataset.heavenReadingTab));
|
||||
});
|
||||
document.querySelector("#heavenReadingHistoryList").addEventListener("click", handleHeavenHistorySelection);
|
||||
document.querySelector("#heavenReadingHistoryDetail").addEventListener("click", handleHeavenHistoryAction);
|
||||
document.querySelectorAll("[data-heart-return]").forEach((button) => {
|
||||
button.addEventListener("click", resetHeartRitual);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user