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:
pengx17
2024-07-29 11:05:22 +00:00
parent 622715d2f3
commit 1efc1d0f5b
88 changed files with 3160 additions and 945 deletions
+9
View File
@@ -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}
+1 -8
View File
@@ -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,