Skip to content

Commit

Permalink
Potential fix. TODO: test.
Browse files Browse the repository at this point in the history
  • Loading branch information
ntoll committed Jan 28, 2020
1 parent 03300d6 commit 1ca7422
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 12 deletions.
2 changes: 1 addition & 1 deletion securedrop_client/api_jobs/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def call_api(self, api_client: API, session: Session) -> Any:
# TODO: Once https://github.com/freedomofpress/securedrop-client/issues/648, we will want to
# pass the default request timeout to api calls instead of setting it on the api object
# directly.
api_client.default_request_timeout = 20
api_client.default_request_timeout = 120
remote_sources, remote_submissions, remote_replies = \
get_remote_data(api_client)

Expand Down
34 changes: 28 additions & 6 deletions securedrop_client/gui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ def __init__(self):

self.active = False

self.download_animation = load_movie("sync_animation.gif")
self.download_animation.frameChanged.connect(self.set_animation_frame)

# Set css id
self.setObjectName('refresh_button')

Expand All @@ -230,7 +233,7 @@ def setup(self, controller):
Assign a controller object (containing the application logic).
"""
self.controller = controller
self.controller.sync_events.connect(self._on_refresh_complete)
self.controller.sync_events.connect(self._on_sync)

def _on_clicked(self):
if self.active:
Expand All @@ -242,21 +245,40 @@ def _on_clicked(self):
# refresh, rather than for just the duration of a click. The icon image will be replaced
# when the controller tells us the refresh has finished. A cleaner solution would be to
# store and update our own icon mode so we don't have to reload any images.
self.setIcon(load_icon(normal='refresh_active.svg', disabled='refresh_offline.svg'))
QTimer.singleShot(300, self.start_animation)
self.active = True

def _on_refresh_complete(self, data):
if (data == 'synced'):
def start_animation(self):
"""
Starts the rotating spinner animation to indicate ongoing activity.
"""
self.download_animation.start()

def set_animation_frame(self, frame_number):
"""
Set the current frame of the animation as the current icon for the
button.
"""
self.setIcon(QIcon(self.download_animation.currentPixmap()))

def _on_sync(self, data):
"""
Ensure the animation is stopped and the icon reset to something static.
"""
if data == "syncing":
QTimer.singleShot(300, self.start_animation)
self.active = True
elif (data == 'synced'):
self.setIcon(load_icon(
normal='refresh.svg',
disabled='refresh_offline.svg',
active='refresh_active.svg',
selected='refresh.svg'))
self.active = False
self.download_animation.stop()
self.active = False

def enable(self):
self.setEnabled(True)
self.active is False

def disable(self):
self.setEnabled(False)
Expand Down
13 changes: 10 additions & 3 deletions securedrop_client/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ def __init__(self, hostname: str, gui, session_maker: sessionmaker,
# File data.
self.data_dir = os.path.join(self.home, 'data')

# Flag to indicate if sync in flight.
self.syncing = False

@property
def is_authenticated(self) -> bool:
return self.__is_authenticated
Expand Down Expand Up @@ -332,7 +335,6 @@ def on_authenticate_success(self, result):
self.api.journalist_last_name,
self.session)
self.gui.show_main_window(user)
self.update_sources()
self.api_job_queue.login(self.api)
self.sync_api()
self.is_authenticated = True
Expand Down Expand Up @@ -375,6 +377,8 @@ def sync_api(self, manual_refresh: bool = False):
"""
logger.debug("In sync_api on thread {}".format(self.thread().currentThreadId()))
self.sync_events.emit('syncing')
self.syncing = True
self.set_status(_('Syncing with server...'), 60000)

if self.authenticated():
logger.debug("You are authenticated, going to make your call")
Expand Down Expand Up @@ -419,6 +423,7 @@ def on_sync_success(self) -> None:
* Update missing files so that they can be re-downloaded
"""
self.gui.clear_error_status() # remove any permanent error status message
self.syncing = False

with open(self.sync_flag, 'w') as f:
f.write(arrow.now().format())
Expand All @@ -436,6 +441,7 @@ def on_sync_failure(self, result: Exception) -> None:
queues so that we continue to retry syncing with the server in the background.
"""
logger.debug('The SecureDrop server cannot be reached due to Error: {}'.format(result))
self.syncing = False
self.gui.update_error_status(
_('The SecureDrop server cannot be reached.'),
duration=0,
Expand All @@ -446,6 +452,7 @@ def on_refresh_failure(self, result: Exception) -> None:
Called when syncronisation of data via the API fails after a user manual clicks refresh.
"""
logger.debug('The SecureDrop server cannot be reached due to Error: {}'.format(result))
self.syncing = False
self.gui.update_error_status(
_('The SecureDrop server cannot be reached.'),
duration=0,
Expand All @@ -455,7 +462,8 @@ def update_sync(self):
"""
Updates the UI to show human time of last sync.
"""
self.gui.show_sync(self.last_sync())
if not self.syncing:
self.gui.show_sync(self.last_sync())

def update_sources(self):
"""
Expand Down Expand Up @@ -732,7 +740,6 @@ def on_file_download_success(self, result: Any) -> None:
"""
self.gui.clear_error_status() # remove any permanent error status message
self.file_ready.emit(result)
self.update_sources()

def on_file_download_failure(self, exception: Exception) -> None:
"""
Expand Down
11 changes: 9 additions & 2 deletions securedrop_client/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,12 @@ def re_add_job(self, job: ApiJob) -> None:
'''
job.remaining_attempts = DEFAULT_NUM_ATTEMPTS
priority = self.JOB_PRIORITIES[type(job)]
self.queue.put_nowait((priority, job))
try:
self.queue.put_nowait((priority, job))
except Full:
# Pass silently if the queue is full. For use with MetadataSyncJob.
# See #652.
pass

@pyqtSlot()
def process(self) -> None:
Expand Down Expand Up @@ -216,7 +221,9 @@ def resume_queues(self) -> None:

def enqueue(self, job: ApiJob) -> None:
# Prevent api jobs being added to the queue when not logged in.
if not self.main_queue.api_client or not self.download_file_queue.api_client:
if (not self.main_queue.api_client or
not self.download_file_queue.api_client or
not self.metadata_queue.api_client):
logger.info('Not adding job, we are not logged in')
return

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1ca7422

Please sign in to comment.