📁 Changed TDrive root folder (#16)

📁 Changed TDrive root folder
This commit is contained in:
Montassar Ghanmy
2023-04-11 10:04:29 +01:00
committed by GitHub
parent 3b3f67af07
commit e0615fa867
10548 changed files with 48 additions and 48 deletions
@@ -0,0 +1,17 @@
import React, { useEffect, useRef } from 'react';
import HiddenNotificationService from 'components/scroll-hidden-components/hidden-notification-service';
type PropsType = {
tag: string;
};
export default ({ tag }: PropsType) => {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const instance = HiddenNotificationService.get(tag);
instance.addBeacon(ref);
return () => instance.removeBeacon(ref);
}, [tag, ref]);
return <div ref={ref} />;
};
@@ -0,0 +1,123 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Observable from 'app/deprecated/Observable/Observable';
type NodeType = React.RefObject<HTMLDivElement | ChildNode> | React.MutableRefObject<any> | any;
type BeaconRef = {
node: NodeType;
top: number;
};
type ScrollerRef = {
node: NodeType | undefined;
top: number | undefined;
};
type InstanceType = { [key: string]: HiddenNotificationService };
let executionTimeout: any = 0;
class HiddenNotificationService extends Observable {
beacons: BeaconRef[] = [];
scroller: ScrollerRef = { node: undefined, top: undefined };
state: any = {
beaconTop: [],
beaconBottom: [],
};
constructor() {
super();
this.detectHiddenBeacons = this.detectHiddenBeacons.bind(this);
(window as any).HiddenNotificationService = this;
}
public addBeacon(node: NodeType) {
this.removeBeacon(node);
this.beacons.push({
node,
top: 0,
});
if (this.scroller && this.scroller.top) {
this.setBeaconsTop(this.scroller);
}
this.detectHiddenBeacons();
}
public removeBeacon(node: NodeType) {
this.beacons = this.beacons.filter(element => node !== element.node);
this.detectHiddenBeacons();
}
private setBeaconsTop(scroller: ScrollerRef) {
this.beacons.forEach((beacon: BeaconRef) => {
beacon.top =
beacon.node.current.getBoundingClientRect().y -
(scroller.node.getBoundingClientRect().y || 0) +
scroller.node.scrollTop;
});
}
private detectHiddenBeacons() {
if (!this.scroller.node) return;
clearTimeout(executionTimeout);
executionTimeout = setTimeout(() => {
if (!this.scroller.node) {
return;
}
const hidden: any = {
beaconTop: [],
beaconBottom: [],
};
const visibleHeight = this.scroller.node.getBoundingClientRect().height;
const scrollerTop = this.scroller.node.getBoundingClientRect().y || 0;
this.beacons.forEach((beacon: BeaconRef) => {
const top = beacon.node.current.getBoundingClientRect().y - scrollerTop;
if (top > visibleHeight) {
hidden.beaconBottom.push(beacon);
}
if (top < 0) {
hidden.beaconTop.push(beacon);
}
});
this.state = hidden;
this.notify();
}, 500);
}
public setScroller(node: NodeType) {
this.scroller = { node, top: node.getBoundingClientRect().y };
node.addEventListener('scroll', this.detectHiddenBeacons, { passive: true });
window.addEventListener('resize', this.detectHiddenBeacons);
this.setBeaconsTop(this.scroller);
this.detectHiddenBeacons();
}
public removeScroller() {
window.removeEventListener('resize', this.detectHiddenBeacons);
this.scroller = { node: undefined, top: undefined };
if (this.scroller.node) {
this.scroller.node.removeEventListener('scroll', this.detectHiddenBeacons);
}
}
}
export default class HiddenNotificationServiceManager {
static instances: InstanceType = {};
public static get(tag: string) {
if (!this.instances[tag]) {
this.instances[tag] = new HiddenNotificationService();
}
return this.instances[tag];
}
}
@@ -0,0 +1,52 @@
import React, { FC } from 'react';
import { ArrowUp, ArrowDown } from 'react-feather';
import { Button } from 'antd';
import Languages from 'app/features/global/services/languages-service';
import './notifications.scss';
type PropsType = {
icon?: React.ReactNode;
iconSize?: number;
position: 'top' | 'bottom';
type?: 'primary' | 'secondary' | 'warning' | 'important' | undefined;
children?: JSX.Element | string;
onClick?: ((event: React.MouseEvent<HTMLElement, MouseEvent>) => void) | undefined;
};
const HiddenNotificationsButton: FC<PropsType> = ({
children,
icon,
iconSize,
position,
type,
onClick,
}) => {
const setDefaultIcon = (): React.ReactNode => {
const defaultSize = iconSize ? iconSize : 16;
switch (position) {
case !icon && 'top':
return <ArrowUp size={defaultSize} />;
case !icon && 'bottom':
return <ArrowDown size={defaultSize} />;
case icon:
case icon && 'top':
case icon && 'bottom':
return icon;
}
};
return (
<Button
icon={setDefaultIcon()}
className={`hidden-notifications-button ${type ? type : 'primary'} ${position}`}
onClick={onClick && onClick}
>
{(children && children) ||
Languages.t('components.notifications.hidden_notifications_button.children')}
</Button>
);
};
export default HiddenNotificationsButton;
@@ -0,0 +1,100 @@
.scroll-top-component,
.scroll-bottom-component {
background-color: transparent;
max-width: 100%;
position: absolute;
right: 0;
left: 0;
z-index: 1;
display: flex;
justify-content: center;
transition: transform 0.2s;
&.hide {
&.scroll-top-component {
transform: translateY(-100%);
}
&.scroll-bottom-component {
transform: translateY(100%);
}
}
}
.scroll-top-component {
top: 0;
}
.scroll-bottom-component {
bottom: 0;
}
.scroll-children-component {
flex: 1;
display: flex;
overflow: hidden;
position: relative;
}
.hidden-notifications-button {
display: flex !important;
justify-content: center;
align-items: center;
cursor: pointer;
&.ant-btn {
&,
&:focus,
&:active,
&:hover {
color: var(--white);
}
padding: 0px 12px;
display: flex;
margin: 4px;
width: 70%;
height: 24px;
border-radius: 12px;
span {
flex: 1;
}
}
&.primary {
&,
&:focus,
&:active,
&:hover {
background-color: var(--primary);
}
}
&.secondary {
&,
&:focus,
&:active,
&:hover {
background-color: var(--secondary);
}
}
&.warning {
&,
&:focus,
&:active,
&:hover {
background-color: var(--warning);
}
}
&.important {
&,
&:focus,
&:active {
background-color: var(--red);
}
&:hover {
background-color: var(--red);
}
}
}
@@ -0,0 +1,81 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { FC, useEffect, useRef } from 'react';
import HiddenNotificationService from 'components/scroll-hidden-components/hidden-notification-service';
import animateScrollTo from 'animated-scroll-to';
import './notifications.scss';
type PropsType = {
children: JSX.Element | any;
scrollTopComponent?: JSX.Element;
scrollBottomComponent?: JSX.Element;
tag: string;
disabled?: boolean;
};
const ScrollWithHiddenComponents: FC<PropsType> = ({
children,
scrollTopComponent,
scrollBottomComponent,
tag,
disabled,
}) => {
const ref = useRef<any>(null);
const service = HiddenNotificationService.get(tag);
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
if (disabled) {
return;
}
service.setScroller(ref.current.firstChild);
return () => service.removeScroller();
}, [tag, ref, disabled]);
/* eslint-enable react-hooks/exhaustive-deps */
const beacon: number[] = service.useWatcher(() => [
service.state.beaconTop.length,
service.state.beaconBottom.length,
]);
const alignCenter = (node: any) =>
node.current.offsetTop - (service.scroller.node.clientHeight + node.current.clientHeight) / 2;
const optionsScroller = {
elementToScroll: service.scroller.node,
};
const previousBeacon = () => {
const previousNode = service.state.beaconTop.sort((a: any, b: any) => b.top - a.top)?.[0]?.node;
if (previousNode) return animateScrollTo(alignCenter(previousNode), optionsScroller);
};
const nextBeacon = () => {
const nextNode = service.state.beaconBottom.sort((a: any, b: any) => a.top - b.top)?.[0]?.node;
if (nextNode) return animateScrollTo(alignCenter(nextNode), optionsScroller);
};
const hideScrollComponent = (beaconLength: number): string => (beaconLength > 0 ? '' : 'hide');
return (
<>
<div ref={ref} className="scroll-children-component">
{children}
<div
className={`scroll-top-component ${hideScrollComponent(beacon[0])}`}
onClick={previousBeacon}
>
{scrollTopComponent}
</div>
<div
className={`scroll-bottom-component ${hideScrollComponent(beacon[1])}`}
onClick={nextBeacon}
>
{scrollBottomComponent}
</div>
</div>
</>
);
};
export default ScrollWithHiddenComponents;