← back to ColonelPanicX__garmin-extract

Function bodies 373 total

All specs Real LLM only Function bodies
action_go_pull method · python · L120-L124 (5 LOC)
garmin_extract/screens/main_menu.py
    def action_go_pull(self) -> None:
        self._cursor = 1
        from garmin_extract.screens.data_pull import DataPullScreen

        self.app.push_screen(DataPullScreen())
action_go_automation method · python · L126-L130 (5 LOC)
garmin_extract/screens/main_menu.py
    def action_go_automation(self) -> None:
        self._cursor = 2
        from garmin_extract.screens.automation import AutomationScreen

        self.app.push_screen(AutomationScreen())
_MfaModal class · python · L25-L78 (54 LOC)
garmin_extract/screens/pull_progress.py
class _MfaModal(ModalScreen[None]):
    """Pop-up dialog to capture an MFA code and write it to .mfa_code."""

    BINDINGS = [Binding("escape", "dismiss", "Cancel", show=True)]

    CSS = """
    _MfaModal {
        align: center middle;
    }

    #mfa-box {
        width: 52;
        height: auto;
        border: round $warning;
        padding: 1 2;
    }

    #mfa-title {
        text-style: bold;
        color: $warning;
        margin-bottom: 1;
    }

    #mfa-hint {
        color: $text-muted;
        margin-bottom: 1;
    }

    #mfa-error {
        color: $error;
        height: 1;
    }
    """

    def compose(self) -> ComposeResult:
        with Static(id="mfa-box"):
            yield Static("MFA Code Required", id="mfa-title")
            yield Static(
                "Check your email for a 6-digit code and enter it below.",
                id="mfa-hint",
            )
            yield Input(placeholder="000000", id="mfa-input", max_length=6)
            yield Static("
compose method · python · L59-L67 (9 LOC)
garmin_extract/screens/pull_progress.py
    def compose(self) -> ComposeResult:
        with Static(id="mfa-box"):
            yield Static("MFA Code Required", id="mfa-title")
            yield Static(
                "Check your email for a 6-digit code and enter it below.",
                id="mfa-hint",
            )
            yield Input(placeholder="000000", id="mfa-input", max_length=6)
            yield Static("", id="mfa-error")
on_input_submitted method · python · L72-L78 (7 LOC)
garmin_extract/screens/pull_progress.py
    def on_input_submitted(self, event: Input.Submitted) -> None:
        code = event.value.strip()
        if not code:
            self.query_one("#mfa-error", Static).update("Please enter the 6-digit code.")
            return
        MFA_FILE.write_text(code + "\n")
        self.dismiss()
_RuntimeCredsModal class · python · L84-L144 (61 LOC)
garmin_extract/screens/pull_progress.py
class _RuntimeCredsModal(ModalScreen[tuple[str, str] | None]):
    """Prompt for email + password when no credentials are saved anywhere."""

    BINDINGS = [Binding("escape", "dismiss", "Cancel", show=True)]

    CSS = """
    _RuntimeCredsModal {
        align: center middle;
    }

    #rc-box {
        width: 58;
        height: auto;
        border: round $primary;
        padding: 1 2;
    }

    #rc-title {
        text-style: bold;
        margin-bottom: 1;
    }

    #rc-hint {
        color: $text-muted;
        margin-bottom: 1;
    }

    #rc-error {
        color: $error;
        height: 1;
    }
    """

    def compose(self) -> ComposeResult:
        with Static(id="rc-box"):
            yield Static("Enter Garmin Connect Credentials", id="rc-title")
            yield Static(
                "No saved credentials found.  These will not be stored.",
                id="rc-hint",
            )
            yield Input(placeholder="Email", id="rc-email")
            yield In
compose method · python · L117-L126 (10 LOC)
garmin_extract/screens/pull_progress.py
    def compose(self) -> ComposeResult:
        with Static(id="rc-box"):
            yield Static("Enter Garmin Connect Credentials", id="rc-title")
            yield Static(
                "No saved credentials found.  These will not be stored.",
                id="rc-hint",
            )
            yield Input(placeholder="Email", id="rc-email")
            yield Input(placeholder="Password", password=True, id="rc-password")
            yield Static("", id="rc-error")
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
on_input_submitted method · python · L131-L144 (14 LOC)
garmin_extract/screens/pull_progress.py
    def on_input_submitted(self, event: Input.Submitted) -> None:
        if event.input.id == "rc-email":
            self.query_one("#rc-password", Input).focus()
            return
        email = self.query_one("#rc-email", Input).value.strip()
        password = self.query_one("#rc-password", Input).value.strip()
        if not email:
            self.query_one("#rc-error", Static).update("Email is required.")
            self.query_one("#rc-email", Input).focus()
            return
        if not password:
            self.query_one("#rc-error", Static).update("Password is required.")
            return
        self.dismiss((email, password))
_DayState class · python · L151-L156 (6 LOC)
garmin_extract/screens/pull_progress.py
class _DayState:
    date_str: str
    total: int = 0
    done: int = 0
    failed: int = 0
    status: str = "pending"  # pending | active | done | skipped
__init__ method · python · L226-L264 (39 LOC)
garmin_extract/screens/pull_progress.py
    def __init__(
        self,
        start_date: str,
        days: int,
        label: str,
        no_skip: bool = False,
        rebuild_only: bool = False,
        zip_path: str = "",
    ) -> None:
        super().__init__()
        self._start_date = start_date
        self._days = days
        self._label = label
        self._no_skip = no_skip
        self._rebuild_only = rebuild_only
        self._zip_path = zip_path

        self._done = False
        self._mfa_shown = False
        self._email = ""
        self._password = ""
        self._proc: subprocess.Popen | None = None

        # Determine display mode
        if days > 1:
            self._mode = "day"
            self._day_states: list[_DayState] = self._init_day_states()
            self._current_day_index: int = -1
            self._metrics_per_day: int = 0
        elif days == 1:
            self._mode = "metric"
            self._live_metrics: list[tuple[str, str]] = []  # (name, "done"|"fail")
            se
compose method · python · L268-L283 (16 LOC)
garmin_extract/screens/pull_progress.py
    def compose(self) -> ComposeResult:
        yield Header(show_clock=True)
        with Horizontal(id="progress-layout"):
            yield RichLog(id="log-panel", highlight=True, markup=True, wrap=True)
            with Vertical(id="metric-panel"):
                yield Static(self._label, id="metric-header")
                yield Static("", id="metric-subheader")
                yield Static(self._initial_panel_body(), id="metric-list")
        with Vertical(id="status-bar"):
            yield ProgressBar(
                total=self._overall_total,
                id="progress-bar",
                show_eta=False,
            )
            yield Static("Starting...", id="status-label")
        yield Footer()
on_mount method · python · L285-L299 (15 LOC)
garmin_extract/screens/pull_progress.py
    def on_mount(self) -> None:
        # Rebuild/import don't need Garmin credentials
        if self._rebuild_only or self._zip_path:
            self._start_pull()
            return

        from garmin_extract._credentials import load_credentials

        email, password = load_credentials()
        if password:
            self._email = email
            self._password = password
            self._start_pull()
        else:
            self.app.push_screen(_RuntimeCredsModal(), self._on_runtime_creds)
_on_runtime_creds method · python · L301-L307 (7 LOC)
garmin_extract/screens/pull_progress.py
    def _on_runtime_creds(self, creds: tuple[str, str] | None) -> None:
        if creds is None:
            # User cancelled — go back
            self.app.pop_screen()
            return
        self._email, self._password = creds
        self._start_pull()
_start_pull method · python · L309-L311 (3 LOC)
garmin_extract/screens/pull_progress.py
    def _start_pull(self) -> None:
        cmd = self._build_cmd()
        self.run_worker(lambda: self._do_pull(cmd), thread=True, name="puller")
_initial_panel_body method · python · L315-L320 (6 LOC)
garmin_extract/screens/pull_progress.py
    def _initial_panel_body(self) -> str:
        if self._mode == "day":
            return self._render_day_list()
        if self._mode == "metric":
            return "[dim]Waiting for first metric...[/]"
        return "[dim]Starting...[/]"
Open data scored by Repobility · https://repobility.com
_build_cmd method · python · L324-L346 (23 LOC)
garmin_extract/screens/pull_progress.py
    def _build_cmd(self) -> list[str]:
        if self._rebuild_only:
            return [sys.executable, "-u", str(ROOT / "reports" / "build_garmin_csvs.py")]
        if self._zip_path:
            return [
                sys.executable,
                "-u",
                str(ROOT / "pullers" / "garmin_import_export.py"),
                "--zip",
                self._zip_path,
            ]
        cmd = [
            sys.executable,
            "-u",
            str(ROOT / "pullers" / "garmin.py"),
            "--date",
            self._start_date,
            "--days",
            str(self._days),
        ]
        if self._no_skip:
            cmd.append("--no-skip")
        return cmd
_init_day_states method · python · L350-L358 (9 LOC)
garmin_extract/screens/pull_progress.py
    def _init_day_states(self) -> list[_DayState]:
        states: list[_DayState] = []
        try:
            start = date.fromisoformat(self._start_date)
            for i in range(self._days):
                states.append(_DayState((start + timedelta(days=i)).isoformat()))
        except ValueError:
            pass
        return states
_do_pull method · python · L362-L391 (30 LOC)
garmin_extract/screens/pull_progress.py
    def _do_pull(self, cmd: list[str]) -> None:
        # Build subprocess env — inject credentials so keyring/runtime creds
        # reach garmin.py even though it calls load_dotenv() internally.
        env = os.environ.copy()
        if self._email:
            env["GARMIN_EMAIL"] = self._email
        if self._password:
            env["GARMIN_PASSWORD"] = self._password

        try:
            proc = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                stdin=subprocess.DEVNULL,
                text=True,
                cwd=str(ROOT),
                env=env,
            )
            self._proc = proc
            assert proc.stdout is not None
            for raw_line in iter(proc.stdout.readline, ""):
                line = raw_line.rstrip("\n")
                self.app.call_from_thread(self._on_line, line)
            proc.wait()
            self._proc = None
            self.app.call_from_th
