dash-frontend: Random supporter on main screen, wgui: prevent unnecessary redraws

This commit is contained in:
Aleksander 2026-08-08 21:44:15 +02:00
parent c85d96c4d9
commit 2b5a94a429
18 changed files with 185 additions and 28 deletions

1
Cargo.lock generated
View File

@ -1406,6 +1406,7 @@ dependencies = [
"keyvalues-parser",
"log",
"lz4_flex",
"rand 0.10.2",
"rust-embed",
"serde",
"serde_json",

View File

@ -27,6 +27,7 @@ xdg.workspace = true
keyvalues-parser = "0.2.4"
lz4_flex = { version = "0.13.1", features = ["frame"] }
ureq = "3.3.0"
rand = "0.10.2"
[features]
default = ["monado"]

View File

@ -34,7 +34,7 @@
<div macro="half">
<sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="48" min_height="48"/>
<div gap="16" align_items="center" width="100%">
<label align="justified" wrap="1" size="18" translation="DONATE.DESCRIPTION" color="on_background"/>
<label align="justified" wrap="1" size="15" translation="DONATE.DESCRIPTION" color="on_background"/>
</div>
<div flex_direction="column" gap="8" align_items="center">

View File

@ -7,12 +7,17 @@
justify_content="center"
align_items="center"
flex_grow="1"
gap="24">
gap="8"
>
<image src_builtin="dashboard/splash.png" width="300" height="89" />
<label id="label_hello" size="32" weight="bold" color="on_background" />
<!-- supporters -->
<Button id="btn_supporter" width="fit_content" height="24" text=" " border="0" color="background_variant(transparent)"/>
<label id="label_hello" margin_top="24" size="32" weight="bold" color="on_background" />
<!-- main button list -->
<div flex_direction="row" gap="8">
<div flex_direction="row" gap="8" margin_top="32">
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "Wir sind ein kleines Team aus 2 Entwicklern, die WayVR in ihrer Freizeit bauen. Wenn dir die Software gefällt, unterstütze uns bitte jede Spende hilft uns dabei, weiterzumachen.",
"THANK_YOU_WAYVR": "Danke vom WayVR-Team!",
"BUTTON_TOOLTIP": "Via Open Collective spenden",
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer"
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Unterstützt durch {USER}|Besonderer Dank an {USER}|Gesponsert von {USER}|Gefördert durch {USER}|Angetrieben durch Community-Mitglieder wie {USER}|Möglich gemacht durch {USER}|Aufrechterhalten durch {USER}|Beigesteuert von {USER}|Finanziert durch {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kaffee gesponsert von {USER}|Angetrieben durch {USER}|Ein Shoutout an {USER}!|Hält uns am Laufen: {USER}|Hilft uns zu wachsen: {USER}|Hält die Server am Laufen: {USER}|Mit Dank an {USER}|Powered by {USER}|Unterstützt durch Freunde wie {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Unterstützt von Legenden wie {USER}|Koffein geliefert von {USER}|Eine wahre Legende: {USER}|Unser Held des Tages: {USER}|Ein absoluter Superstar: {USER}|Bezahlt die Stromrechnung: {USER}|Der Retter unseres Verstands: {USER}|Mentale Stabilität gesponsert von: {USER}|Koffein-zu-Code-Konverter bereitgestellt von {USER}|Hält die Produktion stabil: {USER}|Der Einzigartige: {USER}|Reicht dmabuf-Buffer weiter: {USER}"
},
"DOWNLOAD": "Herunterladen",
"DOWNLOADER": "Downloader",

View File

@ -272,6 +272,9 @@ DONATE.DESCRIPTION,"We're a small team of 2 developers building WayVR in our fre
DONATE.THANK_YOU_WAYVR,Thank you from the WayVR Team!,Thank you message displayed on the donate tab.
DONATE.BUTTON_TOOLTIP,Donate via Open Collective,Tooltip on the donate button on the donate tab.
DONATE.CURRENT_SUPPORTERS,Current Supporters,Section header on the donate tab listing supporters.
DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN,Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it.
DONATE.BROUGHT_TO_YOU_VARIANTS_RARE,Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE,Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|The savior of our sanity: {USER}|Mental stability sponsored by: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
DOWNLOAD,Download,Button in the Whisper model download dialog to confirm downloading a model.
DOWNLOADER,Downloader,Window title for the file download popup.
WELCOME.ALL_SET,You're all set!,Main heading on the final welcome/tutorial page.

1 DEFINITIONS.ANCHORED Anchored A movement option that makes this window move together with the rest of the workspace. Emphasize the "moving together" part as opposed to "not moving at all".
272 FAILED_TO_LAUNCH_APPLICATION WELCOME.WORKING_SET Failed to launch a application: Working Set Error prefix in the toast shown when app launch fails. Page title on the working set tutorial page. "Set" was previously translated as "${DEFINITIONS.SET}". Working as in "Current".
273 GAME_LAUNCHED DOWNLOAD_AGAIN Game launched Download again Toast notification shown after successfully launching a game via Steam. Button in the skymap already downloaded dialog to re-download a skymap.
274 GAME_LIST.NO_GAMES_FOUND DOWNLOADING_FILE No games found Downloading file... Empty state text shown in the game list when no games are installed. Status label in the download file popup showing download progress.
275 FAILED_TO_LAUNCH_APPLICATION Failed to launch a application: Error prefix in the toast shown when app launch fails.
276 GAME_LAUNCHED Game launched Toast notification shown after successfully launching a game via Steam.
277 GAME_LIST.NO_GAMES_FOUND No games found Empty state text shown in the game list when no games are installed.
278 GAME_LIST.RUNNING_GAMES_LIST List of running games Section label in the running games list view.
279 GAMES Games Tab label in the dashboard sidebar for the Games tab.
280 GENERAL_SETTINGS General settings Tab name and group box title in the Monado runtime settings.

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",
"THANK_YOU_WAYVR": "Thank you from the WayVR Team!",
"BUTTON_TOOLTIP": "Donate via Open Collective",
"CURRENT_SUPPORTERS": "Current Supporters"
"CURRENT_SUPPORTERS": "Current Supporters",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|The savior of our sanity: {USER}|Mental stability sponsored by: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER}"
},
"DOWNLOAD": "Download",
"DOWNLOADER": "Downloader",

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "Somos un pequeño equipo de 2 desarrolladores creando WayVR en nuestro tiempo libre. Si disfrutas usando este software, considera apoyarnos; cada donación nos ayuda a seguir adelante.",
"THANK_YOU_WAYVR": "¡Gracias del equipo de WayVR!",
"BUTTON_TOOLTIP": "Dona a través de Open Collective",
"CURRENT_SUPPORTERS": "Colaboradores actuales"
"CURRENT_SUPPORTERS": "Colaboradores actuales",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Apoyado por {USER}|Agradecimiento especial a {USER}|Patrocinado por {USER}|Respaldado por {USER}|Impulsado por miembros de la comunidad como {USER}|Posible gracias a {USER}|Sostenido por {USER}|Contribuido por {USER}|Financiado por {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Café cortesía de {USER}|Impulsado por {USER}|¡Un saludo a {USER}!|Manteniéndonos en marcha: {USER}|Ayudándonos a crecer: {USER}|Manteniendo los servidores activos: {USER}|Con gratitud a {USER}|Potenciado por {USER}|Apoyado por amigos como {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Apoyado por leyendas como {USER}|Cafeína suministrada por {USER}|Una auténtica leyenda: {USER}|Nuestro héroe del día: {USER}|Una superestrella absoluta: {USER}|Pagando la factura de la luz: {USER}|El salvador de nuestra cordura: {USER}|Estabilidad mental patrocinada por: {USER}|Convertidor de cafeína a código proporcionado por {USER}|Manteniendo la producción estable: {USER}|El único e inigualable: {USER}|Pasando buffers dmabuf: {USER}"
},
"DOWNLOAD": "Descargar",
"DOWNLOADER": "Descargador",

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "Siamo un piccolo team di 2 sviluppatori che realizza WayVR nel tempo libero. Se ti piace usare questo software, considera di supportarci: ogni donazione ci aiuta a continuare.",
"THANK_YOU_WAYVR": "Grazie dal team di WayVR!",
"BUTTON_TOOLTIP": "Donazione tramite Open Collective",
"CURRENT_SUPPORTERS": "Supporter attuali"
"CURRENT_SUPPORTERS": "Supporter attuali",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supportato da {USER}|Speciale ringraziamento a {USER}|Sponsorizzato da {USER}|Sostenuto da {USER}|Grazie ai membri della community come {USER}|Reso possibile da {USER}|Mantenuto da {USER}|Contribuito da {USER}|Finanziato da {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Caffè offerto da {USER}|Alimentato da {USER}|Un saluto a {USER}!|Ci tiene in moto: {USER}|Ci aiuta a crescere: {USER}|Mantiene attivi i server: {USER}|Con gratitudine verso {USER}|Powered by {USER}|Supportato da amici come {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supportato da leggende come {USER}|Caffeina fornita da {USER}|Una vera leggenda: {USER}|Il nostro eroe del giorno: {USER}|Una superstar assoluta: {USER}|Sta pagando la bolletta della luce: {USER}|Il salvatore della nostra sanità mentale: {USER}|Stabilità mentale sponsorizzata da: {USER}|Convertitore caffeina-codice fornito da {USER}|Mantenendo la produzione stabile: {USER}|L'unico e inimitabile: {USER}|Passa buffer dmabuf: {USER}"
},
"DOWNLOAD": "Scarica",
"DOWNLOADER": "Download",

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "WayVRは、2人の開発者が空き時間を利用して作っている小規模なプロジェクトです。もしこのソフトを気に入っていただけたら、ぜひサポートをお願いします。皆様の寄付が開発の大きな励みになります。",
"THANK_YOU_WAYVR": "WayVRチームより、感謝を込めて",
"BUTTON_TOOLTIP": "Open Collectiveで寄付する",
"CURRENT_SUPPORTERS": "現在のサポーター"
"CURRENT_SUPPORTERS": "現在のサポーター",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "{USER} の支援を受けています|{USER} に特別な感謝を|{USER} のスポンサーシップにより|{USER} のバックアップにより|{USER} などのコミュニティメンバーによって推進|{USER} の協力により実現|{USER} の支援により継続|{USER} の寄付により|{USER} の資金提供により",
"BROUGHT_TO_YOU_VARIANTS_RARE": "{USER}が提供してくれたコーヒー|{USER}のエネルギーを注入!|{USER}に感謝!|活動を支えてくれているのは: {USER}|成長を助けてくれているのは: {USER}|サーバーを維持してくれているのは: {USER}|{USER}に感謝を込めて|Powered by {USER}|{USER}のような友人たちの支援により",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "{USER}のような伝説的存在が支援してくれました|{USER}がカフェインを供給|真の伝説:{USER}|今日のヒーロー:{USER}|超スーパースター:{USER}|電気代を負担:{USER}|精神の安定を守る救世主:{USER}|心の平穏のスポンサー:{USER}|{USER}提供のカフェイン・コード変換機|安定した稼働を支える:{USER}|唯一無二の存在:{USER}|dmabufバッファをパス{USER}"
},
"DOWNLOAD": "ダウンロード",
"DOWNLOADER": "ダウンローダー",

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "Jesteśmy małym zespołem dwóch programistów, którzy tworzą WayVR w wolnym czasie. Jeśli lubisz korzystać z tego programu, rozważ wsparcie nas finansowo każda darowizna pomaga nam działać dalej.",
"THANK_YOU_WAYVR": "Dzięki od zespołu WayVR!",
"BUTTON_TOOLTIP": "Wesprzyj projekt przez Open Collective",
"CURRENT_SUPPORTERS": "Obecni darczyńcy"
"CURRENT_SUPPORTERS": "Obecni darczyńcy",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Wspierane przez {USER}|Specjalne podziękowania dla {USER}|Sponsorowane przez {USER}|Wspierane przez {USER}|Napędzane przez członków społeczności, takich jak {USER}|Umożliwione przez {USER}|Utrzymywane przez {USER}|Wniesiony wkład: {USER}|Sfinansowane przez {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kawa od {USER}|Napędza nas {USER}|Pozdrowienia dla {USER}!|Utrzymuje nas przy życiu: {USER}|Pomaga nam rosnąć: {USER}|Utrzymuje serwery: {USER}|Z wdzięcznością dla {USER}|Napędzane przez {USER}|Wspierane przez przyjaciół takich jak {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Wspierane przez legendy, takie jak {USER}|Kofeina dostarczona przez {USER}|Prawdziwa legenda: {USER}|Nasz dzisiejszy bohater: {USER}|Absolutna gwiazda: {USER}|Opłacanie rachunków za prąd: {USER}|Zbawca naszego zdrowia psychicznego: {USER}|Stabilność psychiczna sponsorowana przez: {USER}|Konwerter kofeiny na kod dostarczony przez {USER}|Dbanie o stabilność produkcji: {USER}|Jedyny i niepowtarzalny: {USER}|Przekazywanie buforów dmabuf: {USER}"
},
"DOWNLOAD": "Pobierz",
"DOWNLOADER": "Menedżer pobierania",
@ -343,4 +346,4 @@
"ADD_TO_FAVOURITES_HINT": "Zapisz preset i przypnij go do szuflady aplikacji",
"REMOVE_FROM_FAVOURITES": "Usuń z przypiętych aplikacji",
"EMPTY": "Puste"
}
}

