Skip to content

Instantly share code, notes, and snippets.

@lexuzieel
Last active June 7, 2023 22:32
Show Gist options
  • Select an option

  • Save lexuzieel/2673f9a15fa1d8ab3e3078aa524650a4 to your computer and use it in GitHub Desktop.

Select an option

Save lexuzieel/2673f9a15fa1d8ab3e3078aa524650a4 to your computer and use it in GitHub Desktop.
grammY menu history middleware

Usage

Extend your session data with navigation data flavor

export type SessionData = {
    // Your custom session data here
} & NavigationHistorySessionFlavor;

Use middleware when building menus

import { history } from "./utils/history";

const main = new Menu("main")
// Add "main" menu to the history stack
.submenu("Go to submenu1", "submenu1", history.add("main"));

const submenu1 = new Menu("submenu1")
// Pop "main" menu from the stack and navigate back to it
.text("Back", history.back);
.row()
// Add "submenu1" menu to the history stack
.submenu("Go to submenu 2", "submenu2", history.add("submenu1"));

const submenu2 = new Menu("submenu2")
// Pop "submenu1" menu from the stack and navigate back to it
.text("Back", history.back);

main.register([submenu1, submenu2]);

How it works

Under the hood it extends session object with _navigationHistory?: string[] array which acts as navigation history stack.

import { MenuFlavor } from "@grammyjs/menu";
import { Context, SessionFlavor } from "grammy";
export interface NavigationHistorySessionFlavor {
_navigationHistory?: string[];
}
type ContextWithHistorySessionData = Context &
SessionFlavor<NavigationHistorySessionFlavor>;
export const history = {
/**
* Deletes the navigation history from the session data of the given context.
*
* @param {ContextWithHistorySessionData} ctx - The context with session data.
*/
delete: (ctx: ContextWithHistorySessionData) => {
ctx.session._navigationHistory = undefined;
},
/**
* Returns a middleware function that adds the given menu to the navigation history.
* If the navigation history does not exist in the context, it is created.
*
* @param {string} menu - The menu id to add to the navigation history.
*/
add: (menu: string) => {
return (ctx: ContextWithHistorySessionData) => {
if (!ctx.session._navigationHistory) {
ctx.session._navigationHistory = [];
}
ctx.session._navigationHistory.push(menu);
};
},
/**
* Middleware function that navigates back in the menu history.
* If there is an error (i.e. invalid menu id in the history),
* then the navigation history is deleted.
*
* @param {ContextWithHistorySessionData & MenuFlavor} ctx The context with history session data and menu flavor.
*/
back: (ctx: ContextWithHistorySessionData & MenuFlavor) => {
const menu = ctx.session._navigationHistory?.pop();
if (menu) {
try {
ctx.menu.nav(menu);
} catch (e) {
history.delete(ctx);
}
}
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment