Merge pull request #217 from michael-lazar/cursor-tracking
Cursor tracking
This commit is contained in:
@@ -92,6 +92,7 @@ class Content(object):
|
|||||||
data['type'] = 'MoreComments'
|
data['type'] = 'MoreComments'
|
||||||
data['count'] = comment.count
|
data['count'] = comment.count
|
||||||
data['body'] = 'More comments'
|
data['body'] = 'More comments'
|
||||||
|
data['hidden'] = True
|
||||||
else:
|
else:
|
||||||
author = getattr(comment, 'author', '[deleted]')
|
author = getattr(comment, 'author', '[deleted]')
|
||||||
name = getattr(author, 'name', '[deleted]')
|
name = getattr(author, 'name', '[deleted]')
|
||||||
@@ -114,6 +115,7 @@ class Content(object):
|
|||||||
data['gold'] = comment.gilded > 0
|
data['gold'] = comment.gilded > 0
|
||||||
data['permalink'] = permalink
|
data['permalink'] = permalink
|
||||||
data['stickied'] = stickied
|
data['stickied'] = stickied
|
||||||
|
data['hidden'] = False
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@@ -154,6 +156,7 @@ class Content(object):
|
|||||||
data['gold'] = sub.gilded > 0
|
data['gold'] = sub.gilded > 0
|
||||||
data['nsfw'] = sub.over_18
|
data['nsfw'] = sub.over_18
|
||||||
data['stickied'] = sub.stickied
|
data['stickied'] = sub.stickied
|
||||||
|
data['hidden'] = False
|
||||||
data['index'] = None # This is filled in later by the method caller
|
data['index'] = None # This is filled in later by the method caller
|
||||||
|
|
||||||
if sub.url.split('/r/')[-1] == sub.permalink.split('/r/')[-1]:
|
if sub.url.split('/r/')[-1] == sub.permalink.split('/r/')[-1]:
|
||||||
@@ -317,7 +320,8 @@ class SubmissionContent(Content):
|
|||||||
'cache': cache,
|
'cache': cache,
|
||||||
'count': count,
|
'count': count,
|
||||||
'level': data['level'],
|
'level': data['level'],
|
||||||
'body': 'Hidden'}
|
'body': 'Hidden',
|
||||||
|
'hidden': True}
|
||||||
|
|
||||||
self._comment_data[index:index + len(cache)] = [comment]
|
self._comment_data[index:index + len(cache)] = [comment]
|
||||||
|
|
||||||
|
|||||||
@@ -315,7 +315,8 @@ class Navigator(object):
|
|||||||
valid_page_cb,
|
valid_page_cb,
|
||||||
page_index=0,
|
page_index=0,
|
||||||
cursor_index=0,
|
cursor_index=0,
|
||||||
inverted=False):
|
inverted=False,
|
||||||
|
top_item_height=None):
|
||||||
"""
|
"""
|
||||||
Params:
|
Params:
|
||||||
valid_page_callback (func): This function, usually `Content.get`,
|
valid_page_callback (func): This function, usually `Content.get`,
|
||||||
@@ -331,11 +332,16 @@ class Navigator(object):
|
|||||||
inverted - The page is drawn from the bottom of the screen,
|
inverted - The page is drawn from the bottom of the screen,
|
||||||
starting with the page index, up to the top of the
|
starting with the page index, up to the top of the
|
||||||
screen.
|
screen.
|
||||||
|
top_item_height (int): If this is set to a non-null value
|
||||||
|
The number of columns that the top-most item
|
||||||
|
should utilize if non-inverted. This is used for a special mode
|
||||||
|
where all items are drawn non-inverted except for the top one.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.page_index = page_index
|
self.page_index = page_index
|
||||||
self.cursor_index = cursor_index
|
self.cursor_index = cursor_index
|
||||||
self.inverted = inverted
|
self.inverted = inverted
|
||||||
|
self.top_item_height = top_item_height
|
||||||
self._page_cb = valid_page_cb
|
self._page_cb = valid_page_cb
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -396,15 +402,21 @@ class Navigator(object):
|
|||||||
# Flip the orientation and reset the cursor
|
# Flip the orientation and reset the cursor
|
||||||
self.flip(self.cursor_index)
|
self.flip(self.cursor_index)
|
||||||
self.cursor_index = 0
|
self.cursor_index = 0
|
||||||
|
self.top_item_height = None
|
||||||
redraw = True
|
redraw = True
|
||||||
else:
|
else:
|
||||||
if self.cursor_index > 0:
|
if self.cursor_index > 0:
|
||||||
self.cursor_index -= 1
|
self.cursor_index -= 1
|
||||||
|
if self.top_item_height and self.cursor_index == 0:
|
||||||
|
# Selecting the partially displayed item
|
||||||
|
self.top_item_height = None
|
||||||
|
redraw = True
|
||||||
else:
|
else:
|
||||||
self.page_index -= self.step
|
self.page_index -= self.step
|
||||||
if self._is_valid(self.absolute_index):
|
if self._is_valid(self.absolute_index):
|
||||||
# We have reached the beginning of the page - move the
|
# We have reached the beginning of the page - move the
|
||||||
# index
|
# index
|
||||||
|
self.top_item_height = None
|
||||||
redraw = True
|
redraw = True
|
||||||
else:
|
else:
|
||||||
self.page_index += self.step
|
self.page_index += self.step
|
||||||
@@ -478,6 +490,7 @@ class Navigator(object):
|
|||||||
self.page_index += (self.step * n_windows)
|
self.page_index += (self.step * n_windows)
|
||||||
self.cursor_index = n_windows
|
self.cursor_index = n_windows
|
||||||
self.inverted = not self.inverted
|
self.inverted = not self.inverted
|
||||||
|
self.top_item_height = None
|
||||||
|
|
||||||
def _is_valid(self, page_index):
|
def _is_valid(self, page_index):
|
||||||
"""
|
"""
|
||||||
|
|||||||
29
rtv/page.py
29
rtv/page.py
@@ -327,29 +327,46 @@ class Page(object):
|
|||||||
# If not inverted, align the first submission with the top and draw
|
# If not inverted, align the first submission with the top and draw
|
||||||
# downwards. If inverted, align the first submission with the bottom
|
# downwards. If inverted, align the first submission with the bottom
|
||||||
# and draw upwards.
|
# and draw upwards.
|
||||||
|
cancel_inverted = True
|
||||||
current_row = (win_n_rows - 1) if inverted else 0
|
current_row = (win_n_rows - 1) if inverted else 0
|
||||||
available_rows = (win_n_rows - 1) if inverted else win_n_rows
|
available_rows = (win_n_rows - 1) if inverted else win_n_rows
|
||||||
|
top_item_height = None if inverted else self.nav.top_item_height
|
||||||
for data in self.content.iterate(page_index, step, win_n_cols - 2):
|
for data in self.content.iterate(page_index, step, win_n_cols - 2):
|
||||||
subwin_n_rows = min(available_rows, data['n_rows'])
|
subwin_n_rows = min(available_rows, data['n_rows'])
|
||||||
|
subwin_inverted = inverted
|
||||||
|
if top_item_height is not None:
|
||||||
|
# Special case: draw the page as non-inverted, except for the
|
||||||
|
# top element. This element will be drawn as inverted with a
|
||||||
|
# restricted height
|
||||||
|
subwin_n_rows = min(subwin_n_rows, top_item_height)
|
||||||
|
subwin_inverted = True
|
||||||
|
top_item_height = None
|
||||||
subwin_n_cols = win_n_cols - data['offset']
|
subwin_n_cols = win_n_cols - data['offset']
|
||||||
start = current_row - subwin_n_rows if inverted else current_row
|
start = current_row - subwin_n_rows if inverted else current_row
|
||||||
subwindow = window.derwin(
|
subwindow = window.derwin(
|
||||||
subwin_n_rows, subwin_n_cols, start, data['offset'])
|
subwin_n_rows, subwin_n_cols, start, data['offset'])
|
||||||
attr = self._draw_item(subwindow, data, inverted)
|
attr = self._draw_item(subwindow, data, subwin_inverted)
|
||||||
self._subwindows.append((subwindow, attr))
|
self._subwindows.append((subwindow, attr))
|
||||||
available_rows -= (subwin_n_rows + 1) # Add one for the blank line
|
available_rows -= (subwin_n_rows + 1) # Add one for the blank line
|
||||||
current_row += step * (subwin_n_rows + 1)
|
current_row += step * (subwin_n_rows + 1)
|
||||||
if available_rows <= 0:
|
if available_rows <= 0:
|
||||||
|
# Indicate the page is full and we can keep the inverted screen.
|
||||||
|
cancel_inverted = False
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
# If the page is not full we need to make sure that it is NOT
|
if len(self._subwindows) == 1:
|
||||||
|
# Never draw inverted if only one subwindow. The top of the
|
||||||
|
# subwindow should always be aligned with the top of the screen.
|
||||||
|
cancel_inverted = True
|
||||||
|
|
||||||
|
if cancel_inverted and self.nav.inverted:
|
||||||
|
# In some cases we need to make sure that the screen is NOT
|
||||||
# inverted. Unfortunately, this currently means drawing the whole
|
# inverted. Unfortunately, this currently means drawing the whole
|
||||||
# page over again. Could not think of a better way to pre-determine
|
# page over again. Could not think of a better way to pre-determine
|
||||||
# if the content will fill up the page, given that it is dependent
|
# if the content will fill up the page, given that it is dependent
|
||||||
# on the size of the terminal.
|
# on the size of the terminal.
|
||||||
if self.nav.inverted:
|
self.nav.flip((len(self._subwindows) - 1))
|
||||||
self.nav.flip((len(self._subwindows) - 1))
|
self._draw_content()
|
||||||
self._draw_content()
|
|
||||||
|
|
||||||
self._row = n_rows
|
self._row = n_rows
|
||||||
|
|
||||||
|
|||||||
@@ -33,11 +33,19 @@ class SubmissionPage(Page):
|
|||||||
|
|
||||||
current_index = self.nav.absolute_index
|
current_index = self.nav.absolute_index
|
||||||
self.content.toggle(current_index)
|
self.content.toggle(current_index)
|
||||||
|
|
||||||
|
# This logic handles a display edge case after a comment toggle. We want
|
||||||
|
# to make sure that when we re-draw the page, the cursor stays at its
|
||||||
|
# current absolute position on the screen. In order to do this, apply
|
||||||
|
# a fixed offset if, while inverted, we either try to hide the bottom
|
||||||
|
# comment or toggle any of the middle comments.
|
||||||
if self.nav.inverted:
|
if self.nav.inverted:
|
||||||
# Reset the navigator so that the cursor is at the bottom of the
|
data = self.content.get(current_index)
|
||||||
# page. This is a workaround to handle if folding the comment
|
if data['hidden'] or self.nav.cursor_index != 0:
|
||||||
# causes the cursor index to go out of bounds.
|
window = self._subwindows[-1][0]
|
||||||
self.nav.page_index, self.nav.cursor_index = current_index, 0
|
n_rows, _ = window.getmaxyx()
|
||||||
|
self.nav.flip(len(self._subwindows) - 1)
|
||||||
|
self.nav.top_item_height = n_rows
|
||||||
|
|
||||||
@SubmissionController.register(Command('SUBMISSION_EXIT'))
|
@SubmissionController.register(Command('SUBMISSION_EXIT'))
|
||||||
def exit_submission(self):
|
def exit_submission(self):
|
||||||
@@ -155,6 +163,16 @@ class SubmissionPage(Page):
|
|||||||
valid_rows = range(0, n_rows)
|
valid_rows = range(0, n_rows)
|
||||||
offset = 0 if not inverted else -(data['n_rows'] - n_rows)
|
offset = 0 if not inverted else -(data['n_rows'] - n_rows)
|
||||||
|
|
||||||
|
# If there isn't enough space to fit the comment body on the screen,
|
||||||
|
# replace the last line with a notification.
|
||||||
|
split_body = data['split_body']
|
||||||
|
if data['n_rows'] > n_rows:
|
||||||
|
# Only when there is a single comment on the page and not inverted
|
||||||
|
if not inverted and len(self._subwindows) == 0:
|
||||||
|
cutoff = data['n_rows'] - n_rows + 1
|
||||||
|
split_body = split_body[:-cutoff]
|
||||||
|
split_body.append('(Not enough space to display)')
|
||||||
|
|
||||||
row = offset
|
row = offset
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
|
|
||||||
@@ -178,7 +196,7 @@ class SubmissionPage(Page):
|
|||||||
text, attr = self.term.stickied
|
text, attr = self.term.stickied
|
||||||
self.term.add_line(win, text, attr=attr)
|
self.term.add_line(win, text, attr=attr)
|
||||||
|
|
||||||
for row, text in enumerate(data['split_body'], start=offset+1):
|
for row, text in enumerate(split_body, start=offset+1):
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
self.term.add_line(win, text, row, 1)
|
self.term.add_line(win, text, row, 1)
|
||||||
|
|
||||||
|
|||||||
173
tests/cassettes/test_submission_comment_not_enough_space.yaml
Normal file
173
tests/cassettes/test_submission_comment_not_enough_space.yaml
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
interactions:
|
||||||
|
- request:
|
||||||
|
body: null
|
||||||
|
headers:
|
||||||
|
Accept: ['*/*']
|
||||||
|
Accept-Encoding: ['gzip, deflate, compress']
|
||||||
|
User-Agent: [!!python/unicode rtv test suite PRAW/3.3.0 Python/2.7.6 Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty]
|
||||||
|
method: !!python/unicode GET
|
||||||
|
uri: https://www.reddit.com/r/Python/comments/2xmo63.json
|
||||||
|
response:
|
||||||
|
body:
|
||||||
|
string: !!binary |
|
||||||
|
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
|
||||||
|
headers:
|
||||||
|
access-control-allow-origin: ['*']
|
||||||
|
access-control-expose-headers: ['X-Reddit-Tracking, X-Moose']
|
||||||
|
cache-control: ['max-age=0, must-revalidate']
|
||||||
|
cf-ray: [296f3f0aeb072858-SJC]
|
||||||
|
connection: [keep-alive]
|
||||||
|
content-encoding: [gzip]
|
||||||
|
content-length: ['7683']
|
||||||
|
content-type: [application/json; charset=UTF-8]
|
||||||
|
date: ['Thu, 21 Apr 2016 07:50:39 GMT']
|
||||||
|
server: [cloudflare-nginx]
|
||||||
|
set-cookie: ['__cfduid=d8e1d83c8cfa76ac404e21fc7d924dc961461225038; expires=Fri,
|
||||||
|
21-Apr-17 07:50:38 GMT; path=/; domain=.reddit.com; HttpOnly', 'loid=hCXBgtTCOflyUpYHv9;
|
||||||
|
Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 21-Apr-2018 07:50:38
|
||||||
|
GMT; secure', 'loidcreated=2016-04-21T07%3A50%3A38.582Z; Domain=reddit.com;
|
||||||
|
Max-Age=63071999; Path=/; expires=Sat, 21-Apr-2018 07:50:38 GMT; secure']
|
||||||
|
strict-transport-security: [max-age=15552000; includeSubDomains; preload]
|
||||||
|
vary: [accept-encoding]
|
||||||
|
x-content-type-options: [nosniff]
|
||||||
|
x-frame-options: [SAMEORIGIN]
|
||||||
|
x-moose: [majestic]
|
||||||
|
x-reddit-tracking: ['https://pixel.redditmedia.com/pixel/of_destiny.png?v=wUoXo%2B%2BbEgovlSTbKrPiRzy5CGl5PaWJAwmKAdLtVFDt9zGb%2FmDNZzDIUNfJZ7SEiQl6UK0WZns%3D']
|
||||||
|
x-ua-compatible: [IE=edge]
|
||||||
|
x-xss-protection: [1; mode=block]
|
||||||
|
status: {code: 200, message: OK}
|
||||||
|
version: 1
|
||||||
@@ -101,7 +101,8 @@ def test_content_submission(reddit, terminal):
|
|||||||
assert content.get(40)['type'] == 'Comment'
|
assert content.get(40)['type'] == 'Comment'
|
||||||
|
|
||||||
for data in content.iterate(-1, 1):
|
for data in content.iterate(-1, 1):
|
||||||
assert all(k in data for k in ('object', 'n_rows', 'offset', 'type'))
|
assert all(k in data for k in ('object', 'n_rows', 'offset', 'type',
|
||||||
|
'hidden'))
|
||||||
# All text should be converted to unicode by this point
|
# All text should be converted to unicode by this point
|
||||||
for val in data.values():
|
for val in data.values():
|
||||||
assert not isinstance(val, six.binary_type)
|
assert not isinstance(val, six.binary_type)
|
||||||
@@ -121,11 +122,14 @@ def test_content_submission(reddit, terminal):
|
|||||||
data = content.get(2)
|
data = content.get(2)
|
||||||
assert data['type'] == 'HiddenComment'
|
assert data['type'] == 'HiddenComment'
|
||||||
assert data['count'] == 3
|
assert data['count'] == 3
|
||||||
|
assert data['hidden'] is True
|
||||||
assert data['level'] >= content.get(3)['level']
|
assert data['level'] >= content.get(3)['level']
|
||||||
assert len(content._comment_data) == 43
|
assert len(content._comment_data) == 43
|
||||||
|
|
||||||
# Toggling again expands the children
|
# Toggling again expands the children
|
||||||
content.toggle(2)
|
content.toggle(2)
|
||||||
|
data = content.get(2)
|
||||||
|
assert data['hidden'] is False
|
||||||
assert len(content._comment_data) == 45
|
assert len(content._comment_data) == 45
|
||||||
|
|
||||||
|
|
||||||
@@ -195,8 +199,9 @@ def test_content_subreddit(reddit, terminal):
|
|||||||
assert content.get(0)['type'] == 'Submission'
|
assert content.get(0)['type'] == 'Submission'
|
||||||
|
|
||||||
for data in content.iterate(0, 1):
|
for data in content.iterate(0, 1):
|
||||||
assert all(k in data for k in ('object', 'n_rows', 'offset', 'type',
|
assert all(k in data for k in (
|
||||||
'index', 'title', 'split_title'))
|
'object', 'n_rows', 'offset', 'type', 'index', 'title',
|
||||||
|
'split_title', 'hidden'))
|
||||||
# All text should be converted to unicode by this point
|
# All text should be converted to unicode by this point
|
||||||
for val in data.values():
|
for val in data.values():
|
||||||
assert not isinstance(val, six.binary_type)
|
assert not isinstance(val, six.binary_type)
|
||||||
@@ -227,6 +232,7 @@ def test_content_subreddit_load_more(reddit, terminal):
|
|||||||
assert data['index'] == i + 1
|
assert data['index'] == i + 1
|
||||||
assert data['title'].startswith(six.text_type(i + 1))
|
assert data['title'].startswith(six.text_type(i + 1))
|
||||||
|
|
||||||
|
|
||||||
def test_content_subreddit_from_name(reddit, terminal):
|
def test_content_subreddit_from_name(reddit, terminal):
|
||||||
|
|
||||||
name = '/r/python'
|
name = '/r/python'
|
||||||
|
|||||||
@@ -346,11 +346,13 @@ def test_objects_navigator_properties():
|
|||||||
assert nav.step == 1
|
assert nav.step == 1
|
||||||
assert nav.position == (0, 0, False)
|
assert nav.position == (0, 0, False)
|
||||||
assert nav.absolute_index == 0
|
assert nav.absolute_index == 0
|
||||||
|
assert nav.top_item_height is None
|
||||||
|
|
||||||
nav = Navigator(valid_page_cb, 5, 2, True)
|
nav = Navigator(valid_page_cb, 5, 2, True, 10)
|
||||||
assert nav.step == -1
|
assert nav.step == -1
|
||||||
assert nav.position == (5, 2, True)
|
assert nav.position == (5, 2, True)
|
||||||
assert nav.absolute_index == 3
|
assert nav.absolute_index == 3
|
||||||
|
assert nav.top_item_height == 10
|
||||||
|
|
||||||
|
|
||||||
def test_objects_navigator_move():
|
def test_objects_navigator_move():
|
||||||
@@ -360,6 +362,7 @@ def test_objects_navigator_move():
|
|||||||
raise IndexError()
|
raise IndexError()
|
||||||
|
|
||||||
nav = Navigator(valid_page_cb)
|
nav = Navigator(valid_page_cb)
|
||||||
|
nav.top_item_height = 5
|
||||||
|
|
||||||
# Try to scroll up past the first item
|
# Try to scroll up past the first item
|
||||||
valid, redraw = nav.move(-1, 2)
|
valid, redraw = nav.move(-1, 2)
|
||||||
@@ -375,6 +378,7 @@ def test_objects_navigator_move():
|
|||||||
|
|
||||||
# Scroll down, reach last item on the page and flip the screen
|
# Scroll down, reach last item on the page and flip the screen
|
||||||
valid, redraw = nav.move(1, 3)
|
valid, redraw = nav.move(1, 3)
|
||||||
|
assert nav.top_item_height is None
|
||||||
assert nav.page_index == 2
|
assert nav.page_index == 2
|
||||||
assert nav.cursor_index == 0
|
assert nav.cursor_index == 0
|
||||||
assert nav.inverted
|
assert nav.inverted
|
||||||
|
|||||||
@@ -111,6 +111,24 @@ def test_submission_pager(submission_page, terminal):
|
|||||||
assert terminal.open_pager.called
|
assert terminal.open_pager.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_submission_comment_not_enough_space(submission_page, terminal):
|
||||||
|
|
||||||
|
# The first comment is 10 lines, shrink the screen so that it won't fit.
|
||||||
|
# Setting the terminal to 10 lines means that there will only be 8 lines
|
||||||
|
# available (after subtracting the header and footer) to draw the comment.
|
||||||
|
terminal.stdscr.nlines = 10
|
||||||
|
|
||||||
|
# Select the first comment
|
||||||
|
with mock.patch.object(submission_page, 'clear_input_queue'):
|
||||||
|
submission_page.move_cursor_down()
|
||||||
|
|
||||||
|
submission_page.draw()
|
||||||
|
|
||||||
|
text = '(Not enough space to display)'.encode('ascii')
|
||||||
|
window = terminal.stdscr.subwin
|
||||||
|
window.subwin.addstr.assert_any_call(7, 1, text)
|
||||||
|
|
||||||
|
|
||||||
def test_submission_vote(submission_page, refresh_token):
|
def test_submission_vote(submission_page, refresh_token):
|
||||||
|
|
||||||
# Log in
|
# Log in
|
||||||
|
|||||||
Reference in New Issue
Block a user