fix(core): shared page mode syncing (#14756)

### Summary
This fixes a few inconsistencies in shared page behavior:
fixes https://github.com/toeverything/AFFiNE/issues/14751
- shared pages now open in the correct published mode when the URL does
not already include ?mode=...
- switching between page and edgeless in shared mode now keeps the URL
query param in sync
- the default Copy Link action now follows the current editor mode
- shared viewers can toggle between page and edgeless mode in readonly
share pages

---

### What Changed
- updated shared page mode resolution to prefer URL mode, with backend
publish mode as fallback
- added query-param syncing for shared page mode changes
- made the default share link copy use:
  - page link in page mode
  - edgeless link in edgeless mode
- allowed EditorModeSwitch to toggle both ways in shared mode
- extracted shared-mode behavior into small hooks to keep share-page.tsx
cleaner

---

### Demo

https://www.loom.com/share/a287172321fb4fc5b94f7c67a39298a9


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Mode switching between page and edgeless no longer blocked by shared
gating; shared pages initialize and respect the resolved editor mode.
* Shared page URLs stay in sync with editor mode and copy-link actions
include/preserve the selected mode.

* **Tests**
* Added tests for publish-mode resolution, query-string mode handling,
and default share-mode behavior.

* **Bug Fixes**
  * Updated shared-page “not found” UI text to match new messaging.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
This commit is contained in:
chauhan_s
2026-04-05 17:50:58 +05:30
committed by GitHub
parent aa48c1c18b
commit f81abe692d
10 changed files with 201 additions and 31 deletions
@@ -3,9 +3,12 @@ import {
registerAffineCommand,
} from '@affine/core/commands';
import { useSharingUrl } from '@affine/core/components/hooks/affine/use-share-url';
import { getDefaultShareMode } from '@affine/core/components/hooks/affine/use-share-url.utils';
import { EditorService } from '@affine/core/modules/editor';
import { useIsActiveView } from '@affine/core/modules/workbench';
import type { WorkspaceMetadata } from '@affine/core/modules/workspace';
import { track } from '@affine/track';
import { useLiveData, useService } from '@toeverything/infra';
import { useEffect } from 'react';
export function useRegisterCopyLinkCommands({
@@ -18,6 +21,7 @@ export function useRegisterCopyLinkCommands({
const isActiveView = useIsActiveView();
const workspaceId = workspaceMeta.id;
const isCloud = workspaceMeta.flavour !== 'local';
const currentMode = useLiveData(useService(EditorService).editor.mode$);
const { onClickCopyLink } = useSharingUrl({
workspaceId,
@@ -42,12 +46,14 @@ export function useRegisterCopyLinkCommands({
icon: null,
run() {
track.$.cmdk.general.copyShareLink();
isActiveView && isCloud && onClickCopyLink();
isActiveView &&
isCloud &&
onClickCopyLink(getDefaultShareMode(currentMode));
},
})
);
return () => {
unsubs.forEach(unsub => unsub());
};
}, [docId, isActiveView, isCloud, onClickCopyLink]);
}, [currentMode, docId, isActiveView, isCloud, onClickCopyLink]);
}
@@ -0,0 +1,7 @@
import type { DocMode } from '@blocksuite/affine/model';
export const getDefaultShareMode = (
currentMode?: DocMode
): DocMode | undefined => {
return currentMode === 'edgeless' ? 'edgeless' : undefined;
};