Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
160 lines (123 loc) · 5.47 KB
/
Copy pathapp.py
File metadata and controls
160 lines (123 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from urllib.parse import urlsplit
import streamlit as st
from package_build.download_parts import download_parts
from package_build.file_list import show_file_list
from package_build.i18n import (
get_available_languages,
get_preferred_languages,
set_preferred_languages,
)
from package_build.i18n import (
gettext as _,
)
from package_build.metadata import get_dict_metadata, get_hook_metadata
from package_build.package import build_package, package_up_to_date, remove_stale_packages
from package_build.parse_metadata import parse_metadata
if TYPE_CHECKING:
from package_build.models import DictInfoEntry
def is_running_locally() -> bool:
app_url = st.context.url
return app_url is None or urlsplit(app_url).hostname in {"localhost", "127.0.0.1", "::1"}
st.set_page_config(page_title=_("DF localization package builder"), page_icon="📦")
if is_running_locally():
application_language = st.segmented_control(
"Language",
options=get_available_languages(),
label_visibility="collapsed",
required=True,
key="application_language",
)
if application_language:
set_preferred_languages([application_language])
st.header(_("DF localization package builder"))
st.write(_("Build/download a package, unpack into the game's directory with file repalacement."))
st.markdown(
_(
"It's recommended to use [dfint-installer](https://github.com/dfint/installer) instead of using this "
"app. Use the package builder only if the installer doesn't work for you or you have some other issues "
"with it.",
),
)
hook_metadata = parse_metadata(get_hook_metadata())
dict_metadata = get_dict_metadata()
df_version_options = hook_metadata.df_version_options
column1, column2 = st.columns(2)
with column1:
df_version: str = st.selectbox(label=_("DF version"), options=sorted(df_version_options, reverse=True))
operating_system: str = st.selectbox(
label=_("Operating system/platform"),
options=sorted(df_version_options[df_version].operating_systems, reverse=True), # show windows first
)
variants_priority = {
"steam": 0,
"itchio": 1,
"classic": 2,
}
variants = sorted(df_version_options[df_version].variants, key=lambda v: variants_priority.get(v, 3))
def normalize_language_code(language_code: str) -> str:
return language_code.replace("_", "-").casefold()
def get_language_priority(user_languages: list[str], language_code: str) -> int:
if language_code.startswith("en"):
return 1000
try:
normalized_language_code = normalize_language_code(language_code)
return user_languages.index(normalized_language_code) - len(user_languages)
except ValueError:
return 0
def language_ordering(dict_info_entry: DictInfoEntry) -> tuple[int, str]:
"""
Set max priority to user's languages (according to their index in the user's browser settings)
and the lowest priority to English.
All other languages are sorted by their codes.
"""
user_languages = [normalize_language_code(language) for language in get_preferred_languages()]
return get_language_priority(user_languages, dict_info_entry.code), dict_info_entry.code
with column2:
df_variant: str = st.selectbox(label=_("DF variant"), options=variants)
dict_entry: DictInfoEntry = st.selectbox(label=_("Language"), options=sorted(dict_metadata, key=language_ordering))
hook_info = hook_metadata.hook_info.get((df_version, df_variant, operating_system))
root_dir = Path(__file__).parent
with st.spinner(_("Removing stale packages...")):
remove_stale_packages(root_dir)
if not hook_info:
st.write(_("Cannot create package with these parameters"))
else:
package_name = f"dfint_{df_version}_{df_variant}_{operating_system}_{dict_entry.code}.zip"
package_path = root_dir / package_name
if not package_up_to_date(package_path):
button_generate = st.button(_("Generate package"))
if button_generate:
with st.status(_("Downloading files..."), expanded=True) as status:
parts = download_parts(hook_info, dict_entry)
status.update(label=_("Downloading complete!"), state="complete", expanded=False)
with st.status(_("Building package..."), expanded=True) as status:
build_dir = root_dir / "build"
build_package(
package_path=package_path,
build_dir=build_dir,
hook_info=hook_info,
parts=parts,
is_win=operating_system.startswith("win"),
)
status.update(label=_("Package is ready!"), state="complete", expanded=False)
if package_up_to_date(package_path):
st.download_button(
label=_("Download package"),
file_name=package_path.name,
data=package_path.read_bytes(),
mime="application/zip",
)
enable_filter = st.checkbox(label=_("Filter available files by DF variant, operating system, language"), value=True)
glob_filter = f"*_{df_variant}_{operating_system}_{dict_entry.code}.zip" if enable_filter else "*.zip"
def file_sort_key(file_path: Path) -> tuple[str, str, str, str]:
_, version, variant, os, language = file_path.name.split("_")
return (
language,
os,
variant,
version,
)
show_file_list(root_dir, glob_filter=glob_filter, sort_key=file_sort_key)