Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Krux now displays a warning instead of blocking QR-encoded passphrases that cont
### Easier to Scan UR QR Codes
Exported Uniform Resource (UR) QR codes, a widely adopted standard for exchanging PSBTs, now use uppercase data to reduce QR density, improving scan reliability without increasing the number of frames.

### Battery Percentage Indicator
Battery level is now displayed as a percentage (configurable in settings). The on-screen value updates automatically.

### Other Bug Fixes and Improvements
- Settings: Reduced default _Buttons Debounce_ value (with an even lower default on _M5StickV_)
- Settings: Expanded value ranges for _Touch Threshold_ and _Buttons Debounce_
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Mnemonik-Backup",
"Bad signature": "Ungültige Signatur",
"Base64 Password": "Base64-Passwort",
"Battery": "Batterie",
"Baudrate": "Baudrate",
"Binary Grid": "Binäres Gitter",
"Border Padding": "Randpolsterung",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Passwortlänge",
"Path mismatch": "Pfad stimmt nicht überein",
"Pattern detected!": "Muster erkannt!",
"Percentage": "Prozentsatz",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Alle gespeicherten verschlüsselten Mnemoniken und Einstellungen dauerhaft vom Flash-Speicher entfernen?",
"Persist": "Speicher",
"Pixels deviation index:": "Pixelabweichungsindex:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/es-MX.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Backup del Mnemónico",
"Bad signature": "Firma incorrecta",
"Base64 Password": "Contraseña Base64",
"Battery": "Batería",
"Baudrate": "Baudrate",
"Binary Grid": "Cuadrícula binaria",
"Border Padding": "Grosor del Borde",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Longitud",
"Path mismatch": "La ruta no coincide",
"Pattern detected!": "¡Patrón detectado!",
"Percentage": "Porcentaje",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "¿Eliminar permanentemente todos los mnemónicos y configuraciones cifradas almacenadas del flash?",
"Persist": "Guardar",
"Pixels deviation index:": "Índice de desviación de píxeles:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Sauvegarde mnémonique",
"Bad signature": "Signature non valide",
"Base64 Password": "Mot de passe Base64",
"Battery": "Batterie",
"Baudrate": "Débit en bauds",
"Binary Grid": "Grille binaire",
"Border Padding": "Rembourrage de bordure",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Longueur du mot de passe",
"Path mismatch": "Inadéquation du chemin",
"Pattern detected!": "Motif détecté !",
"Percentage": "Pourcentage",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Supprimer définitivement tous les mnémoniques et paramètres chiffrés stockés dans le flash ?",
"Persist": "Persistance",
"Pixels deviation index:": "Indice de déviation des pixels :",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "ニーモニックのバックアップ",
"Bad signature": "無効なサイン",
"Base64 Password": "Base64パスワード",
"Battery": "バッテリー",
"Baudrate": "Baudrate",
"Binary Grid": "バイナリグリッド",
"Border Padding": "ボーダーパディング",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "パスワードの長さ",
"Path mismatch": "パスの不一致",
"Pattern detected!": "パターンが検出されました!",
"Percentage": "パーセンテージ",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "フラッシュからすべての保存された暗号化mnemonicsと設定を永久に削除しますか?",
"Persist": "永続させる",
"Pixels deviation index:": "ピクセル偏差指数:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/ko-KR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "니모닉 백업",
"Bad signature": "잘못된 서명",
"Base64 Password": "Base64 비밀번호",
"Battery": "배터리",
"Baudrate": "Baudrate",
"Binary Grid": "이진수 그리드",
"Border Padding": "테두리 여백",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "비밀번호 길이",
"Path mismatch": "경로 불일치",
"Pattern detected!": "패턴이 감지되었습니다!",
"Percentage": "백분율",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "저장된 모든 니모닉 및 설정값을 영구적으로 제거하시겠습니까?",
"Persist": "저장",
"Pixels deviation index:": "픽셀 편차 지수:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/nl-NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Backup geheugensteun",
"Bad signature": "Ongeldige handtekening",
"Base64 Password": "Base64-wachtwoord",
"Battery": "Batterij",
"Baudrate": "Baudratio",
"Binary Grid": "Binair raster",
"Border Padding": "Rand opvulling",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Wachtwoordlengte",
"Path mismatch": "Pad komt niet overeen",
"Pattern detected!": "Patroon gevonden!",
"Percentage": "Percentage",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Alle opgeslagen versleutelde mnemonics en instellingen permanent uit het flashgeheugen verwijderen?",
"Persist": "Opslag",
"Pixels deviation index:": "Pixelafwijkingsindex:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Mnemônico Backup",
"Bad signature": "Assinatura inválida",
"Base64 Password": "Senha em Base64",
"Battery": "Bateria",
"Baudrate": "Baudrate",
"Binary Grid": "Grade binária",
"Border Padding": "Espaçamento da borda",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Comprimento da Senha",
"Path mismatch": "Incompatibilidade de caminho",
"Pattern detected!": "Padrão detectado!",
"Percentage": "Percentual",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Remover permanentemente todos os mnemônicos criptografados e configurações armazenados na memória flash?",
"Persist": "Salvar",
"Pixels deviation index:": "Índice de desvio de pixels:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/ru-RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Резервная мнемоника",
"Bad signature": "Плохая подпись",
"Base64 Password": "Пароль Base64",
"Battery": "Аккумулятор",
"Baudrate": "Скорость Передачи Данных",
"Binary Grid": "Двоичная сетка",
"Border Padding": "Заполнение Границ",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Длина пароля",
"Path mismatch": "Несоответствие пути",
"Pattern detected!": "Образец обнаружен!",
"Percentage": "Процент",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Окончательно удалить все сохраненные зашифрованные мнемоники и настройки из флеш-памяти?",
"Persist": "Постоянная Память",
"Pixels deviation index:": "Индекс отклонения пикселей:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/tr-TR.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Yedek Mnemonic",
"Bad signature": "Geçersiz imza",
"Base64 Password": "Base64 Parola",
"Battery": "Pil",
"Baudrate": "Baud Hızı",
"Binary Grid": "İkili Izgara",
"Border Padding": "Kenarlık Dolgusu",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Parola Uzunluğu",
"Path mismatch": "Yol uyuşmazlığı",
"Pattern detected!": "Örüntü algılandı!",
"Percentage": "Yüzde",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Tüm depolanmış ve şifrelenmiş mnemonic'ler ve ayarlar flash'tan kalıcı olarak kaldırılsın mı?",
"Persist": "Kalıcı Depolama",
"Pixels deviation index:": "Piksel sapma indeksi:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/vi-VN.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "Sao lưu Mnemonic",
"Bad signature": "Chữ ký xấu",
"Base64 Password": "Mật khẩu Base64",
"Battery": "Pin",
"Baudrate": "Tốc độ baud",
"Binary Grid": "Lưới nhị phân",
"Border Padding": "Đệm viền",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "Độ dài mật khẩu tối thiểu",
"Path mismatch": "Đường dẫn không khớp",
"Pattern detected!": "Đã phát hiện mẫu!",
"Percentage": "Phần trăm",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "Xóa vĩnh viễn mọi Mnemonics và cài đặt được mã hóa lưu trữ trong flash?",
"Persist": "Vị trí lưu",
"Pixels deviation index:": "Chỉ số độ lệch điểm ảnh:",
Expand Down
2 changes: 2 additions & 0 deletions i18n/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Backup Mnemonic": "备份助记词",
"Bad signature": "签名无效",
"Base64 Password": "Base64密码",
"Battery": "电池",
"Baudrate": "波特率",
"Binary Grid": "二进制网格",
"Border Padding": "边框填充",
Expand Down Expand Up @@ -199,6 +200,7 @@
"Password Length": "密码长度:",
"Path mismatch": "路径不匹配",
"Pattern detected!": "检测到模式!",
"Percentage": "百分比",
"Permanently remove all stored encrypted mnemonics and settings from flash?": "从 Flash 中永久删除所有存储的加密助记词和设置?",
"Persist": "保存",
"Pixels deviation index:": "像素偏差指数:",
Expand Down
24 changes: 19 additions & 5 deletions src/krux/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,9 @@ def wdt_feed_inc_entropy(self):
self.entropy += 1
wdt.feed()

