diff --git a/src/alga/cli_app.py b/src/alga/cli_app.py index f9cf215..62be015 100644 --- a/src/alga/cli_app.py +++ b/src/alga/cli_app.py @@ -1,12 +1,14 @@ import json from typing import Annotated, Optional +from pzp import pzp from rich import print from rich.console import Console from rich.table import Table from typer import Argument, Typer from alga import client +from alga.types import App app = Typer(no_args_is_help=True, help="Apps installed on the TV") @@ -72,3 +74,18 @@ def list() -> None: console = Console() console.print(table) + + +@app.command() +def pick() -> None: + """Show picker for selecting an app.""" + + response = client.request("ssap://com.webos.applicationManager/listApps") + apps = [] + + for app in response["apps"]: + apps.append(App(app)) + + app = pzp(candidates=apps, fullscreen=False, layout="reverse") + if app: + client.request("ssap://system.launcher/launch", {"id": app.id_}) diff --git a/src/alga/types.py b/src/alga/types.py index 5799841..73a8fd9 100644 --- a/src/alga/types.py +++ b/src/alga/types.py @@ -2,6 +2,19 @@ from typing import Any +@dataclass +class App: + id_: str + name: str + + def __init__(self, app: dict[str, Any]) -> None: + self.id_ = app["id"] + self.name = app["title"] + + def __str__(self) -> str: + return f"{self.name} ({self.id_})" + + @dataclass class Channel: id_: str diff --git a/tests/test_cli_app.py b/tests/test_cli_app.py index 042819a..7cca4b6 100644 --- a/tests/test_cli_app.py +++ b/tests/test_cli_app.py @@ -1,10 +1,11 @@ import json -from unittest.mock import MagicMock +from unittest.mock import MagicMock, call, patch from faker import Faker from typer.testing import CliRunner from alga.__main__ import app +from alga.types import App runner = CliRunner() @@ -95,3 +96,28 @@ def test_info(faker: Faker, mock_request: MagicMock) -> None: ) assert result.exit_code == 0 assert result.stdout == f"{app_info}\n" + + +def test_pick(faker: Faker, mock_request: MagicMock) -> None: + return_value = { + "apps": [ + {"id": faker.pystr(), "title": faker.pystr()}, + {"id": faker.pystr(), "title": faker.pystr()}, + {"id": faker.pystr(), "title": faker.pystr()}, + ] + } + mock_request.return_value = return_value + first_app = return_value["apps"][0] + + with patch("alga.cli_app.pzp") as mock_pzp: + mock_pzp.return_value = App(first_app) + + result = runner.invoke(app, ["app", "pick"]) + + mock_request.assert_has_calls( + [ + call("ssap://com.webos.applicationManager/listApps"), + call("ssap://system.launcher/launch", {"id": first_app["id"]}), + ] + ) + assert result.exit_code == 0 diff --git a/tests/test_types.py b/tests/test_types.py index f3f82a5..d16c2ba 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,24 +1,29 @@ from faker import Faker -from alga.types import Channel, InputDevice, SoundOutputDevice +from alga.types import App, Channel, InputDevice, SoundOutputDevice + + +def test_app(faker: Faker) -> None: + id_, title = faker.pystr(), faker.pystr() + app = App({"id": id_, "title": title}) + + assert str(app) == f"{title} ({id_})" def test_channel(faker: Faker) -> None: + number, name = faker.pystr(), faker.pystr() channel = Channel( - { - "channelId": faker.pystr(), - "channelNumber": faker.pystr(), - "channelName": faker.pystr(), - } + {"channelId": faker.pystr(), "channelNumber": number, "channelName": name} ) - assert str(channel) == f"{channel.number}: {channel.name}" + assert str(channel) == f"{number}: {name}" def test_input_device(faker: Faker) -> None: - input_device = InputDevice({"id": faker.pystr(), "label": faker.pystr()}) + id_, name = faker.pystr(), faker.pystr() + input_device = InputDevice({"id": id_, "label": name}) - assert str(input_device) == f"{input_device.name} ({input_device.id_})" + assert str(input_device) == f"{name} ({id_})" def test_sound_output_device(faker: Faker) -> None: diff --git a/usage.md b/usage.md index 3abc6bc..d1937a4 100644 --- a/usage.md +++ b/usage.md @@ -66,6 +66,7 @@ $ alga app [OPTIONS] COMMAND [ARGS]... * `info`: Show info about specific app * `launch`: Launch an app * `list`: List installed apps +* `pick`: Show picker for selecting an app. ### `alga app close` @@ -150,6 +151,20 @@ $ alga app list [OPTIONS] * `--help`: Show this message and exit. +### `alga app pick` + +Show picker for selecting an app. + +**Usage**: + +```console +$ alga app pick [OPTIONS] +``` + +**Options**: + +* `--help`: Show this message and exit. + ## `alga channel` TV channels