192 lines
5.7 KiB
JavaScript
192 lines
5.7 KiB
JavaScript
(function () {
|
|
if (window.GIAComposePanel) {
|
|
window.GIAComposePanel.initAll(document);
|
|
return;
|
|
}
|
|
|
|
const core = window.GIAComposePanelCore;
|
|
const threadModule = window.GIAComposePanelThread;
|
|
const sendModule = window.GIAComposePanelSend;
|
|
if (!core || !threadModule || !sendModule) {
|
|
return;
|
|
}
|
|
|
|
const destroyPanelState = function (state) {
|
|
if (!state) {
|
|
return;
|
|
}
|
|
if (state.pollTimer) {
|
|
clearInterval(state.pollTimer);
|
|
}
|
|
if (state.pendingCommandPoll) {
|
|
clearInterval(state.pendingCommandPoll);
|
|
}
|
|
if (state.socket) {
|
|
try {
|
|
state.socket.close();
|
|
} catch (_err) {
|
|
// Ignore socket close failures.
|
|
}
|
|
}
|
|
if (state.eventHandler) {
|
|
document.body.removeEventListener("composeMessageSent", state.eventHandler);
|
|
}
|
|
if (state.sendResultHandler) {
|
|
document.body.removeEventListener(
|
|
"composeSendResult",
|
|
state.sendResultHandler
|
|
);
|
|
}
|
|
if (state.commandIdHandler) {
|
|
document.body.removeEventListener(
|
|
"composeSendCommandId",
|
|
state.commandIdHandler
|
|
);
|
|
}
|
|
delete window.giaComposePanels[state.panelId];
|
|
};
|
|
|
|
const initPanel = function (panel) {
|
|
if (!panel) {
|
|
return;
|
|
}
|
|
const panelId = String(panel.id || "").trim();
|
|
if (!panelId) {
|
|
return;
|
|
}
|
|
if (panel.dataset.composeInitialized === "1" && window.giaComposePanels[panelId]) {
|
|
return;
|
|
}
|
|
destroyPanelState(window.giaComposePanels[panelId]);
|
|
|
|
const thread = document.getElementById(panelId + "-thread");
|
|
const form = document.getElementById(panelId + "-form");
|
|
const textarea = document.getElementById(panelId + "-textarea");
|
|
if (!thread || !form || !textarea) {
|
|
return;
|
|
}
|
|
|
|
const state = {
|
|
panelId: panelId,
|
|
pollTimer: null,
|
|
polling: false,
|
|
socket: null,
|
|
websocketReady: false,
|
|
pendingCommandPoll: null,
|
|
pendingCommandId: "",
|
|
pendingCommandAttempts: 0,
|
|
pendingCommandStartedAt: 0,
|
|
pendingCommandInFlight: false,
|
|
eventHandler: null,
|
|
sendResultHandler: null,
|
|
commandIdHandler: null,
|
|
};
|
|
window.giaComposePanels[panelId] = state;
|
|
panel.dataset.composeInitialized = "1";
|
|
|
|
const statusBox = document.getElementById(panelId + "-status");
|
|
const setStatus = function (message, level) {
|
|
if (!statusBox) {
|
|
return;
|
|
}
|
|
statusBox.innerHTML = "";
|
|
if (!message) {
|
|
return;
|
|
}
|
|
statusBox.appendChild(
|
|
core.createNode(
|
|
"p",
|
|
"compose-status-line is-" + String(level || "info"),
|
|
String(message)
|
|
)
|
|
);
|
|
};
|
|
|
|
const flashCompose = function (className) {
|
|
panel.classList.remove("is-send-success", "is-send-fail");
|
|
void panel.offsetWidth;
|
|
panel.classList.add(className);
|
|
window.setTimeout(function () {
|
|
panel.classList.remove(className);
|
|
}, 420);
|
|
};
|
|
|
|
const autosize = function () {
|
|
textarea.style.height = "auto";
|
|
textarea.style.height = Math.min(Math.max(textarea.scrollHeight, 44), 128) + "px";
|
|
};
|
|
|
|
const threadController = threadModule.createController({
|
|
contactSelect: document.getElementById(panelId + "-contact-select"),
|
|
hiddenIdentifier: document.getElementById(panelId + "-input-identifier"),
|
|
hiddenPerson: document.getElementById(panelId + "-input-person"),
|
|
hiddenReplyTo: form.querySelector('input[name="reply_to_message_id"]'),
|
|
hiddenService: document.getElementById(panelId + "-input-service"),
|
|
metaLine: document.getElementById(panelId + "-meta-line"),
|
|
panel: panel,
|
|
panelId: panelId,
|
|
platformSelect: document.getElementById(panelId + "-platform-select"),
|
|
renderMode: String(panel.dataset.renderMode || "page"),
|
|
replyBanner: document.getElementById(panelId + "-reply-banner"),
|
|
replyBannerText: document.getElementById(panelId + "-reply-text"),
|
|
replyClearBtn: document.getElementById(panelId + "-reply-clear"),
|
|
state: state,
|
|
textarea: textarea,
|
|
thread: thread,
|
|
typingNode: document.getElementById(panelId + "-typing"),
|
|
});
|
|
|
|
const sendController = sendModule.createController({
|
|
armInput: form.querySelector('input[name="failsafe_arm"]'),
|
|
autosize: autosize,
|
|
clearReplyTarget: threadController.clearReplyTarget,
|
|
confirmInput: form.querySelector('input[name="failsafe_confirm"]'),
|
|
csrfToken: String(panel.dataset.csrfToken || ""),
|
|
flashCompose: flashCompose,
|
|
form: form,
|
|
manualConfirm: form.querySelector(".manual-confirm"),
|
|
panel: panel,
|
|
panelId: panelId,
|
|
poll: threadController.poll,
|
|
queryParams: threadController.queryParams,
|
|
sendButton: form.querySelector(".compose-send-btn"),
|
|
sendCapable: String(panel.dataset.capabilitySend || "").toLowerCase() === "true",
|
|
setStatus: setStatus,
|
|
state: state,
|
|
statusBox: statusBox,
|
|
textarea: textarea,
|
|
thread: thread,
|
|
});
|
|
|
|
threadController.setBeforeContextReset(sendController.resetForContextSwitch);
|
|
autosize();
|
|
textarea.addEventListener("input", autosize);
|
|
threadController.init();
|
|
sendController.init();
|
|
};
|
|
|
|
const initAll = function (root) {
|
|
core.collectPanels(root).forEach(function (panel) {
|
|
initPanel(panel);
|
|
});
|
|
};
|
|
|
|
window.GIAComposePanel = {
|
|
destroyPanel: function (panelId) {
|
|
destroyPanelState(window.giaComposePanels[panelId]);
|
|
},
|
|
initAll: initAll,
|
|
initPanel: initPanel,
|
|
};
|
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
initAll(document);
|
|
});
|
|
if (document.body) {
|
|
document.body.addEventListener("htmx:afterSwap", function (event) {
|
|
initAll((event && event.target) || document);
|
|
});
|
|
}
|
|
initAll(document);
|
|
})();
|