UI gradient intensity slider, update wgui Defaults for dashboard, prepend ui-related config entries with ui_
This commit is contained in:
@@ -82,7 +82,8 @@
|
|||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen",
|
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen",
|
||||||
"HANDSFREE_POINTER": "Freihändige Modus",
|
"HANDSFREE_POINTER": "Freihändige Modus",
|
||||||
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt."
|
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt.",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UI-Verlaufsintensität"
|
||||||
},
|
},
|
||||||
"HELLO": "Hallo!",
|
"HELLO": "Hallo!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"APP_SETTINGS": {
|
"APP_SETTINGS": {
|
||||||
"ALLOW_SLIDING": "Stick interaction during grab",
|
"ALLOW_SLIDING": "Stick interaction during grab",
|
||||||
"ANIMATION_SPEED": "UI Animation speed",
|
"ANIMATION_SPEED": "UI Animation speed",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UI Gradient intensity",
|
||||||
"BLOCK_GAME_INPUT": "Block game input",
|
"BLOCK_GAME_INPUT": "Block game input",
|
||||||
"BLOCK_GAME_INPUT_HELP": "Blocks all input when an overlay is hovered",
|
"BLOCK_GAME_INPUT_HELP": "Blocks all input when an overlay is hovered",
|
||||||
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignore watch when blocking input",
|
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignore watch when blocking input",
|
||||||
|
|||||||
@@ -82,7 +82,8 @@
|
|||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio",
|
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio",
|
||||||
"HANDSFREE_POINTER": "Modo manos libres",
|
"HANDSFREE_POINTER": "Modo manos libres",
|
||||||
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic."
|
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic.",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la IU"
|
||||||
},
|
},
|
||||||
"HELLO": "¡Hola!",
|
"HELLO": "¡Hola!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|||||||
@@ -102,7 +102,8 @@
|
|||||||
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
|
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
|
||||||
"AUTOSTART_APPS": "App da avviare all'avvio",
|
"AUTOSTART_APPS": "App da avviare all'avvio",
|
||||||
"HANDSFREE_POINTER": "Modalità a mani libere",
|
"HANDSFREE_POINTER": "Modalità a mani libere",
|
||||||
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare."
|
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensità gradiente dell'interfaccia utente"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
||||||
"APPLICATION_STARTED": "Applicazione avviata",
|
"APPLICATION_STARTED": "Applicazione avviata",
|
||||||
|
|||||||
@@ -82,7 +82,8 @@
|
|||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "起動時に実行するアプリ",
|
"AUTOSTART_APPS": "起動時に実行するアプリ",
|
||||||
"HANDSFREE_POINTER": "ハンズフリーモード",
|
"HANDSFREE_POINTER": "ハンズフリーモード",
|
||||||
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。"
|
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UIグラデーションの強さ"
|
||||||
},
|
},
|
||||||
"HELLO": "こんにちは!",
|
"HELLO": "こんにちは!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|||||||
@@ -77,7 +77,8 @@
|
|||||||
},
|
},
|
||||||
"AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie",
|
"AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie",
|
||||||
"HANDSFREE_POINTER": "Tryb bez użycia rąk",
|
"HANDSFREE_POINTER": "Tryb bez użycia rąk",
|
||||||
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie."
|
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie.",
|
||||||
|
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
||||||
"APPLICATIONS": "Aplikacje",
|
"APPLICATIONS": "Aplikacje",
|
||||||
|
|||||||
@@ -102,7 +102,8 @@
|
|||||||
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
|
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
|
||||||
"AUTOSTART_APPS": "开机启动应用",
|
"AUTOSTART_APPS": "开机启动应用",
|
||||||
"HANDSFREE_POINTER": "免提模式",
|
"HANDSFREE_POINTER": "免提模式",
|
||||||
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取,右手为点击。"
|
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取,右手为点击。",
|
||||||
|
"UI_GRADIENT_INTENSITY": "UI 渐变强度"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "应用启动器",
|
"APPLICATION_LAUNCHER": "应用启动器",
|
||||||
"APPLICATION_STARTED": "应用已启动",
|
"APPLICATION_STARTED": "应用已启动",
|
||||||
|
|||||||
@@ -97,11 +97,12 @@ pub enum FrontendTask {
|
|||||||
RecenterPlayspace,
|
RecenterPlayspace,
|
||||||
PushToast(Translation),
|
PushToast(Translation),
|
||||||
PlaySound(SoundType),
|
PlaySound(SoundType),
|
||||||
|
UpdateWguiDefaultsFromConfig,
|
||||||
HideDashboard,
|
HideDashboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Frontend<T> {
|
impl<T: 'static> Frontend<T> {
|
||||||
pub fn new(params: InitParams<T>, data: &mut T) -> anyhow::Result<Frontend<T>> {
|
pub fn new(mut params: InitParams<T>, data: &mut T) -> anyhow::Result<Frontend<T>> {
|
||||||
let mut assets = Box::new(assets::Asset {});
|
let mut assets = Box::new(assets::Asset {});
|
||||||
|
|
||||||
let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?;
|
let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?;
|
||||||
@@ -120,6 +121,8 @@ impl<T: 'static> Frontend<T> {
|
|||||||
PathBuf::new(), //FIXME: pass from somewhere else
|
PathBuf::new(), //FIXME: pass from somewhere else
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
Frontend::update_defaults_from_config(&globals, &mut params.interface, data);
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
&ParseDocumentParams {
|
&ParseDocumentParams {
|
||||||
globals: globals.clone(),
|
globals: globals.clone(),
|
||||||
@@ -166,8 +169,9 @@ impl<T: 'static> Frontend<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// init some things first
|
// init some things first
|
||||||
frontend.update_background(data)?;
|
frontend.tasks.push(FrontendTask::RefreshBackground);
|
||||||
frontend.update_time(data)?;
|
frontend.tasks.push(FrontendTask::RefreshClock);
|
||||||
|
frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig);
|
||||||
|
|
||||||
Frontend::register_widgets(&mut frontend)?;
|
Frontend::register_widgets(&mut frontend)?;
|
||||||
|
|
||||||
@@ -178,6 +182,16 @@ impl<T: 'static> Frontend<T> {
|
|||||||
self.sounds_to_play.push(sound_type);
|
self.sounds_to_play.push(sound_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_defaults_from_config(globals: &WguiGlobals, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
||||||
|
let config = interface.general_config(data);
|
||||||
|
|
||||||
|
let mut globals = globals.get();
|
||||||
|
let defaults = &mut globals.defaults;
|
||||||
|
|
||||||
|
defaults.animation_mult = 1.0 / config.ui_animation_speed;
|
||||||
|
defaults.gradient_intensity = config.ui_gradient_intensity;
|
||||||
|
}
|
||||||
|
|
||||||
fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> {
|
fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> {
|
||||||
let mut assets = self.globals.assets_builtin();
|
let mut assets = self.globals.assets_builtin();
|
||||||
|
|
||||||
@@ -192,7 +206,7 @@ impl<T: 'static> Frontend<T> {
|
|||||||
Err(_) => assets.load_from_path(path)?.into(),
|
Err(_) => assets.load_from_path(path)?.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let sample = audio::AudioSample::from_mp3(&*sound_bytes)?;
|
let sample = audio::AudioSample::from_mp3(&sound_bytes)?;
|
||||||
audio_system.play_sample(&sample);
|
audio_system.play_sample(&sample);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -307,6 +321,8 @@ impl<T: 'static> Frontend<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_background(&mut self, data: &mut T) -> anyhow::Result<()> {
|
fn update_background(&mut self, data: &mut T) -> anyhow::Result<()> {
|
||||||
|
self.layout.mark_redraw();
|
||||||
|
|
||||||
let Some(mut rect) = self
|
let Some(mut rect) = self
|
||||||
.layout
|
.layout
|
||||||
.state
|
.state
|
||||||
@@ -341,6 +357,9 @@ impl<T: 'static> Frontend<T> {
|
|||||||
FrontendTask::PushToast(content) => self.toast_manager.push(content),
|
FrontendTask::PushToast(content) => self.toast_manager.push(content),
|
||||||
FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type),
|
FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type),
|
||||||
FrontendTask::HideDashboard => self.action_hide_dashboard(params.data),
|
FrontendTask::HideDashboard => self.action_hide_dashboard(params.data),
|
||||||
|
FrontendTask::UpdateWguiDefaultsFromConfig => {
|
||||||
|
Frontend::update_defaults_from_config(&self.globals, &mut self.interface, params.data)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ enum Task {
|
|||||||
UpdateBool(SettingType, bool),
|
UpdateBool(SettingType, bool),
|
||||||
UpdateFloat(SettingType, f32),
|
UpdateFloat(SettingType, f32),
|
||||||
UpdateInt(SettingType, i32),
|
UpdateInt(SettingType, i32),
|
||||||
|
SettingUpdated(SettingType),
|
||||||
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
OpenContextMenu(Vec2, Vec<context_menu::Cell>),
|
||||||
ClearPipewireTokens,
|
ClearPipewireTokens,
|
||||||
ClearSavedState,
|
ClearSavedState,
|
||||||
@@ -87,6 +88,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
self.set_tab(frontend, data, tab)?;
|
self.set_tab(frontend, data, tab)?;
|
||||||
}
|
}
|
||||||
Task::UpdateBool(setting, n) => {
|
Task::UpdateBool(setting, n) => {
|
||||||
|
self.tasks.push(Task::SettingUpdated(setting));
|
||||||
if let Some(task) = setting.get_frontend_task() {
|
if let Some(task) = setting.get_frontend_task() {
|
||||||
frontend.tasks.push(task)
|
frontend.tasks.push(task)
|
||||||
}
|
}
|
||||||
@@ -95,6 +97,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
Task::UpdateFloat(setting, n) => {
|
Task::UpdateFloat(setting, n) => {
|
||||||
|
self.tasks.push(Task::SettingUpdated(setting));
|
||||||
if let Some(task) = setting.get_frontend_task() {
|
if let Some(task) = setting.get_frontend_task() {
|
||||||
frontend.tasks.push(task)
|
frontend.tasks.push(task)
|
||||||
}
|
}
|
||||||
@@ -103,6 +106,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
Task::UpdateInt(setting, n) => {
|
Task::UpdateInt(setting, n) => {
|
||||||
|
self.tasks.push(Task::SettingUpdated(setting));
|
||||||
if let Some(task) = setting.get_frontend_task() {
|
if let Some(task) = setting.get_frontend_task() {
|
||||||
frontend.tasks.push(task)
|
frontend.tasks.push(task)
|
||||||
}
|
}
|
||||||
@@ -146,6 +150,12 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Task::SettingUpdated(setting) => match setting {
|
||||||
|
SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => {
|
||||||
|
frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig);
|
||||||
|
}
|
||||||
|
_ => { /* do nothing */ }
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +200,9 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
#[allow(clippy::enum_variant_names)]
|
#[allow(clippy::enum_variant_names)]
|
||||||
#[derive(Clone, Copy, AsRefStr, EnumString)]
|
#[derive(Clone, Copy, AsRefStr, EnumString)]
|
||||||
enum SettingType {
|
enum SettingType {
|
||||||
AnimationSpeed,
|
UiAnimationSpeed,
|
||||||
RoundMultiplier,
|
UiGradientIntensity,
|
||||||
|
UiRoundMultiplier,
|
||||||
InvertScrollDirectionX,
|
InvertScrollDirectionX,
|
||||||
InvertScrollDirectionY,
|
InvertScrollDirectionY,
|
||||||
ScrollSpeed,
|
ScrollSpeed,
|
||||||
@@ -259,8 +270,9 @@ impl SettingType {
|
|||||||
|
|
||||||
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
||||||
match self {
|
match self {
|
||||||
Self::AnimationSpeed => &mut config.animation_speed,
|
Self::UiAnimationSpeed => &mut config.ui_animation_speed,
|
||||||
Self::RoundMultiplier => &mut config.round_multiplier,
|
Self::UiGradientIntensity => &mut config.ui_gradient_intensity,
|
||||||
|
Self::UiRoundMultiplier => &mut config.ui_round_multiplier,
|
||||||
Self::ScrollSpeed => &mut config.scroll_speed,
|
Self::ScrollSpeed => &mut config.scroll_speed,
|
||||||
Self::LongPressDuration => &mut config.long_press_duration,
|
Self::LongPressDuration => &mut config.long_press_duration,
|
||||||
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
||||||
@@ -324,8 +336,9 @@ impl SettingType {
|
|||||||
/// Ok is translation, Err is raw text
|
/// Ok is translation, Err is raw text
|
||||||
fn get_translation(self) -> Result<&'static str, &'static str> {
|
fn get_translation(self) -> Result<&'static str, &'static str> {
|
||||||
match self {
|
match self {
|
||||||
Self::AnimationSpeed => Ok("APP_SETTINGS.ANIMATION_SPEED"),
|
Self::UiAnimationSpeed => Ok("APP_SETTINGS.ANIMATION_SPEED"),
|
||||||
Self::RoundMultiplier => Ok("APP_SETTINGS.ROUND_MULTIPLIER"),
|
Self::UiGradientIntensity => Ok("APP_SETTINGS.UI_GRADIENT_INTENSITY"),
|
||||||
|
Self::UiRoundMultiplier => Ok("APP_SETTINGS.ROUND_MULTIPLIER"),
|
||||||
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
|
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
|
||||||
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
|
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
|
||||||
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
||||||
@@ -385,8 +398,8 @@ impl SettingType {
|
|||||||
//TODO: incorporate this
|
//TODO: incorporate this
|
||||||
fn requires_restart(self) -> bool {
|
fn requires_restart(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::AnimationSpeed
|
Self::UiAnimationSpeed
|
||||||
| Self::RoundMultiplier
|
| Self::UiRoundMultiplier
|
||||||
| Self::UprightScreenFix
|
| Self::UprightScreenFix
|
||||||
| Self::DoubleCursorFix
|
| Self::DoubleCursorFix
|
||||||
| Self::UseSkybox
|
| Self::UseSkybox
|
||||||
@@ -692,8 +705,9 @@ impl<T> TabSettings<T> {
|
|||||||
checkbox!(mp, c, SettingType::OpaqueBackground);
|
checkbox!(mp, c, SettingType::OpaqueBackground);
|
||||||
checkbox!(mp, c, SettingType::HideUsername);
|
checkbox!(mp, c, SettingType::HideUsername);
|
||||||
checkbox!(mp, c, SettingType::HideGrabHelp);
|
checkbox!(mp, c, SettingType::HideGrabHelp);
|
||||||
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
slider_f32!(mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
||||||
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1);
|
slider_f32!(mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05); // min, max, step
|
||||||
|
slider_f32!(mp, c, SettingType::UiRoundMultiplier, 0.5, 5.0, 0.1);
|
||||||
checkbox!(mp, c, SettingType::SetsOnWatch);
|
checkbox!(mp, c, SettingType::SetsOnWatch);
|
||||||
checkbox!(mp, c, SettingType::UseSkybox);
|
checkbox!(mp, c, SettingType::UseSkybox);
|
||||||
checkbox!(mp, c, SettingType::UsePassthrough);
|
checkbox!(mp, c, SettingType::UsePassthrough);
|
||||||
|
|||||||
@@ -9,187 +9,181 @@ const template_name = process.env["TEMPLATE"] as string;
|
|||||||
let lang_path = process.env["LANG_PATH"] as string;
|
let lang_path = process.env["LANG_PATH"] as string;
|
||||||
|
|
||||||
if (model_name === undefined) {
|
if (model_name === undefined) {
|
||||||
console.log("MODEL not set");
|
console.log("MODEL not set");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template_name === undefined) {
|
if (template_name === undefined) {
|
||||||
console.log("TEMPLATE not set");
|
console.log("TEMPLATE not set");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lang_path === undefined) {
|
if (lang_path === undefined) {
|
||||||
console.log(
|
console.log(
|
||||||
`LANG_PATH is not set.
|
`LANG_PATH is not set.
|
||||||
Try one of these:
|
Try one of these:
|
||||||
LANG_PATH=../../uidev/assets/lang/ ./run.sh
|
LANG_PATH=../../uidev/assets/lang/ ./run.sh
|
||||||
LANG_PATH=../../dash-frontend/assets/lang/ ./run.sh
|
LANG_PATH=../../dash-frontend/assets/lang/ ./run.sh
|
||||||
LANG_PATH=../../wayvr/src/assets/lang/ ./run.sh`);
|
LANG_PATH=../../wayvr/src/assets/lang/ ./run.sh`);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lang_path = path.resolve(__dirname + "/" + lang_path);
|
lang_path = path.resolve(__dirname + "/" + lang_path);
|
||||||
if (lang_path === undefined || !fs.existsSync(lang_path)) {
|
if (lang_path === undefined || !fs.existsSync(lang_path)) {
|
||||||
console.log("Invalid or non-existent LANG_PATH");
|
console.log("Invalid or non-existent LANG_PATH");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const current_path = path.resolve(__dirname);
|
const current_path = path.resolve(__dirname);
|
||||||
const templates_path = path.resolve(__dirname + "/templates");
|
const templates_path = path.resolve(__dirname + "/templates");
|
||||||
|
|
||||||
async function loop_object(obj: any, initial_str: string, callback: (key: string, value: string) => Promise<void>) {
|
async function loop_object(obj: any, initial_str: string, callback: (key: string, value: string) => Promise<void>) {
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
let full_key = initial_str + key;
|
let full_key = initial_str + key;
|
||||||
if (typeof obj[key] === "object" && obj[key] !== null) {
|
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||||
await loop_object(obj[key], full_key + ".", callback)
|
await loop_object(obj[key], full_key + ".", callback)
|
||||||
} else if (obj.hasOwnProperty(key)) {
|
} else if (obj.hasOwnProperty(key)) {
|
||||||
await callback(full_key, obj[key])
|
await callback(full_key, obj[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract_backticks(str: string) {
|
function extract_backticks(str: string) {
|
||||||
const regex = /`([^`]+)`/g;
|
const regex = /`([^`]+)`/g;
|
||||||
return str.match(regex)?.map(match => match.slice(1, -1).trim());
|
return str.match(regex)?.map(match => match.slice(1, -1).trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_i18n_key(obj: any, key: string, value: string | undefined) {
|
function set_i18n_key(obj: any, key: string, value: string | undefined) {
|
||||||
const parts = key.split('.');
|
const parts = key.split('.');
|
||||||
let cur_level = obj;
|
let cur_level = obj;
|
||||||
for (let i = 0; i < parts.length - 1; i++) {
|
for (let i = 0; i < parts.length - 1; i++) {
|
||||||
const part = parts[i]!;
|
const part = parts[i]!;
|
||||||
if (!cur_level[part]) {
|
if (!cur_level[part]) {
|
||||||
cur_level[part] = {};
|
cur_level[part] = {};
|
||||||
}
|
}
|
||||||
cur_level = cur_level[part];
|
cur_level = cur_level[part];
|
||||||
}
|
}
|
||||||
cur_level[parts[parts.length - 1]!] = value;
|
cur_level[parts[parts.length - 1]!] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function key_exists(obj: any, key: string) {
|
function key_exists(obj: any, key: string) {
|
||||||
const parts = key.split('.');
|
const parts = key.split('.');
|
||||||
let level = obj;
|
let level = obj;
|
||||||
|
|
||||||
for (let i = 0; i < parts.length; i++) {
|
for (let i = 0; i < parts.length; i++) {
|
||||||
const part = parts[i]!;
|
const part = parts[i]!;
|
||||||
if (!level || !level[part]) {
|
if (!level || !level[part]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
level = level[part];
|
level = level[part];
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Example {
|
interface Example {
|
||||||
key: string;
|
key: string;
|
||||||
en: string;
|
en: string;
|
||||||
translated: string;
|
translated: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Template {
|
interface Template {
|
||||||
full_name: string; // "Polish"
|
full_name: string; // "Polish"
|
||||||
examples: Example[]
|
examples: Example[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function gen_prompt(description: string, template: Template, key: string, english_translation: string) {
|
function gen_prompt(description: string, template: Template, key: string, english_translation: string) {
|
||||||
let num = 1;
|
let num = 1;
|
||||||
for (const example of template.examples) {
|
for (const example of template.examples) {
|
||||||
description += "\nExample " + num + ":\n\n";
|
description += "\nExample " + num + ":\n\n";
|
||||||
description += "Translate key `" + example.key + "` from English to " + template.full_name + ":\n\n";
|
description += "Translate key `" + example.key + "` from English to " + template.full_name + ":\n\n";
|
||||||
description += "```\n";
|
description += "```\n";
|
||||||
description += example.en + "\n";
|
description += example.en + "\n";
|
||||||
description += "```\n\n";
|
description += "```\n\n";
|
||||||
description += "Result:\n\n";
|
description += "Result:\n\n";
|
||||||
description += "```\n";
|
description += "```\n";
|
||||||
description += example.translated + "\n";
|
description += example.translated + "\n";
|
||||||
description += "```\n";
|
description += "```\n";
|
||||||
num += 1;
|
num += 1;
|
||||||
}
|
}
|
||||||
description += "\nEnd of examples.\n\n";
|
description += "\nEnd of examples.\n\n";
|
||||||
description += "Translate key `" + key + "` from English to " + template.full_name + ":\n\n";
|
description += "Translate key `" + key + "` from English to " + template.full_name + ":\n\n";
|
||||||
description += "```\n";
|
description += "```\n";
|
||||||
description += english_translation + "\n";
|
description += english_translation + "\n";
|
||||||
description += "```\n";
|
description += "```\n";
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const template = JSON.parse(await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8")) as Template;
|
const template = JSON.parse(await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8")) as Template;
|
||||||
|
|
||||||
let description_txt = await fsp.readFile(current_path + "/description.txt", "utf-8");
|
let description_txt = await fsp.readFile(current_path + "/description.txt", "utf-8");
|
||||||
description_txt = description_txt.replaceAll("{TARGET_LANG}", template.full_name);
|
description_txt = description_txt.replaceAll("{TARGET_LANG}", template.full_name);
|
||||||
|
|
||||||
const orig_english_json = JSON.parse(await fsp.readFile(lang_path + "/en.json") as any);
|
const orig_english_json = JSON.parse(await fsp.readFile(lang_path + "/en.json") as any);
|
||||||
|
|
||||||
let orig_translated_json = {};
|
let orig_translated_json = {};
|
||||||
try {
|
try {
|
||||||
orig_translated_json = JSON.parse((await fsp.readFile(lang_path + "/" + template_name + ".json")).toString());
|
orig_translated_json = JSON.parse((await fsp.readFile(lang_path + "/" + template_name + ".json")).toString());
|
||||||
}
|
}
|
||||||
catch (_e) { }
|
catch (_e) { }
|
||||||
|
|
||||||
let llm_translated_json = {};
|
let llm_translated_json = {};
|
||||||
const translated_json_path = lang_path + "/" + template_name + ".json";
|
const translated_json_path = lang_path + "/" + template_name + ".json";
|
||||||
if (await fsp.exists(translated_json_path)) {
|
if (await fsp.exists(translated_json_path)) {
|
||||||
console.log("Loading file", translated_json_path);
|
console.log("Loading file", translated_json_path);
|
||||||
llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString());
|
llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
let human = 0;
|
let total_count = 0;
|
||||||
let llm = 0;
|
await loop_object(orig_english_json, "", async () => {
|
||||||
|
total_count += 1;
|
||||||
|
});
|
||||||
|
|
||||||
let total_count = 0;
|
await loop_object(llm_translated_json, "", async (key, _) => {
|
||||||
await loop_object(orig_english_json, "", async () => {
|
if (!key_exists(orig_english_json, key)) {
|
||||||
total_count += 1;
|
console.log("Removing key", key);
|
||||||
});
|
set_i18n_key(llm_translated_json, key, undefined);
|
||||||
|
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await loop_object(llm_translated_json, "", async (key, _) => {
|
await loop_object(orig_english_json, "", async (key, english_translation) => {
|
||||||
if (!key_exists(orig_english_json, key)) {
|
if (key_exists(orig_translated_json, key)) {
|
||||||
console.log("Removing key", key);
|
return;
|
||||||
set_i18n_key(llm_translated_json, key, undefined);
|
}
|
||||||
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await loop_object(orig_english_json, "", async (key, english_translation) => {
|
if (key_exists(llm_translated_json, key)) {
|
||||||
if (key_exists(orig_translated_json, key)) {
|
return;
|
||||||
human += 1;
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_exists(llm_translated_json, key)) {
|
console.log("Translating", key, "...");
|
||||||
llm += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Translating", key, "...");
|
const prompt = gen_prompt(description_txt, template, key, english_translation);
|
||||||
llm++;
|
|
||||||
|
|
||||||
const prompt = gen_prompt(description_txt, template, key, english_translation);
|
const response = await ollama.chat({
|
||||||
|
model: model_name,
|
||||||
|
messages: [{ role: "user", content: prompt }],
|
||||||
|
options: {
|
||||||
|
seed: 12345,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const response = await ollama.chat({
|
const msg = extract_backticks(response.message.content);
|
||||||
model: model_name,
|
if (msg === undefined || msg[0] === undefined) {
|
||||||
messages: [{ role: "user", content: prompt }],
|
throw new Error("backticks failed. Raw content: " + response.message.content);
|
||||||
options: {
|
}
|
||||||
seed: 12345,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const msg = extract_backticks(response.message.content);
|
console.log(" >>>", msg);
|
||||||
if (msg === undefined || msg[0] === undefined) {
|
|
||||||
throw new Error("backticks failed. Raw content: " + response.message.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(" >>>", msg);
|
set_i18n_key(llm_translated_json, key, msg[0]);
|
||||||
|
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
||||||
|
});
|
||||||
|
|
||||||
set_i18n_key(llm_translated_json, key, msg[0]);
|
console.log("Translation", template_name, "finished");
|
||||||
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("\"" + template_name + "\" translation finished,", human, "were already human translated,", llm, "llm-translated (" + Math.round((llm / total_count) * 100.0) + "% machine-translated)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch((e) => {
|
run().catch((e) => {
|
||||||
console.log("Fatal error:", e);
|
console.log("Fatal error:", e);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Do not run this script if you don’t have at least 32 GiB of system memory,
|
||||||
|
# unless you have enabled the mmap option in the Ollama startup settings.
|
||||||
|
# Submitting PRs that lack translated strings is okay if you don’t meet the
|
||||||
|
# system requirements to run this script, or if you simply prefer not to; we are
|
||||||
|
# regularly updating the missing translation strings anyway.
|
||||||
|
#
|
||||||
|
# Base language: English (en.json)
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
|||||||
@@ -104,8 +104,9 @@ pub fn load_general_config() -> GeneralConfig {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct AutoSettings {
|
pub struct AutoSettings {
|
||||||
pub animation_speed: f32,
|
pub ui_animation_speed: f32,
|
||||||
pub round_multiplier: f32,
|
pub ui_round_multiplier: f32,
|
||||||
|
pub ui_gradient_intensity: f32,
|
||||||
pub click_freeze_time_ms: i32,
|
pub click_freeze_time_ms: i32,
|
||||||
pub invert_scroll_direction_x: bool,
|
pub invert_scroll_direction_x: bool,
|
||||||
pub invert_scroll_direction_y: bool,
|
pub invert_scroll_direction_y: bool,
|
||||||
@@ -151,8 +152,9 @@ fn get_settings_path() -> PathBuf {
|
|||||||
|
|
||||||
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
||||||
let conf = AutoSettings {
|
let conf = AutoSettings {
|
||||||
animation_speed: config.animation_speed,
|
ui_animation_speed: config.ui_animation_speed,
|
||||||
round_multiplier: config.round_multiplier,
|
ui_round_multiplier: config.ui_round_multiplier,
|
||||||
|
ui_gradient_intensity: config.ui_gradient_intensity,
|
||||||
click_freeze_time_ms: config.click_freeze_time_ms,
|
click_freeze_time_ms: config.click_freeze_time_ms,
|
||||||
invert_scroll_direction_x: config.invert_scroll_direction_x,
|
invert_scroll_direction_x: config.invert_scroll_direction_x,
|
||||||
invert_scroll_direction_y: config.invert_scroll_direction_y,
|
invert_scroll_direction_y: config.invert_scroll_direction_y,
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
## Set whether notifications should be shown at all
|
## Set whether notifications should be shown at all
|
||||||
#notifications_enabled: true
|
#notifications_enabled: true
|
||||||
|
|
||||||
## Set whether notfications should make a sound
|
## Set whether notifications should make a sound
|
||||||
#notifications_sound_enabled: true
|
#notifications_sound_enabled: true
|
||||||
|
|
||||||
## Toggle keyboard click sound
|
## Toggle keyboard click sound
|
||||||
|
|||||||
@@ -128,8 +128,8 @@ impl AppState {
|
|||||||
apply_color(&mut defaults.bg_color, &session.config.color_background);
|
apply_color(&mut defaults.bg_color, &session.config.color_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults.animation_mult = 1. / session.config.animation_speed;
|
defaults.animation_mult = 1. / session.config.ui_animation_speed;
|
||||||
defaults.rounding_mult = session.config.round_multiplier;
|
defaults.rounding_mult = session.config.ui_round_multiplier;
|
||||||
|
|
||||||
let dbus = DbusConnector::default();
|
let dbus = DbusConnector::default();
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use slotmap::{DenseSlotMap, new_key_type};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
animation::{self, Animation},
|
animation::{self, Animation},
|
||||||
components::Component,
|
|
||||||
globals,
|
globals,
|
||||||
i18n::I18n,
|
i18n::I18n,
|
||||||
layout::{LayoutState, LayoutTask, WidgetID},
|
layout::{LayoutState, LayoutTask, WidgetID},
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets::AssetPath,
|
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
parser::{
|
parser::{
|
||||||
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,
|
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets::AssetPath,
|
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
parser::{
|
parser::{
|
||||||
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,
|
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,
|
||||||
|
|||||||
@@ -148,10 +148,15 @@ pub struct GeneralConfig {
|
|||||||
pub color_background: Option<String>,
|
pub color_background: Option<String>,
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
#[serde(default = "def_one")]
|
||||||
pub animation_speed: f32,
|
#[serde(alias = "ui_animation_speed", alias = "animation_speed" /* old name */)]
|
||||||
|
pub ui_animation_speed: f32,
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
#[serde(default = "def_one")]
|
||||||
pub round_multiplier: f32,
|
#[serde(alias = "ui_round_multiplier", alias = "round_multiplier" /* old name */)]
|
||||||
|
pub ui_round_multiplier: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_point3")]
|
||||||
|
pub ui_gradient_intensity: f32,
|
||||||
|
|
||||||
pub default_keymap: Option<String>,
|
pub default_keymap: Option<String>,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user