ProgressΒΆ

The Progress widget is used when you need to display the progress of a process.

Code example:

import asyncio

from aiogram.filters import Command
from aiogram.fsm.state import StatesGroup, State
from aiogram.types import Message

from aiogram_dialog import Dialog, Window, DialogManager, BaseDialogManager
from aiogram_dialog.widgets.text import Multi, Const, Progress


class Main(StatesGroup):
    progress = State()


async def get_bg_data(dialog_manager: DialogManager, **kwargs):
    return {
        "progress": dialog_manager.dialog_data.get("progress", 0)
    }


async def background(manager: BaseDialogManager):
    count = 10
    for i in range(1, count + 1):
        await asyncio.sleep(1)
        await manager.update({
            "progress": i * 100 / count,
        })
    await asyncio.sleep(1)
    await manager.done()


dialog = Dialog(
    Window(
        Multi(
            Const("Your click is processing, please wait..."),
            Progress("progress", 10),
        ),
        state=Main.progress,
        getter=get_bg_data,
    ),
)


@dp.message(Command("start"))
async def start_handler(message: Message, dialog_manager: DialogManager):
    await dialog_manager.start(state=Main.progress)
    asyncio.create_task(background(dialog_manager.bg()))

Result:

../../../_images/progress.png

Prevent new messages while Progress is running

When Progress is running and the user sends a message to the bot, aiogram_dialog automatically updates the window and sends a new message. However, you can prevent this by using MessageInput and a handler that sets ShowMode to EDIT mode.

async def set_edit_show_mode(_, __, dialog_manager: DialogManager):
    dialog_manager.show_mode = ShowMode.EDIT


Window(
    Multi(
        Const("Your click is processing, please wait..."),
        Progress("progress", 10),
    ),
    MessageInput(set_edit_show_mode),
    state=Main.progress,
    getter=get_bg_data,
),

Allow the bot to be used while Progress running

If you want to allow the user to use the bot while Progress is running, you can open a window through a background manager, pass a stack_id, and use that manager in a background task.

async def start_bg(callback: CallbackQuery, button: Button,
                   manager: DialogManager):
    bg = manager.bg(
        user_id=callback.from_user.id,
        chat_id=callback.message.chat.id,
        stack_id="progress_stack",
        load=True,
    )
    await bg.start(Bg.progress)
    asyncio.create_task(background(callback, bg))