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

View File

@@ -80,7 +80,10 @@ export const NotificationCard = ({ notification }: NotificationCardProps) => {
data-float={!!thumb}
className={clsx(styles.headAlignWrapper, styles.closeButton)}
>
<IconButton onClick={onDismiss}>
<IconButton
data-testid="notification-close-button"
onClick={onDismiss}
>
<CloseIcon className={styles.closeIcon} width={16} height={16} />
</IconButton>
</div>

View File

@@ -1,7 +1,6 @@
import * as ScrollArea from '@radix-ui/react-scroll-area';
import clsx from 'clsx';
import type { PropsWithChildren } from 'react';
import { useRef } from 'react';
import * as styles from './index.css';
import { useHasScrollTop } from './use-has-scroll-top';
@@ -24,8 +23,7 @@ export const ScrollableContainer = ({
viewPortClassName,
scrollBarClassName,
}: PropsWithChildren<ScrollableContainerProps>) => {
const ref = useRef<HTMLDivElement>(null);
const hasScrollTop = useHasScrollTop(ref);
const [setContainer, hasScrollTop] = useHasScrollTop();
return (
<ScrollArea.Root
style={_styles}
@@ -37,7 +35,7 @@ export const ScrollableContainer = ({
/>
<ScrollArea.Viewport
className={clsx([styles.scrollableViewport, viewPortClassName])}
ref={ref}
ref={setContainer}
>
<div className={styles.scrollableContainer}>{children}</div>
</ScrollArea.Viewport>

View File

@@ -1,31 +1,27 @@
import type { RefObject } from 'react';
import { useEffect, useState } from 'react';
import { debounce } from 'lodash-es';
import { useMemo, useState } from 'react';
export function useHasScrollTop(ref: RefObject<HTMLElement> | null) {
export function useHasScrollTop() {
const [hasScrollTop, setHasScrollTop] = useState(false);
useEffect(() => {
if (!ref?.current) {
return;
}
const container = ref.current;
function updateScrollTop() {
if (container) {
setTimeout(() => {
const hasScrollTop = container.scrollTop > 0;
setHasScrollTop(hasScrollTop);
});
}
}
container.addEventListener('scroll', updateScrollTop);
updateScrollTop();
return () => {
container.removeEventListener('scroll', updateScrollTop);
const containerRefFn = useMemo(() => {
let unsub: (() => void) | null = null;
return (container: HTMLElement | null) => {
unsub?.();
const updateScrollTop = debounce(() => {
if (container) {
setTimeout(() => {
const hasScrollTop = container.scrollTop > 0;
setHasScrollTop(hasScrollTop);
});
}
}, 50);
container?.addEventListener('scroll', updateScrollTop);
updateScrollTop();
unsub = () => {
container?.removeEventListener('scroll', updateScrollTop);
};
};
}, [ref]);
}, []);
return hasScrollTop;
return [containerRefFn, hasScrollTop] as const;
}