replace confirm

This commit is contained in:
Gamosoft 2026-04-17 09:39:52 +02:00
parent f1c35be539
commit 48695b94be
13 changed files with 122 additions and 9 deletions

View File

@ -311,6 +311,15 @@ function noteApp() {
renameFolderOldName: '',
renameFolderInput: '',
// Generic confirm dialog (replaces window.confirm)
showConfirmModal: false,
confirmModalTitle: '',
confirmModalMessage: '',
confirmModalDanger: true,
confirmModalConfirmLabel: '',
confirmModalCancelLabel: '',
_confirmModalResolve: null,
// Share state
showShareModal: false,
shareInfo: null,
@ -2689,7 +2698,10 @@ function noteApp() {
// Delete a media file (image, audio, video, PDF)
async deleteMedia(mediaPath) {
const filename = mediaPath.split('/').pop();
if (!confirm(this.t('media.confirm_delete', { name: filename }))) return;
const ok = await this.confirmModalAsk({
message: this.t('media.confirm_delete', { name: filename }),
});
if (!ok) return;
try {
const response = await fetch(`/api/notes/${encodeURIComponent(mediaPath)}`, {
@ -2777,9 +2789,15 @@ function noteApp() {
setTimeout(() => this.scrollToAnchor(anchor), 100);
}
});
} else if (confirm(this.t('notes.create_from_link', { path: notePath }))) {
// Note doesn't exist - create it (reuses createNote with duplicate check)
this.createNote(null, notePath);
} else {
this.confirmModalAsk({
message: this.t('notes.create_from_link', { path: notePath }),
danger: false,
title: this.t('sidebar.new_note'),
confirmLabel: this.t('common.create'),
}).then((ok) => {
if (ok) this.createNote(null, notePath);
});
}
},
@ -3558,6 +3576,42 @@ function noteApp() {
this.closeRenameFolderModal();
},
/**
* Theme-styled confirm dialog (replaces window.confirm).
* @param {{ message: string, title?: string, danger?: boolean, confirmLabel?: string, cancelLabel?: string }} options
* @returns {Promise<boolean>}
*/
confirmModalAsk(options = {}) {
const { message, title, danger = true, confirmLabel, cancelLabel } = options;
return new Promise((resolve) => {
this.confirmModalTitle = title || this.t('common.confirm_title');
this.confirmModalMessage = message || '';
this.confirmModalDanger = danger;
this.confirmModalConfirmLabel = confirmLabel
|| (danger ? this.t('common.delete') : this.t('common.ok'));
this.confirmModalCancelLabel = cancelLabel || this.t('common.cancel');
this._confirmModalResolve = resolve;
this.showConfirmModal = true;
this.mobileSidebarOpen = false;
});
},
confirmModalConfirm() {
this._confirmModalFinish(true);
},
confirmModalCancel() {
this._confirmModalFinish(false);
},
_confirmModalFinish(ok) {
if (!this._confirmModalResolve) return;
this.showConfirmModal = false;
const fn = this._confirmModalResolve;
this._confirmModalResolve = null;
fn(!!ok);
},
async submitRenameFolderModal() {
const folderPath = this.renameFolderPath;
const currentName = this.renameFolderOldName;
@ -3630,9 +3684,10 @@ function noteApp() {
// Delete folder
async deleteFolder(folderPath, folderName) {
const confirmation = confirm(this.t('folders.confirm_delete', { name: folderName }));
if (!confirmation) return;
const ok = await this.confirmModalAsk({
message: this.t('folders.confirm_delete', { name: folderName }),
});
if (!ok) return;
try {
const response = await fetch(`/api/folders/${encodeURIComponent(folderPath)}`, {
@ -4128,7 +4183,10 @@ function noteApp() {
// Delete any note from sidebar
async deleteNote(notePath, noteName) {
if (!confirm(this.t('notes.confirm_delete', { name: noteName }))) return;
const ok = await this.confirmModalAsk({
message: this.t('notes.confirm_delete', { name: noteName }),
});
if (!ok) return;
try {
const response = await fetch(`/api/notes/${notePath}`, {
@ -5647,7 +5705,12 @@ function noteApp() {
async revokeShareLink() {
if (!this.currentNote) return;
if (!confirm(this.t('share.confirm_revoke'))) return;
const ok = await this.confirmModalAsk({
message: this.t('share.confirm_revoke'),
danger: false,
confirmLabel: this.t('common.yes'),
});
if (!ok) return;
this.shareLoading = true;

View File

@ -3300,6 +3300,45 @@
</div>
</div>
<!-- Confirm dialog (replaces window.confirm) -->
<div x-show="showConfirmModal"
@click.self="confirmModalCancel()"
@keydown.escape.window="showConfirmModal && confirmModalCancel()"
class="fixed inset-0 flex items-center justify-center p-4"
style="background-color: rgba(0, 0, 0, 0.5); z-index: 1250;"
x-cloak>
<div class="rounded-lg shadow-xl p-6 max-w-lg w-full mx-auto max-h-[90vh] overflow-y-auto"
style="background-color: var(--bg-secondary); color: var(--text-primary);"
@click.stop
role="alertdialog"
aria-modal="true"
:aria-labelledby="'confirm-modal-title'"
:aria-describedby="'confirm-modal-desc'">
<h2 id="confirm-modal-title" class="text-xl font-bold mb-3" style="color: var(--text-primary);" x-text="confirmModalTitle"></h2>
<p id="confirm-modal-desc" class="text-sm mb-6 whitespace-pre-line leading-relaxed" style="color: var(--text-secondary);" x-text="confirmModalMessage"></p>
<div class="flex flex-col-reverse sm:flex-row gap-2 sm:justify-end">
<button
type="button"
@click="confirmModalCancel()"
class="w-full sm:w-auto px-4 py-2.5 rounded font-medium transition-colors"
style="background-color: var(--bg-tertiary); color: var(--text-primary);"
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
onmouseout="this.style.backgroundColor='var(--bg-tertiary)'"
x-text="confirmModalCancelLabel"
></button>
<button
type="button"
@click="confirmModalConfirm()"
class="w-full sm:w-auto px-4 py-2.5 rounded font-medium text-white transition-colors"
:style="confirmModalDanger ? 'background-color: var(--error);' : 'background-color: var(--accent-primary);'"
@mouseenter="$el.style.backgroundColor = confirmModalDanger ? '#dc2626' : 'var(--accent-hover)'"
@mouseleave="$el.style.backgroundColor = confirmModalDanger ? 'var(--error)' : 'var(--accent-primary)'"
x-text="confirmModalConfirmLabel"
></button>
</div>
</div>
</div>
<!-- Quick Switcher Modal (Ctrl+K) -->
<div x-show="showQuickSwitcher"
@click.self="closeQuickSwitcher()"

View File

@ -16,6 +16,7 @@
"rename": "Umbenennen",
"create": "Erstellen",
"close": "Schließen",
"confirm_title": "Bestätigen",
"yes": "✓ Ja",
"no": "✗ Nein",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Rename",
"create": "Create",
"close": "Close",
"confirm_title": "Confirm",
"yes": "✓ Yes",
"no": "✗ No",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Rename",
"create": "Create",
"close": "Close",
"confirm_title": "Confirm",
"yes": "✓ Yes",
"no": "✗ No",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Renombrar",
"create": "Crear",
"close": "Cerrar",
"confirm_title": "Confirmar",
"yes": "✓ Sí",
"no": "✗ No",
"ok": "Aceptar",

View File

@ -16,6 +16,7 @@
"rename": "Renommer",
"create": "Créer",
"close": "Fermer",
"confirm_title": "Confirmer",
"yes": "✓ Oui",
"no": "✗ Non",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Átnevez",
"create": "Létrehoz",
"close": "Bezár",
"confirm_title": "Megerősítés",
"yes": "✓ Igen",
"no": "✗ Nem",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Rinomina",
"create": "Crea",
"close": "Chiudi",
"confirm_title": "Conferma",
"yes": "✓ Sì",
"no": "✗ No",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "名前変更",
"create": "作成",
"close": "閉じる",
"confirm_title": "確認",
"yes": "✓ はい",
"no": "✗ いいえ",
"ok": "OK",

View File

@ -16,6 +16,7 @@
"rename": "Переименовать",
"create": "Создать",
"close": "Закрыть",
"confirm_title": "Подтвердить",
"yes": "✓ Да",
"no": "✗ Нет",
"ok": "ОК",

View File

@ -16,6 +16,7 @@
"rename": "Preimenuj",
"create": "Ustvari",
"close": "Zapri",
"confirm_title": "Potrdi",
"yes": "✓ Da",
"no": "✗ Ne",
"ok": "V redu",

View File

@ -16,6 +16,7 @@
"rename": "重命名",
"create": "创建",
"close": "关闭",
"confirm_title": "确认",
"yes": "✓ 是",
"no": "✗ 否",
"ok": "确定",