```
from __future__ import annotations

import random
import threading
import time
from typing import Callable

import flet as ft
from uuid6 import uuid7


class PubSubBus:
    def __init__(self, page: ft.Page):
        self._page = page

    def send(self, topic: str, msg: dict) -> None:
        self._page.pubsub.send_all({"topic": topic, **msg})

    def subscribe(self, topic: str, callback: Callable[[dict], None]) -> None:
        def wrapper(raw: dict):
            if raw.get("topic") == topic:
                callback(raw)

        self._page.pubsub.subscribe(wrapper)


class FletRenderer:
    def __init__(self, page: ft.Page, container: ft.Control):
        self.page = page
        self.container = container

    def add(self, control: ft.Control):
        self.container.controls.append(control)

    def update(self):
        self.page.update()


class Worker(threading.Thread):
    def __init__(
            self,
            bus: PubSubBus,
            task_id: str,
            title: str,
            work_fn: Callable[[Callable[..., None], threading.Event], None],
            cancel_evt: threading.Event,
    ):
        super().__init__(daemon=False)
        self.bus = bus
        self.tid = task_id
        self.title = title
        self.work = work_fn
        self.cancel = cancel_evt

    def _pub(self, typ: str, **kw) -> None:
        self.bus.send("task", {"topic": "task", "type": typ, "task_id": self.tid, **kw})

    def run(self):
        try:
            self._pub("start", text=self.title, value=0)
            self.work(self._pub, self.cancel)
            if not self.cancel.is_set():
                self._pub("done")
        except Exception as e:
            self._pub("error", text=str(e))


class TaskCard(ft.Card):
    def __init__(self, bus: PubSubBus, renderer: FletRenderer, task_id: str, title: str):
        super().__init__(elevation=2, shape=ft.RoundedRectangleBorder(radius=8), width=260)
        self.bus = bus
        self.renderer = renderer
        self.task_id = task_id

        self.title_text = ft.Text(title, weight=ft.FontWeight.BOLD)
        self.progress_bar = ft.ProgressBar(width=220, height=6, value=0)
        self.state_text = ft.Text("待機中", size=12)
        self.cancel_btn = ft.IconButton(ft.Icons.CANCEL, tooltip="キャンセル", on_click=self._on_cancel)

        self.content = ft.Container(
            padding=10,
            content=ft.Column([
                self.title_text,
                self.progress_bar,
                ft.Row([
                    self.state_text,
                    ft.Container(expand=True),
                    self.cancel_btn
                ], vertical_alignment=ft.CrossAxisAlignment.CENTER)
            ], tight=True, spacing=5)
        )
        bus.subscribe("task", self._on_message)

    def _on_message(self, msg: dict):
        if msg.get("task_id") != self.task_id:
            return
        m = msg["type"]
        table = {
            "start": ("開始", 0, None),
            "progress": (None, msg.get("value"), None),
            "done": ("完了", 1, None),
            "canceled": ("キャンセル済", None, ft.Colors.BLUE_200),
            "error": (f"⚠ {msg.get('text')}", None, ft.Colors.RED_300),
        }
        state, val, col = table.get(m, (None, None, None))
        if state is not None:
            self.state_text.value = state
        if val is not None:
            self.progress_bar.value = val
        if col:
            self.progress_bar.color = col
        if m in ("done", "error", "canceled"):
            self.cancel_btn.icon = ft.Icons.DELETE
            self.cancel_btn.tooltip = "カードを削除する"
            self.cancel_btn.on_click = self._on_remove
        self.renderer.update()

    def _on_cancel(self, _) -> None:
        self.bus.send("cancel_request", {"task_id": self.task_id})

    def _on_remove(self, _) -> None:
        self.visible = False
        self.renderer.update()


class TaskManager:
    def __init__(
            self,
            bus: PubSubBus,
            renderer: FletRenderer,
            create_card: Callable[[str, str], TaskCard],
    ):
        self.bus = bus
        self.renderer = renderer
        self.create_card = create_card
        self.cancel_events: dict[str, threading.Event] = {}
        self.count = 0
        bus.subscribe("cancel_request", self._handle_cancel)

    def add_task(
            self,
            work_fn: Callable[[Callable[..., None], threading.Event], None],
            title: str | None = None,
    ) -> None:
        self.count += 1
        tid = uuid7().hex
        title = title or f"Task #{self.count}"
        evt = threading.Event()
        self.cancel_events[tid] = evt

        card = self.create_card(tid, title)
        self.renderer.add(card)
        self.renderer.update()

        Worker(self.bus, tid, title, work_fn, evt).start()

    def _handle_cancel(self, msg: dict) -> None:
        tid = msg.get("task_id")
        evt = self.cancel_events.get(tid)
        if evt:
            evt.set()

    def cancel_all(self) -> None:
        for evt in self.cancel_events.values():
            evt.set()


def main(page: ft.Page) -> None:
    page.title = "Task Cards + PubSub Refactor"
    page.horizontal_alignment = "center"

    tasks = ft.Row(spacing=10, scroll=ft.ScrollMode.ADAPTIVE, expand=True)
    bus = PubSubBus(page)
    renderer = FletRenderer(page, tasks)

    def make_card(tid: str, title: str) -> TaskCard:
        return TaskCard(bus, renderer, tid, title)

    manager = TaskManager(bus, renderer, make_card)
    page.on_disconnect = manager.cancel_all

    # タスク例：フェイクダウンロード
    def fake_download(pub, cancel_evt):
        for i in range(101):
            if cancel_evt.is_set():
                pub("canceled")
                return
            time.sleep(0.05)
            if i == 60 and random.random() < 0.2:
                raise RuntimeError("ネットワークが切断されました")
            pub("progress", value=i / 100)

    # UI
    page.add(
        ft.Column([
            ft.ElevatedButton("フェイクDLを追加", icon=ft.Icons.DOWNLOAD,
                              on_click=lambda _: manager.add_task(fake_download, "Fake Download")),
            ft.Divider(),
            tasks
        ], expand=True)
    )

    # 初期タスク
    manager.add_task(fake_download, "Initial Download")


if __name__ == "__main__":
    ft.app(target=main)
```

Python 3.12, Flet 0.28.3.
結合度を上げることなく、page.run...で実行するように変更できる？