Added animated loading box.

This commit is contained in:
Michael Lazar
2015-01-29 21:41:50 -08:00
parent a6ab60514c
commit 1b0a8893c6
5 changed files with 76 additions and 41 deletions

View File

@@ -3,6 +3,7 @@ import praw
from utils import clean, strip_subreddit_url, humanize_timestamp
# TODO: rename, ... container?
class BaseContent(object):
@staticmethod

View File

@@ -3,7 +3,7 @@ import curses
import sys
from content_generators import SubmissionContent, SubredditContent
from utils import curses_session
from utils import curses_session, LoadScreen
from viewer import BaseViewer
class SubmissionViewer(BaseViewer):
@@ -50,7 +50,8 @@ class SubmissionViewer(BaseViewer):
def refresh_content(self):
self.add_loading()
self.content.reset()
with LoadScreen(self.stdscr):
self.content.reset()
self.stdscr.clear()
self.draw()
@@ -138,17 +139,3 @@ class SubmissionViewer(BaseViewer):
win.addnstr(row, 1, text, n_cols)
win.border()
def main():
with curses_session() as stdscr:
r = praw.Reddit(user_agent='reddit terminal viewer (rtv) v0.0')
submission = SubredditContent(r).get(0)['object']
generator = SubmissionContent(submission)
viewer = SubmissionViewer(stdscr, generator)
viewer.loop()
if __name__ == '__main__':
main()

View File

@@ -6,7 +6,7 @@ import sys
from content_generators import SubredditContent, SubmissionContent
from submission_viewer import SubmissionViewer
from viewer import BaseViewer
from utils import curses_session, text_input
from utils import curses_session, text_input, LoadScreen
class SubredditViewer(BaseViewer):
@@ -49,10 +49,10 @@ class SubredditViewer(BaseViewer):
def refresh_content(self, subreddit=None):
self.add_loading()
self.nav.page_index, self.nav.cursor_index = 0, 0
self.nav.inverted = False
self.content.reset(subreddit=subreddit)
with LoadScreen(self.stdscr):
self.content.reset(subreddit=subreddit)
self.stdscr.clear()
self.draw()
@@ -73,10 +73,9 @@ class SubredditViewer(BaseViewer):
def open_submission(self):
"Select the current submission to view posts"
self.add_loading()
submission = self.content.get(self.nav.absolute_index)['object']
content = SubmissionContent(submission)
with LoadScreen(self.stdscr):
submission = self.content.get(self.nav.absolute_index)['object']
content = SubmissionContent(submission)
viewer = SubmissionViewer(self.stdscr, content)
viewer.loop()

View File

@@ -1,13 +1,76 @@
from datetime import datetime, timedelta
from contextlib import contextmanager
import os
import curses
import time
import threading
from curses import textpad
from datetime import datetime, timedelta
from contextlib import contextmanager
class EscapePressed(Exception):
pass
class LoadScreen(object):
def __init__(
self,
stdscr,
message='Downloading',
trail='...',
delay=0.5,
interval=0.4):
self._stdscr = stdscr
self.message = message
self.delay = delay
self.interval=interval
self.trail = trail
message_len = len(self.message) + len(self.trail)
n_rows, n_cols = stdscr.getmaxyx()
s_row = (n_rows - 2) / 2
s_col = (n_cols - message_len - 1) / 2
self.window = stdscr.derwin(3, message_len+2, s_row, s_col)
self._animator = threading.Thread(target=self.animate)
self._animator.daemon = True
self._is_running = None
def __enter__(self):
self._is_running = True
self._animator.start()
def __exit__(self, exc_type, exc_val, exc_tb):
self._is_running = False
self._animator.join()
del self.window
self._stdscr.refresh()
def animate(self):
# Delay before popping up the animation to avoid flashing
# the screen if the load time is effectively zero
start = time.time()
while (time.time() - start) < self.delay:
if not self._is_running:
return
while True:
for i in xrange(len(self.trail)+1):
if not self._is_running:
return
self.window.erase()
self.window.border()
self.window.addstr(1, 1, self.message + self.trail[:i])
self.window.refresh()
time.sleep(self.interval)
def clean(unicode_string):
"""
Convert unicode string into ascii-safe characters.

View File

@@ -83,7 +83,6 @@ class BaseViewer(object):
self.nav = Navigator(self.content.get, **kwargs)
self._subwindows = None
self.add_loading()
def draw(self):
raise NotImplementedError
@@ -107,20 +106,6 @@ class BaseViewer(object):
continue
self.stdscr.nodelay(0)
def add_loading(self):
"Draw a `loading` popup dialog in the center of the screen"
message = 'Loading...'
n_rows, n_cols = self.stdscr.getmaxyx()
win_rows, win_cols = 3, len(message)+2
start_row = (n_rows - win_rows) / 2
start_col = (n_cols - win_cols) / 2
window = self.stdscr.derwin(win_rows, win_cols, start_row, start_col)
window.border()
window.addstr(1, 1, message)
window.refresh()
def draw_header(self):
n_rows, n_cols = self._header_window.getmaxyx()