View File

@ -271,7 +271,10 @@
"DESCRIPTION": "我们是由两名开发者组成的小团队,在业余时间构建 WayVR。如果你喜欢这款软件请考虑支持我们 —— 每一份捐赠都能帮助我们坚持下去。",
"THANK_YOU_WAYVR": "WayVR 团队向您致谢!",
"BUTTON_TOOLTIP": "通过 Open Collective 捐赠",
"CURRENT_SUPPORTERS": "当前支持者"
"CURRENT_SUPPORTERS": "当前支持者",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "由 {USER} 提供支持|特别感谢 {USER}|由 {USER} 赞助|由 {USER} 提供后援|由社区成员 {USER} 等驱动|由 {USER} 助力实现|由 {USER} 维持运行|由 {USER} 贡献|由 {USER} 资助",
"BROUGHT_TO_YOU_VARIANTS_RARE": "咖啡由 {USER} 提供|由 {USER} 提供动力|感谢 {USER}!|让我们可以持续下去的人: {USER}|帮助我们成长的人: {USER}|维持服务器运行的人: {USER}|诚挚感谢 {USER}|由 {USER} 提供支持|得到了像 {USER} 这样的朋友的支持",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "由传奇人物支持:{USER}|由 {USER} 提供咖啡因|真正的传奇:{USER}|今日英雄:{USER}|绝对的超级巨星:{USER}|在付电费:{USER}|我们精神状态的救星:{USER}|精神稳定性由 {USER} 赞助|由 {USER} 提供咖啡因转代码服务|维持生产稳定:{USER}|独一无二的:{USER}|正在传递 dmabuf 缓冲区:{USER}"
},
"DOWNLOAD": "下载",
"DOWNLOADER": "下载管理器",

