Implemented client_serverlist module! Close #200
* Will store servers that are not already in the list when logging in * Can add servers manually if required too * Fixed a bug in table.size
This commit is contained in:
parent
2296e35174
commit
8e9f65779c
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -66,4 +66,18 @@ PreviousButton < UIButton
|
||||||
image-clip: 0 21 12 21
|
image-clip: 0 21 12 21
|
||||||
|
|
||||||
$disabled:
|
$disabled:
|
||||||
image-color: #ffffff55
|
image-color: #ffffff55
|
||||||
|
|
||||||
|
AddButton < UIButton
|
||||||
|
size: 20 20
|
||||||
|
image-source: /images/ui/icon_add
|
||||||
|
image-color: #ffffffff
|
||||||
|
|
||||||
|
$hover !disabled:
|
||||||
|
image-color: #ffffff99
|
||||||
|
|
||||||
|
$pressed:
|
||||||
|
image-color: #ffffff44
|
||||||
|
|
||||||
|
$disabled:
|
||||||
|
image-color: #ffffff55
|
||||||
|
|
|
@ -18,4 +18,5 @@ Module
|
||||||
- client_options
|
- client_options
|
||||||
- client_terminal
|
- client_terminal
|
||||||
- client_modulemanager
|
- client_modulemanager
|
||||||
|
- client_serverlist
|
||||||
//- client_stats
|
//- client_stats
|
||||||
|
|
|
@ -34,9 +34,19 @@ local function onMotd(protocol, motd)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function onCharacterList(protocol, characters, account, otui)
|
local function onCharacterList(protocol, characters, account, otui)
|
||||||
|
-- Try add server to the server list
|
||||||
|
ServerList.add(G.host, G.port, g_game.getProtocolVersion())
|
||||||
|
|
||||||
if enterGame:getChildById('rememberPasswordBox'):isChecked() then
|
if enterGame:getChildById('rememberPasswordBox'):isChecked() then
|
||||||
g_settings.set('account', g_crypt.encrypt(G.account))
|
local account = g_crypt.encrypt(G.account)
|
||||||
g_settings.set('password', g_crypt.encrypt(G.password))
|
local password = g_crypt.encrypt(G.password)
|
||||||
|
|
||||||
|
g_settings.set('account', account)
|
||||||
|
g_settings.set('password', password)
|
||||||
|
|
||||||
|
ServerList.setServerAccount(G.host, account)
|
||||||
|
ServerList.setServerPassword(G.host, password)
|
||||||
|
|
||||||
g_settings.set('autologin', enterGame:getChildById('autoLoginBox'):isChecked())
|
g_settings.set('autologin', enterGame:getChildById('autoLoginBox'):isChecked())
|
||||||
else
|
else
|
||||||
EnterGame.clearAccountFields()
|
EnterGame.clearAccountFields()
|
||||||
|
@ -90,8 +100,8 @@ function EnterGame.init()
|
||||||
motdButton:show()
|
motdButton:show()
|
||||||
end
|
end
|
||||||
|
|
||||||
local account = g_crypt.decrypt(g_settings.get('account'))
|
local account = g_settings.get('account')
|
||||||
local password = g_crypt.decrypt(g_settings.get('password'))
|
local password = g_settings.get('password')
|
||||||
local host = g_settings.get('host')
|
local host = g_settings.get('host')
|
||||||
local port = g_settings.get('port')
|
local port = g_settings.get('port')
|
||||||
local autologin = g_settings.getBoolean('autologin')
|
local autologin = g_settings.getBoolean('autologin')
|
||||||
|
@ -99,16 +109,15 @@ function EnterGame.init()
|
||||||
|
|
||||||
if port == nil or port == 0 then port = 7171 end
|
if port == nil or port == 0 then port = 7171 end
|
||||||
|
|
||||||
enterGame:getChildById('accountNameTextEdit'):setText(account)
|
EnterGame.setAccountName(account)
|
||||||
enterGame:getChildById('accountNameTextEdit'):setCursorPos(-1)
|
EnterGame.setPassword(password)
|
||||||
enterGame:getChildById('accountPasswordTextEdit'):setText(password)
|
|
||||||
enterGame:getChildById('serverHostTextEdit'):setText(host)
|
enterGame:getChildById('serverHostTextEdit'):setText(host)
|
||||||
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
||||||
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
||||||
enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0)
|
|
||||||
|
|
||||||
protocolBox = enterGame:getChildById('protocolComboBox')
|
protocolBox = enterGame:getChildById('protocolComboBox')
|
||||||
protocolBox.onOptionChange = onChangeProtocol
|
protocolBox.onOptionChange = onChangeProtocol
|
||||||
for _i, proto in pairs(g_game.getSupportedProtocols()) do
|
for _i, proto in pairs(g_game.getSupportedProtocols()) do
|
||||||
protocolBox:addOption(proto)
|
protocolBox:addOption(proto)
|
||||||
end
|
end
|
||||||
|
@ -184,6 +193,18 @@ function EnterGame.openWindow()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function EnterGame.setAccountName(account)
|
||||||
|
local account = g_crypt.decrypt(account)
|
||||||
|
enterGame:getChildById('accountNameTextEdit'):setText(account)
|
||||||
|
enterGame:getChildById('accountNameTextEdit'):setCursorPos(-1)
|
||||||
|
enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGame.setPassword(password)
|
||||||
|
local password = g_crypt.decrypt(password)
|
||||||
|
enterGame:getChildById('accountPasswordTextEdit'):setText(password)
|
||||||
|
end
|
||||||
|
|
||||||
function EnterGame.clearAccountFields()
|
function EnterGame.clearAccountFields()
|
||||||
enterGame:getChildById('accountNameTextEdit'):clearText()
|
enterGame:getChildById('accountNameTextEdit'):clearText()
|
||||||
enterGame:getChildById('accountPasswordTextEdit'):clearText()
|
enterGame:getChildById('accountPasswordTextEdit'):clearText()
|
||||||
|
@ -285,6 +306,11 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
||||||
protocolLabel:setVisible(false)
|
protocolLabel:setVisible(false)
|
||||||
protocolLabel:setHeight(0)
|
protocolLabel:setHeight(0)
|
||||||
|
|
||||||
|
local serverListButton = enterGame:getChildById('serverListButton')
|
||||||
|
serverListButton:setVisible(false)
|
||||||
|
serverListButton:setHeight(0)
|
||||||
|
serverListButton:setWidth(0)
|
||||||
|
|
||||||
local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox')
|
local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox')
|
||||||
rememberPasswordBox:setMarginTop(-5)
|
rememberPasswordBox:setMarginTop(-5)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
EnterGameWindow < MainWindow
|
EnterGameWindow < MainWindow
|
||||||
|
|
||||||
|
ServerListButton < UIButton
|
||||||
|
size: 17 17
|
||||||
|
image-source: /images/topbuttons/minimap
|
||||||
|
image-color: #ffffffff
|
||||||
|
|
||||||
|
$hover !disabled:
|
||||||
|
image-color: #ffffff99
|
||||||
|
|
||||||
|
$pressed:
|
||||||
|
image-color: #ffffff44
|
||||||
|
|
||||||
|
$disabled:
|
||||||
|
image-color: #ffffff55
|
||||||
|
|
||||||
EnterGameWindow
|
EnterGameWindow
|
||||||
id: enterGame
|
id: enterGame
|
||||||
!text: tr('Enter Game')
|
!text: tr('Enter Game')
|
||||||
|
@ -41,13 +55,21 @@ EnterGameWindow
|
||||||
margin-top: 8
|
margin-top: 8
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
|
|
||||||
|
ServerListButton
|
||||||
|
id: serverListButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: serverLabel.bottom
|
||||||
|
margin-top: 3
|
||||||
|
@onClick: ServerList.show()
|
||||||
|
|
||||||
TextEdit
|
TextEdit
|
||||||
id: serverHostTextEdit
|
id: serverHostTextEdit
|
||||||
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
|
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: serverListButton.left
|
||||||
anchors.top: serverLabel.bottom
|
anchors.top: serverLabel.bottom
|
||||||
margin-top: 2
|
margin-top: 2
|
||||||
|
margin-right: 4
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
id: protocolLabel
|
id: protocolLabel
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
AddServer = {}
|
||||||
|
|
||||||
|
-- private variables
|
||||||
|
local addServerWindow = nil
|
||||||
|
|
||||||
|
-- public functions
|
||||||
|
function AddServer.init()
|
||||||
|
addServerWindow = g_ui.displayUI('addserver')
|
||||||
|
end
|
||||||
|
|
||||||
|
function AddServer.terminate()
|
||||||
|
addServerWindow:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
function AddServer.add()
|
||||||
|
local host = addServerWindow:getChildById('host'):getText()
|
||||||
|
local port = addServerWindow:getChildById('port'):getText()
|
||||||
|
local protocol = addServerWindow:getChildById('protocol'):getCurrentOption().text
|
||||||
|
|
||||||
|
local added, error = ServerList.add(host, port, protocol)
|
||||||
|
if not added then
|
||||||
|
displayErrorBox(tr('Add Error'), tr(error))
|
||||||
|
else
|
||||||
|
AddServer.hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AddServer.show()
|
||||||
|
addServerWindow:show()
|
||||||
|
addServerWindow:raise()
|
||||||
|
addServerWindow:focus()
|
||||||
|
addServerWindow:lock()
|
||||||
|
end
|
||||||
|
|
||||||
|
function AddServer.hide()
|
||||||
|
addServerWindow:hide()
|
||||||
|
addServerWindow:unlock()
|
||||||
|
end
|
|
@ -0,0 +1,73 @@
|
||||||
|
MainWindow
|
||||||
|
id: addServerWindow
|
||||||
|
!text: tr('New Server')
|
||||||
|
size: 180 180
|
||||||
|
visible: false
|
||||||
|
@onEscape: AddServer.hide()
|
||||||
|
@onEnter: |
|
||||||
|
AddServer.add()
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: hostLabel
|
||||||
|
!text: tr('Host:')
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
margin-bottom: 2
|
||||||
|
|
||||||
|
TextEdit
|
||||||
|
id: host
|
||||||
|
anchors.top: hostLabel.bottom
|
||||||
|
anchors.left: hostLabel.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
auto-focus: first
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: portLabel
|
||||||
|
!text: tr('Port:')
|
||||||
|
anchors.top: host.bottom
|
||||||
|
anchors.left: host.left
|
||||||
|
margin-top: 3
|
||||||
|
margin-bottom: 2
|
||||||
|
|
||||||
|
TextEdit
|
||||||
|
id: port
|
||||||
|
text: 7171
|
||||||
|
anchors.top: portLabel.bottom
|
||||||
|
anchors.left: portLabel.left
|
||||||
|
anchors.right: host.right
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: protocolLabel
|
||||||
|
!text: tr('Protocol:')
|
||||||
|
anchors.top: port.bottom
|
||||||
|
anchors.left: port.left
|
||||||
|
margin-top: 3
|
||||||
|
margin-bottom: 2
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
id: protocol
|
||||||
|
anchors.top: protocolLabel.bottom
|
||||||
|
anchors.left: protocolLabel.left
|
||||||
|
anchors.right: port.right
|
||||||
|
@onSetup: |
|
||||||
|
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
||||||
|
self:addOption(proto)
|
||||||
|
end
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonAdd
|
||||||
|
!text: tr('Add')
|
||||||
|
width: 64
|
||||||
|
anchors.right: parent.horizontalCenter
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
margin-right: 5
|
||||||
|
@onClick: |
|
||||||
|
AddServer.add()
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonCancel
|
||||||
|
!text: tr('Cancel')
|
||||||
|
width: 64
|
||||||
|
anchors.left: parent.horizontalCenter
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: AddServer.hide()
|
|
@ -0,0 +1,127 @@
|
||||||
|
ServerList = {}
|
||||||
|
|
||||||
|
-- private variables
|
||||||
|
local serverListWindow = nil
|
||||||
|
local serverTextList = nil
|
||||||
|
local servers = {}
|
||||||
|
|
||||||
|
-- private functions
|
||||||
|
function getServer(host)
|
||||||
|
for k,server in pairs(servers) do
|
||||||
|
if server.host == host then
|
||||||
|
return server
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getServerKey(host)
|
||||||
|
for k,server in pairs(servers) do
|
||||||
|
if server.host == host then
|
||||||
|
return k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- public functions
|
||||||
|
function ServerList.init()
|
||||||
|
serverListWindow = g_ui.displayUI('serverlist')
|
||||||
|
serverTextList = serverListWindow:getChildById('serverList')
|
||||||
|
|
||||||
|
servers = g_settings.getNode('ServerList') or {}
|
||||||
|
ServerList.load()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.terminate()
|
||||||
|
ServerList.destroy()
|
||||||
|
|
||||||
|
g_settings.setNode('ServerList', servers)
|
||||||
|
|
||||||
|
ServerList = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.load()
|
||||||
|
for k,server in pairs(servers) do
|
||||||
|
ServerList.add(server.host, server.port, server.protocol, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.select()
|
||||||
|
local selected = serverTextList:getFocusedChild()
|
||||||
|
if selected then
|
||||||
|
local server = servers[getServerKey(selected:getId())]
|
||||||
|
if server then
|
||||||
|
EnterGame.setDefaultServer(server.host, server.port, server.protocol)
|
||||||
|
EnterGame.setAccountName(server.account)
|
||||||
|
EnterGame.setPassword(server.password)
|
||||||
|
ServerList.hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.add(host, port, protocol, load)
|
||||||
|
if not load and getServerKey(host) then
|
||||||
|
return false, 'Server already exists'
|
||||||
|
elseif host == '' or port == '' then
|
||||||
|
return false, 'Required fields are missing'
|
||||||
|
end
|
||||||
|
local widget = g_ui.createWidget('ServerWidget', serverTextList)
|
||||||
|
widget:setId(host)
|
||||||
|
|
||||||
|
if not load then
|
||||||
|
servers[table.size(servers)+1] = {
|
||||||
|
host = host,
|
||||||
|
port = port,
|
||||||
|
protocol = protocol,
|
||||||
|
account = '',
|
||||||
|
password = ''
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local details = widget:getChildById('details')
|
||||||
|
details:setText(host..':'..port)
|
||||||
|
|
||||||
|
local proto = widget:getChildById('protocol')
|
||||||
|
proto:setText(protocol)
|
||||||
|
|
||||||
|
connect(widget, { onDoubleClick = function () ServerList.select() return true end } )
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.remove(host)
|
||||||
|
servers[getServerKey(host)] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.destroy()
|
||||||
|
if serverListWindow then
|
||||||
|
serverTextList = nil
|
||||||
|
serverListWindow:destroy()
|
||||||
|
serverListWindow = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.show()
|
||||||
|
if g_game.isOnline() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
serverListWindow:show()
|
||||||
|
serverListWindow:raise()
|
||||||
|
serverListWindow:focus()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.hide()
|
||||||
|
serverListWindow:hide()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.setServerAccount(host, account)
|
||||||
|
local key = getServerKey(host)
|
||||||
|
if servers[key] then
|
||||||
|
servers[key].account = account
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServerList.setServerPassword(host, password)
|
||||||
|
local key = getServerKey(host)
|
||||||
|
if servers[key] then
|
||||||
|
servers[key].password = password
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,18 @@
|
||||||
|
Module
|
||||||
|
name: client_serverlist
|
||||||
|
description: Manages a server list of previously entered servers
|
||||||
|
author: BeniS
|
||||||
|
website: www.otclient.info
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- client_entergame
|
||||||
|
|
||||||
|
@onLoad: |
|
||||||
|
dofile 'serverlist'
|
||||||
|
dofile 'addserver'
|
||||||
|
ServerList.init()
|
||||||
|
AddServer.init()
|
||||||
|
|
||||||
|
@onUnload: |
|
||||||
|
ServerList.terminate()
|
||||||
|
AddServer.terminate()
|
|
@ -0,0 +1,113 @@
|
||||||
|
ServerWidget < UIWidget
|
||||||
|
height: 14
|
||||||
|
background-color: alpha
|
||||||
|
&updateOnStates: |
|
||||||
|
function(self)
|
||||||
|
local children = self:getChildren()
|
||||||
|
for i=1,#children do
|
||||||
|
children[i]:setOn(self:isFocused())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@onFocusChange: self:updateOnStates()
|
||||||
|
@onSetup: self:updateOnStates()
|
||||||
|
|
||||||
|
$focus:
|
||||||
|
background-color: #ffffff22
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: details
|
||||||
|
color: #aaaaaa
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
font: verdana-11px-monochrome
|
||||||
|
text-auto-resize: true
|
||||||
|
background-color: alpha
|
||||||
|
text-offset: 2 0
|
||||||
|
|
||||||
|
$on:
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: protocol
|
||||||
|
color: #ffffff
|
||||||
|
color: #aaaaaa
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: next.left
|
||||||
|
margin-right: 5
|
||||||
|
font: verdana-11px-monochrome
|
||||||
|
text-auto-resize: true
|
||||||
|
background-color: alpha
|
||||||
|
&baseText: '(%s)'
|
||||||
|
|
||||||
|
$on:
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: remove
|
||||||
|
!text: tr('x')
|
||||||
|
width: 12
|
||||||
|
height: 12
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-right: 4
|
||||||
|
margin-top: 1
|
||||||
|
@onClick: |
|
||||||
|
local parent = self:getParent()
|
||||||
|
ServerList.remove(parent:getId())
|
||||||
|
parent:destroy()
|
||||||
|
|
||||||
|
MainWindow
|
||||||
|
id: serverListWindow
|
||||||
|
!text: tr('Server List')
|
||||||
|
size: 340 290
|
||||||
|
visible: false
|
||||||
|
@onEnter: ServerList.select()
|
||||||
|
@onEscape: ServerList.hide()
|
||||||
|
@onSetup: |
|
||||||
|
g_keyboard.bindKeyPress('Up', function() self:getChildById('serverList'):focusPreviousChild(KeyboardFocusReason) end, self)
|
||||||
|
g_keyboard.bindKeyPress('Down', function() self:getChildById('serverList'):focusNextChild(KeyboardFocusReason) end, self)
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: serverList
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: serverListScrollBar.left
|
||||||
|
anchors.bottom: buttonOk.top
|
||||||
|
margin-bottom: 5
|
||||||
|
padding: 1
|
||||||
|
focusable: false
|
||||||
|
vertical-scrollbar: serverListScrollBar
|
||||||
|
auto-focus: first
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: serverListScrollBar
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: buttonOk.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-bottom: 5
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
||||||
|
|
||||||
|
AddButton
|
||||||
|
id: buttonAdd
|
||||||
|
!tooltip: tr('Add new server')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: AddServer.show()
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonOk
|
||||||
|
!text: tr('Select')
|
||||||
|
width: 64
|
||||||
|
anchors.right: next.left
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
margin-right: 10
|
||||||
|
@onClick: ServerList.select()
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonCancel
|
||||||
|
!text: tr('Cancel')
|
||||||
|
width: 64
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: ServerList.hide()
|
|
@ -146,7 +146,7 @@ end
|
||||||
|
|
||||||
function table.size(t)
|
function table.size(t)
|
||||||
local size = 0
|
local size = 0
|
||||||
for i, n in pairs(table) do
|
for i, n in pairs(t) do
|
||||||
size = size + 1
|
size = size + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue