Merge branch 'develop' into 1305_receive_messages

This commit is contained in:
Micah Lee 2021-04-29 16:58:33 -07:00
commit 343e1be3d0
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
21 changed files with 367 additions and 84 deletions

View File

@ -43,57 +43,7 @@ def main(cwd=None):
onionshare uses. onionshare uses.
""" """
common = Common() common = Common()
common.display_banner()
# Display OnionShare banner
print(f"OnionShare {common.version} | https://onionshare.org/")
reset = "\033[0m"
purple = "\33[95m"
print(purple)
print(" @@@@@@@@@ ")
print(" @@@@@@@@@@@@@@@@@@@ ")
print(" @@@@@@@@@@@@@@@@@@@@@@@@@ ")
print(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ")
print(
" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ___ _ "
)
print(
" @@@@@@ @@@@@@@@@@@@@ / _ \\ (_) "
)
print(
" @@@@ @ @@@@@@@@@@@ | | | |_ __ _ ___ _ __ "
)
print(
" @@@@@@@@ @@@@@@@@@@ | | | | '_ \\| |/ _ \\| '_ \\ "
)
print(
" @@@@@@@@@@@@ @@@@@@@@@@ \\ \\_/ / | | | | (_) | | | | "
)
print(
" @@@@@@@@@@@@@@@@ @@@@@@@@@ \\___/|_| |_|_|\\___/|_| |_| "
)
print(
" @@@@@@@@@ @@@@@@@@@@@@@@@@ _____ _ "
)
print(
" @@@@@@@@@@ @@@@@@@@@@@@ / ___| | "
)
print(
" @@@@@@@@@@ @@@@@@@@ \\ `--.| |__ __ _ _ __ ___ "
)
print(
" @@@@@@@@@@@ @ @@@@ `--. \\ '_ \\ / _` | '__/ _ \\"
)
print(
" @@@@@@@@@@@@@ @@@@@@ /\\__/ / | | | (_| | | | __/"
)
print(
" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \\____/|_| |_|\\__,_|_| \\___|"
)
print(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ")
print(" @@@@@@@@@@@@@@@@@@@@@@@@@ ")
print(" @@@@@@@@@@@@@@@@@@@ ")
print(" @@@@@@@@@ ")
print(reset)
# OnionShare CLI in OSX needs to change current working directory (#132) # OnionShare CLI in OSX needs to change current working directory (#132)
if common.platform == "Darwin": if common.platform == "Darwin":
@ -143,6 +93,12 @@ def main(cwd=None):
help="Filename of persistent session", help="Filename of persistent session",
) )
# General args # General args
parser.add_argument(
"--title",
metavar="TITLE",
default=None,
help="Set a title",
)
parser.add_argument( parser.add_argument(
"--public", "--public",
action="store_true", action="store_true",
@ -246,6 +202,7 @@ def main(cwd=None):
connect_timeout = int(args.connect_timeout) connect_timeout = int(args.connect_timeout)
config_filename = args.config config_filename = args.config
persistent_filename = args.persistent persistent_filename = args.persistent
title = args.title
public = bool(args.public) public = bool(args.public)
autostart_timer = int(args.autostart_timer) autostart_timer = int(args.autostart_timer)
autostop_timer = int(args.autostop_timer) autostop_timer = int(args.autostop_timer)
@ -294,6 +251,7 @@ def main(cwd=None):
if mode_settings.just_created: if mode_settings.just_created:
# This means the mode settings were just created, not loaded from disk # This means the mode settings were just created, not loaded from disk
mode_settings.set("general", "title", title)
mode_settings.set("general", "public", public) mode_settings.set("general", "public", public)
mode_settings.set("general", "autostart_timer", autostart_timer) mode_settings.set("general", "autostart_timer", autostart_timer)
mode_settings.set("general", "autostop_timer", autostop_timer) mode_settings.set("general", "autostop_timer", autostop_timer)

View File

@ -44,8 +44,13 @@ class Common:
""" """
C_RESET = "\033[0m" C_RESET = "\033[0m"
C_BG_PURPLE = "\033[45m"
C_BOLD = "\033[01m"
C_WHITE = "\033[97m"
C_LIGHTGRAY = "\033[37m" C_LIGHTGRAY = "\033[37m"
C_DARKGRAY = "\033[90m" C_DARKGRAY = "\033[90m"
C_LIGHTPURPLE = "\033[95m"
C_DARKPURPLE = "\033[35m"
def __init__(self, verbose=False): def __init__(self, verbose=False):
self.verbose = verbose self.verbose = verbose
@ -59,6 +64,248 @@ class Common:
with open(self.get_resource_path("version.txt")) as f: with open(self.get_resource_path("version.txt")) as f:
self.version = f.read().strip() self.version = f.read().strip()
def display_banner(self):
"""
Raw ASCII art example:
* *
*
*
-+-
* *
*
-+- *
v2.3.1
https://onionshare.org/
"""
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ "╭───────────────────────────────────────────╮"
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_WHITE
+ "▄▄█████▄▄"
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▄████▀▀▀████▄"
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▀▀█▀ ▀██▄ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_WHITE
+ "▄█▄ ▀██▄ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▄█████▄ ███"
+ self.C_LIGHTPURPLE
+ " -+- "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ███ ▀█████▀ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▀██▄ ▀█▀ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_WHITE
+ "▀██▄ ▄█▄▄"
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTPURPLE
+ " * "
+ self.C_WHITE
+ "▀████▄▄▄████▀ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▀▀█████▀▀ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTPURPLE
+ " -+- * "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▄▀▄ ▄▀▀ █ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " █ █ ▀ ▀▄ █ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " █ █ █▀▄ █ ▄▀▄ █▀▄ ▀▄ █▀▄ ▄▀▄ █▄▀ ▄█▄ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_WHITE
+ " ▀▄▀ █ █ █ ▀▄▀ █ █ ▄▄▀ █ █ ▀▄█ █ ▀▄▄ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ "│ │"
+ self.C_RESET
)
left_spaces = (43 - len(self.version) - 1) // 2
right_spaces = left_spaces
if left_spaces + len(self.version) + right_spaces < 43:
right_spaces += 1
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTGRAY
+ f"{' '*left_spaces}v{self.version}{' '*right_spaces}"
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ "│ │"
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ ""
+ self.C_LIGHTGRAY
+ " https://onionshare.org/ "
+ self.C_LIGHTGRAY
+ ""
+ self.C_RESET
)
print(
self.C_BG_PURPLE
+ self.C_LIGHTGRAY
+ "╰───────────────────────────────────────────╯"
+ self.C_RESET
)
print()
def load_settings(self, config=None): def load_settings(self, config=None):
""" """
Loading settings, optionally from a custom config json file. Loading settings, optionally from a custom config json file.
@ -130,16 +377,24 @@ class Common:
try: try:
appdata = os.environ["APPDATA"] appdata = os.environ["APPDATA"]
onionshare_data_dir = f"{appdata}\\OnionShare" onionshare_data_dir = f"{appdata}\\OnionShare"
except: except Exception:
# If for some reason we don't have the 'APPDATA' environment variable # If for some reason we don't have the 'APPDATA' environment variable
# (like running tests in Linux while pretending to be in Windows) # (like running tests in Linux while pretending to be in Windows)
onionshare_data_dir = os.path.expanduser("~/.config/onionshare") try:
xdg_config_home = os.environ["XDG_CONFIG_HOME"]
onionshare_data_dir = f"{xdg_config_home}/onionshare"
except:
onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
elif self.platform == "Darwin": elif self.platform == "Darwin":
onionshare_data_dir = os.path.expanduser( onionshare_data_dir = os.path.expanduser(
"~/Library/Application Support/OnionShare" "~/Library/Application Support/OnionShare"
) )
else: else:
onionshare_data_dir = os.path.expanduser("~/.config/onionshare") try:
xdg_config_home = os.environ["XDG_CONFIG_HOME"]
onionshare_data_dir = f"{xdg_config_home}/onionshare"
except:
onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
# Modify the data dir if running tests # Modify the data dir if running tests
if getattr(sys, "onionshare_test_mode", False): if getattr(sys, "onionshare_test_mode", False):
@ -257,7 +512,7 @@ class Common:
try: try:
tmpsock.bind(("127.0.0.1", random.randint(min_port, max_port))) tmpsock.bind(("127.0.0.1", random.randint(min_port, max_port)))
break break
except OSError as e: except OSError:
pass pass
_, port = tmpsock.getsockname() _, port = tmpsock.getsockname()
return port return port