def _wait_for_press(self, block=True, wait_duration=QR_ANIM_PERIOD):
def _wait_for_press(
self, block=True, wait_duration=QR_ANIM_PERIOD, update_callback=None
):
"""
Wait for first button press or for wait_duration ms.
Use block to wait indefinitely
Expand All @@ -226,6 +228,8 @@ def _wait_for_press(self, block=True, wait_duration=QR_ANIM_PERIOD):
self.flush_events()
self.flushed_flag = not block

update_count = 0
update_trigger = BUTTON_WAIT_PRESS_DELAY * BUTTON_WAIT_PRESS_DELAY
while True:
if self.enter_event():
return BUTTON_ENTER
Expand All @@ -243,6 +247,12 @@ def _wait_for_press(self, block=True, wait_duration=QR_ANIM_PERIOD):
if not block and time.ticks_ms() > start_time + wait_duration:
return None

if update_callback is not None:
update_count += 1
if update_count > update_trigger:
update_count = 0
update_callback()

time.sleep_ms(BUTTON_WAIT_PRESS_DELAY)

def wait_for_release(self):
Expand Down Expand Up @@ -327,19 +337,23 @@ def _handle_touch_input():

return btn

def wait_for_button(self, block=True, wait_duration=QR_ANIM_PERIOD):
def wait_for_button(
self, block=True, wait_duration=QR_ANIM_PERIOD, update_callback=None
):
"""Waits for any button to release, optionally blocking if block=True.
Returns the button that was released, or None if non blocking.
"""
self.wait_for_release()
btn = self._wait_for_press(block, wait_duration)
btn = self._wait_for_press(block, wait_duration, update_callback)
if btn is not None:
auto_shutdown.feed()
btn = self._detect_press_type(btn)
self.debounce_time = time.ticks_ms()
return btn

def wait_for_fastnav_button(self, block=True, wait_duration=QR_ANIM_PERIOD):
def wait_for_fastnav_button(
self, block=True, wait_duration=QR_ANIM_PERIOD, update_callback=None
):
"""Wait for a button press, with support for fast navigation."""
if self.page_value() == PRESSED:
time.sleep_ms(KEY_REPEAT_DELAY_MS)
Expand All @@ -349,7 +363,7 @@ def wait_for_fastnav_button(self, block=True, wait_duration=QR_ANIM_PERIOD):
if kboard.is_yahboom:
return FAST_FORWARD
return FAST_BACKWARD
return self.wait_for_button(block, wait_duration)
return self.wait_for_button(block, wait_duration, update_callback)

def flush_events(self):
"""Clean eventual event flags unintentionally collected"""
Expand Down
17 changes: 17 additions & 0 deletions src/krux/krux_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,19 @@ def label(self, attr):
}[attr]


class BatterySettings(SettingsNamespace):
"""Battery display settings"""

namespace = "settings.battery"
percentage = CategorySetting("percentage", True, [False, True])

def label(self, attr):
"""Returns a label for UI when given a setting name or namespace"""
return {
"percentage": t("Percentage"),
}[attr]


class TouchSettings(SettingsNamespace):
"""Touch sensitivity settings"""

Expand Down Expand Up @@ -376,6 +389,8 @@ class HardwareSettings(SettingsNamespace):
def __init__(self):
self.printer = PrinterSettings()
self.buttons = ButtonsSettings()
if kboard.has_battery:
self.battery = BatterySettings()
if board.config["krux"]["display"].get("touch", False):
self.touch = TouchSettings()
if kboard.is_amigo:
Expand All @@ -390,6 +405,8 @@ def label(self, attr):
"printer": t("Printer"),
}
hardware_menu["buttons"] = t("Buttons")
if kboard.has_battery:
hardware_menu["battery"] = t("Battery")
if board.config["krux"]["display"].get("touch", False):
hardware_menu["touchscreen"] = t("Touchscreen")
if kboard.is_amigo:
Expand Down
58 changes: 40 additions & 18 deletions src/krux/pages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
MINIMAL_PADDING,
FLASH_MSG_TIME,
FONT_HEIGHT,
FONT_WIDTH,
STATUS_BAR_HEIGHT,
BOTTOM_LINE,
)
Expand Down Expand Up @@ -757,6 +758,7 @@ def run_loop(self, start_from_index=None, swipe_up_fnc=None, swipe_down_fnc=None
# Block if screen saver not active
screensaver_time == 0,
screensaver_time * ONE_MINUTE,
update_callback=self.draw_status_bar,
)
if kboard.has_touchscreen:
if btn == BUTTON_TOUCH:
Expand Down Expand Up @@ -863,24 +865,44 @@ def draw_battery_indicator(self):
width = self.ctx.display.width()
x_padding = FONT_HEIGHT // 3
y_padding = (STATUS_BAR_HEIGHT // 2) - (BATTERY_HEIGHT // 2)
self.ctx.display.outline(
width - x_padding - BATTERY_WIDTH,
y_padding,
BATTERY_WIDTH,
BATTERY_HEIGHT,
battery_color,
)
self.ctx.display.fill_rectangle(
width - x_padding + 1, y_padding + 2, 2, BATTERY_HEIGHT - 3, battery_color
)
charge_length = int((BATTERY_WIDTH - 3) * charge)
self.ctx.display.fill_rectangle(
width - x_padding - BATTERY_WIDTH + 2,
y_padding + 2,
charge_length,
BATTERY_HEIGHT - 3,
battery_color,
)
if not Settings().hardware.battery.percentage:
self.ctx.display.outline(
width - x_padding - BATTERY_WIDTH,
y_padding,
BATTERY_WIDTH,
BATTERY_HEIGHT,
battery_color,
)
self.ctx.display.fill_rectangle(
width - x_padding + 1,
y_padding + 2,
2,
BATTERY_HEIGHT - 3,
battery_color,
)
charge_length = int((BATTERY_WIDTH - 3) * charge)
self.ctx.display.fill_rectangle(
width - x_padding - BATTERY_WIDTH + 2,
y_padding + 2,
charge_length,
BATTERY_HEIGHT - 3,
battery_color,
)
else:
charge = min(5 * round(int(charge * 100) / 5), 95)
x_padding = self.ctx.display.width() - (3 * FONT_WIDTH)
x_padding = (
x_padding - 1
if kboard.has_minimal_display
else x_padding - MINIMAL_PADDING
)
self.ctx.display.draw_string(
x_padding,
STATUS_BAR_HEIGHT - FONT_HEIGHT - 1,
"{:>3}".format(str(charge) + "%"),
battery_color,
theme.info_bg_color,
)

def draw_wallet_indicator(self):
"""Draws wallet fingerprint or BIP85 child at top if wallet is loaded"""
Expand Down
2 changes: 2 additions & 0 deletions src/krux/translations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
2756316330,
2256777600,
2568189522,
529780018,
3937333362,
2046615409,
928727036,
Expand Down Expand Up @@ -233,6 +234,7 @@
433951968,
3745269737,
500286397,
3696641006,
3040011773,
140802882,
2578106186,
Expand Down
Loading