Add show/hide feature for passwords

This commit is contained in:
jpirnay
2026-04-12 23:16:47 +02:00
parent 714e389678
commit 32df69ea80
2 changed files with 71 additions and 21 deletions
+67 -20
View File
@@ -2,6 +2,8 @@
#include <I18n.h> #include <I18n.h>
#include <vector>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "components/UITheme.h" #include "components/UITheme.h"
#include "fontIds.h" #include "fontIds.h"
@@ -19,6 +21,8 @@ int KeyboardEntryActivity::getContentRowCount() const { return ABC_ROWS; }
int KeyboardEntryActivity::getTotalRowCount() const { return getContentRowCount() + 1; } int KeyboardEntryActivity::getTotalRowCount() const { return getContentRowCount() + 1; }
int KeyboardEntryActivity::getBottomKeyCount() const { return isPassword ? 6 : 5; }
bool KeyboardEntryActivity::isBottomRow(const int row) const { return row == getContentRowCount(); } bool KeyboardEntryActivity::isBottomRow(const int row) const { return row == getContentRowCount(); }
char KeyboardEntryActivity::getSelectedChar() const { char KeyboardEntryActivity::getSelectedChar() const {
@@ -54,9 +58,43 @@ bool KeyboardEntryActivity::insertChar(char c) {
return true; return true;
} }
SpecialKeyType KeyboardEntryActivity::getBottomSpecialKey(int index) const {
if (isPassword) {
switch (index) {
case 0:
return SpecShift;
case 1:
return SpecMode;
case 2:
return SpecReveal;
case 3:
return SpecSpace;
case 4:
return SpecDel;
case 5:
default:
return SpecOk;
}
}
switch (index) {
case 0:
return SpecShift;
case 1:
return SpecMode;
case 2:
return SpecSpace;
case 3:
return SpecDel;
case 4:
default:
return SpecOk;
}
}
bool KeyboardEntryActivity::handleKeyPress() { bool KeyboardEntryActivity::handleKeyPress() {
if (isBottomRow(selectedRow)) { if (isBottomRow(selectedRow)) {
switch (static_cast<SpecialKeyType>(selectedCol)) { switch (getBottomSpecialKey(selectedCol)) {
case SpecShift: case SpecShift:
if (symMode) return true; if (symMode) return true;
shiftState = (shiftState + 1) % 2; shiftState = (shiftState + 1) % 2;
@@ -66,12 +104,16 @@ bool KeyboardEntryActivity::handleKeyPress() {
int maxRow = getTotalRowCount() - 1; int maxRow = getTotalRowCount() - 1;
if (selectedRow > maxRow) selectedRow = maxRow; if (selectedRow > maxRow) selectedRow = maxRow;
if (isBottomRow(selectedRow)) { if (isBottomRow(selectedRow)) {
if (selectedCol >= BOTTOM_KEY_COUNT) selectedCol = BOTTOM_KEY_COUNT - 1; int bottomCount = getBottomKeyCount();
if (selectedCol >= bottomCount) selectedCol = bottomCount - 1;
} else { } else {
if (selectedCol >= COLS) selectedCol = COLS - 1; if (selectedCol >= COLS) selectedCol = COLS - 1;
} }
return true; return true;
} }
case SpecReveal:
passwordVisible = !passwordVisible;
return true;
case SpecSpace: case SpecSpace:
return insertChar(' '); return insertChar(' ');
case SpecDel: case SpecDel:
@@ -97,11 +139,11 @@ void KeyboardEntryActivity::loop() {
bool wasBottom = isBottomRow(selectedRow); bool wasBottom = isBottomRow(selectedRow);
selectedRow = ButtonNavigator::previousIndex(selectedRow, totalRows); selectedRow = ButtonNavigator::previousIndex(selectedRow, totalRows);
if (wasBottom && !isBottomRow(selectedRow)) { if (wasBottom && !isBottomRow(selectedRow)) {
selectedCol = selectedCol * 2; selectedCol = selectedCol * COLS / getBottomKeyCount();
} else if (!wasBottom && isBottomRow(selectedRow)) { } else if (!wasBottom && isBottomRow(selectedRow)) {
selectedCol = selectedCol / 2; selectedCol = selectedCol * getBottomKeyCount() / COLS;
} }
int maxCol = isBottomRow(selectedRow) ? BOTTOM_KEY_COUNT - 1 : COLS - 1; int maxCol = isBottomRow(selectedRow) ? getBottomKeyCount() - 1 : COLS - 1;
if (selectedCol > maxCol) selectedCol = maxCol; if (selectedCol > maxCol) selectedCol = maxCol;
requestUpdate(); requestUpdate();
}); });
@@ -110,23 +152,23 @@ void KeyboardEntryActivity::loop() {
bool wasBottom = isBottomRow(selectedRow); bool wasBottom = isBottomRow(selectedRow);
selectedRow = ButtonNavigator::nextIndex(selectedRow, totalRows); selectedRow = ButtonNavigator::nextIndex(selectedRow, totalRows);
if (wasBottom && !isBottomRow(selectedRow)) { if (wasBottom && !isBottomRow(selectedRow)) {
selectedCol = selectedCol * 2; selectedCol = selectedCol * COLS / getBottomKeyCount();
} else if (!wasBottom && isBottomRow(selectedRow)) { } else if (!wasBottom && isBottomRow(selectedRow)) {
selectedCol = selectedCol / 2; selectedCol = selectedCol * getBottomKeyCount() / COLS;
} }
int maxCol = isBottomRow(selectedRow) ? BOTTOM_KEY_COUNT - 1 : COLS - 1; int maxCol = isBottomRow(selectedRow) ? getBottomKeyCount() - 1 : COLS - 1;
if (selectedCol > maxCol) selectedCol = maxCol; if (selectedCol > maxCol) selectedCol = maxCol;
requestUpdate(); requestUpdate();
}); });
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Left}, [this] { buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Left}, [this] {
int maxCol = isBottomRow(selectedRow) ? BOTTOM_KEY_COUNT - 1 : COLS - 1; int maxCol = isBottomRow(selectedRow) ? getBottomKeyCount() - 1 : COLS - 1;
selectedCol = ButtonNavigator::previousIndex(selectedCol, maxCol + 1); selectedCol = ButtonNavigator::previousIndex(selectedCol, maxCol + 1);
requestUpdate(); requestUpdate();
}); });
buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Right}, [this] { buttonNavigator.onPressAndContinuous({MappedInputManager::Button::Right}, [this] {
int maxCol = isBottomRow(selectedRow) ? BOTTOM_KEY_COUNT - 1 : COLS - 1; int maxCol = isBottomRow(selectedRow) ? getBottomKeyCount() - 1 : COLS - 1;
selectedCol = ButtonNavigator::nextIndex(selectedCol, maxCol + 1); selectedCol = ButtonNavigator::nextIndex(selectedCol, maxCol + 1);
requestUpdate(); requestUpdate();
}); });
@@ -178,7 +220,7 @@ void KeyboardEntryActivity::render(RenderLock&&) {
int inputHeight = 0; int inputHeight = 0;
std::string displayText; std::string displayText;
if (isPassword) { if (isPassword && !passwordVisible) {
displayText = std::string(text.length(), '*'); displayText = std::string(text.length(), '*');
} else { } else {
displayText = text; displayText = text;
@@ -255,22 +297,27 @@ void KeyboardEntryActivity::render(RenderLock&&) {
const int bottomRowY = keyboardStartY + contentRows * (keyHeight + keySpacing) + bottomRowGap; const int bottomRowY = keyboardStartY + contentRows * (keyHeight + keySpacing) + bottomRowGap;
const int bkSpacing = metrics.keyboardBottomKeySpacing; const int bkSpacing = metrics.keyboardBottomKeySpacing;
const int contentTotalWidth = COLS * keyWidth + (COLS - 1) * keySpacing; const int contentTotalWidth = COLS * keyWidth + (COLS - 1) * keySpacing;
const int bottomKeyWidth = (contentTotalWidth - (BOTTOM_KEY_COUNT - 1) * bkSpacing) / BOTTOM_KEY_COUNT; const int bottomKeyCount = getBottomKeyCount();
const int bottomKeyWidth = (contentTotalWidth - (bottomKeyCount - 1) * bkSpacing) / bottomKeyCount;
const bool bottomSelected = isBottomRow(selectedRow); const bool bottomSelected = isBottomRow(selectedRow);
struct BottomKeyInfo { struct BottomKeyInfo {
KeyboardKeyType themeType; KeyboardKeyType themeType;
const char* label; const char* label;
}; };
const BottomKeyInfo bottomKeys[BOTTOM_KEY_COUNT] = {
{KeyboardKeyType::Shift, symMode ? shiftString[0] : shiftString[shiftState]},
{KeyboardKeyType::Mode, symMode ? "abc" : "#@!"},
{KeyboardKeyType::Space, nullptr},
{KeyboardKeyType::Del, nullptr},
{KeyboardKeyType::Ok, tr(STR_OK_BUTTON)},
};
for (int i = 0; i < BOTTOM_KEY_COUNT; i++) { std::vector<BottomKeyInfo> bottomKeys;
bottomKeys.reserve(6);
bottomKeys.push_back({KeyboardKeyType::Shift, symMode ? shiftString[0] : shiftString[shiftState]});
bottomKeys.push_back({KeyboardKeyType::Mode, symMode ? "abc" : "#@!"});
if (isPassword) {
bottomKeys.push_back({KeyboardKeyType::Normal, passwordVisible ? tr(STR_HIDE) : tr(STR_SHOW)});
}
bottomKeys.push_back({KeyboardKeyType::Space, nullptr});
bottomKeys.push_back({KeyboardKeyType::Del, nullptr});
bottomKeys.push_back({KeyboardKeyType::Ok, tr(STR_OK_BUTTON)});
for (int i = 0; i < bottomKeyCount; i++) {
const int keyX = leftMargin + i * (bottomKeyWidth + bkSpacing); const int keyX = leftMargin + i * (bottomKeyWidth + bkSpacing);
const bool isSelected = bottomSelected && i == selectedCol; const bool isSelected = bottomSelected && i == selectedCol;
+4 -1
View File
@@ -14,7 +14,7 @@ struct KeyDef {
char secondary; char secondary;
}; };
enum SpecialKeyType { SpecShift, SpecMode, SpecSpace, SpecDel, SpecOk }; enum SpecialKeyType { SpecShift, SpecMode, SpecReveal, SpecSpace, SpecDel, SpecOk };
class KeyboardEntryActivity : public Activity { class KeyboardEntryActivity : public Activity {
public: public:
@@ -37,6 +37,7 @@ class KeyboardEntryActivity : public Activity {
std::string text; std::string text;
size_t maxLength; size_t maxLength;
bool isPassword; bool isPassword;
bool passwordVisible = false;
ButtonNavigator buttonNavigator; ButtonNavigator buttonNavigator;
@@ -147,6 +148,8 @@ class KeyboardEntryActivity : public Activity {
int getContentRowCount() const; int getContentRowCount() const;
int getTotalRowCount() const; int getTotalRowCount() const;
int getBottomKeyCount() const;
SpecialKeyType getBottomSpecialKey(int index) const;
bool isBottomRow(int row) const; bool isBottomRow(int row) const;
char getSelectedChar() const; char getSelectedChar() const;
char getAlternativeChar() const; char getAlternativeChar() const;