65 lines
2.3 KiB
Python
65 lines
2.3 KiB
Python
"""Playback intent tracking for optimistic UI updates.
|
|
|
|
Bridges the gap between instant commands and slow state polling.
|
|
"""
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class PlaybackIntent:
|
|
"""A pending user intent for playback state.
|
|
|
|
Attributes:
|
|
target_state: The MediaPlayerState we expect after the command.
|
|
command: The command/service name (for retries and logging).
|
|
created_at: Monotonic timestamp when the intent was created.
|
|
prior_state: The source state before the intent (for detecting external overrides).
|
|
retry_count: Number of retries attempted so far.
|
|
via_adb: True when the command was successfully served by the ADB
|
|
keyevent path — the retry must then go over ADB too, not back to
|
|
the remote that did not serve it.
|
|
adb_command: The ADB keycode command name matching the intent
|
|
(play/pause/stop/next/previous); set together with via_adb.
|
|
via_protocol: True when the command was served by the remote-protocol
|
|
key push (Phase 2) — the retry then goes over the protocol key
|
|
again instead of the other transports.
|
|
protocol_key: The protocol keycode string served with via_protocol.
|
|
"""
|
|
target_state: str # MediaPlayerState value (e.g. "playing", "paused")
|
|
command: str
|
|
created_at: float
|
|
prior_state: str | None = None
|
|
retry_count: int = 0
|
|
via_adb: bool = False
|
|
adb_command: str | None = None
|
|
via_protocol: bool = False
|
|
protocol_key: str | None = None
|
|
|
|
@classmethod
|
|
def create(
|
|
cls, target_state: str, command: str, prior_state: str | None = None
|
|
) -> "PlaybackIntent":
|
|
return cls(
|
|
target_state=target_state,
|
|
command=command,
|
|
created_at=time.monotonic(),
|
|
prior_state=prior_state,
|
|
)
|
|
|
|
@property
|
|
def age_seconds(self) -> float:
|
|
return round(time.monotonic() - self.created_at, 1)
|
|
|
|
def to_debug_dict(self) -> dict:
|
|
"""Serialize for the _intent debug attribute."""
|
|
return {
|
|
"target": self.target_state,
|
|
"command": self.command,
|
|
"retries": self.retry_count,
|
|
"age_s": self.age_seconds,
|
|
"via_adb": self.via_adb,
|
|
"adb_command": self.adb_command,
|
|
}
|