mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-30 04:35:13 +08:00
update 2026-09-20 23:17:18
This commit is contained in:
1 parent
735d247cbe
commit
d657bc36f5
23 files changed
+2655
-667
No files matched your search
@@ -620,6 +620,17 @@ function createConfigEditor(mode) {
|
||||
};
|
||||
}
|
||||
|
||||
// 全局锁:内核操作互斥(切换配置 / 更新订阅 / 删除)
|
||||
function clKernelBusy() { return !!document.body.getAttribute('data-cl-kernel-busy'); }
|
||||
function clKernelLock() {
|
||||
document.body.setAttribute('data-cl-kernel-busy', '1');
|
||||
document.querySelectorAll('.cl-btn-switch, .cl-btn-update-sub, .cl-btn-delete').forEach(function (b) { b.disabled = true; });
|
||||
}
|
||||
function clKernelUnlock() {
|
||||
document.body.removeAttribute('data-cl-kernel-busy');
|
||||
document.querySelectorAll('.cl-btn-switch, .cl-btn-update-sub, .cl-btn-delete').forEach(function (b) { b.disabled = false; });
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
_tab: null,
|
||||
_sbTab: null,
|
||||
@@ -841,17 +852,37 @@ return view.extend({
|
||||
E('div', { 'class': 'cl-file-actions' }, [
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cl-btn-sm cl-btn-update-sub',
|
||||
click: function () {
|
||||
click: function (ev) {
|
||||
var btn = ev.target;
|
||||
if (btn.disabled || clKernelBusy()) return;
|
||||
clKernelLock();
|
||||
btn.disabled = true;
|
||||
btn.textContent = _("Updating…");
|
||||
L.resolveDefault(callUpdateSub(sub.name), {}).then(function (r) {
|
||||
ui.addNotification(null, E('p', r.success ? sub.name + _(" update succeeded") : _("Update failed")));
|
||||
location.reload();
|
||||
}).catch(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = _("Update");
|
||||
clKernelUnlock();
|
||||
});
|
||||
}
|
||||
}, _("Update")),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cl-btn-sm cl-btn-switch',
|
||||
click: function () {
|
||||
L.resolveDefault(callSetConfig(sub.name), {}).then(function () { location.reload(); });
|
||||
click: function (ev) {
|
||||
var btn = ev.target;
|
||||
if (btn.disabled || clKernelBusy()) return;
|
||||
clKernelLock();
|
||||
btn.disabled = true;
|
||||
btn.textContent = _("Loading…");
|
||||
L.resolveDefault(callSetConfig(sub.name), {}).then(function () {
|
||||
location.reload();
|
||||
}).catch(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = _("Switch Profile");
|
||||
clKernelUnlock();
|
||||
});
|
||||
}
|
||||
}, _("Switch Profile")),
|
||||
E('button', {
|
||||
@@ -1022,19 +1053,54 @@ return view.extend({
|
||||
E('div', { 'class': 'cl-file-actions' }, [
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cl-btn-sm cl-btn-edit',
|
||||
click: function () { loadOtherEditor(f.name, type); }
|
||||
click: function (ev) {
|
||||
var btn = ev.target;
|
||||
if (btn.disabled) return;
|
||||
btn.disabled = true;
|
||||
var orig = btn.textContent;
|
||||
btn.textContent = _("Loading…");
|
||||
Promise.resolve(loadOtherEditor(f.name, type)).then(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = orig;
|
||||
}).catch(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = orig;
|
||||
});
|
||||
}
|
||||
}, _("Edit")),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cl-btn-sm cl-btn-switch',
|
||||
click: function () {
|
||||
L.resolveDefault(callSetConfig(f.name), {}).then(function () { location.reload(); });
|
||||
click: function (ev) {
|
||||
var btn = ev.target;
|
||||
if (btn.disabled || clKernelBusy()) return;
|
||||
clKernelLock();
|
||||
btn.disabled = true;
|
||||
btn.textContent = _("Loading…");
|
||||
L.resolveDefault(callSetConfig(f.name), {}).then(function () {
|
||||
location.reload();
|
||||
}).catch(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = _("Switch Profile");
|
||||
clKernelUnlock();
|
||||
});
|
||||
}
|
||||
}, _("Switch Profile")),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cl-btn-sm cl-btn-delete',
|
||||
click: function () {
|
||||
click: function (ev) {
|
||||
var btn = ev.target;
|
||||
if (btn.disabled || clKernelBusy()) return;
|
||||
if (!confirm(_("Delete ") + f.name + '?')) return;
|
||||
L.resolveDefault(callDeleteCfg(f.name, type), {}).then(function () { location.reload(); });
|
||||
clKernelLock();
|
||||
btn.disabled = true;
|
||||
btn.textContent = _("Loading…");
|
||||
L.resolveDefault(callDeleteCfg(f.name, type), {}).then(function () {
|
||||
location.reload();
|
||||
}).catch(function () {
|
||||
btn.disabled = false;
|
||||
btn.textContent = _("Delete");
|
||||
clKernelUnlock();
|
||||
});
|
||||
}
|
||||
}, _("Delete"))
|
||||
])
|
||||
|
||||
@@ -231,6 +231,17 @@ var MSGS = {
|
||||
}
|
||||
};
|
||||
|
||||
// 全局锁:内核操作互斥(切换配置 / 更新订阅 / 删除)
|
||||
function clKernelBusy() { return !!document.body.getAttribute('data-cl-kernel-busy'); }
|
||||
function clKernelLock() {
|
||||
document.body.setAttribute('data-cl-kernel-busy', '1');
|
||||
document.querySelectorAll('.cl-btn-switch, .cl-btn-update-sub, .cl-btn-delete, .cl-kernel-sel').forEach(function (b) { b.disabled = true; });
|
||||
}
|
||||
function clKernelUnlock() {
|
||||
document.body.removeAttribute('data-cl-kernel-busy');
|
||||
document.querySelectorAll('.cl-btn-switch, .cl-btn-update-sub, .cl-btn-delete, .cl-kernel-sel').forEach(function (b) { b.disabled = false; });
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
_busy: false,
|
||||
_op: null, /* 'start' | 'stop' | 'restart' | null */
|
||||
@@ -1561,8 +1572,8 @@ return view.extend({
|
||||
var panelUrl = this._dashboardUrl(st);
|
||||
var panels = ['metacubexd', 'yacd', 'zashboard', 'razord'];
|
||||
|
||||
var mkSel = function (opts, val, fn) {
|
||||
return E('select', { 'class': 'cbi-input-select', change: fn },
|
||||
var mkSel = function (opts, val, fn, extraCls) {
|
||||
return E('select', { 'class': 'cbi-input-select' + (extraCls ? ' ' + extraCls : ''), change: fn },
|
||||
opts.map(function (o) {
|
||||
return E('option', { value: o[0], selected: o[0] === val ? '' : null, disabled: o[2] ? '' : null }, o[1]);
|
||||
}));
|
||||
@@ -1598,7 +1609,18 @@ return view.extend({
|
||||
E('div', { 'class': 'cl-ctrl' }, [
|
||||
E('label', {}, _("Proxy Mode")),
|
||||
mkSel([['rule',_("Rule")],['global',_("Global")],['direct',_("Direct")]], proxyMode,
|
||||
function (ev) { clashoo.setProxyMode(ev.target.value); })
|
||||
function (ev) {
|
||||
var sel = ev.target;
|
||||
if (sel.disabled || clKernelBusy()) return;
|
||||
clKernelLock();
|
||||
sel.disabled = true;
|
||||
Promise.resolve(clashoo.setProxyMode(sel.value)).then(function () {
|
||||
return self._pollOverview(true);
|
||||
}).catch(function () {}).then(function () {
|
||||
sel.disabled = false;
|
||||
clKernelUnlock();
|
||||
});
|
||||
}, 'cl-kernel-sel')
|
||||
]),
|
||||
E('div', { 'class': 'cl-ctrl' }, [
|
||||
E('label', {}, _("Run Mode")),
|
||||
@@ -1607,7 +1629,10 @@ return view.extend({
|
||||
var mode = ev.target.value;
|
||||
if (mode === 'custom')
|
||||
return;
|
||||
ev.target.disabled = true;
|
||||
var sel = ev.target;
|
||||
if (sel.disabled || clKernelBusy()) return;
|
||||
clKernelLock();
|
||||
sel.disabled = true;
|
||||
self._op = 'mode';
|
||||
self._lastSt = self._lastSt || {};
|
||||
if (mode === 'tun-mixed') {
|
||||
@@ -1634,9 +1659,10 @@ return view.extend({
|
||||
ui.addNotification(null, E('p', _("Run mode setting failed: ") + (e.message || e)));
|
||||
}).then(function () {
|
||||
self._op = null;
|
||||
ev.target.disabled = false;
|
||||
sel.disabled = false;
|
||||
clKernelUnlock();
|
||||
});
|
||||
})
|
||||
}, 'cl-kernel-sel')
|
||||
]),
|
||||
E('div', { 'class': 'cl-ctrl' }, [
|
||||
E('label', {}, _("Configuration Files")),
|
||||
@@ -1644,8 +1670,10 @@ return view.extend({
|
||||
mkSel(configs.length ? configs.map(function(c){return[c,c];}) : [['',_("(empty)")]], current,
|
||||
function (ev) {
|
||||
var sel = ev.target;
|
||||
if (sel.disabled || clKernelBusy()) return;
|
||||
var name = sel.value;
|
||||
var prev = sel.getAttribute('data-cl-prev') || current;
|
||||
clKernelLock();
|
||||
sel.disabled = true;
|
||||
var setter = (st.core_type === 'singbox')
|
||||
? clashoo.setSingboxProfile(name)
|
||||
@@ -1665,13 +1693,14 @@ return view.extend({
|
||||
})
|
||||
.then(function () {
|
||||
sel.disabled = false;
|
||||
clKernelUnlock();
|
||||
/* force immediate state refresh so cards get new current */
|
||||
return self._pollOverview(true);
|
||||
});
|
||||
}),
|
||||
}, 'cl-kernel-sel'),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button-action cl-btn-update-sub',
|
||||
click: L.bind(this._updSubs, this)
|
||||
click: L.bind(function (ev) { this._updSubs(ev); }, this)
|
||||
}, _("Update Subscription"))
|
||||
])
|
||||
]),
|
||||
@@ -1971,7 +2000,13 @@ return view.extend({
|
||||
_stop: function () { return this._svc(function () { return clashoo.stop(); }, 'stop'); },
|
||||
_restart: function () { return this._svc(function () { return clashoo.restart(); }, 'restart'); },
|
||||
|
||||
_updSubs: function () {
|
||||
_updSubs: function (ev) {
|
||||
var btn = ev && ev.target;
|
||||
if (btn && btn.disabled) return Promise.resolve();
|
||||
if (clKernelBusy()) return Promise.resolve();
|
||||
clKernelLock();
|
||||
var origText = btn ? btn.textContent : '';
|
||||
if (btn) { btn.disabled = true; btn.textContent = _("Updating…"); }
|
||||
return L.resolveDefault(callUpdateCurrentSubscription(), {}).then(function (r) {
|
||||
if (r && r.reason === 'not_subscription') {
|
||||
ui.addNotification(null, E('p', _("Current configuration is a custom file; no subscription update needed")), 'info');
|
||||
@@ -1979,6 +2014,9 @@ return view.extend({
|
||||
}
|
||||
ui.addNotification(null, E('p', r.success ? (r.message || _("Subscription updated successfully"))
|
||||
: (_("Update failed: ") + (r.message || _("Current configuration has no recorded subscription URL")))));
|
||||
}).catch(function () {}).then(function () {
|
||||
if (btn) { btn.disabled = false; btn.textContent = origText; }
|
||||
clKernelUnlock();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in new issue
Block a user