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 from utils import clean, strip_subreddit_url, humanize_timestamp
# TODO: rename, ... container?
class BaseContent(object): class BaseContent(object):
@staticmethod @staticmethod

View File

@@ -3,7 +3,7 @@ import curses
import sys import sys
from content_generators import SubmissionContent, SubredditContent from content_generators import SubmissionContent, SubredditContent
from utils import curses_session from utils import curses_session, LoadScreen
from viewer import BaseViewer from viewer import BaseViewer
class SubmissionViewer(BaseViewer): class SubmissionViewer(BaseViewer):
@@ -50,6 +50,7 @@ class SubmissionViewer(BaseViewer):
def refresh_content(self): def refresh_content(self):
self.add_loading() self.add_loading()
with LoadScreen(self.stdscr):
self.content.reset() self.content.reset()
self.stdscr.clear() self.stdscr.clear()
self.draw() self.draw()
@@ -138,17 +139,3 @@ class SubmissionViewer(BaseViewer):
win.addnstr(row, 1, text, n_cols) win.addnstr(row, 1, text, n_cols)
win.border() 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 content_generators import SubredditContent, SubmissionContent
from submission_viewer import SubmissionViewer from submission_viewer import SubmissionViewer
from viewer import BaseViewer from viewer import BaseViewer
from utils import curses_session, text_input from utils import curses_session, text_input, LoadScreen
class SubredditViewer(BaseViewer): class SubredditViewer(BaseViewer):
@@ -49,9 +49,9 @@ class SubredditViewer(BaseViewer):
def refresh_content(self, subreddit=None): def refresh_content(self, subreddit=None):
self.add_loading()
self.nav.page_index, self.nav.cursor_index = 0, 0 self.nav.page_index, self.nav.cursor_index = 0, 0
self.nav.inverted = False self.nav.inverted = False
with LoadScreen(self.stdscr):
self.content.reset(subreddit=subreddit) self.content.reset(subreddit=subreddit)
self.stdscr.clear() self.stdscr.clear()
self.draw() self.draw()
@@ -73,8 +73,7 @@ class SubredditViewer(BaseViewer):
def open_submission(self): def open_submission(self):
"Select the current submission to view posts" "Select the current submission to view posts"
self.add_loading() with LoadScreen(self.stdscr):
submission = self.content.get(self.nav.absolute_index)['object'] submission = self.content.get(self.nav.absolute_index)['object']
content = SubmissionContent(submission) content = SubmissionContent(submission)
viewer = SubmissionViewer(self.stdscr, content) viewer = SubmissionViewer(self.stdscr, content)

View File

@@ -1,13 +1,76 @@
from datetime import datetime, timedelta
from contextlib import contextmanager
import os import os
import curses import curses
import time
import threading
from curses import textpad from curses import textpad
from datetime import datetime, timedelta
from contextlib import contextmanager
class EscapePressed(Exception): class EscapePressed(Exception):
pass 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): def clean(unicode_string):
""" """
Convert unicode string into ascii-safe characters. Convert unicode string into ascii-safe characters.

View File

@@ -83,7 +83,6 @@ class BaseViewer(object):
self.nav = Navigator(self.content.get, **kwargs) self.nav = Navigator(self.content.get, **kwargs)
self._subwindows = None self._subwindows = None
self.add_loading()
def draw(self): def draw(self):
raise NotImplementedError raise NotImplementedError
@@ -107,20 +106,6 @@ class BaseViewer(object):
continue continue
self.stdscr.nodelay(0) 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): def draw_header(self):
n_rows, n_cols = self._header_window.getmaxyx() n_rows, n_cols = self._header_window.getmaxyx()