fix: public sharing performance improvements (#1841)

This commit is contained in:
Philip Okugbe
2026-01-13 16:00:22 +00:00
committed by GitHub
parent 47097969a0
commit 0bbc1c35de
4 changed files with 63 additions and 59 deletions
@@ -269,12 +269,15 @@ function Node({ node, style, dragHandle, tree }: NodeRendererProps<any>) {
const toggleMobileSidebar = useToggleSidebar(mobileSidebarAtom);
const prefetchPage = () => {
timerRef.current = setTimeout(() => {
queryClient.prefetchQuery({
queryKey: ["pages", node.data.slugId],
queryFn: () => getPageById({ pageId: node.data.slugId }),
timerRef.current = setTimeout(async () => {
const page = await queryClient.fetchQuery({
queryKey: ["pages", node.data.id],
queryFn: () => getPageById({ pageId: node.data.id }),
staleTime: 5 * 60 * 1000,
});
if (page?.slugId) {
queryClient.setQueryData(["pages", page.slugId], page);
}
}, 150);
};
@@ -8,7 +8,6 @@ import {
Switch,
Text,
TextInput,
Tooltip,
} from "@mantine/core";
import { IconExternalLink, IconWorld, IconLock } from "@tabler/icons-react";
import React, { useEffect, useMemo, useState } from "react";
@@ -21,12 +20,12 @@ import {
import { Link, useNavigate, useParams } from "react-router-dom";
import { extractPageSlugId, getPageIcon } from "@/lib";
import { useTranslation } from "react-i18next";
import { usePageQuery } from "@/features/page/queries/page-query.ts";
import CopyTextButton from "@/components/common/copy.tsx";
import { getAppUrl, isCloud } from "@/lib/config.ts";
import { buildPageUrl } from "@/features/page/page.utils.ts";
import classes from "@/features/share/components/share.module.css";
import useTrial from "@/ee/hooks/use-trial.tsx";
import { getCheckoutLink } from "@/ee/billing/services/billing-service.ts";
interface ShareModalProps {
readOnly: boolean;
@@ -35,7 +34,9 @@ export default function ShareModal({ readOnly }: ShareModalProps) {
const { t } = useTranslation();
const navigate = useNavigate();
const { pageSlug } = useParams();
const pageId = extractPageSlugId(pageSlug);
const pageSlugId = extractPageSlugId(pageSlug);
const { data: page } = usePageQuery({ pageId: pageSlugId });
const pageId = page?.id;
const { data: share } = useShareForPageQuery(pageId);
const { spaceSlug } = useParams();
const { isTrial } = useTrial();
@@ -27,9 +27,7 @@ import {
getShares,
updateShare,
} from "@/features/share/services/share-service.ts";
import { IPage } from "@/features/page/types/page.types.ts";
import { IPagination, QueryParams } from "@/lib/types.ts";
import { useEffect } from "react";
export function useGetSharesQuery(
params?: QueryParams,
@@ -72,7 +70,7 @@ export function useShareForPageQuery(
queryKey: ["share-for-page", pageId],
queryFn: () => getShareForPage(pageId),
enabled: !!pageId,
staleTime: 0,
staleTime: 60 * 1000,
retry: false,
});
+51 -49
View File
@@ -123,80 +123,82 @@ export class ShareService {
.withRecursive('page_hierarchy', (cte) =>
cte
.selectFrom('pages')
.leftJoin('shares', 'shares.pageId', 'pages.id')
.select([
'id',
'slugId',
'pages.id',
'pages.slugId',
'pages.title',
'pages.icon',
'parentPageId',
'pages.parentPageId',
sql`0`.as('level'),
'shares.id as shareId',
'shares.key as shareKey',
'shares.includeSubPages',
'shares.searchIndexing',
'shares.creatorId',
'shares.spaceId',
'shares.workspaceId',
'shares.createdAt',
])
.where(isValidUUID(pageId) ? 'id' : 'slugId', '=', pageId)
.where('deletedAt', 'is', null)
.unionAll((union) =>
union
.selectFrom('pages as p')
.select([
'p.id',
'p.slugId',
'p.title',
'p.icon',
'p.parentPageId',
// Increase the level by 1 for each ancestor.
sql`ph.level + 1`.as('level'),
])
.innerJoin('page_hierarchy as ph', 'ph.parentPageId', 'p.id')
.where('p.deletedAt', 'is', null),
.where(isValidUUID(pageId) ? 'pages.id' : 'pages.slugId', '=', pageId)
.where('pages.deletedAt', 'is', null)
.unionAll(
(union) =>
union
.selectFrom('pages as p')
.innerJoin('page_hierarchy as ph', 'ph.parentPageId', 'p.id')
.leftJoin('shares as s', 's.pageId', 'p.id')
.select([
'p.id',
'p.slugId',
'p.title',
'p.icon',
'p.parentPageId',
sql`ph.level + 1`.as('level'),
's.id as shareId',
's.key as shareKey',
's.includeSubPages',
's.searchIndexing',
's.creatorId',
's.spaceId',
's.workspaceId',
's.createdAt',
])
.where('p.deletedAt', 'is', null)
.where(sql`ph.share_id`, 'is', null) // stop if share found
.where(sql`ph.level`, '<', sql`25`), // prevent loop
),
)
.selectFrom('page_hierarchy')
.leftJoin('shares', 'shares.pageId', 'page_hierarchy.id')
.select([
'page_hierarchy.id as sharedPageId',
'page_hierarchy.slugId as sharedPageSlugId',
'page_hierarchy.title as sharedPageTitle',
'page_hierarchy.icon as sharedPageIcon',
'page_hierarchy.level as level',
'shares.id',
'shares.key',
'shares.pageId',
'shares.includeSubPages',
'shares.searchIndexing',
'shares.creatorId',
'shares.spaceId',
'shares.workspaceId',
'shares.createdAt',
'shares.updatedAt',
])
.where('shares.id', 'is not', null)
.orderBy('page_hierarchy.level', 'asc')
.selectAll()
.where('shareId', 'is not', null)
.limit(1)
.executeTakeFirst();
if (!share || share.workspaceId != workspaceId) {
if (!share || share.workspaceId !== workspaceId) {
return undefined;
}
if (share.level === 1 && !share.includeSubPages) {
// we can only show a page if its shared ancestor permits it
if ((share.level as number) > 0 && !share.includeSubPages) {
return undefined;
}
return {
id: share.id,
key: share.key,
id: share.shareId,
key: share.shareKey,
includeSubPages: share.includeSubPages,
searchIndexing: share.searchIndexing,
pageId: share.pageId,
pageId: share.id,
creatorId: share.creatorId,
spaceId: share.spaceId,
workspaceId: share.workspaceId,
createdAt: share.createdAt,
level: share.level,
sharedPage: {
id: share.sharedPageId,
slugId: share.sharedPageSlugId,
title: share.sharedPageTitle,
icon: share.sharedPageIcon,
id: share.id,
slugId: share.slugId,
title: share.title,
icon: share.icon,
},
};
}