Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 25 additions & 116 deletions luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,122 +22,31 @@ local function is_installed(e)
return luci.model.ipkg.installed(e)
end

-- 判断系统是否 JS 版 LuCI
local function is_js_luci()
return luci.sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end

-- 显示提示条
local function showMsg_Redirect(redirectUrl, delay)
local message = translate("Applying configuration changes… %ds")
luci.http.write([[
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// 创建遮罩层
var overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
overlay.style.zIndex = '9999';
// 创建提示条
var messageDiv = document.createElement('div');
messageDiv.style.position = 'fixed';
messageDiv.style.top = '20%';
messageDiv.style.left = '50%';
messageDiv.style.transform = 'translateX(-50%)';
messageDiv.style.width = '81%';
//messageDiv.style.maxWidth = '1200px';
messageDiv.style.background = '#ffffff';
messageDiv.style.border = '1px solid #000000';
messageDiv.style.borderRadius = '5px';
messageDiv.style.padding = '18px 20px';
messageDiv.style.color = '#000000';
//messageDiv.style.fontWeight = 'bold';
messageDiv.style.fontFamily = 'Arial, Helvetica, sans-serif';
messageDiv.style.textAlign = 'left';
messageDiv.style.zIndex = '10000';
var spinner = document.createElement('span');
spinner.style.display = 'inline-block';
spinner.style.width = '20px';
spinner.style.height = '20px';
spinner.style.marginRight = '10px';
spinner.style.border = '3px solid #666';
spinner.style.borderTopColor = '#000';
spinner.style.borderRadius = '50%';
spinner.style.animation = 'spin 1s linear infinite';
messageDiv.appendChild(spinner);
var textSpan = document.createElement('span');
var remaining = Math.ceil(]] .. 90000 .. [[ / 1000);
function updateMessage() {
textSpan.textContent = "]] .. message .. [[".replace("%ds", remaining + "s");
}
updateMessage();
messageDiv.appendChild(textSpan);
document.body.appendChild(messageDiv);
var style = document.createElement('style');
style.innerHTML = `
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}`;
document.head.appendChild(style);
var countdownInterval = setInterval(function() {
remaining--;
if (remaining < 0) remaining = 0;
updateMessage();
if (remaining <= 0) clearInterval(countdownInterval);
}, 1000);
// 将遮罩层和提示条添加到页面
document.body.appendChild(overlay);
document.body.appendChild(messageDiv);
// 重定向或隐藏提示条和遮罩层
var redirectUrl = ']] .. (redirectUrl or "") .. [[';
var delay = ]] .. (delay or 3000) .. [[;
setTimeout(function() {
if (redirectUrl) {
window.location.href = redirectUrl;
} else {
if (messageDiv && messageDiv.parentNode) {
messageDiv.parentNode.removeChild(messageDiv);
}
if (overlay && overlay.parentNode) {
overlay.parentNode.removeChild(overlay);
}
window.location.href = window.location.href;
}
}, delay);
});
</script>
]])
end

-- 兼容新旧版本 LuCI
local function set_apply_on_parse(map)
if not map then
return
end

if is_js_luci() then
-- JS 版 LuCI:显示提示条并延迟跳转
map.apply_on_parse = false
map.on_after_apply = function(self)
luci.http.prepare_content("text/html")
showMsg_Redirect(self.redirect or luci.dispatcher.build_url() , 3000)
end
-- 默认的保存并应用行为
local function apply_redirect(m)
local tmp_uci_file = "/etc/config/" .. "shadowsocksr" .. "_redirect"
if m.redirect and m.redirect ~= "" then
if nixio.fs.access(tmp_uci_file) then
local redirect
for line in io.lines(tmp_uci_file) do
redirect = line:match("option%s+url%s+['\"]([^'\"]+)['\"]")
if redirect and redirect ~= "" then break end
end
if redirect and redirect ~= "" then
luci.sys.call("/bin/rm -f " .. tmp_uci_file)
luci.http.redirect(redirect)
end
else
nixio.fs.writefile(tmp_uci_file, "config redirect\n")
end
m.on_after_save = function(self)
local redirect = self.redirect
if redirect and redirect ~= "" then
uci:set("shadowsocksr" .. "_redirect", "@redirect[0]", "url", redirect)
end
end
else
-- Lua 版 LuCI:直接跳转
map.apply_on_parse = true
map.on_after_apply = function(self)
luci.http.redirect(self.redirect)
end
end

-- 保持原渲染流程
map.render = function(self, ...)
getmetatable(self).__index.render(self, ...) -- 保持原渲染流程
luci.sys.call("/bin/rm -f " .. tmp_uci_file)
end
end

Expand Down Expand Up @@ -263,7 +172,7 @@ if m.uci:get("shadowsocksr", sid) ~= "servers" then
return
end
-- 保存&应用成功后跳转到节点列表
set_apply_on_parse(m)
apply_redirect(m)