View File

@ -42,6 +42,7 @@ class ModeSettings:
}, },
"persistent": {"mode": None, "enabled": False}, "persistent": {"mode": None, "enabled": False},
"general": { "general": {
"title": None,
"public": False, "public": False,
"autostart_timer": False, "autostart_timer": False,
"autostop_timer": False, "autostop_timer": False,

View File

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>{% if title %}{{ title }}{% else %}OnionShare Chat{% endif %}</title>
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
@ -11,7 +11,7 @@
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>{% if title %}{{ title }}{% else %}OnionShare Chat{% endif %}</h1>
</header> </header>
<noscript> <noscript>
<p> <p>

View File

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>{% if title %}{{ title }}{% else %}OnionShare{% endif %}</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" /> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
@ -14,7 +14,7 @@
<header class="d-flex"> <header class="d-flex">
<div class="logo-container"> <div class="logo-container">
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>{% if title %}{{ title }}{% else %}OnionShare{% endif %}</h1>
</div> </div>
</header> </header>
@ -57,4 +57,4 @@
</div> </div>
</body> </body>
</html> </html>

View File

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>{% if title %}{{ title }}{% else %}OnionShare Dropbox{% endif %}</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
@ -13,7 +13,7 @@
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>{% if title %}{{ title }}{% else %}OnionShare Dropbox{% endif %}</h1>
</header> </header>
<div class="upload-wrapper"> <div class="upload-wrapper">

View File

@ -2,9 +2,9 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>{% if title %}{{ title }}{% else %}OnionShare{% endif %}</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
<meta name="onionshare-filename" content="{{ filename }}"> <meta name="onionshare-filename" content="{{ filename }}">
@ -16,7 +16,7 @@
<header class="d-flex"> <header class="d-flex">
<div class="logo-container"> <div class="logo-container">
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>{% if title %}{{ title }}{% else %}OnionShare{% endif %}</h1>
</div> </div>
<div class="information d-flex"> <div class="information d-flex">
<div>Total size: <strong>{{ filesize_human }}</strong> {% if is_zipped %} (compressed){% endif %}</div> <div>Total size: <strong>{{ filesize_human }}</strong> {% if is_zipped %} (compressed){% endif %}</div>
@ -25,10 +25,11 @@
</header> </header>
{% if breadcrumbs %} {% if breadcrumbs %}
<ul class="breadcrumbs"> <ul class="breadcrumbs">
{% for breadcrumb in breadcrumbs %}<li><a href="{{ breadcrumb[1] }}">{{ breadcrumb[0] }}</a> <span class="sep">&#8227;</span></li>{% endfor %}<li>{{ breadcrumbs_leaf }}</li> {% for breadcrumb in breadcrumbs %}<li><a href="{{ breadcrumb[1] }}">{{ breadcrumb[0] }}</a> <span
</ul> class="sep">&#8227;</span></li>{% endfor %}<li>{{ breadcrumbs_leaf }}</li>
{% endif %} </ul>
{% endif %}
<div class="file-list" id="file-list"> <div class="file-list" id="file-list">
<div class="d-flex"> <div class="d-flex">
@ -66,4 +67,4 @@
<script async src="{{ static_url_path }}/js/send.js" charset="utf-8"></script> <script async src="{{ static_url_path }}/js/send.js" charset="utf-8"></script>
</body> </body>
</html> </html>

View File

@ -4,7 +4,7 @@
<head> <head>
<title>OnionShare is closed</title> <title>OnionShare is closed</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
@ -12,7 +12,7 @@
<body> <body>
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>{% if title %}{{ title }}{% else %}OnionShare{% endif %}</h1>
</header> </header>
<div class="info-wrapper"> <div class="info-wrapper">
@ -24,4 +24,4 @@
</div> </div>
</body> </body>
</html> </html>

View File

@ -18,12 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from flask import ( from flask import request, render_template, make_response, jsonify, session
request,
render_template,
make_response,
jsonify,
session)
from flask_socketio import emit, join_room, leave_room from flask_socketio import emit, join_room, leave_room
@ -72,6 +67,7 @@ class ChatModeWeb:
"chat.html", "chat.html",
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
username=session.get("name"), username=session.get("name"),
title=self.web.settings.get("general", "title"),
) )
) )
return self.web.add_security_headers(r) return self.web.add_security_headers(r)

