Add show/hide feature for passwords
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user