mirror of
				https://github.com/kenzok8/openwrt-packages.git
				synced 2025-10-30 07:50:37 +08:00 
			
		
		
		
	update 2025-10-25 02:25:22
This commit is contained in:
		| @ -7,8 +7,8 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
|  | ||||
| PKG_NAME:=luci-app-ddns-go | ||||
| PKG_VERSION:=1.5.4 | ||||
| PKG_RELEASE:=20250601 | ||||
| PKG_VERSION:=1.6.2 | ||||
| PKG_RELEASE:=20251024 | ||||
|  | ||||
| PKG_MAINTAINER:=sirpdboy  <herboy2008@gmail.com> | ||||
| PKG_CONFIG_DEPENDS:= | ||||
| @ -17,11 +17,6 @@ LUCI_TITLE:=LuCI Support for Dynamic ddns-go Client | ||||
| LUCI_DEPENDS:=+ddns-go | ||||
| LUCI_PKGARCH:=all | ||||
|  | ||||
| define Package/$(PKG_NAME)/conffiles | ||||
| /etc/config/ddns-go | ||||
| /etc/ddns-go/ddns-go-config.yaml | ||||
| endef | ||||
|  | ||||
| include $(TOPDIR)/feeds/luci/luci.mk | ||||
|  | ||||
| # call BuildPackage - OpenWrt buildroot signature | ||||
|  | ||||
| @ -6,9 +6,21 @@ | ||||
| 'require uci'; | ||||
| 'require form'; | ||||
| 'require poll'; | ||||
| 'require rpc'; | ||||
|  | ||||
| const getDDNSGoInfo = rpc.declare({ | ||||
|     object: 'luci.ddns-go', | ||||
|     method: 'get_ver', | ||||
|     expect: { 'ver': {} } | ||||
| }); | ||||
|  | ||||
|  async function checkProcess() { | ||||
| const getUpdateInfo = rpc.declare({ | ||||
|     object: 'luci.ddns-go', | ||||
|     method: 'last_update', | ||||
|     expect: { 'update': {} } | ||||
| }); | ||||
|  | ||||
| async function checkProcess() { | ||||
|     // 先尝试用 pidof | ||||
|     try { | ||||
|         const pidofRes = await fs.exec('/bin/pidof', ['ddns-go']); | ||||
| @ -21,8 +33,6 @@ | ||||
|     } catch (err) { | ||||
|         // pidof 失败,继续尝试 ps | ||||
|     } | ||||
|  | ||||
|     // 回退到 ps | ||||
|     try { | ||||
|         const psRes = await fs.exec('/bin/ps', ['-C', 'ddns-go', '-o', 'pid=']); | ||||
|         const pid = psRes.stdout.trim(); | ||||
| @ -33,29 +43,70 @@ | ||||
|     } catch (err) { | ||||
|         return { running: false, pid: null }; | ||||
|     } | ||||
|    } | ||||
| function renderStatus(isRunning, listen_port, noweb) { | ||||
| } | ||||
|  | ||||
| function getVersionInfo() { | ||||
|     return L.resolveDefault(getDDNSGoInfo(), {}).then(function(result) { | ||||
|         //console.log('getVersionInfo result:', result); | ||||
|         return result || {}; | ||||
|     }).catch(function(error) { | ||||
|         console.error('Failed to get version:', error); | ||||
|         return {}; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function checkUpdateStatus() { | ||||
|     return L.resolveDefault(getUpdateInfo(), {}).then(function(result) { | ||||
|         //console.log('checkUpdateStatus result:', result); | ||||
|         return result || {}; | ||||
|     }).catch(function(error) { | ||||
|         console.error('Failed to get update info:', error); | ||||
|         return {}; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function renderStatus(isRunning, listen_port, noweb, version) { | ||||
|     var statusText = isRunning ? _('RUNNING') : _('NOT RUNNING'); | ||||
|     var color = isRunning ? 'green' : 'red'; | ||||
|     var icon = isRunning ? '✓' : '✗'; | ||||
|     var versionText = version ? `v${version}` : ''; | ||||
|      | ||||
|     var html = String.format( | ||||
|         '<em><span style="color:%s">%s <strong>%s %s</strong></span></em>', | ||||
|         color, icon, _('DDNS-Go'), statusText | ||||
|         '<em><span style="color:%s">%s <strong>%s %s - %s</strong></span></em>', | ||||
|         color, icon, _('DDNS-Go'), versionText, statusText | ||||
|     ); | ||||
|      | ||||
|     if (isRunning && res.pid) { | ||||
|         html += ' <small>(PID: ' + res.pid + ')</small>'; | ||||
|     if (isRunning) { | ||||
|         html += String.format(' <a class="btn cbi-button" href="%s//%s:%s" target="_blank">%s</a>',  | ||||
|             window.location.protocol, window.location.hostname, listen_port, _('Open Web Interface')); | ||||
|     } | ||||
|      | ||||
|     if (isRunning && noweb !== '1') { | ||||
|         const baseUrl = `${window.location.protocol}//${window.location.hostname}`; | ||||
|         const fullUrl = `${baseUrl}:${listen_port}`; | ||||
|         html += String.format(' <a class="btn cbi-button" href="%s" target="_blank">%s</a>', fullUrl, _('Open Web Interface')); | ||||
|      } | ||||
|      | ||||
|     return html; | ||||
| } | ||||
|  | ||||
| function renderUpdateStatus(updateInfo) { | ||||
|     if (!updateInfo || !updateInfo.status) { | ||||
|         return '<span style="color:orange"> ⚠ ' + _('Update status unknown') + '</span>'; | ||||
|     } | ||||
|      | ||||
|     var status = updateInfo.status; | ||||
|     var message = updateInfo.message || ''; | ||||
|      | ||||
|     switch(status) { | ||||
|         case 'updated': | ||||
|             return String.format('<span style="color:green">✓ %s</span>', message); | ||||
|         case 'update_available': | ||||
|             return String.format('<span style="color:blue">↻ %s</span>', message); | ||||
|         case 'latest': | ||||
|             return String.format('<span style="color:green">✓ %s</span>', message); | ||||
|         case 'download_failed': | ||||
|         case 'check_failed': | ||||
|             return String.format('<span style="color:red">✗ %s</span>', message); | ||||
|         default: | ||||
|             return String.format('<span style="color:orange">? %s</span>', message); | ||||
|     } | ||||
| } | ||||
|  | ||||
| return view.extend({ | ||||
|     load: function() { | ||||
|         return Promise.all([ | ||||
| @ -63,6 +114,118 @@ return view.extend({ | ||||
|         ]); | ||||
|     }, | ||||
|  | ||||
|     handleResetPassword: async function () { | ||||
|     try { | ||||
|         ui.showModal(_('Resetting Password'), [ | ||||
|             E('p', { 'class': 'spinning' }, _('Resetting admin password, please wait...')) | ||||
|         ]); | ||||
|  | ||||
|         const result = await fs.exec('/usr/bin/ddns-go', ['-resetPassword', 'admin12345', '-c', '/etc/ddns-go/ddns-go-config.yaml']); | ||||
|  | ||||
|         ui.hideModal(); | ||||
|  | ||||
|         const output = (result.stdout + result.stderr).trim(); | ||||
|  | ||||
|         let success = false; | ||||
|         let message = ''; | ||||
|  | ||||
|         if (result.code === 0) { | ||||
|              | ||||
|  | ||||
|                 message = _('Password reset successfully to admin12345'); | ||||
|  | ||||
|             ui.showModal(_('Password Reset Successful'), [ | ||||
|                 E('p', _('Admin password has been reset to: admin12345')), | ||||
|                 E('p', _('You need to restart DDNS-Go service for the changes to take effect.')), | ||||
|                 E('div', { 'class': 'right' }, [ | ||||
|                     E('button', { | ||||
|                         'class': 'btn cbi-button cbi-button-positive', | ||||
|                         'click': ui.createHandlerFn(this, function() { | ||||
|                             ui.hideModal(); | ||||
|                             this.handleRestartService(); | ||||
|                         }) | ||||
|                     }, _('Restart Service Now')), | ||||
|                     ' ', | ||||
|                     E('button', { | ||||
|                         'class': 'btn cbi-button cbi-button-neutral', | ||||
|                         'click': ui.hideModal | ||||
|                     }, _('Restart Later')) | ||||
|                 ]) | ||||
|             ]); | ||||
|         } else { | ||||
|             alert(_('Reset may have failed:') + '\n' + output); | ||||
|         } | ||||
|          | ||||
|     } catch (error) { | ||||
|         ui.hideModal(); | ||||
|         console.error('Reset password failed:', error); | ||||
|         alert(_('ERROR:') + '\n' + _('Reset password failed:') + '\n' + error.message); | ||||
|     } | ||||
|     }, | ||||
|   | ||||
|     handleRestartService: async function() { | ||||
|     try { | ||||
|         await fs.exec('/etc/init.d/ddns-go', ['stop']); | ||||
|         await new Promise(resolve => setTimeout(resolve, 1000)); | ||||
|         await fs.exec('/etc/init.d/ddns-go', ['start']); | ||||
|          | ||||
|         alert(_('SUCCESS:') + '\n' + _('DDNS-Go service restarted successfully')); | ||||
|         if (window.statusPoll) { | ||||
|             window.statusPoll(); | ||||
|         } | ||||
|     } catch (error) { | ||||
|         alert(_('ERROR:') + '\n' + _('Failed to restart service:') + '\n' + error.message); | ||||
|     } | ||||
|     }, | ||||
|  | ||||
|      | ||||
|     handleUpdate: async function () { | ||||
|         try { | ||||
|             var updateView = document.getElementById('update_status'); | ||||
|             if (updateView) { | ||||
|                 updateView.innerHTML = '<span class="spinning"></span> ' + _('Updating, please wait...'); | ||||
|             } | ||||
|             const updateInfo = await checkUpdateStatus(); | ||||
|             if (updateView) { | ||||
|                 updateView.innerHTML = renderUpdateStatus(updateInfo); | ||||
|             } | ||||
|  | ||||
|             if (updateInfo.update_successful || updateInfo.status === 'updated') { | ||||
|                 if (window.statusPoll) { | ||||
|                     window.statusPoll(); | ||||
|                 } | ||||
|                  | ||||
|                 // 3秒后恢复显示版本信息 | ||||
|                 setTimeout(() => { | ||||
|                     var updateView = document.getElementById('update_status'); | ||||
|                     if (updateView) { | ||||
|                         getVersionInfo().then(function(versionInfo) { | ||||
|                             var version = versionInfo.version || ''; | ||||
|                             updateView.innerHTML = String.format('<span style="color:green">✓ %s v%s</span>',  | ||||
|                                 _('Current Version:'), version); | ||||
|                         }); | ||||
|                     } | ||||
|                 }, 3000); | ||||
|             } | ||||
|  | ||||
|         } catch (error) { | ||||
|             console.error('Update failed:', error); | ||||
|             var updateView = document.getElementById('update_status'); | ||||
|             if (updateView) { | ||||
|                 updateView.innerHTML = '<span style="color:red">✗ ' + _('Update failed') + '</span>'; | ||||
|  | ||||
|                 // 5秒后恢复显示版本信息 | ||||
|                 setTimeout(() => { | ||||
|                     getVersionInfo().then(function(versionInfo) { | ||||
|                         var version = versionInfo.version || ''; | ||||
|                         updateView.innerHTML = String.format('<span>%s v%s</span>',  | ||||
|                             _('Current Version:'), version); | ||||
|                     }); | ||||
|                 }, 5000); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|      | ||||
|     render: function(data) { | ||||
|         var m, s, o; | ||||
|         var listen_port = (uci.get('ddns-go', 'config', 'port') || '[::]:9876').split(':').slice(-1)[0]; | ||||
| @ -74,20 +237,27 @@ return view.extend({ | ||||
|         // 状态显示部分 | ||||
|         s = m.section(form.TypedSection); | ||||
|         s.anonymous = true; | ||||
|     | ||||
|         s.render = function() { | ||||
|             var statusView = E('p', { id: 'control_status' },  | ||||
|                 '<span class="spinning"></span> ' + _('Checking status...')); | ||||
|              | ||||
|             var pollInterval = poll.add(function() { | ||||
|                 return checkProcess() | ||||
|                     .then(function(res) { | ||||
|                         statusView.innerHTML = renderStatus(res.running, listen_port, noweb); | ||||
|                     }) | ||||
|                     .catch(function(err) { | ||||
|                         console.error('Status check failed:', err); | ||||
|                         statusView.innerHTML = '<span style="color:orange">⚠ ' + _('Status check error') + '</span>'; | ||||
|                     }); | ||||
|             }, 5); // 每5秒检查一次 | ||||
|  | ||||
|             window.statusPoll = function() { | ||||
|                 return Promise.all([ | ||||
|                     checkProcess(), | ||||
|                     getVersionInfo() | ||||
|                 ]).then(function(results) { | ||||
|                     var [processInfo, versionInfo] = results; | ||||
|                     var version = versionInfo.version || ''; | ||||
|                     statusView.innerHTML = renderStatus(processInfo.running, listen_port, noweb, version); | ||||
|                 }).catch(function(err) { | ||||
|                     console.error('Status check failed:', err); | ||||
|                     statusView.innerHTML = '<span style="color:orange">⚠ ' + _('Status check error') + '</span>'; | ||||
|                 }); | ||||
|             }; | ||||
|              | ||||
|             var pollInterval = poll.add(window.statusPoll, 5); // 每5秒检查一次 | ||||
|              | ||||
|             return E('div', { class: 'cbi-section', id: 'status_bar' }, [ | ||||
|                 statusView, | ||||
| @ -102,44 +272,73 @@ return view.extend({ | ||||
|                     ]) | ||||
|                 ]) | ||||
|             ]); | ||||
|         } | ||||
|         }; | ||||
|  | ||||
|         s = m.section(form.NamedSection, 'config', 'basic'); | ||||
|  | ||||
| 		s = m.section(form.NamedSection, 'config', 'basic'); | ||||
|         o = s.option(form.Flag, 'enabled', _('Enable')); | ||||
|         o.default = o.disabled; | ||||
|         o.rmempty = false; | ||||
|  | ||||
| 		o = s.option(form.Flag, 'enabled', _('Enable')); | ||||
| 		o.default = o.disabled; | ||||
| 		o.rmempty = false; | ||||
|         o = s.option(form.Value, 'port', _('Listen port')); | ||||
|         o.default = '[::]:9876'; | ||||
|         o.rmempty = false; | ||||
|  | ||||
| 		o = s.option(form.Value, 'port', _('Listen port')); | ||||
| 		o.default = '[::]:9876'; | ||||
| 		o.rmempty = false; | ||||
|         o = s.option(form.Value, 'time', _('Update interval')); | ||||
|         o.default = '300'; | ||||
|  | ||||
| 		o = s.option(form.Value, 'time', _('Update interval')); | ||||
| 		o.default = '300'; | ||||
|         o = s.option(form.Value, 'ctimes', _('Compare with service provider N times intervals')); | ||||
|         o.default = '5'; | ||||
|  | ||||
| 		o = s.option(form.Value, 'ctimes', _('Compare with service provider N times intervals')); | ||||
| 		o.default = '5'; | ||||
|         o = s.option(form.Value, 'skipverify', _('Skip verifying certificates')); | ||||
|         o.default = '0'; | ||||
|  | ||||
| 		o = s.option(form.Value, 'skipverify', _('Skip verifying certificates')); | ||||
| 		o.default = '0'; | ||||
|         o = s.option(form.Value, 'dns', _('Specify DNS resolution server')); | ||||
|         o.value('223.5.5.5', _('Ali DNS 223.5.5.5')); | ||||
|         o.value('223.6.6.6', _('Ali DNS 223.6.6.6')); | ||||
|         o.value('119.29.29.29', _('Tencent DNS 119.29.29.29')); | ||||
|         o.value('1.1.1.1', _('CloudFlare DNS 1.1.1.1')); | ||||
|         o.value('8.8.8.8', _('Google DNS 8.8.8.8')); | ||||
|         o.value('8.8.4.4', _('Google DNS 8.8.4.4')); | ||||
|         o.datatype = 'ipaddr';  | ||||
|  | ||||
| 		o = s.option(form.Value, 'dns', _('Specify DNS resolution server')); | ||||
| 		o.value('223.5.5.5', _('Ali DNS 223.5.5.5')); | ||||
| 		o.value('223.6.6.6', _('Ali DNS 223.6.6.6')); | ||||
| 		o.value('119.29.29.29', _('Tencent DNS 119.29.29.29')); | ||||
| 		o.value('1.1.1.1', _('CloudFlare DNS 1.1.1.1')); | ||||
| 		o.value('8.8.8.8', _('Google DNS 8.8.8.8')); | ||||
| 		o.value('8.8.4.4', _('Google DNS 8.8.4.4')); | ||||
| 		o.datatype = 'ipaddr';  | ||||
|         o = s.option(form.Flag, 'noweb', _('Do not start web services')); | ||||
|         o.default = '0'; | ||||
|         o.rmempty = false; | ||||
|  | ||||
| 		o = s.option(form.Flag, 'noweb', _('Do not start web services')); | ||||
| 		o.default = '0'; | ||||
| 		o.rmempty = false; | ||||
|         o = s.option(form.Value, 'delay', _('Delayed Start (seconds)')); | ||||
|         o.default = '60'; | ||||
|          | ||||
| 		o = s.option(form.Value, 'delay', _('Delayed Start (seconds)')); | ||||
| 		o.default = '60'; | ||||
|         o = s.option(form.Button, '_newpassword', _('Reset account password')); | ||||
|         o.inputtitle = _('ResetPassword'); | ||||
|         o.inputstyle = 'apply'; | ||||
|         o.onclick = L.bind(this.handleResetPassword, this, data); | ||||
|          | ||||
| 		return m.render(); | ||||
| 	} | ||||
|         o = s.option(form.DummyValue, '_update_status', _('Current Version')); | ||||
|         o.rawhtml = true; | ||||
|         var currentVersion = ''; | ||||
| 	 | ||||
|         getVersionInfo().then(function(versionInfo) { | ||||
|             currentVersion = versionInfo.version || ''; | ||||
|             var updateView = document.getElementById('update_status'); | ||||
|             if (updateView) { | ||||
|                 updateView.innerHTML = String.format('<span>v%s</span>', currentVersion); | ||||
|             } | ||||
|         }); | ||||
|          | ||||
|         o.cfgvalue = function() { | ||||
|             return E('div', { style: 'margin: 5px 0;' }, [ | ||||
|                 E('span', { id: 'update_status' },  | ||||
|                     currentVersion ? String.format('v%s', currentVersion) : _('Loading...')) | ||||
|             ]); | ||||
|         }; | ||||
|  | ||||
|         o = s.option(form.Button, '_update', _('Update kernel'), | ||||
|                 _('Check and update DDNS-Go to the latest version')); | ||||
|         o.inputtitle = _('Check Update'); | ||||
|         o.inputstyle = 'apply'; | ||||
|         o.onclick = L.bind(this.handleUpdate, this, data); | ||||
|          | ||||
|         return m.render(); | ||||
|     } | ||||
| }); | ||||
| @ -43,7 +43,7 @@ msgstr "" | ||||
| msgid "DDNS-GO Service Not Running" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Please enable the DDNS-GO service" | ||||
| msgid "DDNS-GO Web Interface Disabled" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Open Web Interface" | ||||
| @ -72,3 +72,33 @@ msgstr "" | ||||
|  | ||||
| msgid "Delayed Start (seconds)" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Update Program" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Check and update DDNS-Go to the latest version" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Check Update" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Updating, please wait..." | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Update failed" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Update status unknown" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Reset account password" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "ResetPassword" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "SUCCESS:" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Reset admin password successfully to admin12345" | ||||
| msgstr "" | ||||
| @ -20,7 +20,7 @@ msgid "DDNS-GO Control panel" | ||||
| msgstr "DDNS-GO操作台" | ||||
|  | ||||
| msgid "Open Web Interface" | ||||
| msgstr "打开 Web 界面" | ||||
| msgstr "打开Web界面" | ||||
|  | ||||
| msgid "Log" | ||||
| msgstr "日志" | ||||
| @ -72,3 +72,51 @@ msgstr "不启动web服务" | ||||
|  | ||||
| msgid "Delayed Start (seconds)" | ||||
| msgstr "开机延时启动(秒)" | ||||
|  | ||||
| msgid "Update kernel" | ||||
| msgstr "更新内核" | ||||
|  | ||||
| msgid "Check and update DDNS-Go to the latest version" | ||||
| msgstr "更新DDNS-Go到最新版本" | ||||
|  | ||||
| msgid "Check Update" | ||||
| msgstr "检查更新" | ||||
|  | ||||
| msgid "Updating, please wait..." | ||||
| msgstr "更新中,请稍等..." | ||||
|  | ||||
| msgid "Update failed" | ||||
| msgstr "更新失败" | ||||
|  | ||||
| msgid "Update status unknown" | ||||
| msgstr "更新状态未知" | ||||
|  | ||||
| msgid "Reset account password" | ||||
| msgstr "重置登录密码" | ||||
|  | ||||
| msgid "ResetPassword" | ||||
| msgstr "重置密码" | ||||
|  | ||||
| msgid "SUCCESS:" | ||||
| msgstr "完成执行:" | ||||
|  | ||||
| msgid "Password reset successfully to admin12345" | ||||
| msgstr "成功重置密码admin12345" | ||||
|  | ||||
| msgid "Password Reset Successful" | ||||
| msgstr "重置密码成功" | ||||
|  | ||||
| msgid "User password has been reset to: admin12345" | ||||
| msgstr "用户密码重置为admin12345" | ||||
|  | ||||
| msgid "You need to restart DDNS-Go service for the changes to take effect." | ||||
| msgstr "需要重启DDNS-GO服务更改才生效" | ||||
|  | ||||
| msgid "Restart Service Now" | ||||
| msgstr "立刻重启服务" | ||||
|  | ||||
| msgid "Restart Later" | ||||
| msgstr "稍后重启" | ||||
|  | ||||
| msgid "" | ||||
| msgstr "" | ||||
|  | ||||
| @ -1,8 +1,9 @@ | ||||
| { | ||||
| 	"luci-app-ddns-go": { | ||||
|     "luci-app-ddns-go": { | ||||
| 		"description": "Grant UCI access for luci-app-ddns-go", | ||||
| 		"read": { | ||||
|       			"file": { | ||||
|         "read": { | ||||
|             "uci": [ "ddns-go" ], | ||||
|             "file": { | ||||
|         			"/etc/init.d/ddns-go": [ "exec" ], | ||||
|         			"/usr/libexec/ddns-go-call": [ "exec" ], | ||||
|         			"/bin/pidof": [ "exec" ], | ||||
| @ -10,14 +11,21 @@ | ||||
|         			"/bin/ash": [ "exec" ], | ||||
|         			"/etc/ddns-go/ddns-go-config.yaml": [ "read" ], | ||||
|         			"/var/log/ddns-go.log": [ "read" ] | ||||
|       			}, | ||||
| 		"ubus": { | ||||
| 		     "service": [ "list" ] | ||||
| 		}, | ||||
| 		"uci": [ "ddns-go" ,"ddns-go" ] | ||||
| 		}, | ||||
| 		"write": { | ||||
| 			"uci": [ "ddns-go" ,"ddns-go" ] | ||||
| 		} | ||||
| 	} | ||||
|       	    }, | ||||
|             "ubus": { | ||||
|                 "rc": [ "*" ], | ||||
|                 "service": ["list"], | ||||
|                 "luci.ddns-go": [ "*" ] | ||||
|             } | ||||
|         }, | ||||
|         "write": { | ||||
|             "ubus": { | ||||
|                 "luci.ddns-go": [ "*" ] | ||||
|             }, | ||||
|             "file": { | ||||
|                 "/etc/ddns-go/ddns-go-config.yaml": ["write"] | ||||
| 	    }, | ||||
|             "uci": ["ddns-go"] | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -10,8 +10,8 @@ THEME_TITLE:=Kucat Theme | ||||
| PKG_NAME:=luci-theme-$(THEME_NAME) | ||||
| LUCI_TITLE:=Kucat Theme by sirpdboy | ||||
| LUCI_DEPENDS:= | ||||
| PKG_VERSION:=2.6.18 | ||||
| PKG_RELEASE:=20251018 | ||||
| PKG_VERSION:=2.7.2 | ||||
| PKG_RELEASE:=20251022 | ||||
|  | ||||
| define Package/luci-theme-$(THEME_NAME)/conffiles | ||||
| /www/luci-static/resources/background/ | ||||
|  | ||||
| @ -474,12 +474,12 @@ | ||||
|   -moz-border-radius: var(--radius0); | ||||
|   border-radius: var(--radius0); | ||||
|   background-clip: content-box; | ||||
|   background: rgba(50,50,50,0.9); | ||||
|   border: 1px solid rgba(var(--primary-rgbm),1) | ||||
|   background: rgba(var(--primary-rgbbody), 0.9); | ||||
|   border: 1px solid rgba(var(--primary-rgbm), 0.6); | ||||
| } | ||||
|  | ||||
| ::-webkit-scrollbar-thumb:hover { | ||||
|   background-color: rgba(var(--primary-rgbm),1) | ||||
|   background-color: rgba(var(--primary-rgbm),0.9) | ||||
| } | ||||
|  | ||||
| ::selection { | ||||
| @ -1433,7 +1433,7 @@ h4 { | ||||
|   padding: 0.75rem 1.25rem; | ||||
|   font-weight: 600; | ||||
|   font-size: var(--font-z); | ||||
|   color: var(--primary-title-color); | ||||
|   color: var(--primary-title-color) !important; | ||||
|   padding-bottom: 10px | ||||
| } | ||||
|  | ||||
| @ -1869,7 +1869,8 @@ button:hover,.btn:hover,.cbi-button:hover { | ||||
|   border-left: 0.18751rem solid var(--menu-item-titlebg-color) !important; | ||||
|   border-right: 0.18751rem solid var(--menu-item-titlebg-color) !important; | ||||
|   border-radius: var(--radius2); | ||||
|   padding: 0.5rem 0rem; | ||||
|   padding: 0.5rem 0.2rem; | ||||
|   line-height: 1.5; | ||||
|   box-shadow: 0 0.5rem 1rem var(--input-boxcolor); | ||||
|   background: var(--menu-item-titlebg-color); | ||||
|   margin: 0.2rem 0rem 0.2rem 0.4rem !important | ||||
| @ -1954,7 +1955,7 @@ button:hover,.btn:hover,.cbi-button:hover { | ||||
| .cbi-value { | ||||
|   display: inline-block; | ||||
|   width: 100%; | ||||
|   padding: 0 0.3rem; | ||||
|   padding: 0.1rem 0.3rem; | ||||
|   line-height: 2.3rem | ||||
| } | ||||
|  | ||||
| @ -3861,7 +3862,9 @@ body.lang_pl.node-main-login .cbi-value-title { | ||||
| .chat_window>.mainContent>.top_menu { | ||||
|   background-color: rgba(var(--primary-rgbm), 0.12)!important | ||||
| } | ||||
|  | ||||
| .showVoiceCls, .showVoiceCls .markdown-body { | ||||
|     background: var(--inputbg-color) !important; | ||||
| } | ||||
| #chatlog .response { | ||||
|   background-color: rgba(255,255,255,0.2) !important | ||||
| } | ||||
| @ -4009,12 +4012,14 @@ pre.command-output { | ||||
|   border-bottom-color: #dee2e6 | ||||
| } | ||||
|  | ||||
| /* openclash */ | ||||
| [data-page^="admin-services-openclash"] .cbi-tabmenu>li:last-child { | ||||
|   margin-right: 0 !important | ||||
| } | ||||
|  | ||||
| [data-page^="admin-services-openclash"]  .select-popup-header, | ||||
| [data-page^="admin-services-openclash"]  .oc, | ||||
| [data-page^="admin-services-openclash"]  .oc .main-cards-container   { | ||||
| .oc .main-cards-container   { | ||||
|    background-color: rgba(255,255,255,0) !important; | ||||
| } | ||||
|  | ||||
| @ -4026,40 +4031,40 @@ pre.command-output { | ||||
|    background-color: rgba(255,255,255,0) !important; | ||||
|    padding: 0 20px 0 10px!important; | ||||
| } | ||||
|  | ||||
| [data-page^="admin-services-openclash"] .oc .version-display, | ||||
| [data-page^="admin-services-openclash"] .oc .value-indicator, | ||||
| [data-page^="admin-services-openclash"] .oc .cbi-button-group{ | ||||
| border: 0px solid rgba(255,255,255,0.3) !important; | ||||
|  /* background-color: var(--input-bgcolor) !important; */ | ||||
| } | ||||
| [data-page^="admin-services-openclash"]  .oc .myip-ip-item, .oc .myip-check-item { | ||||
|    background-color: rgba(255,255,255,0.1) !important; | ||||
|    background-color: rgba(var(--primary-rgbbody),0.2) !important; | ||||
|    border: 1px solid rgba(255, 255, 255, 0.15) !important; | ||||
|    border: 1px solid rgba(var(--primary-rgbm),0.1) !important; | ||||
| border: 0px solid #ddd !important; | ||||
| } | ||||
|  | ||||
| [data-page^="admin-services-openclash"]  .oc .developer-container, | ||||
| [data-page^="admin-services-openclash"]  .oc .myip-main-card, | ||||
| [data-page^="admin-services-openclash"]  .oc .sub-card  { | ||||
|   background-color: rgba(255,255,255,0.1) !important; | ||||
|   background-color: rgba(var(--primary-rgbm),0.2) !important; | ||||
|   border: 1px solid rgba(255,255,255,0.15) !important; | ||||
|   border: 1px solid rgba(var(--primary-rgbm),0.1) !important; | ||||
| [data-page^="admin-services-openclash"] .oc .myip-ip-item,  | ||||
| [data-page^="admin-services-openclash"] .oc .myip-check-item, | ||||
| [data-page^="admin-services-openclash"] .oc .developer-container, | ||||
| [data-page^="admin-services-openclash"] .oc .sub-card  { | ||||
|   background-color: rgba(var(--primary-rgbm),0.02) !important; | ||||
|   border: 1px solid rgba(var(--primary-rgbm),0.2) ; | ||||
| } | ||||
|  | ||||
| [data-page^="admin-services-openclash"]  .oc .main-card { | ||||
|   background-color: rgba(255,255,255,0) !important; | ||||
|   border: 1px solid rgba(255,255,255,0.15) !important; | ||||
|   border: 1px solid rgba(var(--primary-rgbm),0.1) !important; | ||||
| [data-page^="admin-services-openclash"] .oc>div>div, | ||||
| [data-page^="admin-services-openclash"] .oc .myip-main-card, | ||||
| [data-page^="admin-services-openclash"] .oc .myip-content-grid, | ||||
| [data-page^="admin-services-openclash"] .oc .main-card, | ||||
| [data-page^="admin-services-openclash"] .oc .announcement-card | ||||
|  { | ||||
|   background-color: rgba(255, 255, 255, 0) !important; | ||||
|   border: 0px solid #ddd !important; | ||||
|   box-shadow: none !important; | ||||
| } | ||||
|  | ||||
| [data-page^="admin-services-openclash"]  .oc .ip-result,.oc .ip-geo, | ||||
| [data-page^="admin-services-openclash"]  .oc .ip-title, .oc .ip-state_title, | ||||
| [data-page^="admin-services-openclash"]  .oc .myip-section-title, | ||||
| [data-page^="admin-services-openclash"]  .oc .card-title | ||||
|  | ||||
| [data-page^="admin-services-openclash"] .oc .ip-result,.oc .ip-geo, | ||||
| [data-page^="admin-services-openclash"] .oc .ip-title, .oc .ip-state_title, | ||||
| [data-page^="admin-services-openclash"] .oc .myip-section-title, | ||||
| .oc .card-title | ||||
| { | ||||
|   color: var(--primary-title-color)!important; | ||||
|   border: 0px solid #ddd !important; | ||||
| } | ||||
|  | ||||
| #tool_label .tool_label_span { | ||||
| @ -4150,63 +4155,67 @@ border: 0px solid rgba(255,255,255,0.3) !important; | ||||
| } | ||||
|  | ||||
| /* bandix */ | ||||
| .bandix-connection-container, | ||||
| .bandix-container { | ||||
|    padding: 5px!important;  | ||||
|    background-color: rgba(255,255,255,0) !important; | ||||
|    color: var(--primary-title-color)!important; | ||||
| } | ||||
|  | ||||
| .bandix-container .bandix-badge | ||||
| .bandix-badge | ||||
| { | ||||
|   color: var(--primary-title-color)!important; | ||||
|   background-color: var(--inputbg-color)!important; | ||||
|   border: 1px solid var(--input-boxcolor); | ||||
|   border: 1px solid var(--input-boxcolor)!important; | ||||
| } | ||||
|  | ||||
| .bandix-container .action-button { | ||||
|   background-color: rgba(var(--primary-rgbm), 0.9); | ||||
| .action-button { | ||||
|   background-color: rgba(var(--primary-rgbm), 0.9)!important; | ||||
| } | ||||
| .bandix-container .history-tooltip>div, | ||||
| .bandix-container .history-tooltip>div>span, | ||||
|  | ||||
| .stats-card-title , | ||||
| .stats-card>div , | ||||
| .history-tooltip>div, | ||||
| .history-tooltip>div>span, | ||||
| .bandix-container .form-label , | ||||
| .bandix-container .bandix-card-title, | ||||
| .bandix-container .bandix-card>div, | ||||
| .bandix-container .stats-title, | ||||
| .bandix-container .bandix-title  { | ||||
|   color: var(--primary-title-color); | ||||
| .bandix-card-title, | ||||
| .bandix-card>div, | ||||
| .stats-title, | ||||
| .bandix-title  { | ||||
|   color: var(--primary-title-color)!important; | ||||
| } | ||||
| .bandix-card-body { | ||||
|    padding: 0!important; | ||||
| } | ||||
| .history-tooltip | ||||
| { | ||||
|   background-color: rgba(var(--primary-rgbbody),1)!important; | ||||
|   color: var(--body-color) !important; | ||||
|   border: 1px solid var(--input-boxcolor)!important; | ||||
|   width: 300px!important; | ||||
| } | ||||
|  | ||||
| .bandix-container .history-tooltip | ||||
| .bandix-card , | ||||
| .stats-card | ||||
| { | ||||
|   background-color: rgba(var(--primary-rgbbody),1) ; | ||||
|   color: var(--body-color) ; | ||||
|   border: 1px solid var(--input-boxcolor); | ||||
|   width: 300px; | ||||
|   background-color: rgba(var(--primary-rgbm), 0.1)!important; | ||||
|   border-radius: 0 !important; | ||||
|   box-shadow: 0 0 0 0 rgba(0, 0, 0, 0) !important; | ||||
|   margin-bottom: 0 !important; | ||||
|   border: 0px solid #333!important; | ||||
|   border-bottom: 0px solid var(--input-boxcolor)!important; | ||||
|   overflow: auto!important; | ||||
| } | ||||
|  | ||||
| .bandix-container .bandix-card , | ||||
| .bandix-container .stats-card | ||||
| .bandix-card .bandix-card-header.history-header | ||||
| { | ||||
|   background-color: rgba(var(--primary-rgbm), 0.1); | ||||
|   background-color: rgba(0, 0, 0, 0) ; | ||||
|   border-radius: 0 ; | ||||
|   box-shadow: 0 0 0 0 rgba(0, 0, 0, 0) ; | ||||
|   margin-bottom: 0 ; | ||||
|   border: 0px solid #3333331c; | ||||
|   border-bottom: 1px solid var(--input-boxcolor); | ||||
|   overflow: auto; | ||||
| } | ||||
|  | ||||
| .bandix-container .bandix-card .bandix-card-header.history-header | ||||
| { | ||||
|   border-bottom: 1px solid var(--input-boxcolor); | ||||
|   background-color: rgba(0, 0, 0, 0) ; | ||||
|   padding: 0; | ||||
|   border-bottom: 1px solid var(--input-boxcolor)!important; | ||||
|   background-color: rgba(0, 0, 0, 0) !important; | ||||
| } | ||||
|  | ||||
| .modal-header, | ||||
| .device-summary, | ||||
| .bandix-container .bandix-card .history-controls | ||||
| .bandix-card .history-controls | ||||
| { | ||||
|  | ||||
|   border: 0px solid var(--input-boxcolor)!important; | ||||
| @ -4220,18 +4229,19 @@ border: 0px solid rgba(255,255,255,0.3) !important; | ||||
| .device-summary>div, | ||||
| .bandix-container .device-name, | ||||
| .bandix-container .legend-item, | ||||
| .stats-card>div>div>span, | ||||
| .bandix-container .bandix-container .stats-card>div>div>span  { | ||||
| .stats-card>div>div>span{ | ||||
|   color: var(--primary-title-color)!important; | ||||
| } | ||||
| .bandix-container .bandix-table | ||||
|  | ||||
| .bandix-table | ||||
| { | ||||
|   table-layout: auto; | ||||
|   table-layout: auto!important; | ||||
| } | ||||
|  | ||||
| .bandix-container .bandix-table td ,.bandix-table th | ||||
| .bandix-table td ,.bandix-table th | ||||
| { | ||||
| padding: 10px 15px; | ||||
| padding: 10px 15px!important; | ||||
| border-bottom: 0px solid #f1f5f9!important; | ||||
| } | ||||
|  | ||||
| .form-input | ||||
| @ -4254,19 +4264,9 @@ padding: 10px 15px; | ||||
|  | ||||
|   background-color: rgba(255, 255, 255, 0) !important; | ||||
|   color: var(--body-color) !important; | ||||
|   border-top: 1px solid var(--inputborder-color)!important; | ||||
| } | ||||
|  | ||||
| .bandix-table tbody tr:nth-child(odd)  | ||||
| { | ||||
|   background-color: rgba(0,0,0,0.1) !important; | ||||
| } | ||||
|  | ||||
| .bandix-table tbody tr:nth-child(even) | ||||
| { | ||||
|   background-color: rgba(0, 0, 0, 0.04) !important; | ||||
| } | ||||
|  | ||||
|  | ||||
| [data-page="admin-services-adguardhome"]>.main .cbi-value .cbi-input-textarea { | ||||
|   width: 100% !important; | ||||
|   box-shadow: 0 0 1px var(--input-boxcolor) !important | ||||
| @ -4324,7 +4324,6 @@ select,input,.cbi-dropdown,.btn,button,.cbi-button,.item::after { | ||||
|  | ||||
| #cbi-appfilter>div>div { | ||||
|   overflow: auto; | ||||
|   /* background-color: rgba(var(--primary-rgbbody),1) !important */ | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div>button { | ||||
| @ -4334,42 +4333,29 @@ select,input,.cbi-dropdown,.btn,button,.cbi-button,.item::after { | ||||
|   height: auto !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div>ul { | ||||
|   border-bottom: 0px solid #ccc !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div>ul>li { | ||||
|   background-color: rgba(var(--primary-rgbm),0.2) !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div>ul>li.active { | ||||
|   background-color: rgba(var(--primary-rgbm),0.7) !important; | ||||
|   color: var(--menu-hover-color) !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div>ul>li:hover { | ||||
|   background-color: rgba(var(--primary-rgbm),0.7) !important; | ||||
|   color: var(--menu-hover-color) !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter #detailsModal .tab-body { | ||||
|   overflow: auto; | ||||
|   background-color: rgba(248,248,248,0.9) !important | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div span { | ||||
|   /* color: var(--body-color) !important*/ | ||||
| } | ||||
|  | ||||
| #cbi-appfilter>div>div input { | ||||
|   /* background-color: rgba(248,248,248,0.2) !important; | ||||
|   color: var(--body-color) !important*/ | ||||
| } | ||||
|  | ||||
| #cbi-appfilter #user_status_table th.th:nth-child(1) { | ||||
|   width: 150px !important; | ||||
| } | ||||
|  | ||||
| .oaf-container>div{ | ||||
|   background: rgba(0, 0, 0, 0.04) !important; | ||||
|   color: var(--body-color) !important; | ||||
|   border-bottom: 0px solid #ddd!important; | ||||
| } | ||||
|  | ||||
| .traffic-info>div>span, | ||||
| .device-details>div, | ||||
| .oaf-container>div span{ | ||||
|   color: var(--body-color)!important; | ||||
| } | ||||
|  | ||||
| .CodeMirror.cm-s-dracula.CodeMirror-wrap { | ||||
|   border-radius: 0.375rem | ||||
| } | ||||
| @ -4980,8 +4966,35 @@ div#file-manager-container #status-bar #status-info { | ||||
|   [data-page="admin-network-dhcp"] [data-tab-active="true"] { | ||||
|     padding: 0 !important | ||||
|   } | ||||
|   .cbi-value:first-child { | ||||
|    padding-top: 0 | ||||
|   } | ||||
|   .cbi-value { | ||||
|   padding: 0; | ||||
|   line-height: 2rem; | ||||
|   } | ||||
|   .history-card-body { | ||||
|     padding: 0 !important | ||||
|   } | ||||
|   /* Bandix  */ | ||||
|   .stats-detail-row>span { | ||||
|     display: none!important | ||||
|   } | ||||
|   .bandix-card .bandix-card-header.history-header { | ||||
|     padding: 0 !important;  | ||||
|   } | ||||
|    | ||||
|   .main-right, | ||||
|   .main-left{ | ||||
|     scrollbar-width: none; | ||||
|     -ms-overflow-style: none; | ||||
|   } | ||||
|    | ||||
|   .main-right::-webkit-scrollbar, | ||||
|   .main-left::-webkit-scrollbar | ||||
|   { | ||||
|     display: none; | ||||
|   } | ||||
|   #file-manager-container .file-manager-header { | ||||
|     flex-wrap: wrap | ||||
|   } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 actions-user
					actions-user