Files
deepseek-harness/apps/desktop/renderer/plugin-manager.js
T

131 lines
5.0 KiB
JavaScript

const api = window.dshDesktop
async function main() {
const locale = await api.locale()
const messages = locale.messages
const message = (key, values = {}) => messages[key].replaceAll(/\{([^{}]+)\}/gu, (placeholder, name) => values[name] ?? placeholder)
document.documentElement.lang = locale.id
document.querySelector('#page-title').textContent = messages.pluginManagerTitle
document.querySelector('#title').textContent = messages.pluginManagerTitle
document.querySelector('#description').textContent = messages.pluginManagerDescription
document.querySelector('#refresh').textContent = messages.refresh
document.querySelector('#package-label').textContent = messages.npmPackage
document.querySelector('#install').textContent = messages.install
document.querySelector('#installed-heading').textContent = messages.installed
document.querySelector('#empty').textContent = messages.noPlugins
const list = document.querySelector('#plugins')
const empty = document.querySelector('#empty')
const status = document.querySelector('#status')
const form = document.querySelector('#install-form')
const input = document.querySelector('#package-spec')
const refresh = document.querySelector('#refresh')
const updateForm = document.querySelector('#update-form')
const updateVersion = document.querySelector('#update-version')
let updateName = ''
let updateTrigger
document.querySelector('#update-submit').textContent = messages.update
document.querySelector('#update-cancel').textContent = messages.cancel
function setBusy(busy, statusMessage = '') {
for (const control of document.querySelectorAll('button, input')) control.disabled = busy
status.textContent = statusMessage
}
async function render() {
const plugins = await api.plugins.list()
list.replaceChildren(...plugins.map(plugin => {
const item = document.createElement('li')
const identity = document.createElement('span')
const version = document.createElement('span')
version.className = 'package-version'
version.textContent = plugin.enabled ? plugin.version : `${plugin.version} · ${messages.disabled}`
identity.append(document.createTextNode(plugin.name), version)
const remove = document.createElement('button')
remove.type = 'button'
remove.textContent = messages.remove
remove.addEventListener('click', () => void run(
() => api.plugins.remove(plugin.name),
message('removing', { name: plugin.name }),
))
const update = document.createElement('button')
update.type = 'button'
update.textContent = messages.update
update.addEventListener('click', () => {
updateName = plugin.name
updateTrigger = update
document.querySelector('#update-label').textContent = message('targetVersion', { name: plugin.name })
updateVersion.value = plugin.version
updateForm.hidden = false
updateVersion.focus()
updateVersion.select()
})
const actions = document.createElement('span')
actions.className = 'package-actions'
const toggle = document.createElement('button')
toggle.type = 'button'
toggle.textContent = plugin.enabled ? messages.disable : messages.enable
toggle.addEventListener('click', () => void run(
() => api.plugins.toggle(plugin.name, !plugin.enabled), messages.changingActivation,
))
actions.append(toggle, update, remove)
item.append(identity, actions)
return item
}))
empty.hidden = plugins.length !== 0
}
async function run(operation, statusMessage) {
setBusy(true, statusMessage)
try {
await operation()
await render()
status.textContent = messages.operationComplete
} catch (error) {
status.textContent = error instanceof Error ? error.message : String(error)
} finally {
setBusy(false, status.textContent)
}
}
async function load(statusMessage, success) {
setBusy(true, statusMessage)
try {
await render()
status.textContent = success
} catch (error) {
status.textContent = error instanceof Error ? error.message : String(error)
} finally {
setBusy(false, status.textContent)
}
}
form.addEventListener('submit', (event) => {
event.preventDefault()
const spec = input.value.trim()
if (spec === '') return
void run(async () => {
await api.plugins.add(spec)
input.value = ''
}, message('installing', { spec }))
})
updateForm.addEventListener('submit', (event) => {
event.preventDefault()
const version = updateVersion.value.trim()
if (version === '') return
const name = updateName
updateForm.hidden = true
void run(() => api.plugins.update(name, version), message('updating', { name }))
})
document.querySelector('#update-cancel').addEventListener('click', () => {
updateForm.hidden = true
updateTrigger.focus()
})
refresh.addEventListener('click', () => void load(messages.refreshing, messages.refreshed))
await load(messages.loadingPlugins, '')
}
void main()