View File

@ -79,6 +79,7 @@ class ReceiveModeWeb:
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
disable_text=self.web.settings.get("receive", "disable_text"), disable_text=self.web.settings.get("receive", "disable_text"),
disable_files=self.web.settings.get("receive", "disable_files"), disable_files=self.web.settings.get("receive", "disable_files"),
title=self.web.settings.get("general", "title"),
) )
) )
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
@ -234,6 +235,7 @@ class ReceiveModeWeb:
"new_body": render_template( "new_body": render_template(
"thankyou.html", "thankyou.html",
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
title=self.web.settings.get("general", "title"),
) )
} }
) )
@ -242,6 +244,7 @@ class ReceiveModeWeb:
r = make_response( r = make_response(
render_template("thankyou.html"), render_template("thankyou.html"),
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
title=self.web.settings.get("general", "title"),
) )
return self.web.add_security_headers(r) return self.web.add_security_headers(r)

View File

@ -390,6 +390,7 @@ class ShareModeWeb(SendBaseModeWeb):
is_zipped=self.is_zipped, is_zipped=self.is_zipped,
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
download_individual_files=self.download_individual_files, download_individual_files=self.download_individual_files,
title=self.web.settings.get("general", "title"),
) )
) )

View File

@ -310,7 +310,7 @@ class Web:
if not self.settings.get("website", "disable_csp") or self.mode != "website": if not self.settings.get("website", "disable_csp") or self.mode != "website":
r.headers.set( r.headers.set(
"Content-Security-Policy", "Content-Security-Policy",
"default-src 'self'; style-src 'self'; script-src 'self'; img-src 'self' data:;", "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;",
) )
return r return r