_on_line method · python · L395-L417 (23 LOC)
garmin_extract/screens/pull_progress.py
    def _on_line(self, line: str) -> None:
        self.query_one("#log-panel", RichLog).write(line)
        stripped = line.strip()

        # ── "[2025-04-06] Pulling N metrics..." ──
        if stripped.startswith("[") and "] Pulling " in stripped and "metrics" in stripped:
            self._handle_day_start(stripped)
            return

        # ── "[2025-04-06] Already pulled — skipping" ──
        if "Already pulled" in stripped and "skipping" in stripped:
            self._handle_day_skipped(stripped)
            return

        # ── "    ✓/✗  metric_name" ──
        if stripped.startswith("✓") or stripped.startswith("✗"):
            self._handle_metric_line(stripped)
            return

        # ── file-based MFA prompt ──
        if "Run: echo YOUR_CODE" in stripped and not self._mfa_shown:
            self._mfa_shown = True
            self.app.push_screen(_MfaModal())
_handle_day_start method · python · L419-L459 (41 LOC)
garmin_extract/screens/pull_progress.py
    def _handle_day_start(self, stripped: str) -> None:
        try:
            date_str = stripped[1 : stripped.index("]")]
            # Parse metric count from "Pulling N metrics..."
            parts = stripped.split()
            count_idx = next((i for i, p in enumerate(parts) if p == "Pulling"), -1)
            n_metrics = int(parts[count_idx + 1]) if count_idx >= 0 else 0
        except (ValueError, IndexError):
            return

        if self._mode == "day":
            # Find matching day state
            idx = next(
                (i for i, s in enumerate(self._day_states) if s.date_str == date_str),
                -1,
            )
            if idx == -1:
                self._day_states.append(_DayState(date_str))
                idx = len(self._day_states) - 1
            self._current_day_index = idx
            self._day_states[idx].status = "active"
            self._day_states[idx].total = n_metrics

            if self._metrics_per_day == 0 and n_metrics > 
