Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show loading screen on startup #581

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
**1.2.6**
- Show a loading screen on startup (thanks to orende)
- Hide Cyberpunk 2077 Digital Goodies and Xenonauts 2 Alpha demo (thanks to orende)

**1.2.5**
- Fix filtering for installed games

Expand Down
10 changes: 7 additions & 3 deletions bin/minigalaxy
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ def main():
if cli_args.reset: conf_reset()

# Import the gi module after parsing arguments
from minigalaxy.ui.gtk import Gtk
from minigalaxy.ui import Window
from minigalaxy.ui.gtk import Gtk, GLib
from minigalaxy.ui import Window, LoadingScreen
from minigalaxy.config import Config
from minigalaxy.api import Api
from minigalaxy.download_manager import DownloadManager
from minigalaxy.css import load_css
from minigalaxy.ui.library import Library

# Start the application
load_css()
Expand All @@ -57,8 +58,11 @@ def main():
session.headers.update({'User-Agent': 'Minigalaxy/{} (Linux {})'.format(VERSION, platform.machine())})
api = Api(config, session)
download_manager = DownloadManager(session)
window = Window(config, api, download_manager, APPLICATION_NAME)
library = Library(config, api, download_manager)
window = Window(config, api, library, APPLICATION_NAME)
window.connect("destroy", Gtk.main_quit)
loading_screen = LoadingScreen()
library.initialize(loading_screen, window)
Gtk.main()


Expand Down
Binary file added data/images/spiral_galaxy.jpg
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use the Minigalaxy logo that's used for the about window instead of this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions data/ui/loadingscreen.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
<template class="LoadingScreen" parent="GtkDialog">
<property name="can_focus">False</property>
<property name="default_width">512</property>
<property name="default_height">522</property>
<property name="type_hint">dialog</property>
<property name="decorated">False</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">0</property>
<child>
<object class="GtkImage" id="splash_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="splash_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="loading" comments="">Loading Minigalaxy...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</template>
</interface>
5 changes: 1 addition & 4 deletions minigalaxy/api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import http
import os
import time
from urllib.parse import urlencode
import requests
Expand Down Expand Up @@ -27,7 +26,6 @@ def __init__(self, config: Config, session: Session):
self.redirect_uri = "https://embed.gog.com/on_login_success?origin=client"
self.client_id = "46899977096215655"
self.client_secret = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9"
self.debug = os.environ.get("MG_DEBUG")
self.active_token = False
self.active_token_expiration_time = time.time()
self.conn_check_thpool = ThreadPoolExecutor(max_workers=2)
Expand Down Expand Up @@ -284,8 +282,7 @@ def __request(self, url: str = None, params: dict = None) -> dict:
result = {}
try:
response = self.session.get(url, headers=headers, params=params)
if self.debug:
logger.debug("Request %s, return code %s, response body %s", url, response.status_code, response.text)
logger.debug("Request %s, return code %s, response body %s", url, response.status_code, response.text)
if response.status_code < 300:
result = response.json()
except requests.exceptions.RequestException:
Expand Down
2 changes: 2 additions & 0 deletions minigalaxy/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@
1980301910, # The Witcher Goodies Collection
2005648906, # Spring Sale Goodies Collection #1
1486144755, # Cyberpunk 2077 Goodies Collection
1548764757, # Cyberpunk 2077 Digital Goodies
1581684020, # A Plague Tale Digital Goodies Pack
1185685769, # CDPR Goodie Pack Content
1497289938, # Xenonauts 2 alpha demo
]

DOWNLOAD_CHUNK_SIZE = 1024 * 1024 # 1 MB
Expand Down
4 changes: 4 additions & 0 deletions minigalaxy/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
os.path.join(LAUNCH_DIR, "../share/icons/hicolor/192x192/apps/io.github.sharkwouter.Minigalaxy.png")
)

