From bd7305ab16aa6900371b0403fde9cb56c79009b3 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 21 Mar 2018 18:27:42 -0700 Subject: [PATCH] Add new WSGI middleware just to attach the Web object to environ, and improve the UI of file upload progress --- onionshare/web.py | 32 +++++++++++++++++++++++++++++--- share/static/css/style.css | 1 + 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/onionshare/web.py b/onionshare/web.py index 15a68cec..7a6a848b 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -66,6 +66,8 @@ class Web(object): # Are we using receive mode? self.receive_mode = receive_mode if self.receive_mode: + # Use custom WSGI middleware, to modify environ + self.app.wsgi_app = ReceiveModeWSGIMiddleware(self.app.wsgi_app, self) # Use a custom Request class to track upload progess self.app.request_class = ReceiveModeRequest @@ -318,7 +320,8 @@ class Web(object): if len(filenames) == 0: flash('No files uploaded') else: - flash('Uploaded {}'.format(', '.join(filenames))) + for filename in filenames: + flash('Uploaded {}'.format(filename)) return redirect('/{}'.format(slug_candidate)) @@ -535,6 +538,19 @@ class ZipWriter(object): self.z.close() +class ReceiveModeWSGIMiddleware(object): + """ + Custom WSGI middleware in order to attach the Web object to environ, so + ReceiveModeRequest can access it. + """ + def __init__(self, app, web): + self.app = app + self.web = web + + def __call__(self, environ, start_response): + environ['web'] = self.web + return self.app(environ, start_response) + class ReceiveModeTemporaryFile(object): """ A custom TemporaryFile that tells ReceiveModeRequest every time data gets @@ -571,6 +587,7 @@ class ReceiveModeRequest(Request): """ def __init__(self, environ, populate_request=True, shallow=False): super(ReceiveModeRequest, self).__init__(environ, populate_request, shallow) + self.web = environ['web'] # A dictionary that maps filenames to the bytes uploaded so far self.onionshare_progress = {} @@ -580,13 +597,22 @@ class ReceiveModeRequest(Request): This gets called for each file that gets uploaded, and returns an file-like writable stream. """ - print('') + if len(self.onionshare_progress) > 0: + print('') self.onionshare_progress[filename] = 0 return ReceiveModeTemporaryFile(filename, self.onionshare_update_func) + def close(self): + """ + When closing the request, print a newline if this was a file upload. + """ + super(ReceiveModeRequest, self).close() + if len(self.onionshare_progress) > 0: + print('') + def onionshare_update_func(self, filename, length): """ Keep track of the bytes uploaded so far for all files. """ self.onionshare_progress[filename] += length - print('\r{}: {} '.format(filename, self.onionshare_progress[filename]), end='') + print('{} - {} '.format(self.web.common.human_readable_filesize(self.onionshare_progress[filename]), filename), end='\r') diff --git a/share/static/css/style.css b/share/static/css/style.css index 6b372f22..29b839a7 100644 --- a/share/static/css/style.css +++ b/share/static/css/style.css @@ -135,6 +135,7 @@ ul.flashes { margin: 0; padding: 0; color: #cc0000; + text-align: left; } ul.flashes li {