Code cleanup and improvements.
This commit is contained in:
@@ -176,7 +176,7 @@ def _parse_patch_note(value: object) -> tuple[float, PatchNote] | None:
|
||||
sections=_parse_sections(value.get("changes")),
|
||||
published_at=_format_timestamp(timestamp),
|
||||
)
|
||||
return (timestamp if timestamp is not None else -1.0, patch)
|
||||
return timestamp if timestamp is not None else -1.0, patch
|
||||
|
||||
|
||||
def _parse_tags(value: object) -> tuple[str, ...]:
|
||||
|
||||
@@ -782,13 +782,15 @@ class DepotClient:
|
||||
try:
|
||||
response = self._opener(request, timeout=self.timeout_seconds)
|
||||
except HTTPError as exc:
|
||||
if exc.code == 416 and requested_offset:
|
||||
status = exc.code
|
||||
exc.close()
|
||||
if status == 416 and requested_offset:
|
||||
raise _RetryableDownloadError(
|
||||
f"server rejected the saved offset for {file.path}",
|
||||
discard_partial=True,
|
||||
) from exc
|
||||
raise _RetryableDownloadError(
|
||||
f"HTTP {exc.code} from {server} for {file.path}"
|
||||
f"HTTP {status} from {server} for {file.path}"
|
||||
) from exc
|
||||
except (OSError, HTTPException) as exc:
|
||||
raise _RetryableDownloadError(
|
||||
|
||||
@@ -64,9 +64,11 @@ def fetch_official_launcher(
|
||||
try:
|
||||
response = urlopen(request, timeout=timeout_seconds)
|
||||
except HTTPError as exc:
|
||||
if exc.code == 304 and destination.is_file():
|
||||
status = exc.code
|
||||
exc.close()
|
||||
if status == 304 and destination.is_file():
|
||||
return _existing_download(destination, metadata, url)
|
||||
raise DownloadError(f"official launcher request failed: HTTP {exc.code}") from exc
|
||||
raise DownloadError(f"official launcher request failed: HTTP {status}") from exc
|
||||
except OSError as exc:
|
||||
raise DownloadError(f"official launcher request failed: {exc}") from exc
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
import hashlib
|
||||
import json
|
||||
@@ -266,10 +266,6 @@ def launch_official_updater(
|
||||
)
|
||||
|
||||
|
||||
def patch_result_dict(result: LauncherPatchResult) -> dict[str, object]:
|
||||
return asdict(result)
|
||||
|
||||
|
||||
def _sha256(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as handle:
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
"""Retired login instrumentation retained only for command compatibility."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
"""Retirement state for the disabled login-trace command."""
|
||||
|
||||
DEFAULT_TRACE_TIMEOUT_SECONDS = 10 * 60.0
|
||||
LOGIN_TRACE_ENABLED = False
|
||||
@@ -12,9 +9,3 @@ LOGIN_TRACE_DISABLED_REASON = (
|
||||
"credential-free check, then use wine-update for one controlled comparison "
|
||||
"through the unmodified publisher launcher."
|
||||
)
|
||||
|
||||
|
||||
def run_login_trace(*_args: object, **_kwargs: object) -> None:
|
||||
"""Refuse to reactivate the retired relay-based authentication trace."""
|
||||
|
||||
raise RuntimeError(LOGIN_TRACE_DISABLED_REASON)
|
||||
|
||||
@@ -1113,14 +1113,6 @@ def _read_legacy_overlay_result(path: Path) -> LegacyOverlayResult | None:
|
||||
)
|
||||
|
||||
|
||||
def _runtime_game_binary_sources(
|
||||
paths: AppPaths,
|
||||
source: Path,
|
||||
) -> tuple[str, Path, Path]:
|
||||
action, game_exe, game_dll, _ = _runtime_game_binary_profile(paths, source)
|
||||
return action, game_exe, game_dll
|
||||
|
||||
|
||||
def _runtime_game_binary_profile(
|
||||
paths: AppPaths,
|
||||
source: Path,
|
||||
|
||||
@@ -239,28 +239,6 @@ class AppPaths:
|
||||
def compatibility_manifest(self) -> Path:
|
||||
return self.state / "compatibility-binaries.json"
|
||||
|
||||
@property
|
||||
def runtime_patch_directory(self) -> Path:
|
||||
"""Retired 0.5.8 disk-patch cache; never selected for play."""
|
||||
|
||||
return self.data / "runtime-patches" / "v21-post-auth-reclaim"
|
||||
|
||||
@property
|
||||
def runtime_patch_dll(self) -> Path:
|
||||
"""Retired 0.5.8 DLL retained only so diagnostics can identify it."""
|
||||
|
||||
return self.runtime_patch_directory / "game.dll"
|
||||
|
||||
@property
|
||||
def runtime_patch_manifest(self) -> Path:
|
||||
return self.state / "runtime-patch.json"
|
||||
|
||||
@property
|
||||
def retired_runtime_patch_dll(self) -> Path:
|
||||
"""The pre-0.5.7 all-session patch, retained only for diagnostics."""
|
||||
|
||||
return self.data / "runtime-patches" / "v21-texture-reclaim" / "game.dll"
|
||||
|
||||
@property
|
||||
def compat_data(self) -> Path:
|
||||
return self.data / "game-compat"
|
||||
|
||||
@@ -507,36 +507,6 @@ def _resolve_runtime_path_case(root: Path, relative: PurePosixPath) -> Path:
|
||||
return cursor
|
||||
|
||||
|
||||
def run_proton_prefix_command(
|
||||
paths: AppPaths,
|
||||
selection: RuntimeSelection,
|
||||
runner: CommandRunner,
|
||||
arguments: Sequence[str],
|
||||
*,
|
||||
check: bool = True,
|
||||
timeout_seconds: float = 60.0,
|
||||
) -> CommandOutcome:
|
||||
"""Run a maintenance command in the pinned Proton 7 prefix."""
|
||||
|
||||
if selection.kind not in {"proton7", "proton7-container"}:
|
||||
raise RuntimeErrorPT("the login trace requires the pinned Proton 7 runtime")
|
||||
if not selection.proton_path or not selection.steam_root:
|
||||
raise RuntimeErrorPT("incomplete Proton 7 runtime selection")
|
||||
return runner.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"ptlinux.proton_compat",
|
||||
selection.proton_path,
|
||||
"runinprefix",
|
||||
*arguments,
|
||||
],
|
||||
env_overrides=_proton_environment(paths, selection),
|
||||
timeout_seconds=timeout_seconds,
|
||||
check=check,
|
||||
)
|
||||
|
||||
|
||||
def run_runtime_prefix_command(
|
||||
paths: AppPaths,
|
||||
selection: RuntimeSelection,
|
||||
|
||||
@@ -603,7 +603,9 @@ def _fetch_small_file(
|
||||
try:
|
||||
response = urlopen(request, timeout=timeout_seconds)
|
||||
except HTTPError as exc:
|
||||
raise LauncherUpdateError(f"{label} request failed: HTTP {exc.code}") from exc
|
||||
status = exc.code
|
||||
exc.close()
|
||||
raise LauncherUpdateError(f"{label} request failed: HTTP {status}") from exc
|
||||
except (URLError, OSError) as exc:
|
||||
raise LauncherUpdateError(f"{label} request failed: {exc}") from exc
|
||||
with response:
|
||||
@@ -695,8 +697,10 @@ def _download_archive(
|
||||
try:
|
||||
response = urlopen(request, timeout=timeout_seconds)
|
||||
except HTTPError as exc:
|
||||
status = exc.code
|
||||
exc.close()
|
||||
raise LauncherUpdateError(
|
||||
f"launcher archive request failed: HTTP {exc.code}"
|
||||
f"launcher archive request failed: HTTP {status}"
|
||||
) from exc
|
||||
except (URLError, OSError) as exc:
|
||||
raise LauncherUpdateError(f"launcher archive request failed: {exc}") from exc
|
||||
|
||||
@@ -5,6 +5,130 @@ from __future__ import annotations
|
||||
from typing import Any
|
||||
|
||||
|
||||
def _settings_checkbox_image(
|
||||
root: Any,
|
||||
*,
|
||||
size: int,
|
||||
gap: int,
|
||||
fill: str,
|
||||
border: str,
|
||||
mark: str | None = None,
|
||||
) -> Any:
|
||||
"""Create one scaled checkbox indicator from the launcher palette."""
|
||||
|
||||
import tkinter as tk
|
||||
|
||||
image = tk.PhotoImage(master=root, width=size + gap, height=size)
|
||||
border_width = max(1, round(size / 16))
|
||||
image.put(fill, to=(0, 0, size, size))
|
||||
image.put(border, to=(0, 0, size, border_width))
|
||||
image.put(border, to=(0, size - border_width, size, size))
|
||||
image.put(border, to=(0, 0, border_width, size))
|
||||
image.put(border, to=(size - border_width, 0, size, size))
|
||||
if mark is not None:
|
||||
stroke = max(2, round(size / 8))
|
||||
for source_x, source_y in (
|
||||
(4, 8),
|
||||
(5, 9),
|
||||
(6, 10),
|
||||
(7, 11),
|
||||
(8, 10),
|
||||
(9, 9),
|
||||
(10, 8),
|
||||
(11, 7),
|
||||
(12, 6),
|
||||
):
|
||||
x = round(source_x * size / 16)
|
||||
y = round(source_y * size / 16)
|
||||
image.put(
|
||||
mark,
|
||||
to=(
|
||||
x,
|
||||
y,
|
||||
min(size - border_width, x + stroke),
|
||||
min(size - border_width, y + stroke),
|
||||
),
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
def _configure_settings_checkbox_indicator(
|
||||
root: Any,
|
||||
style: Any,
|
||||
launcher_ui_scale: float,
|
||||
) -> None:
|
||||
"""Replace the platform X indicator with the launcher's checkmark."""
|
||||
|
||||
element_name = "Settings.Checkbutton.indicator"
|
||||
if element_name in style.element_names():
|
||||
return
|
||||
size = max(16, round(16 * launcher_ui_scale))
|
||||
gap = max(9, round(9 * launcher_ui_scale))
|
||||
palettes = {
|
||||
"unchecked": ("#100d0c", "#6a4d38", None),
|
||||
"unchecked_active": ("#211916", "#d98927", None),
|
||||
"unchecked_focus": ("#100d0c", "#f4bd61", None),
|
||||
"checked": ("#d98927", "#f4bd61", "#24170f"),
|
||||
"checked_active": ("#efaa4c", "#fff0c2", "#24170f"),
|
||||
"checked_focus": ("#d98927", "#fff0c2", "#24170f"),
|
||||
"disabled": ("#171412", "#30251f", None),
|
||||
"checked_disabled": ("#6c4826", "#776b62", "#30251f"),
|
||||
}
|
||||
images = {
|
||||
name: _settings_checkbox_image(
|
||||
root,
|
||||
size=size,
|
||||
gap=gap,
|
||||
fill=fill,
|
||||
border=border,
|
||||
mark=mark,
|
||||
)
|
||||
for name, (fill, border, mark) in palettes.items()
|
||||
}
|
||||
style.element_create(
|
||||
element_name,
|
||||
"image",
|
||||
images["unchecked"],
|
||||
("disabled selected", images["checked_disabled"]),
|
||||
("disabled", images["disabled"]),
|
||||
("pressed selected", images["checked_active"]),
|
||||
("active selected", images["checked_active"]),
|
||||
("focus selected", images["checked_focus"]),
|
||||
("selected", images["checked"]),
|
||||
("pressed", images["unchecked_active"]),
|
||||
("active", images["unchecked_active"]),
|
||||
("focus", images["unchecked_focus"]),
|
||||
)
|
||||
style.layout(
|
||||
"Settings.TCheckbutton",
|
||||
[
|
||||
(
|
||||
"Checkbutton.padding",
|
||||
{
|
||||
"sticky": "nswe",
|
||||
"children": [
|
||||
(element_name, {"side": "left", "sticky": ""}),
|
||||
(
|
||||
"Checkbutton.focus",
|
||||
{
|
||||
"side": "left",
|
||||
"sticky": "w",
|
||||
"children": [
|
||||
(
|
||||
"Checkbutton.label",
|
||||
{"sticky": "nswe"},
|
||||
)
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
setattr(root, "_ptlinux_settings_checkbox_images", tuple(images.values()))
|
||||
|
||||
|
||||
def configure_dashboard_style(root: Any, ttk: Any, launcher_ui_scale: float) -> None:
|
||||
style = ttk.Style(root)
|
||||
style.theme_use("clam")
|
||||
@@ -100,8 +224,8 @@ def configure_dashboard_style(root: Any, ttk: Any, launcher_ui_scale: float) ->
|
||||
style.configure(
|
||||
"SettingsText.TLabel",
|
||||
background="#191311",
|
||||
foreground="#d8cbbd",
|
||||
font=("Sans", 9),
|
||||
foreground="#e5b66c",
|
||||
font=("Sans", 8, "bold"),
|
||||
)
|
||||
style.configure(
|
||||
"SettingsHint.TLabel",
|
||||
@@ -165,30 +289,110 @@ def configure_dashboard_style(root: Any, ttk: Any, launcher_ui_scale: float) ->
|
||||
"Settings.TEntry",
|
||||
fieldbackground="#100d0c",
|
||||
foreground="#f8ead2",
|
||||
insertcolor="#f8fafc",
|
||||
insertcolor="#f4bd61",
|
||||
selectbackground="#6a482d",
|
||||
selectforeground="#fff8e9",
|
||||
font=("Sans", 9),
|
||||
padding=(10, 7),
|
||||
bordercolor="#4a3528",
|
||||
lightcolor="#4a3528",
|
||||
darkcolor="#4a3528",
|
||||
borderwidth=1,
|
||||
relief="flat",
|
||||
focuscolor="#f4bd61",
|
||||
focusthickness=2,
|
||||
focusthickness=1,
|
||||
)
|
||||
style.map(
|
||||
"Settings.TEntry",
|
||||
fieldbackground=[
|
||||
("disabled", "#171412"),
|
||||
("!disabled", "#100d0c"),
|
||||
],
|
||||
foreground=[
|
||||
("disabled", "#776b62"),
|
||||
("!disabled", "#f8ead2"),
|
||||
],
|
||||
bordercolor=[
|
||||
("disabled", "#30251f"),
|
||||
("focus", "#f4bd61"),
|
||||
("!disabled", "#4a3528"),
|
||||
],
|
||||
lightcolor=[
|
||||
("focus", "#f4bd61"),
|
||||
("!focus", "#4a3528"),
|
||||
],
|
||||
darkcolor=[
|
||||
("focus", "#f4bd61"),
|
||||
("!focus", "#4a3528"),
|
||||
],
|
||||
)
|
||||
style.map("Settings.TEntry", bordercolor=[("focus", "#f4bd61")])
|
||||
style.configure(
|
||||
"Settings.TCombobox",
|
||||
fieldbackground="#100d0c",
|
||||
background="#211916",
|
||||
background="#191311",
|
||||
foreground="#f8ead2",
|
||||
arrowcolor="#e5b66c",
|
||||
selectbackground="#6a482d",
|
||||
selectforeground="#fff8e9",
|
||||
font=("Sans", 9),
|
||||
padding=(10, 7),
|
||||
arrowsize=max(12, round(12 * launcher_ui_scale)),
|
||||
bordercolor="#4a3528",
|
||||
lightcolor="#4a3528",
|
||||
darkcolor="#4a3528",
|
||||
borderwidth=1,
|
||||
relief="flat",
|
||||
focuscolor="#f4bd61",
|
||||
focusthickness=2,
|
||||
focusthickness=1,
|
||||
)
|
||||
style.map(
|
||||
"Settings.TCombobox",
|
||||
fieldbackground=[("readonly", "#100d0c")],
|
||||
foreground=[("readonly", "#f8ead2")],
|
||||
bordercolor=[("focus", "#f4bd61")],
|
||||
fieldbackground=[
|
||||
("disabled", "#171412"),
|
||||
("readonly", "#100d0c"),
|
||||
],
|
||||
background=[
|
||||
("disabled", "#171412"),
|
||||
("pressed", "#32251f"),
|
||||
("active", "#2a201c"),
|
||||
("readonly", "#191311"),
|
||||
],
|
||||
foreground=[
|
||||
("disabled", "#776b62"),
|
||||
("readonly", "#f8ead2"),
|
||||
],
|
||||
arrowcolor=[
|
||||
("disabled", "#776b62"),
|
||||
("pressed", "#fff0c2"),
|
||||
("active", "#f4bd61"),
|
||||
("readonly", "#e5b66c"),
|
||||
],
|
||||
bordercolor=[
|
||||
("disabled", "#30251f"),
|
||||
("focus", "#f4bd61"),
|
||||
("active", "#6a4d38"),
|
||||
("readonly", "#4a3528"),
|
||||
],
|
||||
lightcolor=[
|
||||
("focus", "#f4bd61"),
|
||||
("!focus", "#4a3528"),
|
||||
],
|
||||
darkcolor=[
|
||||
("focus", "#f4bd61"),
|
||||
("!focus", "#4a3528"),
|
||||
],
|
||||
)
|
||||
root.option_add("*TCombobox*Listbox.background", "#100d0c")
|
||||
root.option_add("*TCombobox*Listbox.foreground", "#f8ead2")
|
||||
root.option_add("*TCombobox*Listbox.selectBackground", "#6a482d")
|
||||
root.option_add("*TCombobox*Listbox.selectForeground", "#fff8e9")
|
||||
root.option_add("*TCombobox*Listbox.font", "Sans 9")
|
||||
root.option_add("*TCombobox*Listbox.borderWidth", 1)
|
||||
root.option_add("*TCombobox*Listbox.highlightThickness", 1)
|
||||
root.option_add("*TCombobox*Listbox.highlightBackground", "#4a3528")
|
||||
root.option_add("*TCombobox*Listbox.highlightColor", "#f4bd61")
|
||||
root.option_add("*TCombobox*Listbox.relief", "flat")
|
||||
root.option_add("*TCombobox*Listbox.activeStyle", "none")
|
||||
style.configure(
|
||||
"Realm.TCombobox",
|
||||
fieldbackground="#211916",
|
||||
@@ -239,18 +443,31 @@ def configure_dashboard_style(root: Any, ttk: Any, launcher_ui_scale: float) ->
|
||||
root.option_add("*realm_selector*Listbox.highlightThickness", 0)
|
||||
root.option_add("*realm_selector*Listbox.relief", "flat")
|
||||
root.option_add("*realm_selector*Listbox.activeStyle", "none")
|
||||
_configure_settings_checkbox_indicator(root, style, launcher_ui_scale)
|
||||
style.configure(
|
||||
"Settings.TCheckbutton",
|
||||
background="#191311",
|
||||
background="#171210",
|
||||
foreground="#d8cbbd",
|
||||
font=("Sans", 9),
|
||||
padding=(9, 7),
|
||||
relief="flat",
|
||||
focuscolor="#f4bd61",
|
||||
focusthickness=2,
|
||||
focusthickness=1,
|
||||
)
|
||||
style.map(
|
||||
"Settings.TCheckbutton",
|
||||
background=[("active", "#191311")],
|
||||
foreground=[("active", "#fff0d2")],
|
||||
background=[
|
||||
("disabled", "#15110f"),
|
||||
("pressed", "#2a201c"),
|
||||
("active", "#241b17"),
|
||||
("selected", "#211916"),
|
||||
("!selected", "#171210"),
|
||||
],
|
||||
foreground=[
|
||||
("disabled", "#776b62"),
|
||||
("active", "#fff0d2"),
|
||||
("selected", "#f8ead2"),
|
||||
],
|
||||
)
|
||||
style.configure(
|
||||
"PreloaderStatus.TLabel",
|
||||
|
||||
@@ -199,8 +199,6 @@ def patch_change_colors(type_key: str) -> tuple[str, str]:
|
||||
}.get(type_key.casefold(), ("#2a201c", "#d8aa61"))
|
||||
|
||||
|
||||
|
||||
|
||||
def run_dashboard(paths: AppPaths) -> None:
|
||||
try:
|
||||
import tkinter as tk
|
||||
@@ -677,19 +675,9 @@ def run_dashboard(paths: AppPaths) -> None:
|
||||
responsive_layout_after: str | None = None
|
||||
buttons = (
|
||||
play_button,
|
||||
update_button,
|
||||
repair_button,
|
||||
doctor_button,
|
||||
settings_button,
|
||||
import_button,
|
||||
launcher_update_button,
|
||||
)
|
||||
game_mutation_buttons = (
|
||||
update_button,
|
||||
repair_button,
|
||||
import_button,
|
||||
launcher_update_button,
|
||||
*action_widgets.operation_buttons,
|
||||
)
|
||||
game_mutation_buttons = action_widgets.mutation_buttons
|
||||
|
||||
def append_log(value: str) -> None:
|
||||
nonlocal activity_log_lines
|
||||
@@ -1050,11 +1038,11 @@ def run_dashboard(paths: AppPaths) -> None:
|
||||
append_log(f"$ {' '.join(command)}")
|
||||
|
||||
def worker() -> None:
|
||||
def publish_output(line: str) -> None:
|
||||
def publish_output(output_line: str) -> None:
|
||||
if game_client_id is None:
|
||||
events.put(("output", line))
|
||||
events.put(("output", output_line))
|
||||
else:
|
||||
events.put(("output", f"[Client {game_client_id}] {line}"))
|
||||
events.put(("output", f"[Client {game_client_id}] {output_line}"))
|
||||
|
||||
if (
|
||||
game_client_id is not None
|
||||
|
||||
@@ -164,6 +164,7 @@ def open_settings_dialog(
|
||||
def add_choice(
|
||||
parent: ttk.LabelFrame,
|
||||
row: int,
|
||||
name: str,
|
||||
label: str,
|
||||
description: str,
|
||||
variable: tk.StringVar,
|
||||
@@ -181,15 +182,20 @@ def open_settings_dialog(
|
||||
)
|
||||
ttk.Combobox(
|
||||
parent,
|
||||
name=name,
|
||||
textvariable=variable,
|
||||
values=choices,
|
||||
state="readonly",
|
||||
style="Settings.TCombobox",
|
||||
cursor="hand2",
|
||||
exportselection=False,
|
||||
takefocus=True,
|
||||
).grid(row=row + 1, column=0, columnspan=2, sticky="ew", pady=(3, 9))
|
||||
|
||||
def add_path(
|
||||
parent: ttk.LabelFrame,
|
||||
row: int,
|
||||
name: str,
|
||||
label: str,
|
||||
description: str,
|
||||
variable: tk.StringVar,
|
||||
@@ -205,7 +211,14 @@ def open_settings_dialog(
|
||||
column=1,
|
||||
sticky="e",
|
||||
)
|
||||
ttk.Entry(parent, textvariable=variable, style="Settings.TEntry").grid(
|
||||
ttk.Entry(
|
||||
parent,
|
||||
name=name,
|
||||
textvariable=variable,
|
||||
style="Settings.TEntry",
|
||||
exportselection=False,
|
||||
takefocus=True,
|
||||
).grid(
|
||||
row=row + 1,
|
||||
column=0,
|
||||
columnspan=1,
|
||||
@@ -295,22 +308,27 @@ def open_settings_dialog(
|
||||
wraplength=360,
|
||||
).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 11))
|
||||
presentation = ttk.Frame(display_card, style="SettingsCard.TFrame")
|
||||
presentation.grid(row=1, column=0, columnspan=2, sticky="w")
|
||||
presentation.grid(row=1, column=0, columnspan=2, sticky="ew")
|
||||
ttk.Checkbutton(
|
||||
presentation,
|
||||
text="Remove title bar and borders (Borderless)",
|
||||
variable=borderless_value,
|
||||
style="Settings.TCheckbutton",
|
||||
).pack(anchor="w")
|
||||
cursor="hand2",
|
||||
takefocus=True,
|
||||
).pack(fill="x")
|
||||
ttk.Checkbutton(
|
||||
presentation,
|
||||
text="Suppress false 'not responding' warnings",
|
||||
variable=suppress_unresponsive_value,
|
||||
style="Settings.TCheckbutton",
|
||||
).pack(anchor="w", pady=(7, 0))
|
||||
cursor="hand2",
|
||||
takefocus=True,
|
||||
).pack(fill="x", pady=(7, 0))
|
||||
add_choice(
|
||||
display_card,
|
||||
2,
|
||||
"settings_selector_ui_scale",
|
||||
"Launcher size",
|
||||
"Applies after launcher restart",
|
||||
ui_scale_value,
|
||||
@@ -335,6 +353,7 @@ def open_settings_dialog(
|
||||
add_choice(
|
||||
rendering_card,
|
||||
1,
|
||||
"settings_selector_runtime",
|
||||
"Runtime",
|
||||
"Compatibility layer",
|
||||
runtime_value,
|
||||
@@ -343,6 +362,7 @@ def open_settings_dialog(
|
||||
add_choice(
|
||||
rendering_card,
|
||||
3,
|
||||
"settings_selector_proton_sync",
|
||||
"Proton synchronization",
|
||||
"Automatic selects the compatible mode",
|
||||
proton_sync_value,
|
||||
@@ -378,7 +398,9 @@ def open_settings_dialog(
|
||||
text="Low-bandwidth mode (cached news, up to 2 workers and 5 MB/s)",
|
||||
variable=low_bandwidth_value,
|
||||
style="Settings.TCheckbutton",
|
||||
).grid(row=1, column=0, sticky="w", padx=(0, 16))
|
||||
cursor="hand2",
|
||||
takefocus=True,
|
||||
).grid(row=1, column=0, rowspan=2, sticky="ew", padx=(0, 16))
|
||||
ttk.Label(
|
||||
downloads_card,
|
||||
text="Speed limit",
|
||||
@@ -391,12 +413,16 @@ def open_settings_dialog(
|
||||
).grid(row=1, column=2, sticky="w", padx=(8, 0))
|
||||
download_speed_selector = ttk.Combobox(
|
||||
downloads_card,
|
||||
name="settings_selector_download_speed",
|
||||
textvariable=download_speed_value,
|
||||
values=tuple(DOWNLOAD_SPEED_PRESETS_MBPS) + (
|
||||
DOWNLOAD_SPEED_CUSTOM_LABEL,
|
||||
),
|
||||
state="readonly",
|
||||
style="Settings.TCombobox",
|
||||
cursor="hand2",
|
||||
exportselection=False,
|
||||
takefocus=True,
|
||||
)
|
||||
download_speed_selector.grid(
|
||||
row=2,
|
||||
@@ -406,9 +432,13 @@ def open_settings_dialog(
|
||||
)
|
||||
custom_download_speed = ttk.Entry(
|
||||
downloads_card,
|
||||
name="settings_download_speed",
|
||||
textvariable=custom_download_speed_value,
|
||||
style="Settings.TEntry",
|
||||
width=12,
|
||||
justify="right",
|
||||
exportselection=False,
|
||||
takefocus=True,
|
||||
)
|
||||
custom_download_speed.grid(
|
||||
row=2,
|
||||
@@ -449,6 +479,7 @@ def open_settings_dialog(
|
||||
add_path(
|
||||
overrides_card,
|
||||
1,
|
||||
"settings_proton_path",
|
||||
"Proton script",
|
||||
"Use a specific Proton executable",
|
||||
proton_path_value,
|
||||
@@ -457,6 +488,7 @@ def open_settings_dialog(
|
||||
add_path(
|
||||
overrides_card,
|
||||
3,
|
||||
"settings_game_source",
|
||||
"Import source",
|
||||
"Seed a new managed installation only",
|
||||
game_source_value,
|
||||
|
||||
@@ -187,8 +187,10 @@ def _download_archive(
|
||||
try:
|
||||
response = opener(request, timeout=timeout_seconds)
|
||||
except HTTPError as exc:
|
||||
status = exc.code
|
||||
exc.close()
|
||||
raise UmuBootstrapError(
|
||||
f"portable UMU request failed: HTTP {exc.code}"
|
||||
f"portable UMU request failed: HTTP {status}"
|
||||
) from exc
|
||||
except OSError as exc:
|
||||
raise UmuBootstrapError(f"portable UMU request failed: {exc}") from exc
|
||||
|
||||
Reference in New Issue
Block a user