SPLASH_IMAGE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../data/images/spiral_galaxy.jpg"))
if not os.path.exists(SPLASH_IMAGE_PATH):
SPLASH_IMAGE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../share/minigalaxy/images/spiral_galaxy.jpg"))

ICON_WINE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../data/images/winehq_logo_glass.png"))
if not os.path.exists(ICON_WINE_PATH):
ICON_WINE_PATH = os.path.abspath(os.path.join(LAUNCH_DIR, "../share/minigalaxy/images/winehq_logo_glass.png"))
Expand Down
1 change: 1 addition & 0 deletions minigalaxy/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from minigalaxy.ui.window import Window # noqa: F401
from minigalaxy.ui.preferences import Preferences # noqa: F401
from minigalaxy.ui.gametile import GameTile # noqa: F401
from minigalaxy.ui.loadingscreen import LoadingScreen # noqa: F401
19 changes: 8 additions & 11 deletions minigalaxy/ui/gametile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from minigalaxy.paths import ICON_WINE_PATH
from minigalaxy.api import NoDownloadLinkFound, Api
from minigalaxy.ui.gtk import Gtk, GLib, Notify
from minigalaxy.ui.information import Information
from minigalaxy.ui.properties import Properties


@Gtk.Template.from_file(os.path.join(UI_DIR, "gametile.ui"))
Expand All @@ -41,7 +39,8 @@ class GameTile(Gtk.Box):
menu_button_properties = Gtk.Template.Child()
progress_bar = Gtk.Template.Child()