_handle_day_skipped method · python · L461-L479 (19 LOC)
garmin_extract/screens/pull_progress.py
    def _handle_day_skipped(self, stripped: str) -> None:
        try:
            date_str = stripped[1 : stripped.index("]")]
        except ValueError:
            return

        if self._mode == "day":
            idx = next(
                (i for i, s in enumerate(self._day_states) if s.date_str == date_str),
                -1,
            )
            if idx >= 0:
                self._day_states[idx].status = "skipped"
                # Advance progress by one day's worth of metrics (or 1 if unknown)
                advance = self._metrics_per_day if self._metrics_per_day else 1
                self._overall_done += advance
                self.query_one("#progress-bar", ProgressBar).advance(advance)
                self._refresh_day_list()
                self._set_status(f"Skipped {date_str}  (already pulled)")
_handle_metric_line method · python · L481-L518 (38 LOC)
garmin_extract/screens/pull_progress.py
    def _handle_metric_line(self, stripped: str) -> None:
        parts = stripped.split()
        if not parts:
            return
        metric_name = parts[-1]
        is_ok = stripped.startswith("✓")
        state = "done" if is_ok else "fail"

        if self._mode == "metric":
            self._live_metrics.append((metric_name, state))
            self._day_done += 1
            self.query_one("#progress-bar", ProgressBar).advance(1)
            self._refresh_metric_list()
            self._set_status(f"{self._day_done} / {self._day_total or '?'} metrics")

        elif self._mode == "day" and self._current_day_index >= 0:
            ds = self._day_states[self._current_day_index]
            if is_ok:
                ds.done += 1
            else:
                ds.failed += 1

            # Only advance progress up to the announced total — per-activity
            # sub-requests emit extra ✓/✗ lines that exceed the day's metric count.
            tally = ds.done + ds.failed
 
