diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 5ea017f..ecdfefc 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -261,6 +261,12 @@ in { default = -1; }; + check_color = mkOption { + description = "The outer color of the input field while checking password"; + type = str; + default = "rgb(204, 136, 34)"; + }; + fail_color = mkOption { description = "If authentication failed, changes outer color and fail message color"; type = str; @@ -432,6 +438,7 @@ in { shadow_size = ${toString input-field.shadow_size} shadow_color = ${input-field.shadow_color} shadow_boost = ${toString input-field.shadow_boost} + check_color = ${input-field.check_color} fail_color = ${input-field.fail_color} fail_text = ${input-field.fail_text} fail_transition = ${toString input-field.fail_transition} diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 200a923..9e7d8ab 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -78,6 +78,7 @@ void CConfigManager::init() { m_config.addSpecialConfigValue("input-field", "placeholder_text", Hyprlang::STRING{"Input Password"}); m_config.addSpecialConfigValue("input-field", "hide_input", Hyprlang::INT{0}); m_config.addSpecialConfigValue("input-field", "rounding", Hyprlang::INT{-1}); + m_config.addSpecialConfigValue("input-field", "check_color", Hyprlang::INT{0xFFCC8822}); m_config.addSpecialConfigValue("input-field", "fail_color", Hyprlang::INT{0xFFCC2222}); m_config.addSpecialConfigValue("input-field", "fail_text", Hyprlang::STRING{"$FAIL"}); m_config.addSpecialConfigValue("input-field", "fail_transition", Hyprlang::INT{300}); @@ -168,6 +169,8 @@ std::vector CConfigManager::getWidgetConfigs() { {"placeholder_text", m_config.getSpecialConfigValue("input-field", "placeholder_text", k.c_str())}, {"hide_input", m_config.getSpecialConfigValue("input-field", "hide_input", k.c_str())}, {"rounding", m_config.getSpecialConfigValue("input-field", "rounding", k.c_str())}, + {"rounding", m_config.getSpecialConfigValue("input-field", "rounding", k.c_str())}, + {"check_color", m_config.getSpecialConfigValue("input-field", "check_color", k.c_str())}, {"fail_color", m_config.getSpecialConfigValue("input-field", "fail_color", k.c_str())}, {"fail_text", m_config.getSpecialConfigValue("input-field", "fail_text", k.c_str())}, {"fail_transition", m_config.getSpecialConfigValue("input-field", "fail_transition", k.c_str())}, diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index 995e4ae..c76d88b 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -20,6 +20,7 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u placeholder.failColor = std::any_cast(props.at("fail_color")); placeholder.failTransitionMs = std::any_cast(props.at("fail_transition")); configFailText = std::any_cast(props.at("fail_text")); + checkColor = std::any_cast(props.at("check_color")); viewport = viewport_; auto POS__ = std::any_cast(props.at("position")); @@ -113,10 +114,10 @@ void CPasswordInputField::updateFade() { else fade.a = std::clamp(1.0 - std::chrono::duration_cast(std::chrono::system_clock::now() - fade.start).count() / 100000.0, 0.0, 1.0); - if ((fade.appearing && fade.a == 1.0) || (!fade.appearing && fade.a == 0.0)) { + if ((fade.appearing && fade.a == 1.0) || (!fade.appearing && fade.a == 0.0)) fade.animated = false; - redrawShadow = true; - } + + redrawShadow = true; } } @@ -168,13 +169,25 @@ bool CPasswordInputField::draw(const SRenderData& data) { static auto ORIGSIZEX = size.x; static auto ORIGPOS = pos; + static auto TIMER = std::chrono::system_clock::now(); - if (placeholder.failAsset && placeholder.failAsset->texture.m_vSize.x > ORIGSIZEX) { - if (placeholder.failAsset->texture.m_vSize.x > size.x) - redrawShadow = true; + if (placeholder.failAsset) { + const auto TARGETSIZEX = placeholder.failAsset->texture.m_vSize.x + inputFieldBox.h; - size.x = placeholder.failAsset->texture.m_vSize.x + inputFieldBox.h; - pos = posFromHVAlign(viewport, size, configPos, halign, valign); + if (size.x < TARGETSIZEX) { + const auto DELTA = std::clamp((int)std::chrono::duration_cast(std::chrono::system_clock::now() - TIMER).count(), 1000, 20000); + TIMER = std::chrono::system_clock::now(); + forceReload = true; + + size.x += (TARGETSIZEX - ORIGSIZEX) * DELTA / 100000.0; + + if (size.x > TARGETSIZEX) { + size.x = TARGETSIZEX; + redrawShadow = true; + } + } + + pos = posFromHVAlign(viewport, size, configPos, halign, valign); } else { size.x = ORIGSIZEX; pos = ORIGPOS; @@ -283,12 +296,14 @@ bool CPasswordInputField::draw(const SRenderData& data) { } void CPasswordInputField::updateFailTex() { - const auto FAIL = g_pHyprlock->passwordLastFailReason(); + const auto FAIL = g_pHyprlock->passwordLastFailReason(); + const auto WAITING = g_pHyprlock->passwordCheckWaiting(); + const auto PASSLEN = g_pHyprlock->getPasswordBufferLen(); - if (g_pHyprlock->passwordCheckWaiting()) + if (WAITING) placeholder.canGetNewFail = true; - if (g_pHyprlock->getPasswordBufferLen() != 0) { + if (PASSLEN != 0 || (WAITING && PASSLEN == 0)) { if (placeholder.failAsset) { g_pRenderer->asyncResourceGatherer->unloadAsset(placeholder.failAsset); placeholder.failAsset = nullptr; @@ -350,31 +365,36 @@ void CPasswordInputField::updateOuter() { if (outThick == 0) return; - static auto OUTERCOL = outer; - static auto TIMER = std::chrono::system_clock::now(); - bool changeToOuter = placeholder.failID.empty(); + static auto OUTERCOL = outer, CHANGETO = OUTERCOL; + static auto TIMER = std::chrono::system_clock::now(); + const auto WAITING = g_pHyprlock->passwordCheckWaiting(); + bool emptyFail = placeholder.failID.empty(); outerAnimated = false; - if (changeToOuter) { - if (outer == OUTERCOL) + if (emptyFail) { + CHANGETO = WAITING ? checkColor : OUTERCOL; + + if (outer == CHANGETO) return; - if (outer == placeholder.failColor) + if (outer == placeholder.failColor || (outer == OUTERCOL && WAITING)) TIMER = std::chrono::system_clock::now(); - } else if (!changeToOuter) { - if (fade.animated || fade.a < 1.0) - changeToOuter = true; + } else if (!emptyFail) { + if (fade.animated || fade.a < 1.0) { + emptyFail = true; + CHANGETO = OUTERCOL; + } - if (outer == OUTERCOL) + if (outer == CHANGETO) TIMER = std::chrono::system_clock::now(); } const auto MULTI = std::clamp( std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - TIMER).count() / (double)placeholder.failTransitionMs, 0.001, 0.5); - const auto DELTA = changeToOuter ? OUTERCOL - placeholder.failColor : placeholder.failColor - OUTERCOL; - const auto TARGET = changeToOuter ? OUTERCOL : placeholder.failColor; - const auto SOURCE = changeToOuter ? placeholder.failColor : OUTERCOL; + const auto DELTA = emptyFail ? CHANGETO - (WAITING ? OUTERCOL : placeholder.failColor) : placeholder.failColor - CHANGETO; + const auto TARGET = emptyFail ? CHANGETO : placeholder.failColor; + const auto SOURCE = emptyFail ? (WAITING ? OUTERCOL : placeholder.failColor) : CHANGETO; if (outer.r != TARGET.r) { outer.r += DELTA.r * MULTI; diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index b6d16f1..62d1365 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -39,7 +39,7 @@ class CPasswordInputField : public IWidget { int outThick, rounding; - CColor inner, outer, font; + CColor inner, outer, font, checkColor; struct { float currentAmount = 0;