import { watch } from "vue";
import type { RouteLocationNormalizedLoaded } from "vue-router";
import { useRoute, useRouter } from "vue-router";

const PAGE_QUERY_KEY = "page";

export function readHashPage(defaultPage = 1) {
    if (typeof location === "undefined") {
        return defaultPage;
    }

    return normalizePage(
        new URLSearchParams(hashQueryString()).get(PAGE_QUERY_KEY),
        defaultPage,
    );
}

export function useHashPageQuery(onPageChange?: (page: number) => void) {
    const route = useRoute();
    const router = useRouter();

    function setHashPage(page: number) {
        const normalizedPage = normalizePage(page);
        const query = { ...route.query };
        if (normalizedPage > 1) {
            query[PAGE_QUERY_KEY] = String(normalizedPage);
        } else {
            delete query[PAGE_QUERY_KEY];
        }

        void router.push({ path: route.path, query });
    }

    function resetHashPage() {
        setHashPage(1);
    }

    function handlePageParamChange(value: unknown) {
        canonicalizePageParam(route, router, value);
        onPageChange?.(normalizePage(value));
    }

    watch(
        () => route.query[PAGE_QUERY_KEY],
        (value) => {
            handlePageParamChange(value);
        },
    );

    handlePageParamChange(route.query[PAGE_QUERY_KEY]);

    return {
        setHashPage,
        resetHashPage,
    };
}

function canonicalizePageParam(
    route: RouteLocationNormalizedLoaded,
    router: ReturnType<typeof useRouter>,
    value: unknown,
) {
    if (value === null || normalizePage(value) > 1) {
        return;
    }

    const query = { ...route.query };
    delete query[PAGE_QUERY_KEY];
    void router.replace({ path: route.path, query });
}

function normalizePage(value: unknown, fallback = 1) {
    const page = Number(value);
    if (!Number.isInteger(page) || page < 1) {
        return fallback;
    }

    return page;
}

function hashQueryString() {
    return location.hash.split("?", 2)[1] ?? "";
}
评论加载中...