def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager):
def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager,
show_properties_callback, show_information_callback):
self.config = config
current_locale = self.config.locale
default_locale = locale.getdefaultlocale()[0]
Expand All @@ -63,6 +62,8 @@ def __init__(self, parent, game: Game, config: Config, api: Api, download_manage
self.download_list = []
self.dlc_dict = {}
self.current_state = State.DOWNLOADABLE
self.show_information_callback = show_information_callback
self.show_properties_callback = show_properties_callback

self.image.set_tooltip_text(self.game.name)

Expand Down Expand Up @@ -129,16 +130,12 @@ def on_button_click(self, widget) -> None:
self.parent.parent.show_error(_("Failed to start {}:").format(self.game.name), err_msg)

@Gtk.Template.Callback("on_menu_button_information_clicked")
def show_information(self, button):
information_window = Information(self, self.game, self.config, self.api, self.download_manager)
information_window.run()
information_window.destroy()
def on_menu_button_information(self, button):
self.show_information_callback(self.game, self.download_manager)

@Gtk.Template.Callback("on_menu_button_properties_clicked")
def show_properties(self, button):
properties_window = Properties(self, self.game, self.api)
properties_window.run()
properties_window.destroy()
def on_menu_button_properties(self, button):
self.show_properties_callback(self.game)

@Gtk.Template.Callback("on_button_cancel_clicked")
def on_button_cancel(self, widget):
Expand Down
19 changes: 8 additions & 11 deletions minigalaxy/ui/gametilelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
from minigalaxy.paths import ICON_WINE_PATH
from minigalaxy.api import NoDownloadLinkFound, Api
from minigalaxy.ui.gtk import Gtk, GLib, Notify
from minigalaxy.ui.information import Information
from minigalaxy.ui.properties import Properties


@Gtk.Template.from_file(os.path.join(UI_DIR, "gametilelist.ui"))
Expand All @@ -42,7 +40,8 @@ class GameTileList(Gtk.Box):
menu_button_properties = Gtk.Template.Child()
game_label = Gtk.Template.Child()

def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager):
def __init__(self, parent, game: Game, config: Config, api: Api, download_manager: DownloadManager,
show_properties_callback, show_information_callback):
self.config = config
current_locale = self.config.locale
default_locale = locale.getdefaultlocale()[0]
Expand All @@ -67,6 +66,8 @@ def __init__(self, parent, game: Game, config: Config, api: Api, download_manage
self.download_list = []
self.dlc_dict = {}
self.current_state = State.DOWNLOADABLE
self.show_information_callback = show_information_callback
self.show_properties_callback = show_properties_callback

self.image.set_tooltip_text(self.game.name)

Expand Down Expand Up @@ -135,16 +136,12 @@ def on_button_click(self, widget) -> None:
self.parent.parent.show_error(_("Failed to start {}:").format(self.game.name), err_msg)

@Gtk.Template.Callback("on_menu_button_information_clicked")
def show_information(self, button):
information_window = Information(self, self.game, self.config, self.api, self.download_manager)
information_window.run()
information_window.destroy()
def on_menu_button_information(self, button):
self.show_information_callback(self.game, self.download_manager)

@Gtk.Template.Callback("on_menu_button_properties_clicked")
def show_properties(self, button):
properties_window = Properties(self, self.game, self.api)
properties_window.run()
properties_window.destroy()
def on_menu_button_properties(self, button):
self.show_properties_callback(self.game)

@Gtk.Template.Callback("on_button_cancel_clicked")
def on_button_cancel(self, widget):
Expand Down
2 changes: 1 addition & 1 deletion minigalaxy/ui/information.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Information(Gtk.Dialog):
label_game_description = Gtk.Template.Child()

def __init__(self, parent, game, config: Config, api: Api, download_manager: DownloadManager):
Gtk.Dialog.__init__(self, title=_("Information about {}").format(game.name), parent=parent.parent.parent,
Gtk.Dialog.__init__(self, title=_("Information about {}").format(game.name), parent=parent,
modal=True)
self.parent = parent
self.game = game
Expand Down
59 changes: 43 additions & 16 deletions minigalaxy/ui/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ class Library(Gtk.Viewport):

flowbox = Gtk.Template.Child()

def __init__(self, parent, config: Config, api: Api, download_manager: DownloadManager):
def __init__(self, config: Config, api: Api, download_manager: DownloadManager):
Gtk.Viewport.__init__(self)
self.parent = parent
self.config = config
self.api = api
self.download_manager = download_manager
Expand All @@ -38,6 +37,28 @@ def __init__(self, parent, config: Config, api: Api, download_manager: DownloadM
self._queue = []
self.category_filters = []

def initialize(self, loading_screen, window):
worker_thread = threading.Thread(target=lambda: self._do_initialization(loading_screen, window))
worker_thread.start()

def _do_initialization(self, loading_screen, window):
logger.debug("Checking API connectivity...")
self.offline = not self.api.can_connect()
logger.debug("Done checking API connectivity, status: %s", "offline" if self.offline else "online")
if not self.offline:
try:
logger.debug("Authenticating...")
window.authenticate()
logger.debug("Authenticated as %s", self.api.get_user_info())
window.set_subtitle(self.api.get_user_info())
except Exception:
logger.warn("Starting in offline mode after receiving exception", exc_info=1)
self.offline = True
self.update_library(window.show_error, window.show_properties, window.show_information)
logger.debug("Worker thread done, closing loading screen, showing main window")
loading_screen.destroy()
window.show_all()

def _debounce(self, thunk):
if thunk not in self._queue:
self._queue.append(thunk)
Expand All @@ -48,28 +69,32 @@ def _run_queue(self):
for thunk in queue:
GLib.idle_add(thunk)

def reset(self):
def reset(self, show_error_callback, show_properties_callback, show_information_callback):
self.games = []
for child in self.flowbox.get_children():
self.flowbox.remove(child)
self.flowbox.show_all()
self.update_library()
self.update_library(show_error_callback, show_properties_callback, show_information_callback)

def update_library(self) -> None:
library_update_thread = threading.Thread(target=self.__update_library)
def update_library(self, show_error_callback, show_properties_callback, show_information_callback) -> None:
library_update_thread = threading.Thread(target=self.__update_library, args=[show_error_callback,
show_properties_callback,
show_information_callback])
library_update_thread.daemon = True
library_update_thread.start()

def __update_library(self):
def __update_library(self, show_error_callback, show_properties_callback, show_information_callback):
GLib.idle_add(self.__load_tile_states)
self.owned_products_ids = self.api.get_owned_products_ids()
# Get already installed games first
self.games = self.__get_installed_games()
GLib.idle_add(self.__create_gametiles)
GLib.idle_add(self.__create_gametiles, show_properties_callback, show_information_callback)

# Get games from the API
self.__add_games_from_api()
GLib.idle_add(self.__create_gametiles)
is_offline, err_msg = self.__add_games_from_api()
if is_offline:
GLib.idle_add(show_error_callback, _("Failed to retrieve library"), _(err_msg))
GLib.idle_add(self.__create_gametiles, show_properties_callback, show_information_callback)
GLib.idle_add(self.filter_library)

def __load_tile_states(self):
Expand Down Expand Up @@ -113,7 +138,7 @@ def __sort_library_func(self, child1, child2):
tile2 = child2.get_children()[0].game
return tile2 < tile1

def __create_gametiles(self) -> None:
def __create_gametiles(self, show_properties_callback, show_information_callback) -> None:
games_with_tiles = []
for child in self.flowbox.get_children():
tile = child.get_children()[0]
Expand All @@ -122,14 +147,16 @@ def __create_gametiles(self) -> None:

for game in self.games:
if game not in games_with_tiles:
self.__add_gametile(game)
self.__add_gametile(game, show_properties_callback, show_information_callback)

def __add_gametile(self, game):
def __add_gametile(self, game, show_properties_callback, show_information_callback):
view = self.config.view
if view == "grid":
self.flowbox.add(GameTile(self, game, self.config, self.api, self.download_manager))
self.flowbox.add(GameTile(self, game, self.config, self.api, self.download_manager,
show_properties_callback, show_information_callback))
elif view == "list":
self.flowbox.add(GameTileList(self, game, self.config, self.api, self.download_manager))
self.flowbox.add(GameTileList(self, game, self.config, self.api, self.download_manager,
show_properties_callback, show_information_callback))
self._debounce(self.sort_library)
self._debounce(self.flowbox.show_all)

Expand Down Expand Up @@ -172,7 +199,6 @@ def __add_games_from_api(self):
else:
self.offline = True
logger.info("Client is offline, showing installed games only")
GLib.idle_add(self.parent.show_error, _("Failed to retrieve library"), _(err_msg))
game_category_dict = {}
for game in retrieved_games:
if game not in self.games:
Expand All @@ -186,6 +212,7 @@ def __add_games_from_api(self):
if len(game.category) > 0: # exclude games without set category
game_category_dict[game.name] = game.category
update_game_categories_file(game_category_dict, CATEGORIES_FILE_PATH)
return self.offline, err_msg


def get_installed_windows_games(full_path, game_categories_dict=None):
Expand Down
17 changes: 17 additions & 0 deletions minigalaxy/ui/loadingscreen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import os

from minigalaxy.paths import UI_DIR, SPLASH_IMAGE_PATH
from minigalaxy.ui.gtk import Gtk


@Gtk.Template.from_file(os.path.join(UI_DIR, "loadingscreen.ui"))
class LoadingScreen(Gtk.Dialog):
__gtype_name__ = "LoadingScreen"

splash_image = Gtk.Template.Child()
splash_label = Gtk.Template.Child()

def __init__(self):
super().__init__(title="Loading - Minigalaxy", modal=True)
self.splash_image.set_from_file(SPLASH_IMAGE_PATH)
self.show_all()
2 changes: 1 addition & 1 deletion minigalaxy/ui/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Properties(Gtk.Dialog):
label_wine_custom = Gtk.Template.Child()

def __init__(self, parent, game, api):
Gtk.Dialog.__init__(self, title=_("Properties of {}").format(game.name), parent=parent.parent.parent,
Gtk.Dialog.__init__(self, title=_("Properties of {}").format(game.name), parent=parent,
modal=True)
self.parent = parent
self.game = game
Expand Down
Loading