Commit b1074577 authored by Lysander Trischler's avatar Lysander Trischler

Implement crude twt preview

parent af41834a
......@@ -4,6 +4,7 @@
import datetime
import dateutil.parser
import subprocess
import twtxt.models
import twtxtmanager
import twtxtparser
import twtxtrenderer
......@@ -444,16 +445,20 @@ class TwtForm(urwid.ListBox):
microsecond=0)
.astimezone()
.isoformat())
preview = urwid.Button("Preview Twt", on_press=self.preview_twt)
publish = urwid.Button("Publish Twt", on_press=self.publish_twt)
cancel = urwid.Button("Cancel", on_press=lambda *_: frame.body.pop_widget())
super().__init__(list(map(widgets.Unselectable, rendered_conversation)) + [
urwid.LineBox(self._text_edit, title="Reply" if original_twt else "New Twt", title_align="left"),
urwid.LineBox(self._created_at_edit, title="Created at", title_align="left"),
urwid.Columns([urwid.Text(""),
(len(preview.label) + 4, preview),
(len(publish.label) + 4, publish),
(len(cancel.label) + 4, cancel)],
dividechars=2)])
self._manager = manager
self._original_twt = original_twt
self._rendered_conversation = rendered_conversation
def _collect_authors(self, twt):
......@@ -467,17 +472,53 @@ class TwtForm(urwid.ListBox):
return authors
def publish_twt(self, *_):
@property
def _created_at(self):
created_at = dateutil.parser.parse(self._created_at_edit.edit_text)
if not created_at.tzinfo:
created_at = created_at.replace(tzinfo=datetime.timezone.utc)
return created_at.replace(tzinfo=datetime.timezone.utc)
return created_at
@property
def _text(self):
return self._text_edit.edit_text
def preview_twt(self, *_):
new_twt = self._manager.enhance_twt(twtxt.models.Tweet(created_at=self._created_at, text=self._text, source=self._manager.own_source))
frame.body.push_widget(PreviewForm(self._manager, new_twt, self._original_twt, self._rendered_conversation))
text = self._text_edit.edit_text
self._manager.publish_twt(created_at, text)
def publish_twt(self, *_):
self._manager.publish_twt(self._created_at, self._text)
frame.body.pop_widget()
__debug = []
def debug(s):
__debug.append("%d: %s" % (len(__debug) + 1, s))
header = frame.header.original_widget
header.set_text("\n".join(__debug[-20:]))
class PreviewForm(urwid.ListBox, TwtFormatter):
def __init__(self, manager, new_twt, original_twt=None, rendered_conversation=[]):
back = urwid.Button("Back", on_press=lambda *_: frame.body.pop_widget())
rendered_widgets = []
twts = []
self.render_conversation(manager, new_twt, rendered_widgets, twts,
level=0 if original_twt is None else 1)
rows_calculating_delegate_widget = rendered_widgets[-1].original_widget
super().__init__(list(map(widgets.Unselectable, rendered_conversation)) + [
urwid.LineBox(widgets.DelegatingBoxAdapter(widgets.VimListBox(urwid.SimpleFocusListWalker(rendered_widgets)),
rows_calculating_delegate_widget),
title="Reply Preview" if original_twt else "New Twt Preview",
title_align="left"),
urwid.Columns([urwid.Text(""),
(len(back.label) + 4, back)],
dividechars=2)])
show_subjects = False
fold_subjects = True
......
......@@ -44,10 +44,10 @@ class TwtxtManager:
MAX_TWEETS_LIMIT = 2000
self._cache = shelve.open(self.config.cachefile)
own_source = twtxt.models.Source(nick=self.config.nick, url=self.config.twturl)
self.own_source = twtxt.models.Source(nick=self.config.nick, url=self.config.twturl)
with open(self.config.twtfile, 'r', encoding='utf-8') as fd:
own_twts = twtxt.parser.parse_tweets(fd.readlines(), own_source)
self._cache[own_source.url] = {'tweets': own_twts}
own_twts = twtxt.parser.parse_tweets(fd.readlines(), self.own_source)
self._cache[self.own_source.url] = {'tweets': own_twts}
os.makedirs(os.path.dirname(self.config.datafile), exist_ok=True)
self._data = shelve.open(self.config.datafile)
for url, feed in self._cache.items():
......@@ -59,17 +59,10 @@ class TwtxtManager:
self.max_author_nick_width = max(self.max_author_nick_width, len(tweets[0].source.nick))
all_tweets.extend(tweets)
for twt in tweets:
twt.hash = twtxthash.create_hash(twt)
twt.old_hash = twtxthash.create_old_hash(twt)
if "\t" in twt.text:
twt.text = twt.text.replace("\t", " ")
twt.tokens = list(twtxtparser.parse_twt_text(twt.text))
twt.subject = next((token.hash for token in twt.tokens
if isinstance(token, twtxtparser.SubjectHash)), None)
self.enhance_twt(twt)
replies_by_subject[twt.subject].append(twt)
known_tweet_hashes.add(twt.hash)
known_tweet_hashes.add(twt.old_hash)
twt.replies = []
entry = self._data.get(twt.hash)
twt.read = bool(entry and entry.get("read", False))
if not twt.read:
......@@ -137,6 +130,25 @@ class TwtxtManager:
self.conversation_tree.append(twt)
def enhance_twt(self, twt):
"""
Parse the text of the given twt, store all its enhanced information
(such as hashes, tokens, subject, replies) in the twt and return it
for further processing.
"""
twt.hash = twtxthash.create_hash(twt)
twt.old_hash = twtxthash.create_old_hash(twt)
if "\t" in twt.text:
twt.text = twt.text.replace("\t", " ")
twt.tokens = list(twtxtparser.parse_twt_text(twt.text))
twt.subject = next((token.hash for token in twt.tokens
if isinstance(token, twtxtparser.SubjectHash)), None)
twt.replies = []
twt.read = False
return twt
def toggle_read(self, twt):
"""
Toggle the read status of the given twt and sync it to disk.
......
......@@ -429,3 +429,63 @@ class PrefixText(urwid.Text):
return urwid.canvas.CanvasJoin([(prefix_canvas, None, False, prefix_len),
(text_canvas, None, False, text_canvas.cols())])
class DelegatingBoxAdapter(urwid.BoxAdapter):
"""
Adapter for using a box widget where a flow widget would usually go. Similar to
`urwid.BoxAdpater`, but delegates to a widget instead of using a hardcoded height.
The delegate widget's `rows(…)` method will be called.
All the overridden methods are the ones, which `urwid.BoxAdapter` overrides, too.
"""
def __init__(self, box_widget, delegate_widget):
super().__init__(box_widget, None)
self._delegate_widget = delegate_widget
def rows(self, size, focus=False):
return self._delegate_widget.rows(size, focus)
def get_cursor_coords(self, size):
(maxcol,) = size
if not hasattr(self._original_widget, 'get_cursor_coords'):
return None
return self._original_widget.get_cursor_coords((maxcol, self.rows(size, focus=False)))
def get_pref_col(self, size):
(maxcol,) = size
if not hasattr(self._original_widget, 'get_pref_col'):
return None
return self._original_widget.get_pref_col((maxcol, self.rows(size, focus=False)))
def keypress(self, size, key):
(maxcol,) = size
return self._original_widget.keypress((maxcol, self.rows(size, focus=False)), key)
def move_cursor_to_coords(self, size, col, row):
(maxcol,) = size
if not hasattr(self._original_widget, 'move_cursor_to_coords'):
return True
return self._original_widget.move_cursor_to_coords((maxcol,
self.rows(size, focus=False)), col, row)
def mouse_event(self, size, event, button, col, row, focus):
(maxcol,) = size
if not hasattr(self._original_widget, 'mouse_event'):
return False
return self._original_widget.mouse_event((maxcol, self.rows(size, focus)),
event, button, col, row, focus)
def render(self, size, focus=False):
(maxcol,) = size
canv = self._original_widget.render((maxcol, self.rows(size, focus)), focus)
canv = urwid.CompositeCanvas(canv)
return canv
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment