mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-06 11:59:51 +08:00
feat(electron): multi tabs support (#7440)
use https://www.electronjs.org/docs/latest/api/web-contents-view to serve different tab views added tabs view manager in electron to handle multi-view actions and events. fix AF-1111 fix AF-999 fix PD-1459 fix AF-964 PD-1458
This commit is contained in:
@@ -9,6 +9,7 @@ import { useCallback, useState } from 'react';
|
||||
|
||||
import { SignOutModal } from '../components/affine/sign-out-modal';
|
||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { AppTabsHeader } from '../modules/app-tabs-header';
|
||||
import { AuthService } from '../modules/cloud';
|
||||
import { SignIn } from './sign-in';
|
||||
|
||||
@@ -38,6 +39,14 @@ export const PageNotFound = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
{environment.isDesktop ? (
|
||||
<AppTabsHeader
|
||||
style={{
|
||||
paddingLeft: environment.isMacOs ? 80 : 0,
|
||||
}}
|
||||
reportBoundingUpdate
|
||||
/>
|
||||
) : null}
|
||||
{noPermission ? (
|
||||
<NoPermissionOrNotFound
|
||||
user={account}
|
||||
|
||||
@@ -23,7 +23,6 @@ import type { LoaderFunction } from 'react-router-dom';
|
||||
import { redirect, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { WindowsAppControls } from '../components/pure/header/windows-app-controls';
|
||||
import { useMutation } from '../hooks/use-mutation';
|
||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { AuthService, ServerConfigService } from '../modules/cloud';
|
||||
@@ -106,13 +105,7 @@ export const AuthPage = (): ReactElement | null => {
|
||||
|
||||
switch (authType) {
|
||||
case 'onboarding':
|
||||
return (
|
||||
<OnboardingPage
|
||||
user={account}
|
||||
onOpenAffine={onOpenAffine}
|
||||
windowControl={<WindowsAppControls />}
|
||||
/>
|
||||
);
|
||||
return <OnboardingPage user={account} onOpenAffine={onOpenAffine} />;
|
||||
case 'signUp': {
|
||||
return (
|
||||
<SignUpPage
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import { AppFallback } from '../components/affine/app-container';
|
||||
import { UserWithWorkspaceList } from '../components/pure/workspace-slider-bar/user-with-workspace-list';
|
||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { AppTabsHeader } from '../modules/app-tabs-header';
|
||||
import { AuthService } from '../modules/cloud';
|
||||
import { WorkspaceSubPath } from '../shared';
|
||||
|
||||
@@ -147,6 +148,14 @@ export const Component = () => {
|
||||
// TODO(@eyhn): We need a no workspace page
|
||||
return (
|
||||
<>
|
||||
{environment.isDesktop ? (
|
||||
<AppTabsHeader
|
||||
style={{
|
||||
paddingLeft: environment.isMacOs ? 80 : 0,
|
||||
}}
|
||||
reportBoundingUpdate
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
|
||||
@@ -6,7 +6,16 @@ export const mainContainer = style({
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
overflow: 'hidden',
|
||||
borderTop: `1px solid ${cssVar('borderColor')}`,
|
||||
borderTop: `0.5px solid transparent`,
|
||||
transition: 'border-color 0.2s',
|
||||
selectors: {
|
||||
'&[data-dynamic-top-border="false"]': {
|
||||
borderColor: cssVar('borderColor'),
|
||||
},
|
||||
'&[data-has-scroll-top="true"]': {
|
||||
borderColor: cssVar('borderColor'),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const editorContainer = style({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Scrollable } from '@affine/component';
|
||||
import { Scrollable, useHasScrollTop } from '@affine/component';
|
||||
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
|
||||
import type { ChatPanel } from '@affine/core/blocksuite/presets/ai';
|
||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||
@@ -212,18 +212,26 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
||||
view.activeSidebarTab('outline');
|
||||
}, [workbench, view]);
|
||||
|
||||
const [refCallback, hasScrollTop] = useHasScrollTop();
|
||||
const dynamicTopBorder = environment.isDesktop;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ViewHeader>
|
||||
<DetailPageHeader page={doc.blockSuiteDoc} workspace={workspace} />
|
||||
</ViewHeader>
|
||||
<ViewBody>
|
||||
<div className={styles.mainContainer}>
|
||||
<div
|
||||
className={styles.mainContainer}
|
||||
data-dynamic-top-border={dynamicTopBorder}
|
||||
data-has-scroll-top={hasScrollTop}
|
||||
>
|
||||
{/* Add a key to force rerender when page changed, to avoid error boundary persisting. */}
|
||||
<AffineErrorBoundary key={doc.id}>
|
||||
<TopTip pageId={doc.id} workspace={workspace} />
|
||||
<Scrollable.Root>
|
||||
<Scrollable.Viewport
|
||||
ref={refCallback}
|
||||
className={clsx(
|
||||
'affine-page-viewport',
|
||||
styles.affineDocViewport,
|
||||
|
||||
@@ -19,7 +19,10 @@ export const useDetailPageHeaderResponsive = (availableWidth: number) => {
|
||||
const hideToday = availableWidth < 300;
|
||||
|
||||
const showDivider =
|
||||
viewPosition.isLast && !rightSidebarOpen && !(hidePresent && hideShare);
|
||||
viewPosition.isLast &&
|
||||
!rightSidebarOpen &&
|
||||
!(hidePresent && hideShare) &&
|
||||
!environment.isDesktop;
|
||||
|
||||
return {
|
||||
hideShare,
|
||||
|
||||
Reference in New Issue
Block a user