image-lab / src /services /session.py
Magnus Persson
Add 'What did the model receive?', fix the how-it-was-made link, update README
31066d6
Raw History Blame Contribute Delete
2.48 kB
"""Per-visitor state held in gr.State: language, style, current image, history, idle tracking."""
from __future__ import annotations
import time
from dataclasses import dataclass, field
@dataclass
class GeneratedImage:
image: bytes = field(repr=False)
prompt: str = field(repr=False)
model_key: str
seconds: float
instruction: str = field(default="", repr=False) # the edit sent to the model, if any
@dataclass
class VisitorSession:
lang: str
last_interaction: float = field(default_factory=time.monotonic)
dirty: bool = False
style: str | None = None
current: GeneratedImage | None = None
previous: GeneratedImage | None = None # the image before the last edit, for before/after
history: list[GeneratedImage] = field(default_factory=list)
undo_text: str | None = field(
default=None, repr=False
) # the text before Help me or Surprise me
epoch: int = 0 # bumped by reset(), so work started for the previous visitor is dropped
def touch(self, now: float | None = None) -> None:
self.last_interaction = time.monotonic() if now is None else now
self.dirty = True
def select_style(self, key: str) -> None:
self.style = None if self.style == key else key
def set_current(self, image: GeneratedImage, history_size: int) -> None:
self.current = image
self.previous = None
self.history = [*self.history, image][-history_size:]
def set_edited(self, image: GeneratedImage, history_size: int) -> None:
before = self.current
self.set_current(image, history_size)
self.previous = before
def swap(self) -> bool:
"""Show the other of the two latest images; False if there is only one."""
if self.current is None or self.previous is None:
return False
self.current, self.previous = self.previous, self.current
return True
def is_idle(self, seconds: float, now: float | None = None) -> bool:
now = time.monotonic() if now is None else now
return self.dirty and now - self.last_interaction >= seconds
def reset(self, lang: str, now: float | None = None) -> None:
self.lang = lang
self.style = None
self.current = None
self.previous = None
self.history = []
self.undo_text = None
self.epoch += 1
self.dirty = False
self.last_interaction = time.monotonic() if now is None else now