-- [[ Servers Setting ]]--
s = m:section(NamedSection, sid, "servers")
Expand Down
33 changes: 2 additions & 31 deletions luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require "luci.sys"
require "nixio.fs"
require "luci.dispatcher"
require "luci.model.uci"
local cbi = require "luci.cbi"
local uci = require "luci.model.uci".cursor()

local m, s, o, node
Expand All @@ -14,31 +15,6 @@ local function is_finded(e)
return luci.sys.exec(string.format('type -t -p "%s" 2>/dev/null', e)) ~= ""
end

-- 优化 CBI UI(新版 LuCI 专用)
local function optimize_cbi_ui()
luci.http.write([[
<script type="text/javascript">
// 修正上移、下移按钮名称
document.querySelectorAll("input.btn.cbi-button.cbi-button-up").forEach(function(btn) {
btn.value = "]] .. translate("Move up") .. [[";
});
document.querySelectorAll("input.btn.cbi-button.cbi-button-down").forEach(function(btn) {
btn.value = "]] .. translate("Move down") .. [[";
});
// 删除控件和说明之间的多余换行
document.querySelectorAll("div.cbi-value-description").forEach(function(descDiv) {
var prev = descDiv.previousSibling;
while (prev && prev.nodeType === Node.TEXT_NODE && prev.textContent.trim() === "") {
prev = prev.previousSibling;
}
if (prev && prev.nodeType === Node.ELEMENT_NODE && prev.tagName === "BR") {
prev.remove();
}
});
</script>
]])
end

local has_xray = is_finded("xray")
local has_hysteria2 = is_finded("hysteria")

Expand Down Expand Up @@ -242,6 +218,7 @@ s = m:section(TypedSection, "servers")
s.anonymous = true
s.addremove = true
s.template = "cbi/tblsection"
s:append(cbi.Template("shadowsocksr" .. "/optimize_cbi_ui"))
s.sortable = true
s.extedit = luci.dispatcher.build_url("admin", "services", "shadowsocksr", "servers", "%s")
function s.create(...)
Expand All @@ -251,12 +228,6 @@ function s.create(...)
return
end
end
s.render = function(self, ...)
Map.render(self, ...)
if type(optimize_cbi_ui) == "function" then
optimize_cbi_ui()
end
end

o = s:option(DummyValue, "type", translate("Type"))
function o.cfgvalue(self, section)
Expand Down
24 changes: 24 additions & 0 deletions luci-app-ssr-plus/luasrc/view/shadowsocksr/optimize_cbi_ui.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
setTimeout(updateElements, 200);
function updateElements() {
//修正上移、下移按钮名称
document.querySelectorAll("input.btn.cbi-button.cbi-button-up").forEach(function(btn) {
btn.value = "<%:Move up%>";
});
document.querySelectorAll("input.btn.cbi-button.cbi-button-down").forEach(function(btn) {
btn.value = "<%:Move down%>";
});
//删除控件和说明之间的多余换行
document.querySelectorAll("div.cbi-value-description").forEach(function(descDiv) {
var prev = descDiv.previousSibling;
while (prev && prev.nodeType === Node.TEXT_NODE && prev.textContent.trim() === "") {
prev = prev.previousSibling;
}
if (prev && prev.nodeType === Node.ELEMENT_NODE && prev.tagName === "BR") {
prev.remove();
}
});
}
});
</script>
55 changes: 55 additions & 0 deletions luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,61 @@
Copyright 2018-2019 Lienol <lawlienol@gmail.com>
Licensed to the public under the Apache License 2.0.
-%>
<%
require "luci.sys"
function is_js_luci()
return luci.sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0
end
-%>
<% if is_js_luci() then -%>
<script type="text/javascript">
var cbi_t = [];
function cbi_t_add(section, tab) {
var t = document.getElementById('tab.' + section + '.' + tab);
var c = document.getElementById('container.' + section + '.' + tab);

if( t && c ) {
cbi_t[section] = (cbi_t[section] || [ ]);
cbi_t[section][tab] = { 'tab': t, 'container': c, 'cid': c.id };
}
}

function cbi_t_switch(section, tab) {
if( cbi_t[section] && cbi_t[section][tab] ) {
//在切换选项卡之前,先取消当前激活选项卡的全选状态
dechecked_all_node();
var o = cbi_t[section][tab];
var h = document.getElementById('tab.' + section);
for( var tid in cbi_t[section] ) {
var o2 = cbi_t[section][tid];
if( o.tab.id != o2.tab.id ) {
o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab( |$)/, " cbi-tab-disabled ");
o2.container.style.display = 'none';
}
else {
if(h) h.value = tab;
o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab-disabled( |$)/, " cbi-tab ");
o2.container.style.display = 'block';
}
}
}
return false
}
</script>
<%- else %>
<script type="text/javascript">
(function() {
if (typeof(cbi_t_switch) === "function") {
var old_switch = cbi_t_switch;
cbi_t_switch = function(section, tab) {
dechecked_all_node();
return old_switch(section, tab);
};
}
})();
</script>
<%- end %>

<script type="text/javascript">
//<![CDATA[
window.addEventListener('load', function () {
Expand Down
Loading