mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-15 04:32:52 +08:00
update 2026-10-24 23:15:37
This commit is contained in:
1 parent
6d61e8bf50
commit
852fced2b3
178 files changed
+381
-38050
No files matched your search
@@ -128,6 +128,15 @@ return view.extend({
|
||||
'type': webUi ? null : 'button',
|
||||
'disabled': webUi ? null : true
|
||||
}, _('Open Doona'));
|
||||
const clashUi = honk.localClashUi(status);
|
||||
const openClash = E(clashUi ? 'a' : 'button', {
|
||||
'class': 'cbi-button cbi-button-action',
|
||||
'href': clashUi || null,
|
||||
'target': clashUi ? '_blank' : null,
|
||||
'rel': clashUi ? 'noopener noreferrer' : null,
|
||||
'type': clashUi ? null : 'button',
|
||||
'disabled': clashUi ? null : true
|
||||
}, _('Open Clash panel'));
|
||||
|
||||
const toggle = E('button', {
|
||||
'class': 'cbi-button cbi-button-action',
|
||||
@@ -140,7 +149,7 @@ return view.extend({
|
||||
runAction(running ? 'stop' : 'start');
|
||||
});
|
||||
|
||||
const actions = [ openDoona, toggle ];
|
||||
const actions = [ openDoona, openClash, toggle ];
|
||||
if (running) {
|
||||
const restart = E('button', { 'class': 'cbi-button', 'type': 'button', 'data-action': 'restart' }, _('Restart'));
|
||||
restart.disabled = busy;
|
||||
@@ -162,7 +171,8 @@ return view.extend({
|
||||
E('div', { 'class': 'honk-meta' }, [
|
||||
metaItem(_('Core version'), status.core_version),
|
||||
metaItem(_('Doona version'), status.doona_version),
|
||||
metaItem(_('Kernel'), status.kernel)
|
||||
metaItem(_('Kernel'), status.kernel),
|
||||
metaItem(_('Clash API'), status.clash_api_enabled ? status.clash_api_url : _('Off'))
|
||||
])
|
||||
]);
|
||||
|
||||
@@ -171,6 +181,8 @@ return view.extend({
|
||||
!running ? _('Start Honk to open Doona.') : _('Doona is not ready yet. Check the service status.');
|
||||
statusCard.appendChild(E('p', { 'class': 'honk-note', 'role': 'status' }, reason));
|
||||
}
|
||||
if (status.clash_api_enabled && running && !clashUi)
|
||||
statusCard.appendChild(E('p', { 'class': 'honk-note', 'role': 'status' }, status.clash_api_ready ? _('Zashboard is still downloading or unavailable.') : _('The Clash API listener is unavailable. Check the service logs.')));
|
||||
|
||||
const errors = (Array.isArray(status.errors) ? status.errors : []).filter(function(token) {
|
||||
return token !== 'disabled' && token !== 'not_initialized' && token !== 'service_not_running';
|
||||
@@ -197,6 +209,9 @@ return view.extend({
|
||||
const networkSelect = E('select', { 'class': 'cbi-input-select', 'name': 'lan_network', 'id': 'honk-lan-network' });
|
||||
const portInput = E('input', { 'class': 'cbi-input-text', 'type': 'number', 'name': 'listen_port', 'id': 'honk-listen-port', 'min': '1024', 'max': '65535', 'step': '1' });
|
||||
const bootEnabledInput = E('input', { 'type': 'checkbox', 'name': 'boot_enabled', 'id': 'honk-boot-enabled' });
|
||||
const clashEnabledInput = E('input', { 'type': 'checkbox', 'name': 'clash_api_enabled', 'id': 'honk-clash-enabled' });
|
||||
const clashPortInput = E('input', { 'class': 'cbi-input-text', 'type': 'number', 'name': 'clash_api_port', 'id': 'honk-clash-port', 'min': '1024', 'max': '65535', 'step': '1' });
|
||||
const clashSecretInput = E('input', { 'class': 'cbi-input-password', 'type': 'password', 'name': 'clash_api_secret', 'id': 'honk-clash-secret', 'autocomplete': 'new-password' });
|
||||
const message = E('p', { 'class': 'honk-status-msg', 'role': 'status' }, '');
|
||||
const save = E('button', { 'class': 'cbi-button cbi-button-positive', 'type': 'submit' }, _('Save service settings'));
|
||||
|
||||
@@ -209,6 +224,8 @@ return view.extend({
|
||||
networkSelect.value = status.lan_network;
|
||||
portInput.value = status.listen_port ? String(status.listen_port) : '9527';
|
||||
bootEnabledInput.checked = status.boot_enabled === true;
|
||||
clashEnabledInput.checked = status.clash_api_enabled === true;
|
||||
clashPortInput.value = status.clash_api_port ? String(status.clash_api_port) : '9090';
|
||||
|
||||
card.appendChild(E('h3', { 'class': 'honk-card-title' }, _('Service settings')));
|
||||
if (!(data.networks || []).length)
|
||||
@@ -216,20 +233,33 @@ return view.extend({
|
||||
form.appendChild(field(_('LAN network'), networkSelect));
|
||||
form.appendChild(field(_('Listen port'), portInput));
|
||||
form.appendChild(field(_('Start Honk at boot'), bootEnabledInput));
|
||||
form.appendChild(field(_('Enable Clash API and Zashboard'), clashEnabledInput));
|
||||
form.appendChild(field(_('Clash API port'), clashPortInput));
|
||||
form.appendChild(field(_('Clash API secret'), clashSecretInput, status.clash_api_secret_set ? _('A secret is set. Leave blank to keep it.') : _('Required when enabling. Use 16–128 letters, numbers, underscores or hyphens.')));
|
||||
form.appendChild(E('p', { 'class': 'honk-note' }, _('Use your existing HTTPS reverse proxy for external access. Enter the secret in Zashboard when connecting.')));
|
||||
form.appendChild(E('div', { 'class': 'cbi-page-actions' }, save));
|
||||
form.appendChild(message);
|
||||
form.addEventListener('submit', function(ev) {
|
||||
ev.preventDefault();
|
||||
const port = Number(portInput.value);
|
||||
const clashPort = Number(clashPortInput.value);
|
||||
const clashSecret = clashSecretInput.value;
|
||||
if (!networkSelect.value || !Number.isInteger(port) || port < 1024 || port > 65535) {
|
||||
message.textContent = _('Choose a LAN network and a port from 1024 to 65535.');
|
||||
return;
|
||||
}
|
||||
if (!Number.isInteger(clashPort) || clashPort < 1024 || clashPort > 65535 ||
|
||||
clashEnabledInput.checked && (clashPort === port || !status.clash_api_secret_set && !clashSecret ||
|
||||
!!clashSecret && !/^[A-Za-z0-9_-]{16,128}$/.test(clashSecret))) {
|
||||
message.textContent = _('Choose a different Clash API port and enter a valid secret.');
|
||||
return;
|
||||
}
|
||||
|
||||
save.disabled = true;
|
||||
settingsBusy = true;
|
||||
message.textContent = _('Saving…');
|
||||
honk.settings(networkSelect.value, port, bootEnabledInput.checked).then(honk.ensureOk).then(function(result) {
|
||||
honk.settings(networkSelect.value, port, bootEnabledInput.checked, clashEnabledInput.checked, clashPort, clashSecret).then(honk.ensureOk).then(function(result) {
|
||||
clashSecretInput.value = '';
|
||||
message.textContent = honk.resultMessage(result, _('Service settings saved.'));
|
||||
}).catch(function(error) {
|
||||
message.textContent = honk.errorMessage(error, _('Settings could not be applied.'));
|
||||
|
||||
@@ -30,7 +30,7 @@ const callRestart = rpc.declare({ object: 'honk', method: 'restart', expect: { '
|
||||
const callSettings = rpc.declare({
|
||||
object: 'honk',
|
||||
method: 'settings',
|
||||
params: [ 'lan_network', 'listen_port', 'boot_enabled' ],
|
||||
params: [ 'lan_network', 'listen_port', 'boot_enabled', 'clash_api_enabled', 'clash_api_port', 'clash_api_secret' ],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
@@ -122,6 +122,12 @@ function localWebUi(status) {
|
||||
}
|
||||
}
|
||||
|
||||
function localClashUi(status) {
|
||||
if (!status || !status.clash_api_enabled || !status.clash_api_ready || !status.clash_ui_ready)
|
||||
return null;
|
||||
return localWebUi(Object.assign({}, status, { api_url: status.clash_api_url, api_ready: true }));
|
||||
}
|
||||
|
||||
function tokenMessage(token) {
|
||||
const messages = {
|
||||
disabled: _('Honk is disabled.'),
|
||||
@@ -198,6 +204,8 @@ function tokenMessage(token) {
|
||||
invalid_lan_network: _('The selected LAN network is invalid or unavailable.'),
|
||||
lan_network_unavailable: _('The selected LAN network is unavailable.'),
|
||||
listen_port_occupied: _('The listen port is already in use.'),
|
||||
clash_api_port_occupied: _('The Clash API port is already in use.'),
|
||||
invalid_clash_api_settings: _('Enter a different Clash API port and a secret of 16–128 letters, numbers, underscores or hyphens.'),
|
||||
invalid_listen_port: _('The listen port is invalid.'),
|
||||
initialize_before_enabling_service: _('Complete initial setup before enabling Honk.'),
|
||||
system_config_unavailable: _('Honk system configuration is unavailable.'),
|
||||
@@ -304,6 +312,7 @@ return baseclass.extend({
|
||||
waitJob: waitJob,
|
||||
ensureOk: ensureOk,
|
||||
localWebUi: localWebUi,
|
||||
localClashUi: localClashUi,
|
||||
statusIssue: statusIssue,
|
||||
resultMessage: resultMessage,
|
||||
errorMessage: errorMessage,
|
||||
|
||||
@@ -49,8 +49,12 @@ return view.extend({
|
||||
const networkSelect = E('select', { 'class': 'cbi-input-select', 'name': 'lan_network', 'id': 'honk-lan-network' });
|
||||
const portInput = E('input', { 'class': 'cbi-input-text', 'type': 'number', 'name': 'listen_port', 'id': 'honk-listen-port', 'min': '1024', 'max': '65535', 'step': '1' });
|
||||
const bootEnabledInput = E('input', { 'type': 'checkbox', 'name': 'boot_enabled', 'id': 'honk-boot-enabled' });
|
||||
const clashEnabledInput = E('input', { 'type': 'checkbox', 'name': 'clash_api_enabled', 'id': 'honk-clash-enabled' });
|
||||
const clashPortInput = E('input', { 'class': 'cbi-input-text', 'type': 'number', 'name': 'clash_api_port', 'id': 'honk-clash-port', 'min': '1024', 'max': '65535', 'step': '1' });
|
||||
const clashSecretInput = E('input', { 'class': 'cbi-input-password', 'type': 'password', 'name': 'clash_api_secret', 'id': 'honk-clash-secret', 'autocomplete': 'new-password' });
|
||||
const message = E('p', { 'class': 'honk-status-msg', 'role': 'status' }, '');
|
||||
const save = E('button', { 'class': 'cbi-button cbi-button-positive', 'type': 'submit' }, _('Save settings'));
|
||||
save.disabled = !!data.statusError;
|
||||
|
||||
(data.networks || []).forEach(function(name) {
|
||||
networkSelect.appendChild(E('option', { 'value': name }, name));
|
||||
@@ -61,6 +65,8 @@ return view.extend({
|
||||
networkSelect.value = data.status.lan_network;
|
||||
portInput.value = data.status && data.status.listen_port ? String(data.status.listen_port) : '9527';
|
||||
bootEnabledInput.checked = !!(data.status && data.status.boot_enabled === true);
|
||||
clashEnabledInput.checked = !!(data.status && data.status.clash_api_enabled === true);
|
||||
clashPortInput.value = data.status && data.status.clash_api_port ? String(data.status.clash_api_port) : '9090';
|
||||
|
||||
section.appendChild(E('h3', { 'class': 'honk-card-title' }, _('Honk settings')));
|
||||
if (data.statusError)
|
||||
@@ -72,19 +78,32 @@ return view.extend({
|
||||
section.appendChild(field(_('LAN network'), networkSelect));
|
||||
section.appendChild(field(_('Listen port'), portInput));
|
||||
section.appendChild(field(_('Start Honk at boot'), bootEnabledInput));
|
||||
section.appendChild(field(_('Enable Clash API and Zashboard'), clashEnabledInput));
|
||||
section.appendChild(field(_('Clash API port'), clashPortInput));
|
||||
section.appendChild(field(_('Clash API secret'), clashSecretInput));
|
||||
section.appendChild(E('p', { 'class': 'honk-note' }, data.status && data.status.clash_api_secret_set ? _('A secret is set. Leave blank to keep it. Use your existing HTTPS reverse proxy for external access.') : _('A secret is required when enabling Clash API. Use 16–128 letters, numbers, underscores or hyphens.')));
|
||||
section.appendChild(E('div', { 'class': 'cbi-page-actions' }, save));
|
||||
section.appendChild(message);
|
||||
section.addEventListener('submit', function(ev) {
|
||||
ev.preventDefault();
|
||||
const port = Number(portInput.value);
|
||||
const clashPort = Number(clashPortInput.value);
|
||||
const clashSecret = clashSecretInput.value;
|
||||
if (!networkSelect.value || !Number.isInteger(port) || port < 1024 || port > 65535) {
|
||||
message.textContent = _('Choose a LAN network and a port from 1024 to 65535.');
|
||||
return;
|
||||
}
|
||||
if (!Number.isInteger(clashPort) || clashPort < 1024 || clashPort > 65535 ||
|
||||
clashEnabledInput.checked && (clashPort === port || !(data.status && data.status.clash_api_secret_set) && !clashSecret ||
|
||||
!!clashSecret && !/^[A-Za-z0-9_-]{16,128}$/.test(clashSecret))) {
|
||||
message.textContent = _('Choose a different Clash API port and enter a valid secret.');
|
||||
return;
|
||||
}
|
||||
|
||||
save.disabled = true;
|
||||
message.textContent = _('Saving…');
|
||||
honk.settings(networkSelect.value, port, bootEnabledInput.checked).then(honk.ensureOk).then(function(result) {
|
||||
honk.settings(networkSelect.value, port, bootEnabledInput.checked, clashEnabledInput.checked, clashPort, clashSecret).then(honk.ensureOk).then(function(result) {
|
||||
clashSecretInput.value = '';
|
||||
message.textContent = honk.resultMessage(result, _('Settings saved and applied.'));
|
||||
}).catch(function(error) {
|
||||
message.textContent = honk.errorMessage(error, _('Save failed. Check the settings and system status.'));
|
||||
|
||||
Reference in new issue
Block a user