Login

NAME

App::Moneymoor::Screen::Login - the centred unlock / create-a-budget dialog, and the only screen that runs before a passphrase exists.

SYNOPSIS


use App::Moneymoor::Screen::Login;
use App::Moneymoor::Themes;

my $login = App::Moneymoor::Screen::Login.new(
    available-budgets => ('household', 'business'),
    theme             => App::Moneymoor::Themes::load('nord'),
);
my $root = $login.build;         # a plain Selkie tree, no terminal needed

$login.on-login.tap: -> %data {
    given %data<action> {
        when 'login'  { unlock(%data<budget-name>, %data<passphrase>) }
        when 'create' { create(%data<budget-name>, %data<passphrase>) }
        when 'focus-next' { $app.focus(...) }
    }
};

$login.set-status('Invalid passphrase (or corrupted budget file)', :error);

DESCRIPTION

A fixed 24 x 64 dialog, centred by flex struts, with a rounded frame and one cell of padding. It has two modes, swapped in place inside a single form container:

  • open a budget β€” the budget Select plus one masked passphrase field.

  • create a budget β€” the same Select (parked on + Create new budget…), a three-row warning, a name field, a passphrase field with a live PasswordStrength meter, and a confirmation field.

Either the picker or Ctrl+N gets you to the second mode; both go through the picker's on-change tap, which is the one place that knows how to swap the form.

Nothing here touches the database β€” it cannot, since the database is exactly what the passphrase typed into this screen unlocks. The only state it reads is the budget-name list the caller hands it, so the screen is safe to build and render before any credential exists.

The row budget

The dialog is centred but never scrolled, so every row it spends is spent at build time and the create-a-budget branch spends all of them. See the comment on DIALOG-ROWS in the source for the full sum; t/63-login-layout.rakutest pins it. Adding a field, or a line of warning copy, without growing DIALOG-ROWS pushes the hint line off the bottom edge.

Error reporting

App::Moneymoor::DB.connect answers with a Failure β€” never an exception β€” carrying one of two distinct messages:

  • "Not an encrypted budget file (plain SQLite file)" β€” the file exists but is plaintext SQLite, i.e. the user picked the wrong file.

  • "Invalid passphrase (or corrupted budget file)" β€” the file is encrypted and the key did not open it.

The distinction is worth surfacing verbatim: one is "you typed the wrong thing", the other is "you opened the wrong thing", and a single "login failed" would leave the user retyping a passphrase that was always correct. App::Moneymoor::UI passes $result.exception.message straight into set-status(:error) and then calls .so on the Failure β€” a handled Failure that is never defused re-throws at sink time.

SUPPLIES

on-login emits a Hash with an action key:

  • focus-next β€” { target = 'name' | 'password' | 'confirm' }>. The screen has no Selkie::App reference, so moving focus between its own fields is a request to whoever owns the app. name is the Ctrl+N case: the field that had focus was destroyed with the form the mode switch replaced.

  • login β€” { budget-name, passphrase }.

  • create β€” { budget-name, passphrase }.

ACCESSORS

  • password-input, confirm-input, name-input, budget-select β€” focus targets.

  • in-new-db-mode β€” which branch the form is currently showing.

  • selected-budget β€” the picked budget name, or the Str type object when the create row is selected.

SEE ALSO

App::Moneymoor v0.4.2

YNAB-style envelope budgeting: a derivation engine

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

DBIish:ver<0.6.7>:auth<zef:raku-community-modules>Notcurses::Native:ver<0.6.5+>:auth<zef:apogee>Selkie:ver<0.16.0+>:auth<zef:apogee>JSON::Fast:ver<0.19>:auth<cpan:TIMOTIMO>MacOS::NativeLib:ver<0.0.6>:auth<zef:lizmat>

Test Dependencies

Provides

  • App::Moneymoor
  • App::Moneymoor::Config
  • App::Moneymoor::DB
  • App::Moneymoor::Gateway::Account
  • App::Moneymoor::Gateway::Assignment
  • App::Moneymoor::Gateway::Category
  • App::Moneymoor::Gateway::Payee
  • App::Moneymoor::Gateway::Transaction
  • App::Moneymoor::Handlers::Boot
  • App::Moneymoor::Model::Account
  • App::Moneymoor::Model::Assignment
  • App::Moneymoor::Model::Category
  • App::Moneymoor::Model::CategoryGroup
  • App::Moneymoor::Model::Payee
  • App::Moneymoor::Model::Split
  • App::Moneymoor::Model::Transaction
  • App::Moneymoor::Screen::Accounts
  • App::Moneymoor::Screen::Budget
  • App::Moneymoor::Screen::Login
  • App::Moneymoor::Screen::Main
  • App::Moneymoor::Screen::Main::Keybinds
  • App::Moneymoor::Screen::Main::Modals
  • App::Moneymoor::Screen::Main::Subscriptions
  • App::Moneymoor::Screen::Reports
  • App::Moneymoor::Service::Budget
  • App::Moneymoor::Service::Icons
  • App::Moneymoor::Service::Target
  • App::Moneymoor::Service::Workspace
  • App::Moneymoor::StoreHandlers
  • App::Moneymoor::Theme
  • App::Moneymoor::Theme::Catppuccin
  • App::Moneymoor::Theme::Dracula
  • App::Moneymoor::Theme::Everforest
  • App::Moneymoor::Theme::Gruvbox
  • App::Moneymoor::Theme::Kanagawa
  • App::Moneymoor::Theme::Monokai
  • App::Moneymoor::Theme::Nord
  • App::Moneymoor::Theme::OneDark
  • App::Moneymoor::Theme::RosePine
  • App::Moneymoor::Theme::Solarized
  • App::Moneymoor::Theme::TokyoNight
  • App::Moneymoor::Themes
  • App::Moneymoor::UI
  • App::Moneymoor::Util::Money
  • App::Moneymoor::Util::Period
  • App::Moneymoor::View::BudgetRow
  • App::Moneymoor::View::EmptyState
  • App::Moneymoor::View::HintBar
  • App::Moneymoor::View::InspectorPane
  • App::Moneymoor::View::ModalChrome
  • App::Moneymoor::View::RegisterRow
  • App::Moneymoor::View::ReportRow
  • App::Moneymoor::Widget::BannerBar
  • App::Moneymoor::Widget::BootProgressModal

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite β€” the markup and publishing tools behind this site.