_on_done method · python · L522-L543 (22 LOC)
garmin_extract/screens/pull_progress.py
    def _on_done(self, returncode: int) -> None:
        self._done = True
        log = self.query_one("#log-panel", RichLog)

        # For simple mode (rebuild-only / zip import), the right panel and progress
        # bar are never updated during the run — complete them now.
        if self._mode == "simple":
            panel_text = "[green]✓ Complete[/]" if returncode == 0 else "[red]✗ Failed[/]"
            self.query_one("#metric-list", Static).update(panel_text)
            bar = self.query_one("#progress-bar", ProgressBar)
            bar.total = 1
            bar.advance(1)

        if returncode == 0:
            self._set_status("Complete ✓  —  press  b  to go back")
            log.write("\n[green]Done.[/green]  Press  [bold]b[/bold]  to go back.")
        else:
            self._set_status(f"Finished with errors (exit {returncode})  —  press  b  to go back")
            log.write(
                f"\n[red]Process exited with code {returncode}.[/red]"
                "  P
About: code-quality intelligence by Repobility · https://repobility.com
_on_error method · python · L545-L548 (4 LOC)
garmin_extract/screens/pull_progress.py
    def _on_error(self, msg: str) -> None:
        self._done = True
        self.query_one("#log-panel", RichLog).write(f"\n[red]Error: {msg}[/red]")
        self._set_status("Error  —  press  b  to go back")
_render_day_list method · python · L552-L567 (16 LOC)
garmin_extract/screens/pull_progress.py
    def _render_day_list(self) -> str:
        lines: list[str] = []
        for ds in self._day_states:
            if ds.status == "done":
                tally = min(ds.done + ds.failed, ds.total) if ds.total else ds.done + ds.failed
                count = f"({tally}/{ds.total})" if ds.total else ""
                failed = f"  [red]{ds.failed} failed[/]" if ds.failed else ""
                lines.append(f"[green]✓[/] {ds.date_str}  [dim]{count}[/]{failed}")
            elif ds.status == "active":
                count = f"{ds.done + ds.failed}/{ds.total}" if ds.total else "…"
                lines.append(f"[yellow]●[/] {ds.date_str}  [dim]({count})[/]")
            elif ds.status == "skipped":
                lines.append(f"[dim]↷ {ds.date_str}  (skipped)[/]")
            else:
                lines.append(f"[dim]○  {ds.date_str}[/]")
        return "\n".join(lines)
_render_metric_list method · python · L569-L578 (10 LOC)
garmin_extract/screens/pull_progress.py
    def _render_metric_list(self) -> str:
        if not self._live_metrics:
            return "[dim]Waiting for first metric...[/]"
        lines: list[str] = []
        for name, state in self._live_metrics:
            if state == "done":
                lines.append(f"[green]✓[/] {name}")
            else:
                lines.append(f"[red]✗[/] {name}")
        return "\n".join(lines)
action_back method · python · L591-L597 (7 LOC)
garmin_extract/screens/pull_progress.py
    def action_back(self) -> None:
        if self._proc is not None:
            try:
                self._proc.terminate()
            except Exception:
                pass
        self.app.pop_screen()
_check_python function · python · L24-L27 (4 LOC)
garmin_extract/screens/setup.py
def _check_python() -> tuple[bool, str]:
    v = sys.version_info
    ok = v >= (3, 12)
    return ok, f"Python {v.major}.{v.minor}.{v.micro}"
_check_chrome function · python · L30-L34 (5 LOC)
garmin_extract/screens/setup.py
def _check_chrome() -> tuple[bool, str]:
    from garmin_extract.menu import _find_chrome

    found, version = _find_chrome()
    return found, version or "Not found"
_check_xvfb function · python · L37-L47 (11 LOC)
garmin_extract/screens/setup.py
def _check_xvfb() -> tuple[bool, str]:
    if platform.system() != "Linux":
        return True, f"Not required on {platform.system()}"
    import os

    if os.environ.get("DISPLAY"):
        return True, "Not needed — display available"
    from garmin_extract.menu import _find_xvfb

    found = _find_xvfb()
    return found, "Installed" if found else "Not found"
_check_packages function · python · L50-L56 (7 LOC)
garmin_extract/screens/setup.py
def _check_packages() -> tuple[bool, str]:
    from garmin_extract.menu import _missing_packages

    missing = _missing_packages()
    if not missing:
        return True, "All installed"
    return False, f"Missing: {', '.join(missing)}"
Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
_load_env function · python · L59-L62 (4 LOC)
garmin_extract/screens/setup.py
def _load_env() -> dict[str, str]:
    from garmin_extract.menu import load_env

    return load_env()
_save_env function · python · L65-L68 (4 LOC)
garmin_extract/screens/setup.py
def _save_env(vals: dict[str, str]) -> None:
    from garmin_extract.menu import save_env

    save_env(vals)
_check_credentials function · python · L71-L74 (4 LOC)
garmin_extract/screens/setup.py
def _check_credentials() -> tuple[bool, str]:
    from garmin_extract._credentials import check_credentials

    return check_credentials()
_check_gmail function · python · L77-L82 (6 LOC)
garmin_extract/screens/setup.py
def _check_gmail() -> tuple[bool, str]:
    if not GMAIL_CREDS_FILE.exists():
        return False, "google_credentials.json missing"
    if not GMAIL_TOKEN_FILE.exists():
        return False, "Credentials found — not yet authorized"
    return True, "Authorized"
_status_tag function · python · L85-L88 (4 LOC)
garmin_extract/screens/setup.py
def _status_tag(ok: bool, text: str) -> str:
    color = "green" if ok else "yellow"
    icon = "✓" if ok else "○"
    return f"[{color}]{icon}[/]  [dim]{text}[/]"
SetupScreen class · python · L94-L283 (190 LOC)
garmin_extract/screens/setup.py
class SetupScreen(Screen[None]):
    """Landing screen for Initial Setup — shows live status for all three areas."""

    _ITEM_COUNT = 3

    BINDINGS = [
        Binding("1", "go_prereqs", show=False),
        Binding("2", "go_credentials", show=False),
        Binding("3", "go_gmail", show=False),
        Binding("up", "cursor_up", show=False),
        Binding("k", "cursor_up", show=False),
        Binding("down", "cursor_down", show=False),
        Binding("j", "cursor_down", show=False),
        Binding("enter", "cursor_select", show=False),
        Binding("b", "back", "Back", show=True),
        Binding("q", "quit", "Quit", show=True),
    ]

    CSS = """
    SetupScreen {
        align: center middle;
    }

    #setup-menu {
        width: 57;
        height: auto;
        color: $text;
        margin-bottom: 1;
    }

    #setup-hint {
        width: 57;
        text-align: center;
        color: $text-muted;
    }
    """

    def compose(self) -> ComposeResult:
        yie
compose method · python · L131-L138 (8 LOC)
garmin_extract/screens/setup.py
    def compose(self) -> ComposeResult:
        yield Header(show_clock=True)
        yield Static(self._build_menu(), id="setup-menu")
        yield Static(
            "↑↓  j/k  navigate  ·  enter  select  ·  1–3  direct  ·  b  back",
            id="setup-hint",
        )
        yield Footer()
on_mount method · python · L140-L148 (9 LOC)
garmin_extract/screens/setup.py
    def on_mount(self) -> None:
        self._cursor = 0
        self._prereq_ok = False
        self._prereq_status = "[dim]checking…[/]"
        self._creds_ok = False
        self._creds_str = "[dim]checking…[/]"
        self._gmail_ok = False
        self._gmail_str = "[dim]checking…[/]"
        self._refresh_status()
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
_refresh_status method · python · L153-L159 (7 LOC)
garmin_extract/screens/setup.py
    def _refresh_status(self) -> None:
        self.run_worker(
            lambda: self._check_all(),
            thread=True,
            name="setup-checker",
            exclusive=True,
        )
_check_all method · python · L161-L188 (28 LOC)
garmin_extract/screens/setup.py
    def _check_all(self) -> None:
        py_ok, py_str = _check_python()
        chrome_ok, chrome_str = _check_chrome()
        xvfb_ok, xvfb_str = _check_xvfb()
        pkg_ok, pkg_str = _check_packages()
        prereq_ok = py_ok and chrome_ok and xvfb_ok and pkg_ok
        prereq_parts = []
        for ok, label in [
            (py_ok, "Python"),
            (chrome_ok, "Chrome"),
            (xvfb_ok, "Xvfb"),
            (pkg_ok, "Packages"),
        ]:
            prereq_parts.append(f"[{'green' if ok else 'red'}]{label}[/]")
        prereq_status = "  ".join(prereq_parts)

        creds_ok, creds_str = _check_credentials()
        gmail_ok, gmail_str = _check_gmail()

        self.app.call_from_thread(
            self._update_menu,
            prereq_ok,
            prereq_status,
            creds_ok,
            creds_str,
            gmail_ok,
            gmail_str,
        )
_update_menu method · python · L190-L205 (16 LOC)
garmin_extract/screens/setup.py
    def _update_menu(
        self,
        prereq_ok: bool,
        prereq_status: str,
        creds_ok: bool,
        creds_str: str,
        gmail_ok: bool,
        gmail_str: str,
    ) -> None:
        self._prereq_ok = prereq_ok
        self._prereq_status = prereq_status
        self._creds_ok = creds_ok
        self._creds_str = creds_str
        self._gmail_ok = gmail_ok
        self._gmail_str = gmail_str
        self._redraw_menu()
_redraw_menu method · python · L207-L217 (11 LOC)
garmin_extract/screens/setup.py
    def _redraw_menu(self) -> None:
        self.query_one("#setup-menu", Static).update(
            self._build_menu(
                self._prereq_ok,
                self._prereq_status,
                self._creds_ok,
                self._creds_str,
                self._gmail_ok,
                self._gmail_str,
            )
        )
_build_menu method · python · L219-L252 (34 LOC)
garmin_extract/screens/setup.py
    def _build_menu(
        self,
        prereq_ok: bool = False,
        prereq_status: str = "[dim]checking…[/]",
        creds_ok: bool = False,
        creds_str: str = "[dim]checking…[/]",
        gmail_ok: bool = False,
        gmail_str: str = "[dim]checking…[/]",
    ) -> str:
        cursor = getattr(self, "_cursor", 0)
        p_icon = "[green]✓[/]" if prereq_ok else "[yellow]○[/]"
        c_icon = "[green]✓[/]" if creds_ok else "[yellow]○[/]"
        g_icon = "[green]✓[/]" if gmail_ok else "[dim]○[/]"

        def _pre(idx: int) -> str:
            return "❯ " if cursor == idx else "  "

        def _lbl(text: str, idx: int) -> str:
            return f"[bold]{text}[/]" if cursor == idx else text

        return (
            f"\n"
            f"  [bold dim]PREREQUISITES[/]\n  {'─' * 51}\n"
            f"{_pre(0)}[bold cyan][1][/]  {_lbl('Check & Install', 0)}\n"
            f"       {p_icon}  {prereq_status}\n"
            f"\n"
            f"  [bold dim]CREDENTIALS[/]\n 
action_cursor_up method · python · L254-L257 (4 LOC)
garmin_extract/screens/setup.py
    def action_cursor_up(self) -> None:
        if self._cursor > 0:
            self._cursor -= 1
            self._redraw_menu()
action_cursor_down method · python · L259-L262 (4 LOC)
garmin_extract/screens/setup.py
    def action_cursor_down(self) -> None:
        if self._cursor < self._ITEM_COUNT - 1:
            self._cursor += 1
            self._redraw_menu()
action_go_prereqs method · python · L267-L269 (3 LOC)
garmin_extract/screens/setup.py
    def action_go_prereqs(self) -> None:
        self._cursor = 0
        self.app.push_screen(PrereqScreen())
Open data scored by Repobility · https://repobility.com
action_go_credentials method · python · L271-L273 (3 LOC)
garmin_extract/screens/setup.py
    def action_go_credentials(self) -> None:
        self._cursor = 1
        self.app.push_screen(CredentialsScreen())
action_go_gmail method · python · L275-L277 (3 LOC)
garmin_extract/screens/setup.py
    def action_go_gmail(self) -> None:
        self._cursor = 2
        self.app.push_screen(GmailSetupScreen())
PrereqScreen class · python · L289-L477 (189 LOC)
garmin_extract/screens/setup.py
class PrereqScreen(Screen[None]):
    """Run prerequisite checks and offer to install missing items (Linux)."""

    BINDINGS = [
        Binding("i", "install", "Install missing", show=False),
        Binding("b", "back", "Back", show=True),
        Binding("q", "quit", "Quit", show=True),
    ]

    CSS = """
    PrereqScreen {
        layout: vertical;
    }

    #prereq-layout {
        height: 1fr;
    }

    #prereq-log {
        width: 2fr;
        border-right: solid $primary-darken-3;
    }

    #prereq-panel {
        width: 1fr;
        padding: 0 1;
    }

    #prereq-header {
        text-style: bold;
        color: $accent;
        margin-bottom: 1;
        height: auto;
    }

    #prereq-list {
        height: auto;
        color: $text;
    }

    #prereq-status-bar {
        height: 3;
        padding: 0 1;
        border-top: solid $primary-darken-3;
    }

    #prereq-progress {
        width: 1fr;
        margin: 1 0;
    }

    #prereq-status {
        height: 1;
‹ prevpage 6 / 8next ›