523 lines
14 KiB
Python
523 lines
14 KiB
Python
import asyncio
|
|
|
|
from izzylib.misc import random_str
|
|
|
|
from .. import cache, var
|
|
from ..base import ComponentBase
|
|
from ..database import default_permissions
|
|
from ..exceptions import AccountNotFoundError, NoAccountsError
|
|
from ..functions import connect, get_buffer_text
|
|
from ..objects import SavedLoginRow
|
|
|
|
|
|
SITEOPTIONS = [
|
|
'instance',
|
|
'adblock',
|
|
'fullscreen',
|
|
'autoplay',
|
|
'dialog',
|
|
'notification',
|
|
'microphone',
|
|
'location',
|
|
'camera'
|
|
]
|
|
|
|
|
|
class StatusBar(ComponentBase):
|
|
def __init__(self, window):
|
|
ComponentBase.__init__(self, 'statusbar')
|
|
|
|
self.window = window
|
|
self.siteoptions_handler_ids = []
|
|
self.bookmark_row = None
|
|
self.theme_enabled = False
|
|
|
|
self.toot_acct = None
|
|
self.toot_post = None
|
|
self.toot_max_len = 500
|
|
|
|
self.unsaved_logins = []
|
|
|
|
self.setup()
|
|
|
|
|
|
@property
|
|
def tab(self):
|
|
return self.window.active_tab
|
|
|
|
|
|
def bookmark_get_data(self):
|
|
data = DotDict()
|
|
|
|
for k,v in self.bookmark_fields.items():
|
|
if k == 'description':
|
|
data[k] = get_buffer_text(v.get_buffer())
|
|
|
|
else:
|
|
data[k] = v.get_text()
|
|
|
|
return data
|
|
|
|
|
|
def bookmark_refresh_categories(self):
|
|
menu = self['bookmark-category-menu']
|
|
menu.foreach(lambda child: child.destroy())
|
|
|
|
with self.db.session as s:
|
|
for category in s.get_categories():
|
|
item = Gtk.MenuItem.new_with_label(category)
|
|
item.show()
|
|
|
|
connect(item, 'activate', self.handle_bookmark_set_category, category)
|
|
menu.add(item)
|
|
|
|
|
|
def bookmark_set_data(self, name=None, url=None, category=None, description=None):
|
|
data = dict(name=name, url=url, category=category, description=description)
|
|
|
|
for k,v in data.items():
|
|
value = v if v != None else ''
|
|
|
|
if k == 'description':
|
|
self.bookmark_fields[k].get_buffer().set_text(value)
|
|
|
|
else:
|
|
self.bookmark_fields[k].set_text(value)
|
|
|
|
|
|
def login_unsaved_del_row(self, row):
|
|
self.logins.unsaved.remove(row['container'])
|
|
self.unsaved_logins.remove(row)
|
|
|
|
|
|
def login_unsaved_get_row(self, widget):
|
|
for row in self.unsaved_logins:
|
|
if widget == row['container']:
|
|
return row
|
|
|
|
|
|
def login_unsaved_new(self, data):
|
|
self.logins.unsaved.add(SavedLoginRow(data))
|
|
|
|
|
|
def login_unsaved_refresh(self):
|
|
for child in self.logins.unsaved.get_children():
|
|
self.logins.unsaved.remove(child)
|
|
child.destroy()
|
|
|
|
for row in self.unsaved_logins:
|
|
self.logins.unsaved(UnsavedLoginRow(row)['container'])
|
|
|
|
|
|
def toot_close(self, *args):
|
|
self['toot-popover'].popdown()
|
|
|
|
|
|
def toot_clear(self, *args):
|
|
self.toot_fields.spoiler.set_text('')
|
|
self.toot_fields.content.get_buffer().set_text('')
|
|
self.toot_fields.visibility.set_active(0)
|
|
self.toot_update_count()
|
|
self.toot_set_reply()
|
|
|
|
|
|
def toot_set_account(self):
|
|
try:
|
|
self.toot_account = self.app.get_default_account()
|
|
|
|
if self.toot_account.avatar.exists():
|
|
avatar = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.toot_account.avatar, -1, 24, True)
|
|
self['toot-avatar'].set_from_pixbuf(avatar)
|
|
self['toot-avatar'].set_tooltip_text(f'{self.toot_account.data.display_name} ({self.toot_account.fullhandle})')
|
|
|
|
except NoAccountsError:
|
|
self.window.notification('No active fedi accounts', 'error')
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def toot_get_info(self):
|
|
return DotDict(
|
|
spoiler = self.toot_fields.spoiler.get_text(),
|
|
content = get_buffer_text(self.toot_fields.content.get_buffer()),
|
|
visibility = self.toot_fields.visibility.get_active_text()
|
|
)
|
|
|
|
|
|
def toot_send(self, *args):
|
|
data = self.toot_get_info()
|
|
options = {
|
|
'visibility': data.visibility.lower()
|
|
}
|
|
|
|
if not (data.spoiler or data.content):
|
|
return self.window.notification('Unwilling to send empty post', level='error')
|
|
|
|
if data.spoiler:
|
|
options['spoiler_text'] = data.spoiler
|
|
|
|
if self['toot-reply-scroll'].get_visible():
|
|
options['in_reply_to_id'] = self.toot_post.id
|
|
|
|
try:
|
|
self.toot_account.api.status_post(data.content, **options)
|
|
|
|
except Exception as e:
|
|
logging.error(f'{type(e).__name__}: {e}')
|
|
self.window.notification('Failed to send toot')
|
|
return
|
|
|
|
self.window.notification('Sent toot')
|
|
self['toot-popover'].popdown()
|
|
self.toot_clear()
|
|
|
|
|
|
def toot_set_reply(self, toot=None):
|
|
self.toot_post = toot
|
|
|
|
reply = self.toot_fields.reply
|
|
scroll = self['toot-reply-scroll']
|
|
privacy = self['toot-visibility']
|
|
account = self.toot_post.get('account') if toot else None
|
|
|
|
if not toot and not account:
|
|
scroll.hide()
|
|
return
|
|
|
|
text_buffer = reply.get_buffer()
|
|
text_buffer.set_text(f'Reply to: {account.display_name} ({account.acct}):\n\n{toot.content}')
|
|
reply.set_buffer(text_buffer)
|
|
|
|
privacy.set_active_id(toot.get('visibility', 'public'))
|
|
|
|
scroll.show()
|
|
|
|
|
|
def toot_update_count(self, *args):
|
|
spoiler = len(self.toot_fields.spoiler.get_text())
|
|
content = self.toot_fields.content.get_buffer().get_char_count()
|
|
num = spoiler + content
|
|
|
|
self.toot_fields.count.set_text(str(self.toot_max_len - num))
|
|
|
|
|
|
def handle_cookie_domains(self, data_manager, result):
|
|
data = data_manager.fetch_finish(result)
|
|
print(set(item.get_name() for item in data))
|
|
|
|
|
|
def handle_status_button(self, name):
|
|
try:
|
|
if not self[name].get_active():
|
|
return
|
|
|
|
except AttributeError:
|
|
pass
|
|
|
|
tab = self.tab
|
|
|
|
if name == 'debug':
|
|
#self.window.notification('Merp!', 'INFO', timeout=0, system=True)
|
|
print(asyncio.get_running_loop())
|
|
|
|
#if self.window.themes.current:
|
|
#self.window.themes.unset()
|
|
|
|
#else:
|
|
#self.window.themes.set('test')
|
|
|
|
elif name == 'bookmark':
|
|
if not tab.url:
|
|
return
|
|
|
|
self['bookmark-popover'].grab_focus()
|
|
|
|
with self.db.session as s:
|
|
self.bookmark_row = s.get_bookmark(tab.url)
|
|
|
|
if not self.bookmark_row:
|
|
self['bookmark-delete'].set_sensitive(False)
|
|
|
|
return self.bookmark_set_data(
|
|
name = tab.title,
|
|
url = tab.url,
|
|
category = 'Default'
|
|
)
|
|
|
|
self['bookmark-delete'].set_sensitive(True)
|
|
self.bookmark_set_data(
|
|
name = self.bookmark_row.name,
|
|
url = self.bookmark_row.url,
|
|
category = self.bookmark_row.category,
|
|
description = self.bookmark_row.description
|
|
)
|
|
|
|
elif name == 'siteoptions':
|
|
if not self['siteoptions'].get_active() or not tab.url.hostname():
|
|
return
|
|
|
|
with self.db.session as s:
|
|
row = s.get_permission(tab.url.hostname())
|
|
|
|
self['siteoptions-domain'].set_text(tab.url.hostname())
|
|
self['siteoptions-reset'].set_sensitive(True if row != None else False)
|
|
self.siteoptions_row = row
|
|
|
|
with self.block_signals(*[f'siteoptions-{name}' for name in SITEOPTIONS]):
|
|
for k, v in default_permissions.items():
|
|
value = row.get(k, v)
|
|
self[f'siteoptions-{k}'].set_state(value)
|
|
|
|
self['siteoptions-reset'].set_sensitive(row and row.id != None)
|
|
|
|
self['siteoptions-reset'].grab_focus()
|
|
|
|
elif name == 'logins':
|
|
self['logins-saved-list'].grab_focus()
|
|
self.handle_logins_refresh()
|
|
|
|
elif name == 'toot':
|
|
if not self.toot_set_account():
|
|
return self['toot-popover'].popdown()
|
|
|
|
self.toot_max_len = self.toot_account.toot_limit
|
|
self.toot_update_count()
|
|
self.toot_set_reply(self.toot_post)
|
|
|
|
self['toot-content'].grab_focus()
|
|
|
|
|
|
def handle_bookmark_button(self, name):
|
|
with self.db.session as s:
|
|
if name == 'save':
|
|
data = self.bookmark_get_data()
|
|
|
|
if self.bookmark_row:
|
|
s.put_bookmark_row(self.bookmark_row, **data)
|
|
|
|
else:
|
|
s.put_bookmark(**data)
|
|
|
|
elif name == 'delete':
|
|
if self.bookmark_row:
|
|
s.remove_row(self.bookmark_row)
|
|
|
|
self['bookmark-popover'].popdown()
|
|
|
|
|
|
def handle_bookmark_category_button(self):
|
|
menu = self['bookmark-category-menu']
|
|
menu.popup_at_widget(
|
|
widget = self['bookmark-category'],
|
|
widget_anchor = Gdk.Gravity.NORTH_EAST,
|
|
menu_anchor = Gdk.Gravity.SOUTH_EAST,
|
|
trigger_event = None
|
|
)
|
|
|
|
|
|
def handle_bookmark_set_category(self, category):
|
|
self['bookmark-category'].set_text(category)
|
|
|
|
|
|
def handle_fedi_button(self, name):
|
|
post = self.tab.fedi_post
|
|
|
|
if not post or not self.toot_set_account():
|
|
return
|
|
|
|
if name == 'reply':
|
|
#self.toot_set_reply(post)
|
|
self.toot_post = post
|
|
self['toot'].activate()
|
|
|
|
elif name == 'favorite':
|
|
if post.favourited == True:
|
|
if self.toot_account.api.status_unfavourite(post.id):
|
|
post.favourited = False
|
|
self.window.notification('Unfavorited post')
|
|
|
|
else:
|
|
self.window.notification('Failed to unfavorite post', 'error')
|
|
|
|
else:
|
|
if self.toot_account.api.status_favourite(post.id):
|
|
post.favourited = True
|
|
self.window.notification('Favorited post')
|
|
|
|
else:
|
|
self.window.notification('Failed to favorite post', 'error')
|
|
|
|
elif name == 'boost':
|
|
if post.reblogged == True:
|
|
if self.toot_account.api.status_unreblog(post.id):
|
|
post.reblogged = False
|
|
self.window.notification('Unboosted post')
|
|
|
|
else:
|
|
self.window.notification('Failed to unboost post', 'error')
|
|
|
|
else:
|
|
if self.toot_account.api.status_reblog(post.id):
|
|
post.reblogged = True
|
|
self.window.notification('Boosted post')
|
|
|
|
else:
|
|
self.window.notification('Failed to boost post', 'error')
|
|
|
|
if post:
|
|
cache.posts.store(self.tab.url, post)
|
|
|
|
|
|
def handle_siteoptions_switch(self, name):
|
|
active = self[f'siteoptions-{name}'].get_active()
|
|
try:
|
|
host = self.tab.url.hostname()
|
|
|
|
except:
|
|
return
|
|
|
|
with self.db.session as s:
|
|
s.put_permission(host, name, active)
|
|
|
|
logging.verbose(f'siteoptions: set {name}: {active}')
|
|
self['siteoptions-reset'].set_sensitive(True)
|
|
|
|
|
|
def handle_siteoptions_button(self, name):
|
|
if name == 'reset':
|
|
host = self.tab.url.hostname()
|
|
|
|
with self.db.session as s:
|
|
s.del_permission(host)
|
|
|
|
self.handle_status_button('siteoptions')
|
|
|
|
elif name == 'close':
|
|
self['siteoptions-popover'].popdown()
|
|
|
|
|
|
def handle_logins_button(self, name):
|
|
if name == 'clear':
|
|
for widget in self['logins-unsaved-list']:
|
|
widget.handle_cancel()
|
|
|
|
elif name == 'passgen':
|
|
self.app.clipboard.set_text(random_str(extra=r'!@#$%^&*()_+-={}[]<>;:'), -1)
|
|
self.window.notification('Copied newly-generated password to clipboard', system=False)
|
|
|
|
self['logins-popover'].popdown()
|
|
|
|
|
|
def handle_logins_refresh(self):
|
|
login_list = self['logins-saved-list']
|
|
url = self.tab.url
|
|
unsaved = len(self['logins-unsaved-list'])
|
|
|
|
for child in login_list.get_children():
|
|
child.destroy()
|
|
|
|
for row in self.app.password.fetch(domain=url.hostname()):
|
|
## todo: fix searching by domain
|
|
if row.domain == url.hostname():
|
|
login_list.add(SavedLoginRow(row, url)['container'])
|
|
|
|
for name in ['scroll', 'label', 'clear']:
|
|
widget = self[f'logins-unsaved-{name}']
|
|
|
|
if unsaved:
|
|
widget.show()
|
|
|
|
else:
|
|
widget.hide()
|
|
|
|
|
|
def handle_toot_key_press(self, textview, event, *args):
|
|
keyname = Gdk.keyval_name(event.keyval)
|
|
|
|
if keyname.lower() == 'return' and event.state == Gdk.ModifierType.CONTROL_MASK:
|
|
self.toot_send()
|
|
return True
|
|
|
|
|
|
def handle_toot_spoiler_activate(self, *args):
|
|
self['toot-content'].grab_focus()
|
|
|
|
|
|
def setup(self):
|
|
self.bookmark_fields = DotDict(
|
|
name = self['bookmark-title'],
|
|
url = self['bookmark-url'],
|
|
category = self['bookmark-category'],
|
|
description = self['bookmark-description']
|
|
)
|
|
|
|
self.toot_fields = DotDict(
|
|
reply = self['toot-reply'],
|
|
spoiler = self['toot-spoiler'],
|
|
content = self['toot-content'],
|
|
visibility = self['toot-visibility'],
|
|
count = self['toot-count']
|
|
)
|
|
|
|
self.logins = DotDict(
|
|
unsaved = self['logins-unsaved-list'],
|
|
saved = self['logins-saved-list']
|
|
)
|
|
|
|
## Status bar
|
|
self.connect('debug', 'clicked', self.handle_status_button, 'debug')
|
|
self.connect('toot', 'toggled', self.handle_status_button, 'toot')
|
|
self.connect('reply', 'clicked', self.handle_fedi_button, 'reply')
|
|
self.connect('boost', 'clicked', self.handle_fedi_button, 'boost')
|
|
self.connect('favorite', 'clicked', self.handle_fedi_button, 'favorite')
|
|
self.connect('logins', 'toggled', self.handle_status_button, 'logins')
|
|
self.connect('bookmark', 'toggled', self.handle_status_button, 'bookmark')
|
|
self.connect('siteoptions', 'toggled', self.handle_status_button, 'siteoptions')
|
|
|
|
## Toot
|
|
self.connect('toot-spoiler', 'changed', self.toot_update_count)
|
|
self.connect('toot-spoiler', 'activate', self.handle_toot_spoiler_activate)
|
|
self.connect('toot-reset', 'clicked', self.toot_clear)
|
|
self.connect('toot-send', 'clicked', self.toot_send)
|
|
self.connect('toot-close', 'clicked', self.toot_close)
|
|
self.connect('toot-content', 'key-press-event', self.handle_toot_key_press)
|
|
connect(self['toot-content'].get_buffer(), 'changed', self.toot_update_count)
|
|
|
|
## Logins
|
|
self.connect('logins-close', 'clicked', self.handle_logins_button, 'close')
|
|
self.connect('logins-unsaved-clear', 'clicked', self.handle_logins_button, 'clear')
|
|
self.connect('logins-saved-passgen', 'clicked', self.handle_logins_button, 'passgen')
|
|
|
|
## Bookmarks
|
|
self.connect('bookmark-save', 'clicked', self.handle_bookmark_button, 'save')
|
|
self.connect('bookmark-delete', 'clicked', self.handle_bookmark_button, 'delete')
|
|
self.connect('bookmark-close', 'clicked', self.handle_bookmark_button, 'close')
|
|
self.connect('bookmark-category', 'icon-press', self.handle_bookmark_category_button)
|
|
|
|
## Siteoptions
|
|
self.connect('siteoptions-reset', 'clicked', self.handle_siteoptions_button, 'reset')
|
|
self.connect('siteoptions-close', 'clicked', self.handle_siteoptions_button, 'close')
|
|
|
|
# extra work needs to be done to toggle webview settings
|
|
self.permissions = DotDict({
|
|
'instance': False,
|
|
'adblock': True,
|
|
'fullscreen': True,
|
|
'autoplay': False,
|
|
'dialog': True,
|
|
'notification': False,
|
|
'microphone': False,
|
|
'location': False,
|
|
'camera': False,
|
|
#'javascript': True,
|
|
#'images': True,
|
|
#'autoplay': False,
|
|
#'insecure': False
|
|
})
|
|
|
|
for name in self.permissions:
|
|
self.connect(f'siteoptions-{name}', 'state-set', self.handle_siteoptions_switch, name)
|
|
|
|
self.bookmark_refresh_categories()
|