View File

@ -60,6 +60,7 @@ class WebsiteModeWeb(SendBaseModeWeb):
breadcrumbs=breadcrumbs, breadcrumbs=breadcrumbs,
breadcrumbs_leaf=breadcrumbs_leaf, breadcrumbs_leaf=breadcrumbs_leaf,
static_url_path=self.web.static_url_path, static_url_path=self.web.static_url_path,
title=self.web.settings.get("general", "title"),
) )
) )

View File

@ -75,14 +75,12 @@ def main():
The main() function implements all of the logic that the GUI version of onionshare uses. The main() function implements all of the logic that the GUI version of onionshare uses.
""" """
common = Common() common = Common()
common.display_banner()
# Required for macOS Big Sur: https://stackoverflow.com/a/64878899 # Required for macOS Big Sur: https://stackoverflow.com/a/64878899
if common.platform == "Darwin": if common.platform == "Darwin":
os.environ["QT_MAC_WANTS_LAYER"] = "1" os.environ["QT_MAC_WANTS_LAYER"] = "1"
# Display OnionShare banner
print(f"OnionShare {common.version} | https://onionshare.org/")
# Start the Qt app # Start the Qt app
global qtapp global qtapp
qtapp = Application(common) qtapp = Application(common)

View File

@ -165,6 +165,7 @@
"gui_quit_warning_cancel": "Cancel", "gui_quit_warning_cancel": "Cancel",
"mode_settings_advanced_toggle_show": "Show advanced settings", "mode_settings_advanced_toggle_show": "Show advanced settings",
"mode_settings_advanced_toggle_hide": "Hide advanced settings", "mode_settings_advanced_toggle_hide": "Hide advanced settings",
"mode_settings_title_label": "Custom title",
"mode_settings_persistent_checkbox": "Save this tab, and automatically open it when I open OnionShare", "mode_settings_persistent_checkbox": "Save this tab, and automatically open it when I open OnionShare",
"mode_settings_public_checkbox": "Don't use a password", "mode_settings_public_checkbox": "Don't use a password",
"mode_settings_autostart_timer_checkbox": "Start onion service at scheduled time", "mode_settings_autostart_timer_checkbox": "Start onion service at scheduled time",

