diff --git a/onionshare/web/chat_mode.py b/onionshare/web/chat_mode.py index d07eba81..6b35b051 100644 --- a/onionshare/web/chat_mode.py +++ b/onionshare/web/chat_mode.py @@ -69,12 +69,7 @@ class ChatModeWeb: ) self.web.add_request(self.web.REQUEST_LOAD, request.path) - r = make_response( - jsonify( - username=session.get("name"), - success=True, - ) - ) + r = make_response(jsonify(username=session.get("name"), success=True,)) return self.web.add_security_headers(r) @self.web.socketio.on("joined", namespace="/chat") @@ -86,6 +81,7 @@ class ChatModeWeb: emit( "status", { + "username": session.get("name"), "msg": "{} has joined.".format(session.get("name")), "connected_users": self.connected_users, "user": session.get("name"), @@ -99,7 +95,7 @@ class ChatModeWeb: The message is sent to all people in the room.""" emit( "message", - {"msg": "{}: {}".format(session.get("name"), message["msg"])}, + {"username": session.get("name"), "msg": message["msg"]}, room=session.get("room"), ) diff --git a/poetry.lock b/poetry.lock index 07693b0c..7dd361aa 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,6 +6,14 @@ optional = false python-versions = "*" version = "0.17" +[[package]] +category = "dev" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" +optional = false +python-versions = "*" +version = "1.4.4" + [[package]] category = "dev" description = "Atomic file writes." @@ -28,6 +36,26 @@ dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.int docs = ["sphinx", "zope.interface"] tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +[[package]] +category = "dev" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6" +version = "19.10b0" + +[package.dependencies] +appdirs = "*" +attrs = ">=18.1.0" +click = ">=6.5" +pathspec = ">=0.6,<1" +regex = "*" +toml = ">=0.9.4" +typed-ast = ">=1.4.0" + +[package.extras] +d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] + [[package]] category = "main" description = "Python package for providing Mozilla's CA Bundle." @@ -249,6 +277,14 @@ version = "20.4" pyparsing = ">=2.0.2" six = "*" +[[package]] +category = "dev" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.0" + [[package]] category = "main" description = "Python PE parsing module" @@ -457,6 +493,14 @@ maintainer = ["zest.releaser"] pil = ["pillow"] test = ["pytest", "pytest-cov", "mock"] +[[package]] +category = "dev" +description = "Alternative regular expression module, to replace re." +name = "regex" +optional = false +python-versions = "*" +version = "2020.7.14" + [[package]] category = "main" description = "Python HTTP for Humans." @@ -499,6 +543,14 @@ optional = false python-versions = "*" version = "0.10.1" +[[package]] +category = "dev" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.4.1" + [[package]] category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." @@ -538,7 +590,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["jaraco.itertools", "func-timeout"] [metadata] -content-hash = "de18641607a5f3bf11a3051b84eb8a02d4263f435f3554c1aa5860136011cbf3" +content-hash = "04baf07d49586f9567f78935d759b4245d75ed42cba8bdfe0bdb6a3bc9533aee" lock-version = "1.0" python-versions = "^3.7" @@ -547,6 +599,10 @@ altgraph = [ {file = "altgraph-0.17-py2.py3-none-any.whl", hash = "sha256:c623e5f3408ca61d4016f23a681b9adb100802ca3e3da5e718915a9e4052cebe"}, {file = "altgraph-0.17.tar.gz", hash = "sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa"}, ] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -555,6 +611,10 @@ attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, ] +black = [ + {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, + {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, +] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, @@ -684,6 +744,10 @@ packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, ] +pathspec = [ + {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, + {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, +] pefile = [ {file = "pefile-2019.4.18.tar.gz", hash = "sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"}, ] @@ -793,6 +857,29 @@ qrcode = [ {file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"}, {file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"}, ] +regex = [ + {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, + {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, + {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, + {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, + {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, + {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, + {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, + {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, + {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, +] requests = [ {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, @@ -808,6 +895,29 @@ toml = [ {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, ] +typed-ast = [ + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, + {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, + {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, + {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, + {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, +] urllib3 = [ {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, diff --git a/pyproject.toml b/pyproject.toml index cc2d9bc4..171f7c47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ six = "*" urllib3 = "*" setuptools = "*" pyinstaller = {version = "*", platform = "darwin"} +black = {version = "^19.10b0", allow-prereleases = true} [build-system] requires = ["poetry>=0.12"] diff --git a/share/static/css/style.css b/share/static/css/style.css index ec53e8c1..ee3d1760 100644 --- a/share/static/css/style.css +++ b/share/static/css/style.css @@ -206,6 +206,16 @@ ul.breadcrumbs li a:link, ul.breadcrumbs li a:visited { padding: 0 1rem; } +.chat-wrapper .username { + font-weight: bold; + display: block; +} +.chat-wrapper .message { + font-weight: normal; + display: block; + margin-bottom: 0.3em; +} + .chat-wrapper .chat-form { display: flex; } diff --git a/share/static/js/chat.js b/share/static/js/chat.js index 8bbcc8ec..95cd5d8a 100644 --- a/share/static/js/chat.js +++ b/share/static/js/chat.js @@ -1,5 +1,5 @@ -$(function(){ - $(document).ready(function(){ +$(function () { + $(document).ready(function () { $('.chat-container').removeClass('no-js'); var socket = io.connect('http://' + document.domain + ':' + location.port + '/chat'); @@ -8,43 +8,45 @@ $(function(){ // On browser connect, emit a socket event to be added to // room and assigned random username - socket.on('connect', function() { + socket.on('connect', function () { socket.emit('joined', {}); }); // Triggered on any status change by any user, such as some // user joined, or changed username, or left, etc. - socket.on('status', function(data) { + socket.on('status', function (data) { addMessageToRoom(data, current_username, 'status'); + console.log(data, current_username); }); // Triggered when message is received from a user. Even when sent // by self, it get triggered after the server sends back the emit. - socket.on('message', function(data) { + socket.on('message', function (data) { addMessageToRoom(data, current_username, 'chat'); + console.log(data, current_username); }); // Triggered when disconnected either by server stop or timeout - socket.on('disconnect', function(data) { - addMessageToRoom({'msg': 'The chat server is disconnected.'}, current_username, 'status'); + socket.on('disconnect', function (data) { + addMessageToRoom({ 'msg': 'The chat server is disconnected.' }, current_username, 'status'); }) - socket.on('connect_error', function(error) { + socket.on('connect_error', function (error) { console.log("error"); }) // Trigger new message on enter or click of send message button. - $('#new-message').on('keypress', function(e) { + $('#new-message').on('keypress', function (e) { var code = e.keyCode || e.which; if (code == 13) { emitMessage(socket); } }); - $('#send-button').on('click', function(e) { + $('#send-button').on('click', function (e) { emitMessage(socket); }); // Keep buttons disabled unless changed or not empty - $('#username').on('keyup',function(event) { + $('#username').on('keyup', function (event) { if ($('#username').val() !== '' && $('#username').val() !== current_username) { $('#update-username').removeAttr('disabled'); if (event.keyCode == 13) { @@ -56,7 +58,7 @@ $(function(){ }); // Update username - $('#update-username').on('click', function() { + $('#update-username').on('click', function () { current_username = updateUsername(socket); }); @@ -69,7 +71,7 @@ $(function(){ }); }); -var addMessageToRoom = function(data, current_username, messageType) { +var addMessageToRoom = function (data, current_username, messageType) { var scrollDiff = getScrollDiffBefore(); if (messageType === 'status') { addStatusMessage(data.msg); @@ -77,28 +79,28 @@ var addMessageToRoom = function(data, current_username, messageType) { addUserList(data.connected_users, current_username); } } else if (messageType === 'chat') { - addChatMessage(data.msg) + addChatMessage(data.username, data.msg) } scrollBottomMaybe(scrollDiff); } -var emitMessage = function(socket) { +var emitMessage = function (socket) { var text = $('#new-message').val(); $('#new-message').val(''); $('#chat').scrollTop($('#chat')[0].scrollHeight); - socket.emit('text', {msg: text}); + socket.emit('text', { msg: text }); } -var updateUsername = function(socket) { +var updateUsername = function (socket) { var username = $('#username').val(); - socket.emit('update_username', {username: username}); + socket.emit('update_username', { username: username }); $.ajax({ method: 'POST', url: `http://${document.domain}:${location.port}/update-session-username`, contentType: 'application/json', dataType: 'json', - data: JSON.stringify({'username': username}) - }).done(function(response) { + data: JSON.stringify({ 'username': username }) + }).done(function (response) { console.log(response); }); $('#update-username').attr('disabled', true); @@ -109,10 +111,10 @@ var updateUsername = function(socket) { /********* Util Functions ***********/ /************************************/ -var createUserListHTML = function(connected_users, current_user) { +var createUserListHTML = function (connected_users, current_user) { var userListHTML = ''; connected_users.sort(); - connected_users.forEach(function(username) { + connected_users.forEach(function (username) { if (username !== current_user) { userListHTML += `
  • ${sanitizeHTML(username)}
  • `; } @@ -120,11 +122,11 @@ var createUserListHTML = function(connected_users, current_user) { return userListHTML; } -var getScrollDiffBefore = function() { +var getScrollDiffBefore = function () { return $('#chat').scrollTop() - ($('#chat')[0].scrollHeight - $('#chat')[0].offsetHeight); } -var scrollBottomMaybe = function(scrollDiff) { +var scrollBottomMaybe = function (scrollDiff) { // Scrolls to bottom if the user is scrolled at bottom // if the user has scrolled upp, it wont scroll at bottom. // Note: when a user themselves send a message, it will still @@ -134,17 +136,17 @@ var scrollBottomMaybe = function(scrollDiff) { } } -var addStatusMessage = function(message) { +var addStatusMessage = function (message) { $('#chat').append( `

    ${sanitizeHTML(message)}

    ` ); } -var addChatMessage = function(message) { - $('#chat').append(`

    ${sanitizeHTML(message)}

    `); +var addChatMessage = function (username, message) { + $('#chat').append(`

    ${sanitizeHTML(username)}${sanitizeHTML(message)}

    `); } -var addUserList = function(connected_users, current_username) { +var addUserList = function (connected_users, current_username) { $('#user-list').html( createUserListHTML( connected_users, @@ -153,8 +155,8 @@ var addUserList = function(connected_users, current_username) { ); } -var sanitizeHTML = function(str) { - var temp = document.createElement('span'); - temp.textContent = str; - return temp.innerHTML; +var sanitizeHTML = function (str) { + var temp = document.createElement('span'); + temp.textContent = str; + return temp.innerHTML; }; diff --git a/share/templates/chat.html b/share/templates/chat.html index 1c40065e..102f1027 100644 --- a/share/templates/chat.html +++ b/share/templates/chat.html @@ -1,46 +1,49 @@ - - OnionShare - - - - -
    - -

    OnionShare

    -
    - - -
    -
    -
    - - -
    - -
    -
    -

    Chat Messages

    - -
    - -
    -

    -

    -
    + + OnionShare + + + + + +
    + +

    OnionShare

    +
    + + +
    +
    +
    + +
    +
      +
    - - - - - +
    +

    Chat Messages

    + +
    + +
    +

    +

    +
    + +
    +
    + + + + + + \ No newline at end of file