View File

@ -1,11 +1,13 @@
use std::marker::PhantomData;
use std::{marker::PhantomData, rc::Rc};
use wgui::{
animation::{Animation, AnimationEasing},
assets::AssetPath,
components::button::ComponentButton,
color::{WguiColor, WguiColorName, WguiNamedColor},
components::{ComponentTrait, button::ComponentButton},
event::CallbackDataCommon,
i18n::Translation,
layout::{Widget, WidgetID},
layout::{LayoutTask, LayoutTasks, Widget, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState},
widget::label::WidgetLabel,
};
@ -14,6 +16,7 @@ use wlx_common::config::GeneralConfig;
use crate::{
frontend::{Frontend, FrontendTask},
tab::{Tab, TabType},
util::cached_fetcher,
various,
};
@ -29,6 +32,88 @@ impl<T> Tab<T> for TabHome<T> {
}
}
fn get_supporter_anim(
btn: Rc<ComponentButton>,
tasks: LayoutTasks,
supporters: Rc<cached_fetcher::Supporters>,
prev_supporter_name: String,
) -> Animation {
let username = loop {
let random_supporter = &supporters.supporters[rand::random_range(0..supporters.supporters.len() - 1)];
let username = random_supporter.username.clone();
if username != prev_supporter_name {
break username;
}
};
const FADE_SPEED: f32 = 10.0;
Animation::new_ex(
btn.base().get_id(),
1234,
480,
AnimationEasing::Linear,
Box::new(move |common, data| {
let opacity_in = f32::clamp(data.pos * FADE_SPEED, 0.0, 1.0);
let opacity_out = f32::clamp((1.0 - data.pos) * FADE_SPEED, 0.0, 1.0);
let opacity = f32::min(opacity_in, opacity_out);
btn.set_text_color(
common,
WguiColor::Named(WguiNamedColor::with_alpha(WguiColorName::OnPrimary, opacity)),
);
// first iter
if data.pos == 0.0 {
let translation_key = match rand::random::<u8>() {
0..=15 => "DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE",
16..=70 => "DONATE.BROUGHT_TO_YOU_VARIANTS_RARE",
71..=u8::MAX => "DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN",
};
let translated = common.globals().i18n_builtin.translate(translation_key);
let variants = translated.split('|').collect::<Vec<&str>>();
let variant = variants[rand::random_range(0..variants.len() - 1)];
btn.set_text(
common,
Translation::from_raw_text_string(variant.replace("{USER}", &username)),
);
}
// last iter
if data.pos == 1.0 {
// infinitely looped animation, re-trigger it.
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
btn.clone(),
tasks.clone(),
supporters.clone(),
username.clone(), /* prev supporter name */
)))
}
}),
)
}
async fn config_supporters(btn: Rc<ComponentButton>, tasks: LayoutTasks) {
let Some(supporters) = cached_fetcher::request_supporters().await else {
return;
};
if supporters.supporters.len() <= 2 {
return; // Welp.
}
let supporters = Rc::new(supporters);
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
btn,
tasks.clone(),
supporters,
String::new(),
)));
}
fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, config: &GeneralConfig) {
let username = wlx_common::locale::capitalize_string(&various::get_username());
@ -61,6 +146,8 @@ impl<T> TabHome<T> {
frontend.interface.general_config(data),
);
let btn_supporter = state.fetch_component_as::<ComponentButton>("btn_supporter")?;
let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?;
let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?;
let btn_monado = state.fetch_component_as::<ComponentButton>("btn_monado")?;
@ -69,14 +156,20 @@ impl<T> TabHome<T> {
let btn_donate = state.fetch_component_as::<ComponentButton>("btn_donate")?;
let btn_website = state.fetch_component_as::<ComponentButton>("btn_website")?;
let tasks = &mut frontend.tasks;
tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps));
tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games));
tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado));
tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings));
tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome));
tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate));
tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into()));
let f_tasks = &mut frontend.tasks;
f_tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps));
f_tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games));
f_tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado));
f_tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings));
f_tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome));
f_tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate));
f_tasks.handle_button(&btn_supporter, FrontendTask::SetTab(TabType::Donate));
f_tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into()));
frontend
.executor
.spawn(config_supporters(btn_supporter, frontend.layout.tasks.clone()))
.detach();
Ok(Self {
state,

View File

@ -3,7 +3,7 @@ use strum::{EnumCount, EnumString};
// Primary: button color
// OnPrimary: text color placed on the Primary-colored button
#[derive(Debug, Copy, Clone, EnumCount, EnumString)]
#[derive(Debug, Copy, Clone, PartialEq, EnumCount, EnumString)]
#[repr(usize)]
#[strum(serialize_all = "snake_case")]
pub enum WguiColorName {
@ -26,7 +26,7 @@ pub enum WguiColorName {
Highlight,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct WguiNamedColor {
name: WguiColorName,
rgb_multiplier: f32,
@ -43,7 +43,7 @@ pub enum ParentColor {
Ignore,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum WguiColor {
Raw(drawing::Color),
Named(WguiNamedColor),
@ -203,6 +203,15 @@ impl Default for WguiColor {
}
impl WguiNamedColor {
pub const fn with_alpha(name: WguiColorName, alpha: f32) -> WguiNamedColor {
WguiNamedColor {
name,
rgb_multiplier: 1.0,
rgb_addition: 0.0,
alpha,
}
}
pub fn resolve(&self, palette: &WguiColorPalette) -> drawing::Color {
let mut color = palette[self.name];
if self.alpha != 1.0 {

View File

@ -211,6 +211,14 @@ impl ComponentButton {
label.set_text(common, text);
}
pub fn set_text_color(&self, common: &mut CallbackDataCommon, color: WguiColor) {
let state = self.state.borrow();
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(state.id_label) else {
return;
};
label.set_color(common, color, true);
}
pub fn set_color(&self, common: &mut CallbackDataCommon, color: WguiColor) {
let gradient_intensity = common.state.theme.gradient_intensity;

View File

@ -6,7 +6,7 @@ use std::{
};
use crate::{
animation::Animations,
animation::{Animation, Animations},
components::{self, Component, ComponentWeak, DestroyData, FocusChangeData, RefreshData},
drawing::{
self, ANSI_BOLD_CODE, ANSI_RESET_CODE, Boundary, PushScissorStackResult, push_scissor_stack, push_transform_stack,
@ -153,6 +153,7 @@ pub enum LayoutTask {
SetWidgetVisible(WidgetID, bool), // if true, sets Display to Flex; None, otherwise
ModifyLayoutState(LayoutModifyStateFunc),
PlaySound(WguiSoundType),
PlayAnimation(Animation),
Dispatch(LayoutDispatchFunc),
SetFocus(ComponentWeak),
RefreshPalette,
@ -653,7 +654,10 @@ impl Layout {
}
}
fn try_recompute_layout(&mut self, size: Vec2) -> anyhow::Result<()> {
fn try_recompute_layout(&mut self, mut size: Vec2) -> anyhow::Result<()> {
size.x = size.x.round();
size.y = size.y.round();
if !self.state.tree.dirty(self.tree_root_node)? && self.prev_size == size {
// Nothing to do
return Ok(());
@ -749,6 +753,9 @@ impl Layout {
let mut tasks = self.tasks.drain();
while let Some(task) = tasks.pop_front() {
match task {
LayoutTask::PlayAnimation(animation) => {
self.animations.add(animation);
}
LayoutTask::RefreshPalette => {
let root = self.tree_root_widget;
LayoutState::refresh_palette_recur(&mut self.common(), root);

View File

@ -122,6 +122,12 @@ impl WidgetLabel {
}
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor, apply_to_existing_text: bool) {
if let Some(current_color) = &self.params.style.color
&& *current_color == color
{
// not changed
return;
}
self.params.style.color = Some(color);
if apply_to_existing_text {
self.update_attrs(&common.globals().palette);

View File

@ -440,12 +440,15 @@ impl WidgetState {
&& (scrolling_cur.y - scrolling_target.y).abs() < epsilon
{
*scrolling_cur = *scrolling_target;
perform_next_tick = false;
}
}
if perform_next_tick {
alterables.mark_tick(this_widget_id);
alterables.mark_redraw();
} else {
self.data.scrolling_cur_prev = self.data.scrolling_cur;
}
}