'use strict'
const api = window.uninstaller
let I18N = {}
function tt(key, params) {
var parts = String(key).split('.')
var cur = I18N
for (var i = 0; i < parts.length; i++) {
if (cur && typeof cur === 'object' && parts[i] in cur) {
cur = cur[parts[i]]
} else {
return key
}
}
if (typeof cur !== 'string') return key
if (!params) return cur
return cur.replace(/\{\{\s*(\w+)\s*\}\}/g, function (_m, name) {
return name in params ? String(params[name]) : '{{' + name + '}}'
})
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, function (c) {
return c === '&' ? '&' : c === '<' ? '<' : c === '>' ? '>' : c === '"' ? '"' : '''
})
}
const pageHost = document.getElementById('pageHost')
const logViewer = document.getElementById('logViewer')
const logBody = document.getElementById('logBody')
const logToggle = document.getElementById('logToggle')
logToggle.addEventListener('click', function () {
logViewer.classList.toggle('collapsed')
if (logViewer.classList.contains('collapsed')) {
logViewer.style.height = '36px'
logToggle.textContent = tt('logViewer.expand')
} else {
logViewer.style.height = ''
logToggle.textContent = tt('logViewer.collapse')
}
})
api.onLog(function (line) {
logViewer.hidden = false
logBody.textContent += line + '\n'
logBody.scrollTop = logBody.scrollHeight
})
function applyStaticI18n() {
document.title = tt('app.title')
var h1 = document.querySelector('.appHeader h1')
if (h1) h1.textContent = tt('app.title')
var logH2 = logViewer.querySelector('header h2')
if (logH2) logH2.textContent = tt('logViewer.heading')
logToggle.textContent = tt('logViewer.collapse')
}
// ── 1단계: 삭제 동의 ──────────────────────────────
function renderConfirm() {
pageHost.innerHTML =
' ' + escapeHtml(tt('confirm.question')) + ' ' + escapeHtml(tt('confirm.detail')) + ' ' +
escapeHtml(tt('confirm.loadingPreview')) + '' + escapeHtml(tt('confirm.heading')) + '
' +
'
' + escapeHtml(tt('confirm.previewTitle')) + '
' + escapeHtml(tt('confirm.nothingFound')) + '
' previewBox.innerHTML = html agreeBtn.disabled = false agreeBtn.addEventListener('click', function () { renderChoose(p) }) }).catch(function (err) { previewBox.innerHTML = '' + escapeHtml(tt('confirm.previewFail', { message: (err && err.message) || String(err) })) + '
' agreeBtn.disabled = false agreeBtn.addEventListener('click', function () { renderChoose({ existingDirs: [], allTargetDirs: [], shortcutExists: false, launcherProfiles: [] }) }) }) } // ── 2단계: 삭제 방식 선택 ───────────────────────── function renderChoose(preview) { pageHost.innerHTML = '' + escapeHtml(tt('choose.intro')) + '
' + '' + escapeHtml(tt('choose.running')) + '
' api.run(mode).then(function (result) { renderResult(result, mode) }).catch(function (err) { runState.innerHTML = '' + escapeHtml(tt('choose.error', { message: (err && err.message) || String(err) })) + '
' trashBtn.disabled = false permBtn.disabled = false backBtn.disabled = false }) } trashBtn.addEventListener('click', function () { runMode('trash') }) permBtn.addEventListener('click', function () { runMode('permanent') }) } // ── 3단계: 결과 ────────────────────────────────── function renderResult(result, mode) { var total = (result.removed ? result.removed.length : 0) + (result.profilesRemoved ? result.profilesRemoved.length : 0) var hasErr = result.errors && result.errors.length var cls = hasErr ? 'error' : 'done' var badge = hasErr ? tt('result.badgePartial') : tt('result.badgeOk') var lines = '' if (result.removed && result.removed.length) { lines += '' + escapeHtml(tt('result.removedTitle')) + '
' + escapeHtml(tt('result.profilesTitle')) + '
' + escapeHtml(tt('result.errorsTitle')) + '
' + escapeHtml(tt('result.nothing')) + '
' } pageHost.innerHTML = '' + escapeHtml(tt('result.note')) + '
' + '