View File

@ -68,6 +68,11 @@ class ChatMode(Mode):
self.image = QtWidgets.QWidget() self.image = QtWidgets.QWidget()
self.image.setLayout(image_layout) self.image.setLayout(image_layout)
# Set title placeholder
self.mode_settings_widget.title_lineedit.setPlaceholderText(
strings._("gui_tab_name_chat")
)
# Server status # Server status
self.server_status.set_mode("chat") self.server_status.set_mode("chat")
self.server_status.server_started_finished.connect(self.update_primary_action) self.server_status.server_started_finished.connect(self.update_primary_action)

View File

@ -57,6 +57,16 @@ class ModeSettingsWidget(QtWidgets.QWidget):
else: else:
self.public_checkbox.setCheckState(QtCore.Qt.Unchecked) self.public_checkbox.setCheckState(QtCore.Qt.Unchecked)
# Title
title_label = QtWidgets.QLabel(strings._("mode_settings_title_label"))
self.title_lineedit = QtWidgets.QLineEdit()
self.title_lineedit.editingFinished.connect(self.title_editing_finished)
if self.settings.get("general", "title"):
self.title_lineedit.setText(self.settings.get("general", "title"))
title_layout = QtWidgets.QHBoxLayout()
title_layout.addWidget(title_label)
title_layout.addWidget(self.title_lineedit)
# Whether or not to use an auto-start timer # Whether or not to use an auto-start timer
self.autostart_timer_checkbox = QtWidgets.QCheckBox() self.autostart_timer_checkbox = QtWidgets.QCheckBox()
self.autostart_timer_checkbox.clicked.connect( self.autostart_timer_checkbox.clicked.connect(
@ -152,6 +162,7 @@ class ModeSettingsWidget(QtWidgets.QWidget):
# Advanced group itself # Advanced group itself
advanced_layout = QtWidgets.QVBoxLayout() advanced_layout = QtWidgets.QVBoxLayout()
advanced_layout.setContentsMargins(0, 0, 0, 0) advanced_layout.setContentsMargins(0, 0, 0, 0)
advanced_layout.addLayout(title_layout)
advanced_layout.addLayout(autostart_timer_layout) advanced_layout.addLayout(autostart_timer_layout)
advanced_layout.addLayout(autostop_timer_layout) advanced_layout.addLayout(autostop_timer_layout)
advanced_layout.addWidget(self.legacy_checkbox) advanced_layout.addWidget(self.legacy_checkbox)
@ -203,6 +214,33 @@ class ModeSettingsWidget(QtWidgets.QWidget):
self.legacy_checkbox.hide() self.legacy_checkbox.hide()
self.client_auth_checkbox.hide() self.client_auth_checkbox.hide()
def title_editing_finished(self):
if self.title_lineedit.text().strip() == "":
self.title_lineedit.setText("")
self.settings.set("general", "title", None)
if self.tab.mode == self.common.gui.MODE_SHARE:
self.tab.change_title.emit(
self.tab.tab_id, strings._("gui_tab_name_share")
)
elif self.tab.mode == self.common.gui.MODE_RECEIVE:
self.tab.change_title.emit(
self.tab.tab_id, strings._("gui_tab_name_receive")
)
elif self.tab.mode == self.common.gui.MODE_WEBSITE:
self.tab.change_title.emit(
self.tab.tab_id, strings._("gui_tab_name_website")
)
elif self.tab.mode == self.common.gui.MODE_CHAT:
self.tab.change_title.emit(
self.tab.tab_id, strings._("gui_tab_name_chat")
)
elif self.tab_mode == None:
pass
else:
title = self.title_lineedit.text()
self.settings.set("general", "title", title)
self.tab.change_title.emit(self.tab.tab_id, title)
def persistent_checkbox_clicked(self): def persistent_checkbox_clicked(self):
self.settings.set("persistent", "enabled", self.persistent_checkbox.isChecked()) self.settings.set("persistent", "enabled", self.persistent_checkbox.isChecked())
self.settings.set("persistent", "mode", self.tab.mode) self.settings.set("persistent", "mode", self.tab.mode)

View File

@ -128,6 +128,11 @@ class ReceiveMode(Mode):
self.hide_webhook_url() self.hide_webhook_url()
self.mode_settings_widget.mode_specific_layout.addLayout(webhook_url_layout) self.mode_settings_widget.mode_specific_layout.addLayout(webhook_url_layout)
# Set title placeholder
self.mode_settings_widget.title_lineedit.setPlaceholderText(
strings._("gui_tab_name_receive")
)
# Server status # Server status
self.server_status.set_mode("receive") self.server_status.set_mode("receive")
self.server_status.server_started_finished.connect(self.update_primary_action) self.server_status.server_started_finished.connect(self.update_primary_action)

View File

@ -77,6 +77,11 @@ class ShareMode(Mode):
for filename in self.filenames: for filename in self.filenames:
self.file_selection.file_list.add_file(filename) self.file_selection.file_list.add_file(filename)
# Set title placeholder
self.mode_settings_widget.title_lineedit.setPlaceholderText(
strings._("gui_tab_name_share")
)
# Server status # Server status
self.server_status.set_mode("share", self.file_selection) self.server_status.set_mode("share", self.file_selection)
self.server_status.server_started.connect(self.file_selection.server_started) self.server_status.server_started.connect(self.file_selection.server_started)

View File

@ -77,6 +77,11 @@ class WebsiteMode(Mode):
for filename in self.filenames: for filename in self.filenames:
self.file_selection.file_list.add_file(filename) self.file_selection.file_list.add_file(filename)
# Set title placeholder
self.mode_settings_widget.title_lineedit.setPlaceholderText(
strings._("gui_tab_name_website")
)
# Server status # Server status
self.server_status.set_mode("website", self.file_selection) self.server_status.set_mode("website", self.file_selection)
self.server_status.server_started.connect(self.file_selection.server_started) self.server_status.server_started.connect(self.file_selection.server_started)

View File

@ -176,6 +176,11 @@ class TabWidget(QtWidgets.QTabWidget):
) )
tab.init(mode_settings) tab.init(mode_settings)
# Make sure the title is set
if tab.get_mode():
tab.get_mode().mode_settings_widget.title_editing_finished()
# If it's persistent, set the persistent image in the tab # If it's persistent, set the persistent image in the tab
self.change_persistent(tab.tab_id, tab.settings.get("persistent", "enabled")) self.change_persistent(tab.tab_id, tab.settings.get("persistent", "enabled"))
@ -183,8 +188,13 @@ class TabWidget(QtWidgets.QTabWidget):
self.bring_to_front.emit() self.bring_to_front.emit()
def change_title(self, tab_id, title): def change_title(self, tab_id, title):
shortened_title = title
if len(shortened_title) > 11:
shortened_title = shortened_title[:10] + "..."
index = self.indexOf(self.tabs[tab_id]) index = self.indexOf(self.tabs[tab_id])
self.setTabText(index, title) self.setTabText(index, shortened_title)
self.setTabToolTip(index, title)
def change_icon(self, tab_id, icon_path): def change_icon(self, tab_id, icon_path):
index = self.indexOf(self.tabs[tab_id]) index = self.indexOf(self.tabs[tab_id])