reorder buttons and split classes into widgets
This commit is contained in:
parent
6e3aefda53
commit
dff6d30fa8
3 changed files with 186 additions and 151 deletions
157
src/main.py
157
src/main.py
|
@ -29,6 +29,8 @@ gi.require_version('Handy', '1')
|
||||||
from gi.repository import Handy
|
from gi.repository import Handy
|
||||||
Handy.init()
|
Handy.init()
|
||||||
|
|
||||||
|
from .widgets import LoginPage, Timeline, PostItem
|
||||||
|
|
||||||
class Application(Gtk.Application):
|
class Application(Gtk.Application):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -127,11 +129,13 @@ class Application(Gtk.Application):
|
||||||
global_tl = Timeline('global')
|
global_tl = Timeline('global')
|
||||||
self.stack.add_titled(global_tl, "global", "Global")
|
self.stack.add_titled(global_tl, "global", "Global")
|
||||||
|
|
||||||
|
new_post_button = Gtk.Button.new_from_icon_name('list-add-symbolic', 1)
|
||||||
|
self.header.pack_start(new_post_button)
|
||||||
|
|
||||||
reload_button = Gtk.Button.new_from_icon_name('view-refresh-symbolic', 1)
|
reload_button = Gtk.Button.new_from_icon_name('view-refresh-symbolic', 1)
|
||||||
reload_button.connect('clicked', self.emit_refresh)
|
reload_button.connect('clicked', self.emit_refresh)
|
||||||
self.header.pack_start(reload_button)
|
self.header.pack_start(reload_button)
|
||||||
new_post_button = Gtk.Button.new_from_icon_name('list-add-symbolic', 1)
|
|
||||||
self.header.pack_start(new_post_button)
|
|
||||||
self.header.show_all()
|
self.header.show_all()
|
||||||
|
|
||||||
self.stack.show_all()
|
self.stack.show_all()
|
||||||
|
@ -140,155 +144,6 @@ class Application(Gtk.Application):
|
||||||
timeline = self.stack.get_visible_child()
|
timeline = self.stack.get_visible_child()
|
||||||
timeline.emit('refresh')
|
timeline.emit('refresh')
|
||||||
|
|
||||||
class LoginPage(Gtk.Box):
|
|
||||||
|
|
||||||
__gsignals__ = {
|
|
||||||
'login': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(orientation='vertical')
|
|
||||||
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
|
||||||
|
|
||||||
client_id = "1PiUzxfX_CQxKvtz93lUzPX9-FMtz-va"
|
|
||||||
redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
|
||||||
scope = "basic,stream,write_post,follow,presence,messages,files,polls"
|
|
||||||
|
|
||||||
uri = "https://pnut.io/oauth/authenticate"
|
|
||||||
uri += "?client_id=" + client_id
|
|
||||||
uri += "&redirect_uri=" + redirect_uri
|
|
||||||
uri += "&scope=" + scope
|
|
||||||
uri += "&response_type=token"
|
|
||||||
|
|
||||||
self.login_button = Gtk.LinkButton.new_with_label(uri, "Log In to pnut.io")
|
|
||||||
self.login_button.connect("clicked", self.prompt_code)
|
|
||||||
|
|
||||||
self.set_center_widget(self.login_button)
|
|
||||||
|
|
||||||
def prompt_code(self, button):
|
|
||||||
self.remove(self.login_button)
|
|
||||||
|
|
||||||
label = Gtk.Label()
|
|
||||||
label.set_markup('<span font="20">Enter authorization code</span>')
|
|
||||||
self.code = Gtk.Entry()
|
|
||||||
|
|
||||||
paste_button = Gtk.Button(label="Paste from clipboard")
|
|
||||||
paste_button.connect("clicked", self.paste_code)
|
|
||||||
|
|
||||||
cancel_button = Gtk.Button(label="Cancel")
|
|
||||||
cancel_button.connect("clicked", self.cancel_login)
|
|
||||||
confirm_button = Gtk.Button(label="Confirm")
|
|
||||||
confirm_button.connect("clicked", self.confirm_login)
|
|
||||||
lbox = Gtk.Box(orientation='horizontal')
|
|
||||||
lbox.pack_start(cancel_button, True, True, 0)
|
|
||||||
lbox.pack_start(confirm_button, True, True, 0)
|
|
||||||
|
|
||||||
vbox = Gtk.Box(orientation='vertical')
|
|
||||||
vbox.pack_start(label, False, False, 10)
|
|
||||||
vbox.pack_start(self.code, False, False, 10)
|
|
||||||
vbox.pack_start(paste_button, False, False, 10)
|
|
||||||
vbox.add(lbox)
|
|
||||||
|
|
||||||
hbox = Gtk.Box(orientation='horizontal')
|
|
||||||
hbox.set_center_widget(vbox)
|
|
||||||
|
|
||||||
self.set_center_widget(hbox)
|
|
||||||
self.show_all()
|
|
||||||
|
|
||||||
def paste_code(self, button):
|
|
||||||
text = self.clipboard.wait_for_text()
|
|
||||||
if text is not None:
|
|
||||||
self.code.set_text(text)
|
|
||||||
|
|
||||||
def cancel_login(self, button):
|
|
||||||
# TODO: something actually useful here
|
|
||||||
logging.debug("uh cancel i guess")
|
|
||||||
|
|
||||||
def confirm_login(self, button):
|
|
||||||
code = self.code.get_text()
|
|
||||||
self.emit('login', code)
|
|
||||||
|
|
||||||
class Timeline(Gtk.Box):
|
|
||||||
|
|
||||||
__gsignals__ = {
|
|
||||||
'refresh': (GObject.SIGNAL_RUN_FIRST, None, ())
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, stream):
|
|
||||||
super().__init__(orientation='vertical')
|
|
||||||
|
|
||||||
scroller = Gtk.ScrolledWindow(
|
|
||||||
halign='fill',
|
|
||||||
kinetic_scrolling=True
|
|
||||||
)
|
|
||||||
self.view = Gtk.ListBox(
|
|
||||||
selection_mode=Gtk.SelectionMode.NONE
|
|
||||||
)
|
|
||||||
scroller.add(self.view)
|
|
||||||
self.pack_start(scroller, True, True, 0)
|
|
||||||
|
|
||||||
self.stream = stream
|
|
||||||
self.load_timeline()
|
|
||||||
|
|
||||||
def load_timeline(self):
|
|
||||||
if self.stream == 'unified':
|
|
||||||
posts, meta = pnutpy.api.users_post_streams_unified()
|
|
||||||
elif self.stream == 'mentions':
|
|
||||||
posts, meta = pnutpy.api.users_mentioned_posts('me')
|
|
||||||
elif self.stream == 'bookmarks':
|
|
||||||
posts, meta = pnutpy.api.users_bookmarked_posts('me')
|
|
||||||
else:
|
|
||||||
posts, meta = pnutpy.api.posts_streams_global()
|
|
||||||
|
|
||||||
for item in posts:
|
|
||||||
if 'is_deleted' in item:
|
|
||||||
continue
|
|
||||||
self.view.add(PostItem(item))
|
|
||||||
|
|
||||||
def do_refresh(self):
|
|
||||||
rows = self.view.get_children()
|
|
||||||
for item in rows:
|
|
||||||
self.view.remove(item)
|
|
||||||
self.load_timeline()
|
|
||||||
self.show_all()
|
|
||||||
|
|
||||||
class PostItem(Gtk.ListBoxRow):
|
|
||||||
|
|
||||||
def __init__(self, post):
|
|
||||||
super(Gtk.ListBoxRow, self).__init__()
|
|
||||||
self.post = post
|
|
||||||
|
|
||||||
self.box = Gtk.Box(orientation='vertical')
|
|
||||||
self.add(self.box)
|
|
||||||
|
|
||||||
# name container
|
|
||||||
self.name_box = Gtk.Box(orientation='vertical')
|
|
||||||
self.username = Gtk.Label(label="@" + post.user.username, xalign=0)
|
|
||||||
self.name = Gtk.Label(xalign=0)
|
|
||||||
if 'name' in post.user:
|
|
||||||
self.name.set_markup(f"<b>{post.user.name}</b>")
|
|
||||||
self.name_box.pack_start(self.name, True, True, 0)
|
|
||||||
self.name_box.pack_start(self.username, True, True, 0)
|
|
||||||
|
|
||||||
# header container
|
|
||||||
self.h_box = Gtk.Box(orientation='horizontal')
|
|
||||||
self.avatar = Handy.Avatar(size=32)
|
|
||||||
# TODO: get the actual image
|
|
||||||
self.h_box.pack_start(self.avatar, False, False, 18)
|
|
||||||
self.h_box.pack_start(self.name_box, False, False, 0)
|
|
||||||
|
|
||||||
# content container
|
|
||||||
self.c_box = Gtk.Box(orientation='horizontal')
|
|
||||||
self.content = Gtk.Label(wrap=True, xalign=0)
|
|
||||||
# TODO: parse content links
|
|
||||||
if 'content' in post:
|
|
||||||
self.content.set_text(post.content.text)
|
|
||||||
# TODO: add media
|
|
||||||
self.c_box.pack_start(self.content, True, True, 18)
|
|
||||||
|
|
||||||
self.box.pack_start(self.h_box, True, True, 10)
|
|
||||||
self.box.pack_start(self.c_box, True, True, 10)
|
|
||||||
|
|
||||||
def main(version):
|
def main(version):
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
app = Application()
|
app = Application()
|
||||||
|
|
|
@ -28,6 +28,7 @@ configure_file(
|
||||||
squeak_sources = [
|
squeak_sources = [
|
||||||
'__init__.py',
|
'__init__.py',
|
||||||
'main.py',
|
'main.py',
|
||||||
|
'widgets.py',
|
||||||
]
|
]
|
||||||
|
|
||||||
install_data(squeak_sources, install_dir: moduledir)
|
install_data(squeak_sources, install_dir: moduledir)
|
||||||
|
|
179
src/widgets.py
Normal file
179
src/widgets.py
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
# widgets.py
|
||||||
|
#
|
||||||
|
# Copyright 2020 Morgan McMillian
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import gi
|
||||||
|
import os
|
||||||
|
import pnutpy
|
||||||
|
import logging
|
||||||
|
|
||||||
|
gi.require_version('Gdk', '3.0')
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import GObject, Gdk, Gtk, Gio, GLib
|
||||||
|
|
||||||
|
gi.require_version('Handy', '1')
|
||||||
|
from gi.repository import Handy
|
||||||
|
|
||||||
|
class LoginPage(Gtk.Box):
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'login': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(orientation='vertical')
|
||||||
|
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||||
|
|
||||||
|
client_id = "1PiUzxfX_CQxKvtz93lUzPX9-FMtz-va"
|
||||||
|
redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
||||||
|
scope = "basic,stream,write_post,follow,presence,messages,files,polls"
|
||||||
|
|
||||||
|
uri = "https://pnut.io/oauth/authenticate"
|
||||||
|
uri += "?client_id=" + client_id
|
||||||
|
uri += "&redirect_uri=" + redirect_uri
|
||||||
|
uri += "&scope=" + scope
|
||||||
|
uri += "&response_type=token"
|
||||||
|
|
||||||
|
self.login_button = Gtk.LinkButton.new_with_label(uri, "Log In to pnut.io")
|
||||||
|
self.login_button.connect("clicked", self.prompt_code)
|
||||||
|
|
||||||
|
self.set_center_widget(self.login_button)
|
||||||
|
|
||||||
|
def prompt_code(self, button):
|
||||||
|
self.remove(self.login_button)
|
||||||
|
|
||||||
|
label = Gtk.Label()
|
||||||
|
label.set_markup('<span font="20">Enter authorization code</span>')
|
||||||
|
self.code = Gtk.Entry()
|
||||||
|
|
||||||
|
paste_button = Gtk.Button(label="Paste from clipboard")
|
||||||
|
paste_button.connect("clicked", self.paste_code)
|
||||||
|
|
||||||
|
cancel_button = Gtk.Button(label="Cancel")
|
||||||
|
cancel_button.connect("clicked", self.cancel_login)
|
||||||
|
confirm_button = Gtk.Button(label="Confirm")
|
||||||
|
confirm_button.connect("clicked", self.confirm_login)
|
||||||
|
lbox = Gtk.Box(orientation='horizontal')
|
||||||
|
lbox.pack_start(cancel_button, True, True, 0)
|
||||||
|
lbox.pack_start(confirm_button, True, True, 0)
|
||||||
|
|
||||||
|
vbox = Gtk.Box(orientation='vertical')
|
||||||
|
vbox.pack_start(label, False, False, 10)
|
||||||
|
vbox.pack_start(self.code, False, False, 10)
|
||||||
|
vbox.pack_start(paste_button, False, False, 10)
|
||||||
|
vbox.add(lbox)
|
||||||
|
|
||||||
|
hbox = Gtk.Box(orientation='horizontal')
|
||||||
|
hbox.set_center_widget(vbox)
|
||||||
|
|
||||||
|
self.set_center_widget(hbox)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
def paste_code(self, button):
|
||||||
|
text = self.clipboard.wait_for_text()
|
||||||
|
if text is not None:
|
||||||
|
self.code.set_text(text)
|
||||||
|
|
||||||
|
def cancel_login(self, button):
|
||||||
|
# TODO: something actually useful here
|
||||||
|
logging.debug("uh cancel i guess")
|
||||||
|
|
||||||
|
def confirm_login(self, button):
|
||||||
|
code = self.code.get_text()
|
||||||
|
self.emit('login', code)
|
||||||
|
|
||||||
|
class Timeline(Gtk.Box):
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'refresh': (GObject.SIGNAL_RUN_FIRST, None, ())
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, stream):
|
||||||
|
super().__init__(orientation='vertical')
|
||||||
|
|
||||||
|
scroller = Gtk.ScrolledWindow(
|
||||||
|
halign='fill',
|
||||||
|
kinetic_scrolling=True
|
||||||
|
)
|
||||||
|
self.view = Gtk.ListBox(
|
||||||
|
selection_mode=Gtk.SelectionMode.NONE
|
||||||
|
)
|
||||||
|
scroller.add(self.view)
|
||||||
|
self.pack_start(scroller, True, True, 0)
|
||||||
|
|
||||||
|
self.stream = stream
|
||||||
|
self.load_timeline()
|
||||||
|
|
||||||
|
def load_timeline(self):
|
||||||
|
if self.stream == 'unified':
|
||||||
|
posts, meta = pnutpy.api.users_post_streams_unified()
|
||||||
|
elif self.stream == 'mentions':
|
||||||
|
posts, meta = pnutpy.api.users_mentioned_posts('me')
|
||||||
|
elif self.stream == 'bookmarks':
|
||||||
|
posts, meta = pnutpy.api.users_bookmarked_posts('me')
|
||||||
|
else:
|
||||||
|
posts, meta = pnutpy.api.posts_streams_global()
|
||||||
|
|
||||||
|
for item in posts:
|
||||||
|
if 'is_deleted' in item:
|
||||||
|
continue
|
||||||
|
self.view.add(PostItem(item))
|
||||||
|
|
||||||
|
def do_refresh(self):
|
||||||
|
rows = self.view.get_children()
|
||||||
|
for item in rows:
|
||||||
|
self.view.remove(item)
|
||||||
|
self.load_timeline()
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
class PostItem(Gtk.ListBoxRow):
|
||||||
|
|
||||||
|
def __init__(self, post):
|
||||||
|
super(Gtk.ListBoxRow, self).__init__()
|
||||||
|
self.post = post
|
||||||
|
|
||||||
|
self.box = Gtk.Box(orientation='vertical')
|
||||||
|
self.add(self.box)
|
||||||
|
|
||||||
|
# name container
|
||||||
|
self.name_box = Gtk.Box(orientation='vertical')
|
||||||
|
self.username = Gtk.Label(label="@" + post.user.username, xalign=0)
|
||||||
|
self.name = Gtk.Label(xalign=0)
|
||||||
|
if 'name' in post.user:
|
||||||
|
self.name.set_markup(f"<b>{post.user.name}</b>")
|
||||||
|
self.name_box.pack_start(self.name, True, True, 0)
|
||||||
|
self.name_box.pack_start(self.username, True, True, 0)
|
||||||
|
|
||||||
|
# header container
|
||||||
|
self.h_box = Gtk.Box(orientation='horizontal')
|
||||||
|
self.avatar = Handy.Avatar(size=32)
|
||||||
|
# TODO: get the actual image
|
||||||
|
self.h_box.pack_start(self.avatar, False, False, 18)
|
||||||
|
self.h_box.pack_start(self.name_box, False, False, 0)
|
||||||
|
|
||||||
|
# content container
|
||||||
|
self.c_box = Gtk.Box(orientation='horizontal')
|
||||||
|
self.content = Gtk.Label(wrap=True, xalign=0)
|
||||||
|
# TODO: parse content links
|
||||||
|
if 'content' in post:
|
||||||
|
self.content.set_text(post.content.text)
|
||||||
|
# TODO: add media
|
||||||
|
self.c_box.pack_start(self.content, True, True, 18)
|
||||||
|
|
||||||
|
self.box.pack_start(self.h_box, True, True, 10)
|
||||||
|
self.box.pack_start(self.c_box, True, True, 10)
|
||||||
|
|
Loading…
Reference in a new issue