Many fixes
This commit is contained in:
parent
825f055387
commit
3acc13e9b6
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
|
@ -83,13 +83,22 @@ jobs:
|
|||
run: |
|
||||
appimage-builder --skip-test
|
||||
mv Rare-*.AppImage Rare.AppImage
|
||||
mv Rare-*.AppImage.zsync Rare.AppImage.zsync
|
||||
|
||||
- name: Upload to GitHub
|
||||
uses: svenstaro/upload-release-action@2.2.1
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: Rare.AppImage
|
||||
asset_name: Rare.AppImage
|
||||
asset_name: Rare-${{github.ref}}.AppImage
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
- name: Upload to GitHub
|
||||
uses: svenstaro/upload-release-action@2.2.1
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: Rare.AppImage
|
||||
asset_name: Rare-${{github.ref}}.AppImage.zsync
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
|
@ -119,6 +128,6 @@ jobs:
|
|||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: dist/Rare.msi
|
||||
asset_name: Rare.msi
|
||||
asset_name: Rare-${{github.ref}}.msi
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
|
|
@ -32,8 +32,8 @@ class TabWidget(QTabWidget):
|
|||
" (" + str(len(self.games_tab.updates)) + ")" if len(self.games_tab.updates) != 0 else ""))
|
||||
self.store = Shop(self.core)
|
||||
self.addTab(self.store, self.tr("Store (Beta)"))
|
||||
self.settings = SettingsTab(self)
|
||||
|
||||
self.settings = SettingsTab(self)
|
||||
if shared.args.debug:
|
||||
self.settings.addTab(DebugSettings(), "Debug")
|
||||
|
||||
|
|
|
@ -41,9 +41,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
self.settings = QSettings()
|
||||
self.game_utils = GameUtils(parent=self)
|
||||
self.before_launch_sync = dict()
|
||||
shared.api_results.saves = []
|
||||
|
||||
self.game_list = shared.api_results.game_list
|
||||
self.dlcs = shared.api_results.dlcs
|
||||
|
@ -51,6 +48,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.mac_games = shared.api_results.mac_games
|
||||
self.no_assets = shared.api_results.no_asset_games
|
||||
|
||||
self.game_utils = GameUtils(parent=self)
|
||||
|
||||
self.head_bar = GameListHeadBar(self)
|
||||
self.head_bar.import_clicked.connect(self.show_import)
|
||||
self.head_bar.egl_sync_clicked.connect(self.show_egl_sync)
|
||||
|
@ -61,6 +60,7 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.addWidget(self.game_info_tabs)
|
||||
|
||||
self.game_info_tabs.info.verification_finished.connect(self.verification_finished)
|
||||
self.game_info_tabs.info.uninstalled.connect(lambda x: self.setCurrentIndex(0))
|
||||
|
||||
self.import_sync_tabs = ImportSyncTabs(self)
|
||||
self.import_sync_tabs.back_clicked.connect(lambda: self.setCurrentIndex(0))
|
||||
|
@ -79,7 +79,6 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.no_asset_names.append(game.app_name)
|
||||
else:
|
||||
self.no_assets = []
|
||||
|
||||
self.setup_game_list()
|
||||
|
||||
if not self.settings.value("icon_view", True, bool):
|
||||
|
@ -104,6 +103,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
self.signals.installation_finished.connect(lambda x: self.installing_widget.setVisible(False))
|
||||
self.signals.uninstall_game.connect(self.uninstall_game)
|
||||
|
||||
self.game_utils.update_list.connect(self.update_list)
|
||||
|
||||
self.game_list_scroll_area.horizontalScrollBar().setDisabled(True)
|
||||
|
||||
def installation_started(self, app_name: str):
|
||||
|
|
|
@ -134,17 +134,43 @@ class CloudSaveUtils(QObject):
|
|||
latest_saves[s.app_name] = s
|
||||
return latest_saves
|
||||
|
||||
def sync_before_launch_game(self, app_name, ignore_settings=False) -> bool:
|
||||
def sync_before_launch_game(self, app_name, ignore_settings=False) -> int:
|
||||
if not ignore_settings:
|
||||
default = self.settings.value("auto_sync_cloud", True, bool)
|
||||
if not self.settings.value(f"{app_name}/auto_sync_cloud", default, bool):
|
||||
return False
|
||||
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
|
||||
if not igame.save_path:
|
||||
try:
|
||||
savepath = self.core.get_save_path(app_name)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
savepath = ""
|
||||
if savepath:
|
||||
igame.save_path = savepath
|
||||
self.core.lgd.set_installed_game(app_name, igame)
|
||||
logger.info(f"Set save path of {igame.title} to {savepath}")
|
||||
elif not ignore_settings: # sync on startup
|
||||
if QMessageBox.question(None, "Warning", self.tr(
|
||||
"Could not compute cloud save path. Please set it in Game settings manually. \nDo you want to launch {} anyway?").format(
|
||||
igame.title, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes):
|
||||
return False
|
||||
else:
|
||||
raise ValueError("No savepath detected")
|
||||
else:
|
||||
QMessageBox.warning(None, "Warning",
|
||||
self.tr("No savepath found. Please set it in Game Settings manually"))
|
||||
return False
|
||||
|
||||
res, (dt_local, dt_remote) = self.core.check_savegame_state(igame.save_path, self.latest_saves.get(app_name))
|
||||
|
||||
if res == SaveGameStatus.NO_SAVE:
|
||||
return False
|
||||
|
||||
if res != SaveGameStatus.SAME_AGE:
|
||||
newer = None
|
||||
newer = ""
|
||||
if res == SaveGameStatus.REMOTE_NEWER:
|
||||
newer = "remote"
|
||||
elif res == SaveGameStatus.LOCAL_NEWER:
|
||||
|
@ -164,12 +190,12 @@ class CloudSaveUtils(QObject):
|
|||
elif result == CloudSaveDialog.DOWNLOAD:
|
||||
self.download_saves(igame)
|
||||
elif result == CloudSaveDialog.CANCEL:
|
||||
return False
|
||||
raise AssertionError()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def game_finished(self, app_name, ignore_settings=False):
|
||||
def game_finished(self, app_name, ignore_settings=False, always_ask: bool = False):
|
||||
if not ignore_settings:
|
||||
default = self.settings.value("auto_sync_cloud", True, bool)
|
||||
if not self.settings.value(f"{app_name}/auto_sync_cloud", default, bool):
|
||||
|
@ -177,26 +203,43 @@ class CloudSaveUtils(QObject):
|
|||
return
|
||||
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
|
||||
if not igame.save_path:
|
||||
try:
|
||||
savepath = self.core.get_save_path(app_name)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
savepath = ""
|
||||
if savepath:
|
||||
igame.save_path = savepath
|
||||
self.core.lgd.set_installed_game(app_name, igame)
|
||||
logger.info(f"Set save path of {igame.title} to {savepath}")
|
||||
else:
|
||||
logger.warning(None, "Warning", self.tr("No savepath set. Skip syncing with cloud"))
|
||||
return False
|
||||
|
||||
res, (dt_local, dt_remote) = self.core.check_savegame_state(igame.save_path, self.latest_saves.get(app_name))
|
||||
|
||||
if res == SaveGameStatus.LOCAL_NEWER:
|
||||
if res == SaveGameStatus.LOCAL_NEWER and not always_ask:
|
||||
self.upload_saves(igame, dt_local)
|
||||
return
|
||||
|
||||
elif res == SaveGameStatus.NO_SAVE:
|
||||
elif res == SaveGameStatus.NO_SAVE and not always_ask:
|
||||
QMessageBox.warning(None, "No saves", self.tr(
|
||||
"There are no saves local and online. Maybe you have to change save path of {}").format(igame.title))
|
||||
self.sync_finished.emit(app_name)
|
||||
return
|
||||
|
||||
elif res == SaveGameStatus.SAME_AGE:
|
||||
elif res == SaveGameStatus.SAME_AGE and not always_ask:
|
||||
self.sync_finished.emit(app_name)
|
||||
return
|
||||
|
||||
# Remote newer
|
||||
newer = None
|
||||
newer = ""
|
||||
if res == SaveGameStatus.REMOTE_NEWER:
|
||||
newer = "remote"
|
||||
elif res == SaveGameStatus.LOCAL_NEWER:
|
||||
newer = "local"
|
||||
result = CloudSaveDialog(igame, dt_local, dt_remote, newer).get_action()
|
||||
if result == CloudSaveDialog.UPLOAD:
|
||||
self.upload_saves(igame, dt_local)
|
||||
|
|
|
@ -16,7 +16,7 @@ class GameInfoTabs(SideTabWidget):
|
|||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
|
||||
self.info = GameInfo(self)
|
||||
self.info = GameInfo(self, game_utils)
|
||||
self.addTab(self.info, self.tr("Information"))
|
||||
|
||||
self.settings = GameSettings(self.core, self)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import platform
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QThreadPool
|
||||
from PyQt5.QtWidgets import QWidget, QMessageBox
|
||||
|
@ -12,19 +13,22 @@ from rare.utils.models import InstallOptionsModel
|
|||
from rare.utils.steam_grades import SteamWorker
|
||||
from rare.utils.utils import get_size, get_pixmap
|
||||
|
||||
logger = getLogger("GameInfo")
|
||||
|
||||
|
||||
class GameInfo(QWidget, Ui_GameInfo):
|
||||
igame: InstalledGame
|
||||
game: Game = None
|
||||
verify_threads = dict()
|
||||
verification_finished = pyqtSignal(InstalledGame)
|
||||
uninstalled = pyqtSignal(Game)
|
||||
uninstalled = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent, game_utils):
|
||||
super(GameInfo, self).__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
self.core = shared.core
|
||||
self.signals = shared.signals
|
||||
self.game_utils = game_utils
|
||||
|
||||
if platform.system() == "Windows":
|
||||
self.lbl_grade.setVisible(False)
|
||||
|
@ -38,13 +42,18 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
self.install_button.setText(self.tr("Link to Origin/Launch"))
|
||||
self.game_actions_stack.resize(self.game_actions_stack.minimumSize())
|
||||
|
||||
self.uninstall_button.clicked.connect(lambda: self.signals.uninstall_game.emit(self.game))
|
||||
self.uninstall_button.clicked.connect(self.uninstall)
|
||||
self.verify_button.clicked.connect(self.verify)
|
||||
self.repair_button.clicked.connect(self.repair)
|
||||
|
||||
self.verify_pool = QThreadPool()
|
||||
self.verify_pool.setMaxThreadCount(2)
|
||||
|
||||
def uninstall(self):
|
||||
if self.game_utils.uninstall_game(self.game.app_name):
|
||||
self.game_utils.update_list.emit(self.game.app_name)
|
||||
self.uninstalled.emit(self.game.app_name)
|
||||
|
||||
def repair(self):
|
||||
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair')
|
||||
if not os.path.exists(repair_file):
|
||||
|
@ -55,11 +64,16 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
update=True))
|
||||
|
||||
def verify(self):
|
||||
if not os.path.exists(self.igame.install_path):
|
||||
logger.error("Path does not exist")
|
||||
QMessageBox.warning(self, "Warning",
|
||||
self.tr("Installation path of {} does not exist. Cannot verify").format(
|
||||
self.igame.title))
|
||||
return
|
||||
self.verify_widget.setCurrentIndex(1)
|
||||
verify_worker = VerifyWorker(self.core, self.game.app_name)
|
||||
verify_worker.signals.status.connect(self.verify_staistics)
|
||||
verify_worker.signals.summary.connect(self.finish_verify)
|
||||
self.verify_pool.start(verify_worker)
|
||||
self.verify_progress.setValue(0)
|
||||
self.verify_threads[self.game.app_name] = verify_worker
|
||||
|
||||
|
|
|
@ -118,26 +118,32 @@ class GameSettings(QWidget, Ui_GameSettings):
|
|||
self.cloud_save_path_edit.setDisabled(True)
|
||||
self.compute_save_path_button.setDisabled(True)
|
||||
resolver = WineResolver(get_raw_save_path(self.game), self.game.app_name, self.core)
|
||||
resolver.signals.result_ready.connect(self.wine_resolver_finished)
|
||||
app_name = self.game.app_name[:]
|
||||
resolver.signals.result_ready.connect(lambda x: self.wine_resolver_finished(x, app_name))
|
||||
QThreadPool.globalInstance().start(resolver)
|
||||
return
|
||||
self.cloud_save_path_edit.setText(new_path)
|
||||
|
||||
def wine_resolver_finished(self, path):
|
||||
self.cloud_save_path_edit.setDisabled(False)
|
||||
self.compute_save_path_button.setDisabled(False)
|
||||
if path and not os.path.exists(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except PermissionError:
|
||||
self.cloud_save_path_edit.setText("")
|
||||
QMessageBox.warning(None, "Error", self.tr(
|
||||
"Error while launching {}. No permission to create {}").format(
|
||||
self.game.app_title, path))
|
||||
def wine_resolver_finished(self, path, app_name):
|
||||
if app_name == self.game.app_name:
|
||||
self.cloud_save_path_edit.setDisabled(False)
|
||||
self.compute_save_path_button.setDisabled(False)
|
||||
if path and not os.path.exists(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except PermissionError:
|
||||
self.cloud_save_path_edit.setText("")
|
||||
QMessageBox.warning(None, "Error", self.tr(
|
||||
"Error while launching {}. No permission to create {}").format(
|
||||
self.game.app_title, path))
|
||||
return
|
||||
if not path:
|
||||
return
|
||||
if not path:
|
||||
return
|
||||
self.cloud_save_path_edit.setText(path)
|
||||
self.cloud_save_path_edit.setText(path)
|
||||
else:
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
igame.save_path = path
|
||||
self.core.lgd.set_installed_game(app_name, igame)
|
||||
|
||||
def save_save_path(self, text):
|
||||
if self.game.supports_cloud_saves and self.change:
|
||||
|
|
|
@ -30,14 +30,16 @@ class GameProcess(QProcess):
|
|||
class RunningGameModel:
|
||||
process: GameProcess
|
||||
app_name: str
|
||||
always_ask_sync: bool = False
|
||||
|
||||
|
||||
class GameUtils(QObject):
|
||||
running_games = dict()
|
||||
finished = pyqtSignal(str, str)
|
||||
finished = pyqtSignal(str, str) # app_name, error
|
||||
cloud_save_finished = pyqtSignal(str)
|
||||
launch_queue = dict()
|
||||
game_launched = pyqtSignal(str)
|
||||
update_list = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(GameUtils, self).__init__(parent=parent)
|
||||
|
@ -48,7 +50,19 @@ class GameUtils(QObject):
|
|||
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
|
||||
|
||||
def uninstall_game(self, app_name) -> bool:
|
||||
# returns if uninstalled
|
||||
game = self.core.get_game(app_name)
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
if not os.path.exists(igame.install_path):
|
||||
if QMessageBox.Yes == QMessageBox.question(None, "Uninstall", self.tr(
|
||||
"Game files of {} do not exist. Remove it from installed games?").format(igame.title),
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes):
|
||||
self.core.lgd.remove_installed_game(app_name)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
infos = UninstallDialog(game).get_information()
|
||||
if infos == 0:
|
||||
return False
|
||||
|
@ -57,17 +71,26 @@ class GameUtils(QObject):
|
|||
|
||||
def prepare_launch(self, app_name, offline: bool = False, skip_update_check: bool = False):
|
||||
game = self.core.get_game(app_name)
|
||||
if game.supports_cloud_saves and self.cloud_save_utils.sync_before_launch_game(app_name):
|
||||
self.launch_queue[app_name] = (app_name, skip_update_check, offline)
|
||||
return
|
||||
elif game.supports_cloud_saves:
|
||||
dont_sync_after_finish = False
|
||||
|
||||
if game.supports_cloud_saves:
|
||||
try:
|
||||
sync = self.cloud_save_utils.sync_before_launch_game(app_name)
|
||||
except ValueError:
|
||||
logger.info("Cancel startup")
|
||||
self.sync_finished(app_name)
|
||||
except AssertionError:
|
||||
dont_sync_after_finish = True
|
||||
else:
|
||||
if sync:
|
||||
self.launch_queue[app_name] = (app_name, skip_update_check, offline)
|
||||
return
|
||||
self.sync_finished(app_name)
|
||||
|
||||
self.launch_game(app_name, offline, skip_update_check)
|
||||
return
|
||||
self.launch_game(app_name, offline, skip_update_check, ask_always_sync=dont_sync_after_finish)
|
||||
|
||||
def launch_game(self, app_name: str, offline: bool = False, skip_update_check: bool = False, wine_bin: str = None,
|
||||
wine_pfx: str = None):
|
||||
wine_pfx: str = None, ask_always_sync: bool = False):
|
||||
game = self.core.get_game(app_name)
|
||||
igame = self.core.get_installed_game(app_name)
|
||||
|
||||
|
@ -90,7 +113,8 @@ class GameUtils(QObject):
|
|||
return
|
||||
if not os.path.exists(igame.install_path):
|
||||
logger.error("Game doesn't exist")
|
||||
self.finished.emit(app_name, self.tr("Game files of {} do not exist. Please install game"))
|
||||
self.finished.emit(app_name,
|
||||
self.tr("Game files of {} do not exist. Please install game").format(game.app_title))
|
||||
return
|
||||
|
||||
process = GameProcess(app_name)
|
||||
|
@ -145,7 +169,7 @@ class GameUtils(QObject):
|
|||
|
||||
process.setProcessEnvironment(environment)
|
||||
process.game_finished.connect(self.game_finished)
|
||||
running_game = RunningGameModel(process=process, app_name=app_name)
|
||||
running_game = RunningGameModel(process=process, app_name=app_name, always_ask_sync=ask_always_sync)
|
||||
process.start(full_params[0], full_params[1:])
|
||||
self.game_launched.emit(app_name)
|
||||
|
||||
|
@ -202,6 +226,7 @@ class GameUtils(QObject):
|
|||
if resp == 0:
|
||||
webbrowser.open("https://www.dm.origin.com/download")
|
||||
|
||||
game: RunningGameModel = self.running_games.get(app_name, None)
|
||||
self.running_games.pop(app_name)
|
||||
self.finished.emit(app_name, "")
|
||||
|
||||
|
@ -216,7 +241,7 @@ class GameUtils(QObject):
|
|||
buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.Yes)
|
||||
if r != QMessageBox.Yes:
|
||||
return
|
||||
self.cloud_save_utils.game_finished(app_name)
|
||||
self.cloud_save_utils.game_finished(app_name, game.always_ask_sync)
|
||||
|
||||
def sync_finished(self, app_name):
|
||||
if app_name in self.launch_queue.keys():
|
||||
|
|
|
@ -154,6 +154,7 @@ class BaseInstalledWidget(QGroupBox):
|
|||
self.syncing_cloud_saves = False
|
||||
|
||||
def sync_game(self):
|
||||
|
||||
if self.game_utils.cloud_save_utils.sync_before_launch_game(self.game.app_name, True):
|
||||
self.syncing_cloud_saves = True
|
||||
|
||||
|
|
|
@ -112,8 +112,7 @@ class InstalledIconWidget(BaseInstalledWidget):
|
|||
def game_finished(self, app_name, error):
|
||||
if app_name != self.game.app_name:
|
||||
return
|
||||
|
||||
super().game_finished(app_name, error)
|
||||
self.game_running = False
|
||||
self.leaveEvent(None)
|
||||
|
||||
def game_started(self, app_name):
|
||||
|
|
|
@ -9,7 +9,6 @@ class ImportSyncTabs(SideTabWidget):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
super(ImportSyncTabs, self).__init__(show_back=True, parent=parent)
|
||||
|
||||
self.import_widget = ImportSyncWidget(
|
||||
ImportGroup(self),
|
||||
self.tr('Import Game'),
|
||||
|
|
|
@ -3,9 +3,9 @@ import os
|
|||
from logging import getLogger
|
||||
from typing import List, Tuple
|
||||
|
||||
from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal, QObject, QEvent
|
||||
from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal
|
||||
from PyQt5.QtGui import QStandardItemModel
|
||||
from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QListView, QTreeView, QHeaderView
|
||||
from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QTreeView, QHeaderView
|
||||
|
||||
import rare.shared as shared
|
||||
from rare.ui.components.tabs.games.import_sync.import_group import Ui_ImportGroup
|
||||
|
@ -65,10 +65,10 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
|
|||
super(ImportGroup, self).__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
self.core = shared.core
|
||||
self.app_name_list = [game.app_name for game in self.core.get_game_list()]
|
||||
self.app_name_list = [game.app_name for game in shared.api_results.game_list]
|
||||
self.install_dir_list = [
|
||||
game.metadata.get('customAttributes', {}).get('FolderName', {}).get('value', game.app_name)
|
||||
for game in self.core.get_game_list(False) if not game.is_dlc]
|
||||
for game in shared.api_results.game_list if not game.is_dlc]
|
||||
|
||||
self.path_edit = PathEdit(
|
||||
self.core.get_default_install_dir(),
|
||||
|
|
|
@ -90,9 +90,9 @@ class VerifyWorker(QRunnable):
|
|||
if not self.core.is_installed(self.app_name):
|
||||
logger.error(f'Game "{self.app_name}" is not installed')
|
||||
return
|
||||
|
||||
logger.info(f'Loading installed manifest for "{self.app_name}"')
|
||||
igame = self.core.get_installed_game(self.app_name)
|
||||
|
||||
logger.info(f'Loading installed manifest for "{igame.title}"')
|
||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
||||
if not manifest_data:
|
||||
update_manifest(self.app_name, self.core)
|
||||
|
|
Loading…
Reference in a new issue