mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-31 06:45:51 +00:00
Merge pull request #118 from gerlofvanek/offers
ui: Refactor offers page / Added TOR <> API / Cache
This commit is contained in:
commit
fe976810e3
9 changed files with 1693 additions and 1411 deletions
|
@ -162,12 +162,13 @@ class BaseApp:
|
|||
socket.getaddrinfo = self.default_socket_getaddrinfo
|
||||
socket.setdefaulttimeout(self.default_socket_timeout)
|
||||
|
||||
def readURL(self, url: str, timeout: int = 120, headers=None) -> bytes:
|
||||
def readURL(self, url: str, timeout: int = 120, headers={}) -> bytes:
|
||||
open_handler = None
|
||||
if self.use_tor_proxy:
|
||||
open_handler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, self.tor_proxy_host, self.tor_proxy_port)
|
||||
opener = urllib.request.build_opener(open_handler) if self.use_tor_proxy else urllib.request.build_opener()
|
||||
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
|
||||
if headers is None:
|
||||
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
|
||||
request = urllib.request.Request(url, headers=headers)
|
||||
return opener.open(request, timeout=timeout).read()
|
||||
|
||||
|
|
|
@ -7716,7 +7716,7 @@ class BasicSwap(BaseApp):
|
|||
exchange_name_to = ci_to.getExchangeName('coingecko.com')
|
||||
ticker_from = ci_from.chainparams()['ticker']
|
||||
ticker_to = ci_to.chainparams()['ticker']
|
||||
headers = {'Connection': 'close'}
|
||||
headers = {'User-Agent': 'Mozilla/5.0', 'Connection': 'close'}
|
||||
rv = {}
|
||||
|
||||
if rate_sources.get('coingecko.com', True):
|
||||
|
|
|
@ -111,7 +111,6 @@ def parse_cmd(cmd: str, type_map: str):
|
|||
|
||||
|
||||
class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def log_error(self, format, *args):
|
||||
super().log_message(format, *args)
|
||||
|
||||
|
@ -145,9 +144,12 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
args_dict['use_tor_proxy'] = True
|
||||
# TODO: Cache value?
|
||||
try:
|
||||
args_dict['tor_established'] = True if get_tor_established_state(swap_client) == '1' else False
|
||||
except Exception:
|
||||
tor_state = get_tor_established_state(swap_client)
|
||||
args_dict['tor_established'] = True if tor_state == '1' else False
|
||||
except Exception as e:
|
||||
args_dict['tor_established'] = False
|
||||
if swap_client.debug:
|
||||
swap_client.log.error(f"Error getting Tor state: {str(e)}")
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
|
||||
if swap_client._show_notifications:
|
||||
|
@ -409,12 +411,10 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
template = env.get_template('index.html')
|
||||
return self.render_template(template, {
|
||||
'refresh': 30,
|
||||
'summary': summary,
|
||||
'use_tor_proxy': swap_client.use_tor_proxy
|
||||
})
|
||||
self.send_response(302)
|
||||
self.send_header('Location', '/offers')
|
||||
self.end_headers()
|
||||
return b''
|
||||
|
||||
def page_404(self, url_split):
|
||||
swap_client = self.server.swap_client
|
||||
|
|
|
@ -38,7 +38,6 @@ from .ui.util import (
|
|||
from .ui.page_offers import postNewOffer
|
||||
from .protocols.xmr_swap_1 import recoverNoScriptTxnWithKey, getChainBSplitKey
|
||||
|
||||
|
||||
def getFormData(post_string: str, is_json: bool):
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
|
@ -763,7 +762,26 @@ def js_help(self, url_split, post_string, is_json) -> bytes:
|
|||
for k in pages:
|
||||
commands.append(k)
|
||||
return bytes(json.dumps({'commands': commands}), 'UTF-8')
|
||||
|
||||
|
||||
def js_readurl(self, url_split, post_string, is_json) -> bytes:
|
||||
swap_client = self.server.swap_client
|
||||
post_data = {} if post_string == '' else getFormData(post_string, is_json)
|
||||
if have_data_entry(post_data, 'url'):
|
||||
url = get_data_entry(post_data, 'url')
|
||||
default_headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
}
|
||||
response = swap_client.readURL(url, headers=default_headers)
|
||||
try:
|
||||
error = json.loads(response.decode())
|
||||
if "Error" in error:
|
||||
return json.dumps({"Error": error['Error']}).encode()
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return response
|
||||
raise ValueError('Requires URL.')
|
||||
|
||||
pages = {
|
||||
'coins': js_coins,
|
||||
|
@ -789,9 +807,9 @@ pages = {
|
|||
'unlock': js_unlock,
|
||||
'lock': js_lock,
|
||||
'help': js_help,
|
||||
'readurl': js_readurl,
|
||||
}
|
||||
|
||||
|
||||
def js_url_to_function(url_split):
|
||||
if len(url_split) > 2:
|
||||
return pages.get(url_split[2], js_404)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<div class="w-full md:w-auto p-3 md:py-0 md:px-6"><a class="inline-block text-coolGray-500 dark:text-gray-300 font-medium" href="https://academy.particl.io/en/latest/basicswap-dex/basicswap_explained.html" target="_blank">BasicSwap Explained</a></div>
|
||||
<div class="w-full md:w-auto p-3 md:py-0 md:px-6"><a class="inline-block text-coolGray-500 dark:text-gray-300 font-medium" href="https://academy.particl.io/en/latest/basicswap-guides/basicswapguides_installation.html" target="_blank">Tutorials and Guides</a></div>
|
||||
<div class="w-full md:w-auto p-3 md:py-0 md:px-6"><a class="inline-block text-coolGray-500 dark:text-gray-300 font-medium" href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank">Get Support</a></div>
|
||||
<div class="w-full md:w-auto p-3 md:py-0 md:px-6"><a class="inline-block text-coolGray-500 dark:text-gray-300 font-medium" href="https://basicswapdex.com/terms" target="_blank">Terms and Conditions</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-1/4 px-4"> </div>
|
||||
|
|
|
@ -519,38 +519,55 @@
|
|||
</section>
|
||||
{% if ws_url %}
|
||||
<script>
|
||||
var ws = new WebSocket("{{ ws_url }}"),
|
||||
// Configuration object
|
||||
const notificationConfig = {
|
||||
showNewOffers: false,
|
||||
showNewBids: true,
|
||||
showBidAccepted: true
|
||||
};
|
||||
|
||||
var ws = new WebSocket("{{ ws_url }}"),
|
||||
floating_div = document.createElement('div');
|
||||
floating_div.classList.add('floatright');
|
||||
messages = document.createElement('ul');
|
||||
messages.setAttribute('id', 'ul_updates');
|
||||
ws.onmessage = function(event) {
|
||||
let json = JSON.parse(event.data);
|
||||
let event_message = 'Unknown event';
|
||||
if (json['event'] == 'new_offer') {
|
||||
floating_div.classList.add('floatright');
|
||||
messages = document.createElement('ul');
|
||||
messages.setAttribute('id', 'ul_updates');
|
||||
|
||||
floating_div.appendChild(messages);
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
let json = JSON.parse(event.data);
|
||||
let event_message = 'Unknown event';
|
||||
let should_display = false;
|
||||
|
||||
if (json['event'] == 'new_offer' && notificationConfig.showNewOffers) {
|
||||
event_message = '<div id="hide"><div id="toast-success" class="flex items-center p-4 mb-4 w-full max-w-xs text-gray-500 bg-white rounded-lg shadow" role="alert"><div class="inline-flex flex-shrink-0 justify-center items-center w-10 h-10 bg-blue-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"><circle cx="5" cy="5" r="4"></circle> <circle cx="19" cy="19" r="4"></circle> <polyline data-cap="butt" points="13,5 21,5 21,11 " stroke="#ffffff"></polyline> <polyline data-cap="butt" points="11,19 3,19 3,13 " stroke="#ffffff"></polyline> <polyline points=" 16,2 13,5 16,8 " stroke="#ffffff"></polyline> <polyline points=" 8,16 11,19 8,22 " stroke="#ffffff"></polyline></g></svg></div><div class="uppercase w-40 ml-3 text-sm font-semibold text-gray-900">New network <a class="underline" href=/offer/' + json['offer_id'] + '>offer</a></div><button type="button" onclick="closeAlert(event)" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-0 focus:outline-none focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8" data-dismiss="#toast-success" aria-label="Close"><span class="sr-only">Close</span><svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg></button></div></div>';
|
||||
}
|
||||
else
|
||||
if (json['event'] == 'new_bid') {
|
||||
should_display = true;
|
||||
}
|
||||
else if (json['event'] == 'new_bid' && notificationConfig.showNewBids) {
|
||||
event_message = '<div id="hide"><div id="toast-success" class="flex items-center p-4 mb-4 w-full max-w-xs text-gray-500 bg-white rounded-lg shadow" role="alert"><div class="inline-flex flex-shrink-0 justify-center items-center w-10 h-10 bg-violet-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round"><rect x="9.843" y="5.379" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -0.7635 13.1569)" width="11.314" height="4.243"></rect> <polyline points="3,23 3,19 15,19 15,23 "></polyline> <line x1="4" y1="15" x2="1" y2="15" stroke="#ffffff"></line> <line x1="5.757" y1="10.757" x2="3.636" y2="8.636" stroke="#ffffff"></line> <line x1="1" y1="23" x2="17" y2="23"></line> <line x1="17" y1="9" x2="23" y2="15"></line></g></svg></div><div class="uppercase w-40 ml-3 text-sm font-normal"><span class="mb-1 text-sm font-semibold text-gray-900"><a class="underline" href=/bid/' + json['bid_id'] + '>New bid</a> on <a class="underline" href=/offer/' + json['offer_id'] + '>offer</a></span></div><button type="button" onclick="closeAlert(event)" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-0 focus:outline-nonefocus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8" data-dismiss="#toast-success" aria-label="Close"><svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg></button></div></div>';
|
||||
}
|
||||
else
|
||||
if (json['event'] == 'bid_accepted') {
|
||||
should_display = true;
|
||||
}
|
||||
else if (json['event'] == 'bid_accepted' && notificationConfig.showBidAccepted) {
|
||||
event_message = '<div id="hide"><div id="toast-success" class="flex items-center p-4 mb-4 w-full max-w-xs text-gray-500 bg-white rounded-lg shadow" role="alert"><div class="inline-flex flex-shrink-0 justify-center items-center w-10 h-10 bg-violet-500 rounded-lg"><svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 24 24"><g fill="#ffffff"><path d="M8.5,20a1.5,1.5,0,0,1-1.061-.439L.379,12.5,2.5,10.379l6,6,13-13L23.621,5.5,9.561,19.561A1.5,1.5,0,0,1,8.5,20Z" fill="#ffffff"></path></g></svg></div><div class="uppercase w-40 ml-3 text-sm font-semibold text-gray-900"><a class="underline" href=/bid/' + json['bid_id'] + '>Bid</a> accepted</div><button type="button" onclick="closeAlert(event)" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-0 focus:outline-none focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8" data-dismiss="#toast-success" aria-label="Close"><span class="sr-only">Close</span><svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg></button></div></div>';
|
||||
}
|
||||
let messages = document.getElementById('ul_updates'),
|
||||
message = document.createElement('li');
|
||||
message.innerHTML = event_message;
|
||||
messages.appendChild(message);
|
||||
};
|
||||
floating_div.appendChild(messages);
|
||||
document.body.appendChild(floating_div);
|
||||
function closeAlert(event){
|
||||
should_display = true;
|
||||
}
|
||||
|
||||
if (should_display) {
|
||||
let messages = document.getElementById('ul_updates'),
|
||||
message = document.createElement('li');
|
||||
message.innerHTML = event_message;
|
||||
messages.appendChild(message);
|
||||
}
|
||||
};
|
||||
|
||||
document.body.appendChild(floating_div);
|
||||
|
||||
function closeAlert(event){
|
||||
let element = event.target;
|
||||
while(element.nodeName !== "BUTTON"){
|
||||
element = element.parentNode;
|
||||
element = element.parentNode;
|
||||
}
|
||||
element.parentNode.parentNode.removeChild(element.parentNode);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,25 +6,25 @@
|
|||
{% if refresh %}
|
||||
<meta http-equiv="refresh" content="{{ refresh }}">
|
||||
{% endif %}
|
||||
<link type="text/css" media="all" href="/static/css/libs/flowbite.min.css" rel="stylesheet" />
|
||||
<link type="text/css" media="all" href="/static/css/libs/tailwind.min.css" rel="stylesheet">
|
||||
<link type="text/css" media="all" href="/static/css/style.css" rel="stylesheet">
|
||||
<script src="/static/js/main.js"></script>
|
||||
<script src="/static/js/libs/flowbite.js"></script>
|
||||
<script>
|
||||
const isDarkMode =
|
||||
localStorage.getItem('color-theme') === 'dark' ||
|
||||
(!localStorage.getItem('color-theme') &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
<link type="text/css" media="all" href="/static/css/libs/flowbite.min.css" rel="stylesheet" />
|
||||
<link type="text/css" media="all" href="/static/css/libs/tailwind.min.css" rel="stylesheet">
|
||||
<link type="text/css" media="all" href="/static/css/style.css" rel="stylesheet">
|
||||
<script src="/static/js/main.js"></script>
|
||||
<script src="/static/js/libs/flowbite.js"></script>
|
||||
<script>
|
||||
const isDarkMode =
|
||||
localStorage.getItem('color-theme') === 'dark' ||
|
||||
(!localStorage.getItem('color-theme') &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
|
||||
if (!localStorage.getItem('color-theme')) {
|
||||
localStorage.setItem('color-theme', isDarkMode ? 'dark' : 'light');
|
||||
}
|
||||
if (!localStorage.getItem('color-theme')) {
|
||||
localStorage.setItem('color-theme', isDarkMode ? 'dark' : 'light');
|
||||
}
|
||||
|
||||
document.documentElement.classList.toggle('dark', isDarkMode);
|
||||
</script>
|
||||
document.documentElement.classList.toggle('dark', isDarkMode);
|
||||
</script>
|
||||
<link rel=icon sizes="32x32" type="image/png" href="/static/images/favicon/favicon-32.png">
|
||||
<title>(BSX) BasicSwap - v{{ version }}</title>
|
||||
<title>(BSX) BasicSwap - v{{ version }}</title>
|
||||
</head>
|
||||
<body class="dark:bg-gray-700">
|
||||
<section class="py-24 md:py-32">
|
||||
|
@ -32,10 +32,10 @@
|
|||
<div class="max-w-sm mx-auto">
|
||||
<div class="mb-3 text-center">
|
||||
<a class="inline-block mb-6" href="#">
|
||||
<img src="/static/images/logos/basicswap-logo.svg" class="h-20 imageshow dark-image">
|
||||
<img src="/static/images/logos/basicswap-logo-dark.svg" class="h-20 imageshow light-image">
|
||||
<img src="/static/images/logos/basicswap-logo.svg" class="h-20 imageshow dark-image">
|
||||
<img src="/static/images/logos/basicswap-logo-dark.svg" class="h-20 imageshow light-image">
|
||||
</a>
|
||||
<p class="text-lg text-coolGray-500 font-medium mb-6 dark:text-white" contenteditable="false">Unlock your wallets</p>
|
||||
<p class="text-lg text-coolGray-500 font-medium mb-6 dark:text-white">Unlock your wallets</p>
|
||||
{% for m in messages %}
|
||||
<section class="py-4" id="messages_{{ m[0] }}" role="alert">
|
||||
<div class="container px-4 mx-auto">
|
||||
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
<form method="post" autocomplete="off">
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-coolGray-800 font-medium dark:text-white" for="" contenteditable="false">Your Password</label>
|
||||
<label class="block mb-2 text-coolGray-800 font-medium dark:text-white" for="">Your Password</label>
|
||||
<div class="relative w-full">
|
||||
<div class="absolute inset-y-0 right-0 flex items-center px-2">
|
||||
<input class="hidden js-password-toggle" id="toggle" type="checkbox" />
|
||||
|
@ -94,41 +94,40 @@
|
|||
</div>
|
||||
<button type="submit" name="unlock" value="Unlock" class="appearance-none focus:outline-none inline-block py-3 px-7 mb-6 w-full text-base text-blue-50 font-medium text-center leading-6 bg-blue-500 hover:bg-blue-600 focus:ring-0 rounded-md shadow-sm">Unlock</button>
|
||||
<p class="text-center">
|
||||
<span class="text-xs font-medium dark:text-white" contenteditable="false">Need help?</span>
|
||||
<a class="inline-block text-xs font-medium text-blue-500 hover:text-blue-600 hover:underline" href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank" contenteditable="false">Help / Tutorials</a>
|
||||
<span class="text-xs font-medium dark:text-white">Need help?</span>
|
||||
<a class="inline-block text-xs font-medium text-blue-500 hover:text-blue-600 hover:underline" href="https://academy.particl.io/en/latest/faq/get_support.html" target="_blank">Help / Tutorials</a>
|
||||
</p>
|
||||
<p class="text-center">
|
||||
<span class="text-xs font-medium text-coolGray-500 dark:text-gray-500" contenteditable="false">{{ title }}</span>
|
||||
<span class="text-xs font-medium text-coolGray-500 dark:text-gray-500">{{ title }}</span>
|
||||
</p>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
const passwordToggle = document.querySelector('.js-password-toggle')
|
||||
passwordToggle.addEventListener('change', function() {
|
||||
const password = document.querySelector('.js-password'),
|
||||
passwordLabel = document.querySelector('.js-password-label')
|
||||
if (password.type === 'password') {
|
||||
password.type = 'text'
|
||||
passwordLabel.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g fill="#8896ab"><path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z" fill="#8896ab"></path><path d="M12,3C6.292,3,2.1,8.062.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z" fill="#8896ab"></path><path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path></g></svg>'
|
||||
} else {
|
||||
password.type = 'password'
|
||||
passwordLabel.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g fill="#8896ab" ><path d="M23.444,10.239C21.905,8.062,17.708,3,12,3S2.1,8.062.555,10.24a3.058,3.058,0,0,0,0,3.52h0C2.1,15.938,6.292,21,12,21s9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z" fill="#8896ab"></path></g></svg>'
|
||||
}
|
||||
password.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<script>
|
||||
window.onload = () => {
|
||||
toggleImages();
|
||||
};
|
||||
|
||||
document.getElementById('theme-toggle').addEventListener('click', () => {
|
||||
toggleImages();
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Password toggle functionality
|
||||
const passwordToggle = document.querySelector('.js-password-toggle');
|
||||
if (passwordToggle) {
|
||||
passwordToggle.addEventListener('change', function() {
|
||||
const password = document.querySelector('.js-password');
|
||||
const passwordLabel = document.querySelector('.js-password-label');
|
||||
if (password && passwordLabel) {
|
||||
if (password.type === 'password') {
|
||||
password.type = 'text';
|
||||
passwordLabel.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g fill="#8896ab"><path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z" fill="#8896ab"></path><path d="M12,3C6.292,3,2.1,8.062.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z" fill="#8896ab"></path><path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path></g></svg>';
|
||||
} else {
|
||||
password.type = 'password';
|
||||
passwordLabel.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><g fill="#8896ab" ><path d="M23.444,10.239C21.905,8.062,17.708,3,12,3S2.1,8.062.555,10.24a3.058,3.058,0,0,0,0,3.52h0C2.1,15.938,6.292,21,12,21s9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z" fill="#8896ab"></path></g></svg>';
|
||||
}
|
||||
password.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Image toggling function
|
||||
function toggleImages() {
|
||||
const html = document.querySelector('html');
|
||||
const darkImages = document.querySelectorAll('.dark-image');
|
||||
|
@ -148,17 +147,8 @@ passwordToggle.addEventListener('change', function() {
|
|||
img.style.display = display;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||
|
||||
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
themeToggleLightIcon.classList.remove('hidden');
|
||||
} else {
|
||||
themeToggleDarkIcon.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Theme toggle functionality
|
||||
function setTheme(theme) {
|
||||
if (theme === 'light') {
|
||||
document.documentElement.classList.remove('dark');
|
||||
|
@ -169,17 +159,33 @@ passwordToggle.addEventListener('change', function() {
|
|||
}
|
||||
}
|
||||
|
||||
document.getElementById('theme-toggle').addEventListener('click', () => {
|
||||
if (localStorage.getItem('color-theme') === 'dark') {
|
||||
setTheme('light');
|
||||
} else {
|
||||
setTheme('dark');
|
||||
}
|
||||
themeToggleDarkIcon.classList.toggle('hidden');
|
||||
themeToggleLightIcon.classList.toggle('hidden');
|
||||
toggleImages();
|
||||
});
|
||||
// Initialize theme
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
if (themeToggle && themeToggleDarkIcon && themeToggleLightIcon) {
|
||||
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
themeToggleLightIcon.classList.remove('hidden');
|
||||
} else {
|
||||
themeToggleDarkIcon.classList.remove('hidden');
|
||||
}
|
||||
|
||||
themeToggle.addEventListener('click', () => {
|
||||
if (localStorage.getItem('color-theme') === 'dark') {
|
||||
setTheme('light');
|
||||
} else {
|
||||
setTheme('dark');
|
||||
}
|
||||
themeToggleDarkIcon.classList.toggle('hidden');
|
||||
themeToggleLightIcon.classList.toggle('hidden');
|
||||
toggleImages();
|
||||
});
|
||||
}
|
||||
|
||||
// Call toggleImages on load
|
||||
toggleImages();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
def extract_data(bytes_in):
|
||||
if bytes_in is None:
|
||||
return None
|
||||
str_in = bytes_in.decode('utf-8')
|
||||
start = str_in.find('=')
|
||||
if start < 0:
|
||||
|
@ -24,28 +26,22 @@ def get_tor_established_state(swap_client):
|
|||
def page_tor(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
page_data = {}
|
||||
|
||||
try:
|
||||
page_data['circuit_established'] = get_tor_established_state(swap_client)
|
||||
except Exception:
|
||||
page_data['circuit_established'] = 'error'
|
||||
|
||||
try:
|
||||
rv = swap_client.torControl('GETINFO traffic/read')
|
||||
page_data['bytes_written'] = extract_data(rv)
|
||||
except Exception:
|
||||
page_data['bytes_written'] = 'error'
|
||||
|
||||
try:
|
||||
rv = swap_client.torControl('GETINFO traffic/written')
|
||||
page_data['bytes_read'] = extract_data(rv)
|
||||
except Exception:
|
||||
page_data['bytes_read'] = 'error'
|
||||
|
||||
messages = []
|
||||
|
||||
template = self.server.env.get_template('tor.html')
|
||||
return self.render_template(template, {
|
||||
'messages': messages,
|
||||
|
|
Loading…
Reference in a new issue