123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990 |
- #####################################################################
- # #
- # THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE #
- # LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet ) #
- # FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk ) #
- # WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
- # IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
- # OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE. #
- # #
- # ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS #
- # (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK. #
- # YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
- # THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER #
- # VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG #
- # WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ). #
- # #
- # THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE #
- # NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
- # THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT #
- # SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
- # THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT. #
- # #
- # THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL #
- # FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE #
- # THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD #
- # TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT. #
- # #
- #####################################################################
- # Preparing the executable of lbrynet to be running. If we don't that
- # there will be a nasty error of permission being denied.
- import os
- os.system("chmod u+x flbry/lbrynet")
- # I'm not trying to make it pretty. I'm trying to make it snappy.
- # It's FastLBRY not SlowLBRY.
- import gi
- import threading
- gi.require_version('Gtk', '3.0')
- from gi.repository import Gtk
- from gi.repository import Gdk
- from gi.repository import GLib
- # It's gonna take a couple of things to make the button run
- from flbry import connect
- from flbry import parse
- from flbry import settings
- from flbry import url
- from flbry import ui
- from flbry import claim_search
- from flbry import fetch
- from flbry import publish
- from flbry import downloads
- from flbry import analytics
- from flbry import livestreams
- from flbry import suggest
- from flbry import odysee
- settings.make_sure_file_exists()
- ##########################################################################
- # #
- # THE MAIN WINDOW OF FASTLBRY GTK #
- # #
- ##########################################################################
- win = Gtk.Window() # Make a GTK window object
- win.connect("destroy", Gtk.main_quit) # If you close the window, program quits
- win.set_title("FastLBRY GTK") # Title
- win.set_default_icon_from_file("icon.png") # Icon
- win.set_size_request(800, 700) # Minimum size
- ##########################################################################
- # #
- # GLOBAL VARIABLES HACK ( adding things to 'win' ) #
- # #
- ##########################################################################
- # This hack is very simple. Our main Gtk.Window() is a class to which we
- # can add variables later on. Like the example you see below.
- # This way, giving some function only 'win' and nothing else, will give
- # that other function the entire list of global variable ( added this way ).
- win.settings = settings.load() # Settings
- win.SDK_running = connect.check() # Is the SDK running ( from 0 to 1 to draw progress bar)
- win.resolved = {} # Last resolved data
- win.commenting = {} # Data for while chatting in comments
- win.subs = [] # What you are subscribed to
- win.tabs = [] # List of Gtk.Notebook tabs
- win.resolve_tab = 0 # What tab to resolve the page
- win.notebook = Gtk.Notebook() # Tabs object
- win.download_buttons = {} # Keep alive handlers for Download buttons
- win.downloads = {} # Data for the Downloads window
- ##########################################################################
- # #
- # TOP PANNEL #
- # #
- ##########################################################################
- # Gtk.HeaderBar() is like a box but it draws itself in the headerbar insead
- # of in the window itself.
- pannel = Gtk.HeaderBar()
- pannel.set_show_close_button(True)
- win.set_titlebar(pannel) # Dumbasses wrote GTK
- # Untill the user connected to the SDK, search and other functions should
- # not work. So we split the pannel into two parts. The other one is a
- # normal box.
- restofpannel = Gtk.HBox() # H for Horrizontal
- pannel.pack_end(restofpannel)
- ############## CONNECT BUTTON ################
- # Connect button will also be a disconnect button
- # Icons for both
- icon_connect = ui.icon(win, "network-wired")
- icon_disconnect = ui.icon(win, "network-wired-disconnected")
- # Boxes for both
- connect_box = Gtk.HBox()
- disconnect_box = Gtk.HBox()
- # Connect box
- connect_box.pack_start(icon_connect, False, False, False)
- connect_box.set_tooltip_text("Connect to LBRY Network")
- connect_box.pack_start(Gtk.Label("Connect "), False, False, False)
- # Disconnect box
- disconnect_box.pack_start(icon_disconnect, False, False, False)
- disconnect_box.set_tooltip_text("Disconnect from LBRY Network")
- disconnect_box.pack_start(Gtk.Label("Disconnect "), False, False, False)
- # By whether SDK was running while the software was launched
- # we present the correct button to the user and set the rest-of-pannel
- # accordingly.
- if win.SDK_running:
- title = disconnect_box
- restofpannel.set_sensitive(True)
- else:
- title = connect_box
- restofpannel.set_sensitive(False)
- connect_disconncet_button = Gtk.Button()
- connect_disconncet_button.add(title)
- connect_disconncet_button.set_relief(Gtk.ReliefStyle.NONE)
- pannel.pack_start(connect_disconncet_button)#, False, False, False)
- ############### CONNECT / DISCONNECT BUTTONS FUNCTION ################
- # The button should do something.
- def connect_disconnect_function(w):
-
- w.set_sensitive(False)
- dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
- for i in dynamic_box.get_children():
- i.destroy()
- progress_connect = Gtk.ProgressBar(show_text=True)
- dynamic_box.pack_start(progress_connect, True, True, 30)
- win.show_all()
- def do_sdk(w, pb):
- wasrunning = win.SDK_running
- if win.SDK_running == 1:
- connect.stop(win)
-
- else:
- connect.start(win)
- def update_pb(pb):
- pb.set_fraction(win.SDK_running)
- pb.set_text("Connecting: "+str(int(round(win.SDK_running*100)))+"%")
-
- def update_buttons(w):
- for i in dynamic_box.get_children():
- i.destroy()
- w.get_child().destroy()
- if win.SDK_running == 1:
- w.add(disconnect_box)
- restofpannel.set_sensitive(True)
- else:
- w.add(connect_box)
- restofpannel.set_sensitive(False)
- w.show_all()
- w.set_sensitive(True)
- if win.SDK_running == 1:
- load_following()
- load_channel(win)
- check_lock_button()
- ui.notify(win, "Connected to LBRY")
- if wasrunning == 0:
- while True:
- win.SDK_running = connect.check()
- if win.SDK_running == 1:
- break
- GLib.idle_add(update_pb, pb)
-
- GLib.idle_add(update_buttons, w)
-
- load_thread = threading.Thread(target=do_sdk, args=(w, progress_connect))
- load_thread.setDaemon(True)
- load_thread.start()
-
- connect_disconncet_button.connect("clicked", connect_disconnect_function)
- ##########################################################################
- # #
- # LOCK BUTTON #
- # #
- ##########################################################################
- win.lock_button = Gtk.ToggleButton()
- def check_lock_button():
- try:
- wallet_status = fetch.lbrynet("wallet_status")
- except:
- wallet_status = {}
- if wallet_status.get("is_locked"):
- win.lock_button.set_active(True)
- if not win.settings["lock_password"]:
- win.lock_button.set_sensitive(False)
- else:
- win.lock_button.set_sensitive(True)
- check_lock_button()
- win.lock_button.set_tooltip_text("Lock / Unlock LBRY wallet. \n\n While the wallet is locked, no transaction could be signed. So nobody could use the running SDK to harm you.\n\nTo set the password look into settings.")
- win.lock_button.set_relief(Gtk.ReliefStyle.NONE)
- win.lock_button.add(ui.icon(win, "system-lock-screen-symbolic"))
- restofpannel.pack_start(win.lock_button, False, False, False)
- def lock_unlock(w):
- passw = win.settings["lock_password"]
- wallets = fetch.lbrynet("wallet_list")
- ID = wallets["items"][0]["id"]
-
- if w.get_active():
- # If we are locking
- print(fetch.lbrynet("wallet_encrypt", {"new_password":passw}))
- print(fetch.lbrynet("wallet_lock", {"wallet_id":ID}))
- else:
- # If decrypt
- print(fetch.lbrynet("wallet_unlock", {"password":passw, "wallet_id":ID}))
- print(fetch.lbrynet("wallet_decrypt", {"wallet_id":ID}))
-
- print("I AM FUCKING PRESSED")
-
- win.lock_button.connect("clicked", lock_unlock)
- ##########################################################################
- # #
- # PUBLISH BUTTON #
- # #
- ##########################################################################
- restofpannel.pack_start(Gtk.VSeparator(), True, True, 20)
- publ = Gtk.Button()
- publ.set_tooltip_text("Publish to LBRY")
- publ.set_relief(Gtk.ReliefStyle.NONE)
- publ.add(ui.icon(win, "list-add"))
- restofpannel.pack_start(publ, False, False, False)
- def do_publish(w):
- publish.window(win)
- publ.connect("clicked", do_publish)
- restofpannel.pack_start(Gtk.VSeparator(), True, True, 20)
- ##########################################################################
- # #
- # SEARCH / URL BAR #
- # #
- ##########################################################################
- # Note that I add this directly into the 'win' to make it a global variable.
- # This let's me to start any url from anywhere in the software.
- win.url = Gtk.Entry() # Gtk.SearchEntry() also looks good, but nah
- win.url.set_size_request(400,40)
- restofpannel.pack_start(win.url, True, True, False)
- ####### SEARCH FUNCTION #######
- def search(w):
- if win.resolve_tab == "current":
- win.resolve_tab = win.notebook.get_current_page()
-
- try:
- dynamic_box = win.tabs[win.resolve_tab]["box"]
- except:
- new_tab()
- dynamic_box = win.tabs[win.resolve_tab]["box"]
-
-
-
- # DRAG AND DROP FOR PUBLISH
- if win.url.get_text().startswith("file://") or os.path.exists(win.url.get_text()):
- # TODO: Some filenames include weird characters like %20 for spacebar and
- # stuff like that. We need to filter that out.
-
- filepath = win.url.get_text().replace("file://", "")
- publish.window(win, {"file_path":filepath})
- win.url.set_text("")
- return
- for i in dynamic_box.get_children():
- i.destroy()
- ## IF WE ARE NOT FORCING IT TO SEACH, IT WILL TRY TO RESOLVE THE LBRY URL FIRST ##
-
- if not force_search.get_active() or win.url.get_text().startswith("lbry://"):
- win.url.set_text(parse.bar(win.url.get_text()))
- ltext = win.url.get_text()
- ltext = ltext[ltext.rfind("/")+1:]
- win.tabs[win.resolve_tab]["label"].set_text(ltext[:10]+"...")
- win.tabs[win.resolve_tab]["label"].set_tooltip_text(win.url.get_text())
-
- resolve = ui.load(win, url.resolve, url.render_resolve, w, win, win.url.get_text())
- dynamic_box.pack_start(resolve, True, True, True)
- win.show_all()
- else:
- resolve = ui.load(win, claim_search.find, claim_search.render, win, win.url.get_text(), [], 1, {"order_by":""})
- dynamic_box.pack_start(resolve, True, True, True)
- win.show_all()
- ltext = win.url.get_text()
- win.tabs[win.resolve_tab]["label"].set_text(ltext[:10]+"...")
- win.tabs[win.resolve_tab]["label"].set_tooltip_text(win.url.get_text())
-
- dynamic_box.show_all()
- win.notebook.set_current_page(win.resolve_tab)
- win.resolve_tab = "current"
- hamburger.hide()
- # Button to activate seach for those who don't know that you can press Enter
- search_button = Gtk.Button()
- search_icon = ui.icon(win, "system-search")
- search_button.add(search_icon)
- search_button.set_relief(Gtk.ReliefStyle.NONE)
- search_button.connect("clicked", search)
- win.url.connect("activate", search)
- restofpannel.pack_start(search_button, False, False, False)
-
- ##########################################################################
- # #
- # HAMBURGER MENU #
- # #
- ##########################################################################
- # Popover is the new GTK menu thingy that looks like a comic book dialog
- # box. Which is what we want here. Because we want it to look nice I suppose.
- def on_hamburger(w):
- ################# NOTIFICATIONS #####################
-
- notifications = odysee.get_odysee_notifications(win)
- for i in win.notifications_box.get_children():
- i.destroy()
- if notifications:
- scrl = Gtk.ScrolledWindow()
- scrl.set_size_request(200,200)
- win.notifications_box.pack_start(scrl, 1,1,0)
-
- notbox = Gtk.VBox()
- scrl.add(notbox)
- for i in notifications:
- i = i.get("notification_parameters", {})
- author = i.get("dynamic", {}).get("reply_author")
- publication = i.get("device", {}).get("target")
- comment = i.get("device", {}).get("text")
- # Channel button
- def resolve_channel(win, url):
- out = fetch.lbrynet("resolve", {"urls":url})
- out = out[url]
- return [win, out]
- def render_channel(out):
- win, out = out
- return ui.go_to_channel(win, out)
- notbox.pack_start(Gtk.HSeparator(), 1,1,5)
-
- channel_button = ui.load(win, resolve_channel, render_channel, win, author)
- notbox.pack_start(channel_button, 1,1,5)
- comment_label = Gtk.Label(comment)
- comment_label.set_selectable(True)
- comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
- comment_label.set_line_wrap(True)
- comment_label.set_max_width_chars(20)
- def resolve_publication(w, publication):
- win.resolve_tab = "new_tab"
- win.url.set_text(publication)
- win.url.activate()
-
- comment_button = Gtk.Button()
- comment_button.add(comment_label)
- comment_button.connect("clicked", resolve_publication, publication)
- comment_button.set_relief(Gtk.ReliefStyle.NONE)
- notbox.pack_start(comment_button, 1,1,5)
-
-
- win.notifications_box.show_all()
-
- hamburger = Gtk.Popover()
- hambutton = Gtk.MenuButton(popover=hamburger)
- hambutton.connect("clicked", on_hamburger)
- hambutton_icon = ui.icon(win, "system-users")
- hambutton.add(hambutton_icon)
- hambutton.set_relief(Gtk.ReliefStyle.NONE)
- pannel.pack_start(hambutton)
- # Let's now pack the hamburger menu with items
- hambox = Gtk.HBox()
- # For the elements inside the box we need a scrolled window, to fit a lot of
- # them there.
- hamscrl = Gtk.ScrolledWindow()
- hamscrl.set_size_request(200,200)
- hamburger.add(hambox)
- hambox.pack_start(hamscrl, False, False, False)
- # "hamchannelbox" will be empty untill the user connects and it loads his channel
- # list
- hamchannelbox = Gtk.VBox()
- hamscrl.add_with_viewport(hamchannelbox)
- #hambox.pack_start(hamchannelbox, False, False, False)
- ###### CHANNELS SELECTOR ########
- win.channel = False
- def load_channel(win):
- def change_channel(w, win, channel ):
- win.channel = channel
- win.settings["channel"] = win.channel["claim_id"]
- settings.save(win.settings)
- try:
- hambutton.get_child().destroy()
- try:
- newicon = ui.load(win, ui.net_image_calculation, ui.net_image_render, channel["value"]["thumbnail"]["url"], 40, 40, "", False )
- except:
- newicon = ui.icon(win, "system-users")
- hambutton.add(newicon)
- pannel.show_all()
- except Exception as e:
- print("What?", e)
-
- out = fetch.lbrynet("channel_list")
- win.my_channels = out
- # We are chooseing first only if there is no channel set in the settings
-
-
- try:
- first = out["items"][0]
- win.channel = first
- except:
- pass
- if "channel" in win.settings:
- try:
- for i in out["items"]:
- if i["claim_id"] == win.settings["channel"]:
- first = i
- break
- except:
- pass
-
- try:
- change_channel(False, win, first)
- except:
- pass
- try:
-
-
- go.set_sensitive(True)
-
- for i in out["items"]:
- channel_button = ui.go_to_channel(win, i, resolve=False)
- channel_button.connect("clicked", change_channel, win, i)
- hamchannelbox.pack_start(channel_button, False, False, False)
- hamchannelbox.show_all()
- second_raw.show_all()
- except Exception as e:
- print("CHANNEL ERROR:", e)
- second_raw = Gtk.VBox()
- hambox.pack_start(Gtk.VSeparator(), False, False, 5)
- hambox.pack_start(second_raw, False, False, False)
-
- ####### Go to channel button #####
- def go_to_channel(w):
- channel_url = win.channel["name"]
- try:
- channel_url = channel_url + "#" + win.channel["claim_id"]
- except:
- pass
-
- win.url.set_text(channel_url)
- win.url.activate()
-
- go = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "folder-remote"), False, False, False)
- b.pack_start(Gtk.Label(" Go To Channel "), True, True, False)
- go.add(b)
- go.set_sensitive(False)
- go.set_relief(Gtk.ReliefStyle.NONE)
- go.connect("clicked", go_to_channel)
- second_raw.pack_start(go, False, False, False)
- ########## UPLOADS BUTTON #########
- def load_uploads(w=False):
- hamburger.hide()
- dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
-
- for i in dynamic_box.get_children():
- i.destroy()
-
- send = {"method":"claim_list"}
- resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
- dynamic_box.pack_start(resolve, True, True, True)
- dynamic_box.show_all()
-
- win.tabs[win.notebook.get_current_page()]["label"].set_text("Uploads")
- win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Uploads")
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "go-up-symbolic"), False, False, False)
- b.pack_start(Gtk.Label(" Uploads "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_uploads)
- second_raw.pack_start(following, False, False,False)
- ############## ANALYTICS ################
- def load_analytics(w):
- hamburger.hide()
- analytics.window(win)
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "text-csv"), False, False, False)
- b.pack_start(Gtk.Label(" Wallet "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_analytics)
- second_raw.pack_start(following, False, False,False)
- second_raw.pack_start(Gtk.HSeparator(), False, False,5)
- ######## FOLLOWING BUTTON ###########
- def load_following( w=False, mode="following"):
- hamburger.hide()
- dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
-
- for i in dynamic_box.get_children():
- i.destroy()
-
- try:
- if not win.subs:
- out = fetch.lbrynet("preference_get")
- win.subs = out["shared"]["value"]["subscriptions"]
- subs_raw = fetch.lbrynet("resolve", {"urls":win.subs})
- subs = []
- for i in subs_raw:
- try:
- subs.append(subs_raw[i]["claim_id"])
- except:
- pass
- except Exception as e:
- print("\n\nERROR:", e, "\n\n")
- subs = []
- suggest_tags = suggest.suggest()
-
- if mode == "suggest":
- send = {"any_tags":suggest_tags,
- "order_by":"trending_mixed"}
- resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
- else:
- resolve = ui.load(win, claim_search.find, claim_search.render, win, "", subs)
-
-
-
- # Currently live!
- all_lives = livestreams.get_all()
- liveids = []
- if mode != "suggest":
- upcoming = livestreams.get_upcoming(channels=subs)
- for s in upcoming.get("items", []):
- if "claim_id" in s:
- liveids.append(s["claim_id"])
-
- for livestream in all_lives.get("data", []):
- live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
- if livestream.get("ChannelClaimID", "") in subs:
- liveids.append(live_id)
- else:
- upcoming = livestreams.get_upcoming(tags=suggest_tags)
- for s in upcoming.get("items", []):
- if "claim_id" in s:
- liveids.append(s["claim_id"])
-
- for livestream in all_lives.get("data", []):
- live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
- liveids.append(live_id)
-
- if liveids:
- send = {"claim_ids":liveids}
- if mode == "suggest":
- send["any_tags"] = suggest.suggest()
- resolve_lives = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
- lives_frame = Gtk.Expander(label=" Livestreams: ")
- if mode != "suggest":
- lives_frame.set_expanded(True)
- resolve_lives.set_size_request(350,350)
- lives_frame.add(resolve_lives)
- dynamic_box.pack_start(lives_frame, 0,0,0)
- dynamic_box.pack_start(Gtk.HSeparator(), 0,0,5)
-
- dynamic_box.pack_start(resolve, True, True, True)
- dynamic_box.show_all()
- if mode == "suggest":
- win.tabs[win.notebook.get_current_page()]["label"].set_text("Suggested")
- win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Suggested")
- else:
- win.tabs[win.notebook.get_current_page()]["label"].set_text("Following")
- win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Following")
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "semi-starred"), False, False, False)
- b.pack_start(Gtk.Label(" Suggested "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_following, "suggest")
- second_raw.pack_start(following, False, False,False)
-
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "emblem-favorite"), False, False, False)
- b.pack_start(Gtk.Label(" Following "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_following)
- second_raw.pack_start(following, False, False,False)
- ######## TRENDING BUTTONS ###########
- def load_trending(w=False, articles=False):
- hamburger.hide()
- dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
-
- for i in dynamic_box.get_children():
- i.destroy()
-
- send = {"order_by":"trending_mixed"}
- if articles:
- send["media_types"] = ["text/markdown"]
- resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
- dynamic_box.pack_start(resolve, True, True, True)
- dynamic_box.show_all()
- if articles:
- lname = "Articles"
- else:
- lname = "Trending"
-
- win.tabs[win.notebook.get_current_page()]["label"].set_text(lname)
- win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text(lname)
-
-
-
- following = Gtk.Button()
- b = Gtk.HBox()
- # The other one was showing web-browsers at some themes
- b.pack_start(ui.icon(win, "emblem-shared"), False, False, False)
- b.pack_start(Gtk.Label(" Trending "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_trending)
- second_raw.pack_start(following, False, False,False)
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "text-x-generic"), False, False, False)
- b.pack_start(Gtk.Label(" Articles "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_trending, True)
- second_raw.pack_start(following, False, False,False)
- #### LIVESTREAMS ####
- def load_livestreams(w):
- hamburger.hide()
-
- # First let's fetch the data about all livestreams
- all_lives = livestreams.get_all()
- liveids = []
- # Upcoming
- upcoming = livestreams.get_upcoming()
- for s in upcoming.get("items", []):
- if "claim_id" in s:
- liveids.append(s["claim_id"])
-
- for livestream in all_lives.get("data", []):
- live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
- liveids.append(live_id)
- # Then we gonna search all the liveids
- dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
-
- for i in dynamic_box.get_children():
- i.destroy()
-
- send = {"claim_ids":liveids}
-
- resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
- dynamic_box.pack_start(resolve, True, True, True)
- dynamic_box.show_all()
- lname = "Live Streams"
-
- win.tabs[win.notebook.get_current_page()]["label"].set_text(lname)
- win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text(lname)
-
-
-
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "emblem-new"), False, False, False)
- b.pack_start(Gtk.Label(" Live Streams "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_livestreams)
- second_raw.pack_start(following, False, False,False)
- second_raw.pack_start(Gtk.HSeparator(), False, False,5)
- ######## DOWNLOADS #########
- def load_downloads(w):
- hamburger.hide()
- downloads.window(win)
- following = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "go-down-symbolic"), False, False, False)
- b.pack_start(Gtk.Label(" Downloads "), True, True, False)
- following.add(b)
- following.set_relief(Gtk.ReliefStyle.NONE)
- following.connect("clicked", load_downloads)
- second_raw.pack_start(following, False, False,False)
- second_raw.pack_start(Gtk.HSeparator(), False, False,5)
- ######## SETTINGS BUTTON ############
- second_raw.pack_start(Gtk.HSeparator(), False, False,5)
- settings_button = Gtk.Button()
- b = Gtk.HBox()
- b.pack_start(ui.icon(win, "preferences-system"), False, False, False)
- b.pack_start(Gtk.Label(" Settings "), True, True, False)
- settings_button.add(b)
- settings_button.set_relief(Gtk.ReliefStyle.NONE)
- settings_button.connect("clicked", settings.dialogue, win)
- second_raw.pack_start(settings_button, False, False, False)
- second_raw.pack_start(Gtk.HSeparator(), False, False,5)
- ########## FORCE SEARCH BUTTON #######
- force_search_box = Gtk.HBox()
- force_search = Gtk.Switch()
- force_search_box.pack_end(force_search, False, False, 0)
- force_search_box.pack_start(ui.icon(win, "system-search"), False, False, 0)
- force_search_box.pack_start(Gtk.Label(" Force Search "), True, True, 0)
- force_search.set_tooltip_text("If not activated it will try to resolve the claim first.")
- second_raw.pack_start(force_search_box, False, False, False)
- ###### THE BOX FOR THE NOTIFICATIONS #####
- win.notifications_box = Gtk.VBox()
- hambox.pack_start(Gtk.VSeparator(), False, False, 5)
- hambox.pack_start(win.notifications_box, False, False, False)
- hambox.show_all()
- ##########################################################################
- # #
- # DYNAMIC BOX ( REST ) #
- # #
- ##########################################################################
- # Dynamic box is a box contents of which will change depending on the "page"
- # that the user is loading.
- box = Gtk.VBox() # I'm making a top level box just in case
- win.add(box)
- win.notebook.set_scrollable(True)
- def new_tab():
- dynamic_box = Gtk.VBox() # And here our dynamic box
- label = Gtk.Label("Tab "+str(len(win.tabs)+1))
-
- kill = Gtk.Button()
-
- kill.add(ui.icon(win, "delete"))
- kill.set_relief(Gtk.ReliefStyle.NONE)
- box = Gtk.HBox()
- box.pack_start(label, False, False, 5)
- box.pack_start(kill, False, False, 0)
- box.show_all()
-
- tab = {"box":dynamic_box, "label":label, "index":len(win.tabs)}
- def on_kill(w, tab):
- if len(win.tabs) == 1:
- load_following(mode=win.settings["default_tab"])
- return
-
- i = tab["index"]
- win.notebook.remove_page(i)
- del win.tabs[i]
- for r, t in enumerate(win.tabs):
- t["index"] = r
-
-
- kill.connect("clicked", on_kill, tab)
-
- win.tabs.append(tab)
- win.resolve_tab = len(win.tabs) - 1
- win.notebook.append_page(win.tabs[-1]["box"], box)
-
-
-
- new_tab()
-
- box.pack_start(win.notebook, True, True, False)
- # Just something to run if we are connected
- if win.SDK_running == 1:
- load_following(mode=win.settings["default_tab"])
- load_channel(win)
- else:
- win.tabs[0]["box"].pack_start(Gtk.Label("LBRY is not connected. Please connect."), True, True, 20)
- ##########################################################################
- # #
- # DRAG AND DROP #
- # #
- ##########################################################################
- def on_drop(widget, drag_context, x, y, data, info, time):
- win.url.set_text(data.get_text())
- win.url.activate()
-
- enforce_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(4), 129)
- box.drag_dest_set(Gtk.DestDefaults.ALL, [enforce_target], Gdk.DragAction.COPY)
- box.connect("drag-data-received", on_drop)
- if win.settings["autoconnect"] and win.SDK_running != 1:
- connect_disconnect_function(connect_disconncet_button)
-
- # Application CSS
- style_provider=Gtk.CssProvider()
- css=b"""
- .thumbnail_overlay {
- background-color: rgba(.5, .5, .5, .7);
- border-radius: 5px;
- padding: 5px;
- }
- """
- style_provider.load_from_data(css)
- Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
- # Starting Everything
-
- win.show_all()
- Gtk.main()
- #### Clearing the cache of images ###
- ui.clean_image_cache()
- if win.settings["autoconnect"]:
- connect.stop(win)
|