@ant-design/icons#FullscreenExitOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#FullscreenExitOutlined. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From covid_dashboard with MIT License 6 votes vote down vote up
render() {
        return <div className='search-box'>
            {this.state.items.length > 0 && <div className="search-result" style={{width: this.state.size === 'small' ? 300 : 450}}>
                <div className="search-control">
                    <div className="control-btn" onClick={() => this.setState({size: this.state.size === 'small' ? 'large' : 'small'})}>{this.state.size === 'small' ? <FullscreenOutlined/> : <FullscreenExitOutlined/>}</div>
                    <div className="control-btn" onClick={() => this.setState({items: []})}><CloseCircleOutlined/></div>
                </div>
                <div className="search-items" style={{maxHeight: this.state.size === 'small' ? 350 : 500}}>
                {this.state.items.map(item => {
                    return <div key={item._id} className="search-item" onClick={() => this.onClickEvent(item)}>
                        <div className="event-type" style={{background: getEventColor(item.type)}}>{_.capitalize(item.type)}</div>
                        <div className="event-time">{item.time}</div>
                        <div className="event-title">{item.title}</div>
                    </div>
                })}
                </div>
            </div>}
            <div className="search-input">
                <Input.Search placeholder={this.props.intl.formatMessage({id: "search.placeholder"})} onChange={(e) => this.search(e.target.value)} onSearch={(text) => this.search(text)} loading={this.state.loading}/><span className='close' onClick={() => this.props.onClose && this.props.onClose()}><CloseCircleOutlined/></span>
            </div>
        </div>
    }
Example #2
Source File: fitWindow.tsx    From imove with MIT License 6 votes vote down vote up
FitWindow: React.FC<IProps> = makeBtnWidget({
  tooltip: '适配窗口',
  getIcon() {
    return <FullscreenExitOutlined />;
  },
  handler(flowChart: Graph) {
    flowChart.zoomToFit({ minScale: 0.5, maxScale: 1 });
  },
})
Example #3
Source File: BuildingPanelCommon.tsx    From condo with MIT License 6 votes vote down vote up
BuildingChooseSections: React.FC<IBuildingChooseSectionsProps> = (props) => {
    const intl = useIntl()
    const RequestFullscreenMessage = intl.formatMessage({ id: 'FullscreenRequest' })
    const ExitFullscreenMessage = intl.formatMessage({ id: 'FullscreenExit' })

    const {
        toggleFullscreen,
        isFullscreen,
        mode = 'view',
        children,
    } = props

    return (

        <Row
            css={FullscreenFooter}
            gutter={FULLSCREEN_FOOTER_GUTTER}
        >
            <Col>
                {mode === 'view' ? (
                    <Button
                        style={FULLSCREEN_BUTTON_STYLE}
                        type={'sberDefaultGradient'}
                        secondary
                        icon={isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
                        size={'large'}
                        onClick={toggleFullscreen}
                    >
                        {isFullscreen
                            ? ExitFullscreenMessage
                            : RequestFullscreenMessage}
                    </Button>
                ) : children}
            </Col>
        </Row>

    )
}
Example #4
Source File: Tile.tsx    From ant-extensions with MIT License 5 votes vote down vote up
Tile: React.FC<ITileConfig> = React.memo((item) => {
  const { isEditing, editWidget, renderWidget, findWidget } = useContext(Context);
  const style = useMemo(
    () => ({
      color: item.color || "inherit"
    }),
    [item.color]
  );

  const [expanded, setExpanded] = useState(false);

  const widget = useMemo(() => findWidget(item.widgetId), [findWidget, item.widgetId]);

  return (
    <Item item={item} expanded={!isEditing && expanded}>
      <div className="ant-ext-pm__tileHead">
        <span style={style}>{item.iconCls && <i className={item.iconCls} />}</span>
        <label style={style}>{item.title}</label>
        <div>
          {item.info && (
            <Tooltip
              overlay={<pre dangerouslySetInnerHTML={{ __html: item.info }} />}
              overlayClassName="ant-ext-pm__tileInfo"
            >
              <button>
                <InfoCircleOutlined />
              </button>
            </Tooltip>
          )}
          {!isEditing && item.expandable && (
            <button className="ant-ext-pm__tileExpander" onClick={() => setExpanded(!expanded)}>
              {expanded ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
            </button>
          )}
          {isEditing && (
            <button onClick={() => editWidget(item.widgetId)}>
              <EditOutlined />
            </button>
          )}
        </div>
      </div>
      <div className="ant-ext-pm__tileBody">
        {!isEditing && renderWidget(item.widgetId)}
        {isEditing && widget && (
          <div style={{ placeSelf: "center", textAlign: "center" }}>
            {widget.icon}
            <div>{widget.title}</div>
          </div>
        )}
      </div>
    </Item>
  );
})
Example #5
Source File: Header.tsx    From react_admin with MIT License 4 votes vote down vote up
Headers: React.FC<Iprops> = (props) => {
  const { collapsed } = props;
  const [fullScreen, setFullScreen] = useState(false); // 当前是否是全屏状态
  // 进入全屏
  const requestFullScreen = useCallback(() => {
    const element: HTMLElement & Element = document.documentElement;
    // 判断各种浏览器,找到正确的方法
    const requestMethod =
      element.requestFullscreen || // W3C
      element.webkitRequestFullscreen || // Chrome等
      element.mozRequestFullScreen || // FireFox
      element.msRequestFullscreen; // IE11
    if (requestMethod) {
      requestMethod.call(element);
    }
    setFullScreen(true);
  }, []);

  // 退出登录
  const onMenuClick = useCallback(
    (e) => {
      // 退出按钮被点击
      if (e.key === "logout") {
        props.onLogout();
      }
    },
    [props]
  );

  // 退出全屏
  const exitFullScreen = useCallback(() => {
    // 判断各种浏览器,找到正确的方法
    const element: Document & Element = document;
    const exitMethod =
      element.exitFullscreen || // W3C
      element.mozCancelFullScreen || // firefox
      element.webkitExitFullscreen || // Chrome等
      element.msExitFullscreen; // IE11

    if (exitMethod) {
      exitMethod.call(document);
    }
    setFullScreen(false);
  }, []);
  const toggle = () => {
    props.setColl(!collapsed);
  };
  return (
    <Header className="site-layout-background header" style={{ padding: 0 }}>
      <Tooltip title={props.collapsed ? "展开菜单" : "收起菜单"}>
        {React.createElement(
          collapsed ? MenuUnfoldOutlined : MenuFoldOutlined,
          {
            className: "trigger",
            onClick: toggle,
          }
        )}
      </Tooltip>
      <div className="rightBox">
        <Tooltip placement="bottom" title={fullScreen ? "退出全屏" : "全屏"}>
          <div className="full all_center">
            {fullScreen ? (
              <FullscreenExitOutlined
                className="icon"
                onClick={exitFullScreen}
              />
            ) : (
              <FullscreenOutlined
                className="icon"
                onClick={requestFullScreen}
              />
            )}
          </div>
        </Tooltip>
        <Dropdown
          overlay={
            <Menu className="menu" selectedKeys={[]} onClick={onMenuClick}>
              <Menu.Item key="user">
                <Link to="/home/user/admin">
                  <UserOutlined />
                  个人中心
                </Link>
              </Menu.Item>
              <Menu.Item key="message">
                <Link to="/home/user/level">
                  <MessageOutlined />
                  个人设置
                </Link>
              </Menu.Item>
              <Menu.Divider />
              <Menu.Item key="logout">
                <LogoutOutlined />
                退出登录
              </Menu.Item>
            </Menu>
          }
          placement="bottomRight"
        >
          <div className="userhead all_center">
            <SmileOutlined />
            <span className="username">admin</span>
          </div>
        </Dropdown>
      </div>
    </Header>
  );
}
Example #6
Source File: DashboardHeader.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function DashboardHeader(): JSX.Element {
    const { dashboard, dashboardMode, lastDashboardModeSource } = useValues(dashboardLogic)
    const { addNewDashboard, triggerDashboardUpdate, setDashboardMode, addGraph, saveNewTag, deleteTag } =
        useActions(dashboardLogic)
    const { dashboardTags } = useValues(dashboardsLogic)
    const { nameSortedDashboards, dashboardsLoading, dashboardLoading } = useValues(dashboardsModel)
    const { pinDashboard, unpinDashboard, deleteDashboard, duplicateDashboard } = useActions(dashboardsModel)
    const { user } = useValues(userLogic)
    const [newName, setNewName] = useState(dashboard?.name || null) // Used to update the input immediately, debouncing API calls

    const nameInputRef = useRef<Input | null>(null)
    const descriptionInputRef = useRef<HTMLInputElement | null>(null)

    if (!dashboard) {
        return <div />
    }

    const actionsDefault = (
        <>
            <Dropdown
                trigger={['click']}
                overlay={
                    <Menu>
                        {dashboard.created_by && (
                            <>
                                <Menu.Item disabled>
                                    Created by {dashboard.created_by.first_name || dashboard.created_by.email || '-'} on{' '}
                                    {dayjs(dashboard.created_at).format(
                                        dayjs(dashboard.created_at).year() === dayjs().year()
                                            ? 'MMMM Do'
                                            : 'MMMM Do YYYY'
                                    )}
                                </Menu.Item>
                                <Menu.Divider />
                            </>
                        )}
                        <Menu.Item
                            icon={<EditOutlined />}
                            onClick={() => setDashboardMode(DashboardMode.Edit, DashboardEventSource.MoreDropdown)}
                        >
                            Edit mode (E)
                        </Menu.Item>
                        <Menu.Item
                            icon={<FullscreenOutlined />}
                            onClick={() =>
                                setDashboardMode(DashboardMode.Fullscreen, DashboardEventSource.MoreDropdown)
                            }
                        >
                            Full screen mode (F)
                        </Menu.Item>
                        {dashboard.pinned ? (
                            <Menu.Item
                                icon={<PushpinFilled />}
                                onClick={() => unpinDashboard(dashboard.id, DashboardEventSource.MoreDropdown)}
                            >
                                Unpin dashboard
                            </Menu.Item>
                        ) : (
                            <Menu.Item
                                icon={<PushpinOutlined />}
                                onClick={() => pinDashboard(dashboard.id, DashboardEventSource.MoreDropdown)}
                            >
                                Pin dashboard
                            </Menu.Item>
                        )}

                        <Menu.Divider />
                        <Menu.Item
                            icon={<CopyOutlined />}
                            onClick={() => duplicateDashboard({ id: dashboard.id, name: dashboard.name, show: true })}
                        >
                            Duplicate dashboard
                        </Menu.Item>
                        <Menu.Item
                            icon={<DeleteOutlined />}
                            onClick={() => deleteDashboard({ id: dashboard.id, redirect: true })}
                            danger
                        >
                            Delete dashboard
                        </Menu.Item>
                    </Menu>
                }
                placement="bottomRight"
            >
                <Button type="link" className="btn-lg-2x" data-attr="dashboard-more" icon={<EllipsisOutlined />} />
            </Dropdown>
            <Button
                type="link"
                data-attr="dashboard-edit-mode"
                icon={<EditOutlined />}
                onClick={() => setDashboardMode(DashboardMode.Edit, DashboardEventSource.DashboardHeader)}
            />
            <HotkeyButton
                onClick={() => addGraph()}
                data-attr="dashboard-add-graph-header"
                icon={<PlusOutlined />}
                hotkey="n"
                className="hide-lte-md"
            >
                New insight
            </HotkeyButton>
            <HotkeyButton
                type="primary"
                onClick={() => setDashboardMode(DashboardMode.Sharing, DashboardEventSource.DashboardHeader)}
                data-attr="dashboard-share-button"
                icon={<ShareAltOutlined />}
                hotkey="k"
            >
                Send or share
            </HotkeyButton>
        </>
    )

    const actionsPresentationMode = (
        <Button
            onClick={() => setDashboardMode(null, DashboardEventSource.DashboardHeader)}
            data-attr="dashboard-exit-presentation-mode"
            icon={<FullscreenExitOutlined />}
        >
            Exit full screen mode
        </Button>
    )

    const actionsEditMode = (
        <Button
            data-attr="dashboard-edit-mode-save"
            type="primary"
            onClick={() => setDashboardMode(null, DashboardEventSource.DashboardHeader)}
            tabIndex={10}
        >
            Finish editing
        </Button>
    )

    useEffect(() => {
        if (dashboardMode === DashboardMode.Edit) {
            if (lastDashboardModeSource === DashboardEventSource.AddDescription) {
                setTimeout(() => descriptionInputRef.current?.focus(), 10)
            } else if (!isMobile()) {
                setTimeout(() => nameInputRef.current?.focus(), 10)
            }
        }
    }, [dashboardMode])

    return (
        <>
            <div className={`dashboard-header${dashboardMode === DashboardMode.Fullscreen ? ' full-screen' : ''}`}>
                {dashboardMode === DashboardMode.Fullscreen && (
                    <FullScreen onExit={() => setDashboardMode(null, DashboardEventSource.Browser)} />
                )}
                <ShareModal
                    onCancel={() => setDashboardMode(null, DashboardEventSource.Browser)}
                    visible={dashboardMode === DashboardMode.Sharing}
                />
                {dashboardsLoading ? (
                    <Loading />
                ) : (
                    <>
                        {dashboardMode === DashboardMode.Edit ? (
                            <Input
                                placeholder="Dashboard name (e.g. Weekly KPIs)"
                                value={newName || ''}
                                size="large"
                                style={{ maxWidth: 400 }}
                                onChange={(e) => {
                                    setNewName(e.target.value) // To update the input immediately
                                    triggerDashboardUpdate({ name: e.target.value }) // This is breakpointed (i.e. debounced) to avoid multiple API calls
                                }}
                                onKeyDown={(e) => {
                                    if (e.key === 'Enter') {
                                        setDashboardMode(null, DashboardEventSource.InputEnter)
                                    }
                                }}
                                ref={nameInputRef}
                                tabIndex={0}
                            />
                        ) : (
                            <div className="dashboard-select">
                                <Select
                                    value={(dashboard?.id || undefined) as number | 'new' | undefined}
                                    onChange={(id) => {
                                        if (id === 'new') {
                                            addNewDashboard()
                                        } else {
                                            router.actions.push(urls.dashboard(id))
                                            eventUsageLogic.actions.reportDashboardDropdownNavigation()
                                        }
                                    }}
                                    bordered={false}
                                    dropdownMatchSelectWidth={false}
                                >
                                    {nameSortedDashboards.map((dash: DashboardType) => (
                                        <Select.Option key={dash.id} value={dash.id}>
                                            {dash.name || <span style={{ color: 'var(--muted)' }}>Untitled</span>}
                                            {dash.is_shared && (
                                                <Tooltip title="This dashboard is publicly shared">
                                                    <ShareAltOutlined style={{ marginLeft: 4, float: 'right' }} />
                                                </Tooltip>
                                            )}
                                        </Select.Option>
                                    ))}
                                    <Select.Option value="new">+ New Dashboard</Select.Option>
                                </Select>
                            </div>
                        )}

                        <div className="dashboard-meta">
                            {dashboardMode === DashboardMode.Edit
                                ? actionsEditMode
                                : dashboardMode === DashboardMode.Fullscreen
                                ? actionsPresentationMode
                                : actionsDefault}
                        </div>
                    </>
                )}
            </div>
            {user?.organization?.available_features?.includes(AvailableFeature.DASHBOARD_COLLABORATION) && (
                <>
                    <div className="mb" data-attr="dashboard-tags">
                        <ObjectTags
                            tags={dashboard.tags}
                            onTagSave={saveNewTag}
                            onTagDelete={deleteTag}
                            saving={dashboardLoading}
                            tagsAvailable={dashboardTags.filter((tag) => !dashboard.tags.includes(tag))}
                        />
                    </div>
                    <Description
                        item={dashboard}
                        setItemMode={setDashboardMode}
                        itemMode={dashboardMode}
                        triggerItemUpdate={triggerDashboardUpdate}
                        descriptionInputRef={descriptionInputRef}
                    />
                </>
            )}
        </>
    )
}
Example #7
Source File: Icon.tsx    From html2sketch with MIT License 4 votes vote down vote up
IconSymbol: FC = () => {
  return (
    <Row>
      {/*<CaretUpOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
      {/*/>*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
      {/*/>*/}
      {/*<StepBackwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      {/*<StepForwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      <StepForwardOutlined />
      <ShrinkOutlined />
      <ArrowsAltOutlined />
      <DownOutlined />
      <UpOutlined />
      <LeftOutlined />
      <RightOutlined />
      <CaretUpOutlined />
      <CaretDownOutlined />
      <CaretLeftOutlined />
      <CaretRightOutlined />
      <VerticalAlignTopOutlined />
      <RollbackOutlined />
      <FastBackwardOutlined />
      <FastForwardOutlined />
      <DoubleRightOutlined />
      <DoubleLeftOutlined />
      <VerticalLeftOutlined />
      <VerticalRightOutlined />
      <VerticalAlignMiddleOutlined />
      <VerticalAlignBottomOutlined />
      <ForwardOutlined />
      <BackwardOutlined />
      <EnterOutlined />
      <RetweetOutlined />
      <SwapOutlined />
      <SwapLeftOutlined />
      <SwapRightOutlined />
      <ArrowUpOutlined />
      <ArrowDownOutlined />
      <ArrowLeftOutlined />
      <ArrowRightOutlined />
      <LoginOutlined />
      <LogoutOutlined />
      <MenuFoldOutlined />
      <MenuUnfoldOutlined />
      <BorderBottomOutlined />
      <BorderHorizontalOutlined />
      <BorderInnerOutlined />
      <BorderOuterOutlined />
      <BorderLeftOutlined />
      <BorderRightOutlined />
      <BorderTopOutlined />
      <BorderVerticleOutlined />
      <PicCenterOutlined />
      <PicLeftOutlined />
      <PicRightOutlined />
      <RadiusBottomleftOutlined />
      <RadiusBottomrightOutlined />
      <RadiusUpleftOutlined />
      <RadiusUprightOutlined />
      <FullscreenOutlined />
      <FullscreenExitOutlined />
      <QuestionOutlined />
      <PauseOutlined />
      <MinusOutlined />
      <PauseCircleOutlined />
      <InfoOutlined />
      <CloseOutlined />
      <ExclamationOutlined />
      <CheckOutlined />
      <WarningOutlined />
      <IssuesCloseOutlined />
      <StopOutlined />
      <EditOutlined />
      <CopyOutlined />
      <ScissorOutlined />
      <DeleteOutlined />
      <SnippetsOutlined />
      <DiffOutlined />
      <HighlightOutlined />
      <AlignCenterOutlined />
      <AlignLeftOutlined />
      <AlignRightOutlined />
      <BgColorsOutlined />
      <BoldOutlined />
      <ItalicOutlined />
      <UnderlineOutlined />
      <StrikethroughOutlined />
      <RedoOutlined />
      <UndoOutlined />
      <ZoomInOutlined />
      <ZoomOutOutlined />
      <FontColorsOutlined />
      <FontSizeOutlined />
      <LineHeightOutlined />
      <SortAscendingOutlined />
      <SortDescendingOutlined />
      <DragOutlined />
      <OrderedListOutlined />
      <UnorderedListOutlined />
      <RadiusSettingOutlined />
      <ColumnWidthOutlined />
      <ColumnHeightOutlined />
      <AreaChartOutlined />
      <PieChartOutlined />
      <BarChartOutlined />
      <DotChartOutlined />
      <LineChartOutlined />
      <RadarChartOutlined />
      <HeatMapOutlined />
      <FallOutlined />
      <RiseOutlined />
      <StockOutlined />
      <BoxPlotOutlined />
      <FundOutlined />
      <SlidersOutlined />
      <AndroidOutlined />
      <AppleOutlined />
      <WindowsOutlined />
      <IeOutlined />
      <ChromeOutlined />
      <GithubOutlined />
      <AliwangwangOutlined />
      <DingdingOutlined />
      <WeiboSquareOutlined />
      <WeiboCircleOutlined />
      <TaobaoCircleOutlined />
      <Html5Outlined />
      <WeiboOutlined />
      <TwitterOutlined />
      <WechatOutlined />
      <AlipayCircleOutlined />
      <TaobaoOutlined />
      <SkypeOutlined />
      <FacebookOutlined />
      <CodepenOutlined />
      <CodeSandboxOutlined />
      <AmazonOutlined />
      <GoogleOutlined />
      <AlipayOutlined />
      <AntDesignOutlined />
      <AntCloudOutlined />
      <ZhihuOutlined />
      <SlackOutlined />
      <SlackSquareOutlined />
      <BehanceSquareOutlined />
      <DribbbleOutlined />
      <DribbbleSquareOutlined />
      <InstagramOutlined />
      <YuqueOutlined />
      <AlibabaOutlined />
      <YahooOutlined />
      <RedditOutlined />
      <SketchOutlined />
      <AccountBookOutlined />
      <AlertOutlined />
      <ApartmentOutlined />
      <ApiOutlined />
      <QqOutlined />
      <MediumWorkmarkOutlined />
      <GitlabOutlined />
      <MediumOutlined />
      <GooglePlusOutlined />
      <AppstoreAddOutlined />
      <AppstoreOutlined />
      <AudioOutlined />
      <AudioMutedOutlined />
      <AuditOutlined />
      <BankOutlined />
      <BarcodeOutlined />
      <BarsOutlined />
      <BellOutlined />
      <BlockOutlined />
      <BookOutlined />
      <BorderOutlined />
      <BranchesOutlined />
      <BuildOutlined />
      <BulbOutlined />
      <CalculatorOutlined />
      <CalendarOutlined />
      <CameraOutlined />
      <CarOutlined />
      <CarryOutOutlined />
      <CiCircleOutlined />
      <CiOutlined />
      <CloudOutlined />
      <ClearOutlined />
      <ClusterOutlined />
      <CodeOutlined />
      <CoffeeOutlined />
      <CompassOutlined />
      <CompressOutlined />
      <ContactsOutlined />
      <ContainerOutlined />
      <ControlOutlined />
      <CopyrightCircleOutlined />
      <CopyrightOutlined />
      <CreditCardOutlined />
      <CrownOutlined />
      <CustomerServiceOutlined />
      <DashboardOutlined />
      <DatabaseOutlined />
      <DeleteColumnOutlined />
      <DeleteRowOutlined />
      <DisconnectOutlined />
      <DislikeOutlined />
      <DollarCircleOutlined />
      <DollarOutlined />
      <DownloadOutlined />
      <EllipsisOutlined />
      <EnvironmentOutlined />
      <EuroCircleOutlined />
      <EuroOutlined />
      <ExceptionOutlined />
      <ExpandAltOutlined />
      <ExpandOutlined />
      <ExperimentOutlined />
      <ExportOutlined />
      <EyeOutlined />
      <FieldBinaryOutlined />
      <FieldNumberOutlined />
      <FieldStringOutlined />
      <DesktopOutlined />
      <DingtalkOutlined />
      <FileAddOutlined />
      <FileDoneOutlined />
      <FileExcelOutlined />
      <FileExclamationOutlined />
      <FileOutlined />
      <FileImageOutlined />
      <FileJpgOutlined />
      <FileMarkdownOutlined />
      <FilePdfOutlined />
      <FilePptOutlined />
      <FileProtectOutlined />
      <FileSearchOutlined />
      <FileSyncOutlined />
      <FileTextOutlined />
      <FileUnknownOutlined />
      <FileWordOutlined />
      <FilterOutlined />
      <FireOutlined />
      <FlagOutlined />
      <FolderAddOutlined />
      <FolderOutlined />
      <FolderOpenOutlined />
      <ForkOutlined />
      <FormatPainterOutlined />
      <FrownOutlined />
      <FunctionOutlined />
      <FunnelPlotOutlined />
      <GatewayOutlined />
      <GifOutlined />
      <GiftOutlined />
      <GlobalOutlined />
      <GoldOutlined />
      <GroupOutlined />
      <HddOutlined />
      <HeartOutlined />
      <HistoryOutlined />
      <HomeOutlined />
      <HourglassOutlined />
      <IdcardOutlined />
      <ImportOutlined />
      <InboxOutlined />
      <InsertRowAboveOutlined />
      <InsertRowBelowOutlined />
      <InsertRowLeftOutlined />
      <InsertRowRightOutlined />
      <InsuranceOutlined />
      <InteractionOutlined />
      <KeyOutlined />
      <LaptopOutlined />
      <LayoutOutlined />
      <LikeOutlined />
      <LineOutlined />
      <LinkOutlined />
      <Loading3QuartersOutlined />
      <LoadingOutlined />
      <LockOutlined />
      <MailOutlined />
      <ManOutlined />
      <MedicineBoxOutlined />
      <MehOutlined />
      <MenuOutlined />
      <MergeCellsOutlined />
      <MessageOutlined />
      <MobileOutlined />
      <MoneyCollectOutlined />
      <MonitorOutlined />
      <MoreOutlined />
      <NodeCollapseOutlined />
      <NodeExpandOutlined />
      <NodeIndexOutlined />
      <NotificationOutlined />
      <NumberOutlined />
      <PaperClipOutlined />
      <PartitionOutlined />
      <PayCircleOutlined />
      <PercentageOutlined />
      <PhoneOutlined />
      <PictureOutlined />
      <PoundCircleOutlined />
      <PoundOutlined />
      <PoweroffOutlined />
      <PrinterOutlined />
      <ProfileOutlined />
      <ProjectOutlined />
      <PropertySafetyOutlined />
      <PullRequestOutlined />
      <PushpinOutlined />
      <QrcodeOutlined />
      <ReadOutlined />
      <ReconciliationOutlined />
      <RedEnvelopeOutlined />
      <ReloadOutlined />
      <RestOutlined />
      <RobotOutlined />
      <RocketOutlined />
      <SafetyCertificateOutlined />
      <SafetyOutlined />
      <ScanOutlined />
      <ScheduleOutlined />
      <SearchOutlined />
      <SecurityScanOutlined />
      <SelectOutlined />
      <SendOutlined />
      <SettingOutlined />
      <ShakeOutlined />
      <ShareAltOutlined />
      <ShopOutlined />
      <ShoppingCartOutlined />
      <ShoppingOutlined />
      <SisternodeOutlined />
      <SkinOutlined />
      <SmileOutlined />
      <SolutionOutlined />
      <SoundOutlined />
      <SplitCellsOutlined />
      <StarOutlined />
      <SubnodeOutlined />
      <SyncOutlined />
      <TableOutlined />
      <TabletOutlined />
      <TagOutlined />
      <TagsOutlined />
      <TeamOutlined />
      <ThunderboltOutlined />
      <ToTopOutlined />
      <ToolOutlined />
      <TrademarkCircleOutlined />
      <TrademarkOutlined />
      <TransactionOutlined />
      <TrophyOutlined />
      <UngroupOutlined />
      <UnlockOutlined />
      <UploadOutlined />
      <UsbOutlined />
      <UserAddOutlined />
      <UserDeleteOutlined />
      <UserOutlined />
      <UserSwitchOutlined />
      <UsergroupAddOutlined />
      <UsergroupDeleteOutlined />
      <VideoCameraOutlined />
      <WalletOutlined />
      <WifiOutlined />
      <BorderlessTableOutlined />
      <WomanOutlined />
      <BehanceOutlined />
      <DropboxOutlined />
      <DeploymentUnitOutlined />
      <UpCircleOutlined />
      <DownCircleOutlined />
      <LeftCircleOutlined />
      <RightCircleOutlined />
      <UpSquareOutlined />
      <DownSquareOutlined />
      <LeftSquareOutlined />
      <RightSquareOutlined />
      <PlayCircleOutlined />
      <QuestionCircleOutlined />
      <PlusCircleOutlined />
      <PlusSquareOutlined />
      <MinusSquareOutlined />
      <MinusCircleOutlined />
      <InfoCircleOutlined />
      <ExclamationCircleOutlined />
      <CloseCircleOutlined />
      <CloseSquareOutlined />
      <CheckCircleOutlined />
      <CheckSquareOutlined />
      <ClockCircleOutlined />
      <FormOutlined />
      <DashOutlined />
      <SmallDashOutlined />
      <YoutubeOutlined />
      <CodepenCircleOutlined />
      <AliyunOutlined />
      <PlusOutlined />
      <LinkedinOutlined />
      <AimOutlined />
      <BugOutlined />
      <CloudDownloadOutlined />
      <CloudServerOutlined />
      <CloudSyncOutlined />
      <CloudUploadOutlined />
      <CommentOutlined />
      <ConsoleSqlOutlined />
      <EyeInvisibleOutlined />
      <FileGifOutlined />
      <DeliveredProcedureOutlined />
      <FieldTimeOutlined />
      <FileZipOutlined />
      <FolderViewOutlined />
      <FundProjectionScreenOutlined />
      <FundViewOutlined />
      <MacCommandOutlined />
      <PlaySquareOutlined />
      <OneToOneOutlined />
      <RotateLeftOutlined />
      <RotateRightOutlined />
      <SaveOutlined />
      <SwitcherOutlined />
      <TranslationOutlined />
      <VerifiedOutlined />
      <VideoCameraAddOutlined />
      <WhatsAppOutlined />

      {/*</Col>*/}
    </Row>
  );
}
Example #8
Source File: BuilderToolbar.spec.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
describe("BuilderToolbar", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it("should work", async () => {
    mockUseBuilderUIContext.mockReturnValue({
      onCurrentRouteClick: mockCurrentRouteClick,
      onBuildAndPush: mockBuildAndPush,
      onPreview: mockPreview,
      dataType: BuilderDataType.ROUTE_OF_BRICKS,
    });
    mockUseBuilderNode.mockReturnValue({
      id: "R-01",
      type: "bricks",
      path: "/",
    });
    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(".tabLink").length).toBe(6);
    wrapper.find(".tabLink[data-testid='view-route']").simulate("click");
    expect(mockCurrentRouteClick).toBeCalledWith({
      id: "R-01",
      type: "bricks",
      path: "/",
    });
    wrapper.find(".tabLink[data-testid='build-and-push']").simulate("click");
    expect(mockBuildAndPush).toBeCalled();
    wrapper.find(".tabLink[data-testid='preview']").simulate("click");
    expect(mockPreview).toBeCalled();
  });

  it("should work with custom template", async () => {
    mockUseBuilderUIContext.mockReturnValue({
      onCurrentTemplateClick: mockCurrentTemplateClick,
      onCurrentSnippetClick: mockCurrentSnippetClick,
      onCurrentRouteClick: mockCurrentRouteClick,
      onBuildAndPush: mockBuildAndPush,
      onPreview: mockPreview,
      dataType: BuilderDataType.CUSTOM_TEMPLATE,
    });
    mockUseBuilderNode.mockReturnValue({
      id: "T-01",
      type: "custom-template",
      templateId: "tpl-test",
    });
    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(".tabLink").length).toBe(6);
    expect(
      wrapper.find(".tabLink").filter("[data-testid='view-template']").length
    ).toBe(1);
    wrapper
      .find(".tabLink")
      .filter("[data-testid='view-template']")
      .simulate("click");
    expect(mockCurrentTemplateClick).toBeCalled();
  });

  it("should work with snippet", async () => {
    mockUseBuilderUIContext.mockReturnValue({
      onCurrentTemplateClick: mockCurrentTemplateClick,
      onCurrentSnippetClick: mockCurrentSnippetClick,
      onCurrentRouteClick: mockCurrentRouteClick,
      onBuildAndPush: mockBuildAndPush,
      onPreview: mockPreview,
      dataType: BuilderDataType.SNIPPET,
    });
    mockUseBuilderNode.mockReturnValue({
      id: "S-01",
      type: "snippet",
      snippetId: "snippet-test",
    });
    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(".tabLink").length).toBe(6);
    expect(
      wrapper.find(".tabLink").filter("[data-testid='view-snippet']").length
    ).toBe(1);
    wrapper
      .find(".tabLink")
      .filter("[data-testid='view-snippet']")
      .simulate("click");
    expect(mockCurrentSnippetClick).toBeCalled();
  });

  it("should enter fullscreen", () => {
    let fullscreen = false;
    const setFullscreen = jest.fn((update) => {
      fullscreen = update(fullscreen);
    });
    mockUseBuilderUIContext.mockImplementation(() => ({
      fullscreen,
      setFullscreen,
    }));
    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(FullscreenOutlined).length).toBe(1);
    expect(wrapper.find(FullscreenExitOutlined).length).toBe(0);
    wrapper.find(".tabLink[data-testid='toggle-fullscreen']").invoke("onClick")(
      null
    );
    expect(setFullscreen).toBeCalled();
    expect(fullscreen).toBe(true);
  });

  it("should invoke onWorkbenchClose", () => {
    const onWorkbenchClose = jest.fn();
    mockUseBuilderUIContext.mockImplementation(() => ({
      onWorkbenchClose,
    }));
    const wrapper = shallow(<BuilderToolbar />);
    wrapper.find(".tabLink[data-testid='workbench-close']").invoke("onClick")(
      null
    );
    expect(onWorkbenchClose).toBeCalled();
  });

  it("should show layer viewer ", () => {
    (getRuntime as jest.Mock).mockReturnValueOnce({
      getFeatureFlags: jest
        .fn()
        .mockReturnValue({ "next-builder-layer-view": true }),
    });

    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(LibraryDropdown).length).toEqual(3);
    wrapper.find(LibraryDropdown).at(0).invoke("onVisbleChange")(true);
    wrapper.find(LibraryDropdown).at(1).invoke("onVisbleChange")(true);
    wrapper.find(LibraryDropdown).at(2).invoke("onVisbleChange")(true);
    const tooltipWrapper = wrapper.find(LibraryDropdown).at(0).shallow();
    expect(tooltipWrapper.find(Tooltip).at(0).prop("overlayStyle")).toEqual({
      display: "none",
    });
  });

  it("should show the hidden wrapper switch", () => {
    mockUseBuilderUIContext.mockReturnValue({
      onCurrentRouteClick: mockCurrentRouteClick,
      onBuildAndPush: mockBuildAndPush,
      onPreview: mockPreview,
      dataType: BuilderDataType.ROUTE_OF_BRICKS,
      hiddenWrapper: true,
      setHiddenWrapper: mockSetHiddenWrapper,
    });
    mockUseBuilderNode.mockReturnValue({
      id: "R-01",
      type: "bricks",
      path: "/",
    });
    mockUseBuilderData.mockReturnValue({
      wrapperNode: {
        $$uid: 1,
      },
    } as any);
    const wrapper = shallow(<BuilderToolbar />);
    expect(wrapper.find(Switch).length).toBe(1);
    wrapper.find(Switch).prop("onChange")(true, {} as MouseEvent);
    expect(mockSetHiddenWrapper).toBeCalled();
  });
});
Example #9
Source File: BuilderToolbar.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
export function BuilderToolbar(): React.ReactElement {
  const { t } = useTranslation(NS_NEXT_BUILDER);
  const enableLayerView = React.useMemo(
    () => getRuntime().getFeatureFlags()["next-builder-layer-view"],
    []
  );

  const [libsDropdownVisible, setLibsDropdownVisible] = useState<{
    [key in typeof LayerType[keyof typeof LayerType]]: boolean;
  }>({
    [LayerType.LAYOUT]: false,
    [LayerType.WIDGET]: false,
    [LayerType.BRICK]: false,
  });

  const { wrapperNode } = useBuilderData();

  const {
    onCurrentRouteClick,
    onCurrentTemplateClick,
    onCurrentSnippetClick,
    onBuildAndPush,
    onPreview,
    dataType,
    fullscreen,
    setFullscreen,
    onWorkbenchClose,
    hiddenWrapper,
    setHiddenWrapper,
  } = useBuilderUIContext();

  const rootNode = useBuilderNode({ isRoot: true });

  const handleRouteClick = (): void => {
    onCurrentRouteClick?.(rootNode as BuilderRouteNode);
  };

  const handleTemplateClick = (): void => {
    onCurrentTemplateClick?.(rootNode as BuilderCustomTemplateNode);
  };

  const handleSnippetClick = (): void => {
    onCurrentSnippetClick?.(rootNode as BuilderSnippetNode);
  };

  const handlePreview = (): void => {
    onPreview?.();
  };

  const handleBuildAndPush = (): void => {
    onBuildAndPush?.();
  };

  const handleToggleFullscreen = React.useCallback(() => {
    setFullscreen((prev) => !prev);
  }, [setFullscreen]);

  const handleClose = (): void => {
    onWorkbenchClose?.();
  };

  const divider = useMemo(
    () => <Divider type="vertical" style={{ height: 25 }} />,
    []
  );

  return (
    <div className={styles.toolbarContainer}>
      <div className={styles.toolbarLeft}>
        {dataType === BuilderDataType.SNIPPET ? (
          <Tooltip title={t(K.VIEW_SNIPPET)} placement="bottomLeft">
            <a
              className={shareStyles.tabLink}
              role="button"
              onClick={handleSnippetClick}
              data-testid="view-snippet"
            >
              <BlockOutlined />
            </a>
          </Tooltip>
        ) : dataType === BuilderDataType.CUSTOM_TEMPLATE ? (
          <Tooltip title={t(K.VIEW_TEMPLATE)} placement="bottomLeft">
            <a
              className={shareStyles.tabLink}
              role="button"
              onClick={handleTemplateClick}
              data-testid="view-template"
            >
              <BlockOutlined />
            </a>
          </Tooltip>
        ) : (
          <Tooltip title={t(K.VIEW_ROUTE)} placement="bottomLeft">
            <a
              className={shareStyles.tabLink}
              role="button"
              onClick={handleRouteClick}
              data-testid="view-route"
            >
              <BranchesOutlined />
            </a>
          </Tooltip>
        )}
        <RootNodeSelect />
      </div>
      <div className={styles.toolbarRight}>
        {wrapperNode ? (
          <Switch
            checkedChildren="显示布局"
            unCheckedChildren="隐藏布局"
            checked={hiddenWrapper}
            onChange={setHiddenWrapper}
            size="small"
            style={{
              marginRight: 10,
              top: -1,
            }}
          />
        ) : null}
        {enableLayerView && (
          <>
            <LibraryDropdown
              menuItems={layoutMenus}
              type={LayerType.LAYOUT}
              onVisbleChange={(visible) =>
                setLibsDropdownVisible({
                  ...libsDropdownVisible,
                  [LayerType.LAYOUT]: visible,
                })
              }
            >
              <Tooltip
                title={t(K.LAYOUT_LIBRARY)}
                placement="bottomRight"
                overlayStyle={{
                  // Hide tooltip when dropdown is open.
                  display: libsDropdownVisible[LayerType.LAYOUT]
                    ? "none"
                    : undefined,
                }}
              >
                <Button
                  type="link"
                  size="small"
                  className={shareStyles.tabLink}
                  style={{ marginRight: "10px" }}
                >
                  <LayoutOutlined />
                </Button>
              </Tooltip>
            </LibraryDropdown>

            <LibraryDropdown
              menuItems={widgetMenus}
              type={LayerType.WIDGET}
              onVisbleChange={(visible) =>
                setLibsDropdownVisible({
                  ...libsDropdownVisible,
                  [LayerType.WIDGET]: visible,
                })
              }
            >
              <Tooltip
                title={t(K.WIDGET_LIBRARY)}
                placement="bottomRight"
                overlayStyle={{
                  display: libsDropdownVisible[LayerType.WIDGET]
                    ? "none"
                    : undefined,
                }}
              >
                <Button
                  type="link"
                  size="small"
                  className={shareStyles.tabLink}
                  style={{ marginRight: "10px" }}
                >
                  <GoldOutlined />
                </Button>
              </Tooltip>
            </LibraryDropdown>
          </>
        )}
        <LibraryDropdown
          menuItems={brickMenus}
          type={LayerType.BRICK}
          onVisbleChange={(visible) =>
            setLibsDropdownVisible({
              ...libsDropdownVisible,
              [LayerType.BRICK]: visible,
            })
          }
        >
          <Tooltip
            title={t(K.BRICK_LIBRARY)}
            placement="bottomRight"
            overlayStyle={{
              display: libsDropdownVisible[LayerType.BRICK]
                ? "none"
                : undefined,
            }}
          >
            <Button
              type="link"
              size="small"
              style={{ marginRight: "10px" }}
              className={shareStyles.tabLink}
            >
              <PlusOutlined />
            </Button>
          </Tooltip>
        </LibraryDropdown>
        {divider}
        <Tooltip title={t(K.BUILD_AND_PUSH_TOOLTIP)} placement="bottomRight">
          <a
            className={shareStyles.tabLink}
            role="button"
            onClick={handleBuildAndPush}
            data-testid="build-and-push"
          >
            <ApiOutlined />
          </a>
        </Tooltip>
        <Tooltip title={t(K.PREVIEW)} placement="bottomRight">
          <a
            className={shareStyles.tabLink}
            role="button"
            onClick={handlePreview}
            data-testid="preview"
          >
            <CaretRightOutlined />
          </a>
        </Tooltip>
        {divider}
        <SettingDropdown />
        {!fullscreen && (
          <Tooltip
            title={t(fullscreen ? K.EXIT_FULLSCREEN : K.ENTER_FULLSCREEN)}
            placement="bottomRight"
          >
            <a
              className={shareStyles.tabLink}
              role="button"
              onClick={handleToggleFullscreen}
              data-testid="toggle-fullscreen"
            >
              {fullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
            </a>
          </Tooltip>
        )}
        <Tooltip title={t(K.CLOSE)} placement="bottomRight">
          <a
            className={shareStyles.tabLink}
            role="button"
            onClick={handleClose}
            data-testid="workbench-close"
          >
            <CloseOutlined />
          </a>
        </Tooltip>
      </div>
    </div>
  );
}
Example #10
Source File: useExtraBtn.tsx    From amiya with MIT License 4 votes vote down vote up
export default function useExtraBtn(
  tableRef: any,
  searchRef: any,
  tableFields: Array<AyTableField>,
  setTableFields: Dispatch<React.SetStateAction<AyTableField[]>>,
  props: AySearchTableProps
) {
  // 合并配置
  const config = Object.assign({}, defaultConfig, props)
  const {
    extraVisible,
    extraRefreshVisible,
    extraSizeVisible,
    extraSizeDefaultValue,
    extraSettingVisible,
    extraFullscreenVisible
  } = config
  /** 表格尺寸 */
  const [size, setSize] = useState<SizeType>(extraSizeDefaultValue)
  /** 表格全屏 */
  const [isEnter, setIsEnter] = useState<boolean>(false)

  const fieldsEdit = useFieldsEdit(tableFields, setTableFields)

  const handleRefresh = () => {
    tableRef.current.refresh()
  }

  const handleSizeChange = (e: any) => {
    setSize(e.key)
  }

  useEffect(() => {
    // body 的 style 防止滚动
    if (isEnter) {
      document.body.style.overflow = 'hidden'
    } else {
      document.body.style.overflow = ''
    }
    searchRef.current && searchRef.current.resize()
  }, [isEnter])

  const extraBtns = extraVisible ? (
    <div className="ay-search-table-extra-btns" key="ay-search-table-extra-btns">
      <Space size="middle">
        {extraRefreshVisible ? (
          <Tooltip title={locale.extra.refresh}>
            <ReloadOutlined onClick={handleRefresh} />
          </Tooltip>
        ) : null}

        {extraSizeVisible ? (
          <Tooltip title={locale.extra.density}>
            <Dropdown
              overlay={
                <Menu style={{ width: 100 }} selectedKeys={[size + '']} onClick={handleSizeChange}>
                  <Menu.Item key="large">{locale.extra.densityLarger}</Menu.Item>
                  <Menu.Item key="middle">{locale.extra.densityMiddle}</Menu.Item>
                  <Menu.Item key="small">{locale.extra.densitySmall}</Menu.Item>
                </Menu>
              }
            >
              <ColumnHeightOutlined />
            </Dropdown>
          </Tooltip>
        ) : null}

        {extraSettingVisible ? fieldsEdit : null}

        {extraFullscreenVisible ? (
          isEnter ? (
            <Tooltip title={locale.extra.exitFullScreen} key={locale.extra.exitFullScreen}>
              <FullscreenExitOutlined className="ay-search-table-fullscrenn-enter" onClick={() => setIsEnter(false)} />
            </Tooltip>
          ) : (
            <Tooltip title={locale.extra.fullScreen} key={locale.extra.fullScreen}>
              <FullscreenOutlined className="ay-search-table-fullscrenn-out" onClick={() => setIsEnter(true)} />
            </Tooltip>
          )
        ) : null}
      </Space>
    </div>
  ) : null

  return {
    extraBtns,
    isEnter,
    setIsEnter,
    size
  }
}
Example #11
Source File: YakExecutor.tsx    From yakit with GNU Affero General Public License v3.0 4 votes vote down vote up
YakExecutor: React.FC<YakExecutorProp> = (props) => {
    const [codePath, setCodePath] = useState<string>("")
    const [loading, setLoading] = useState<boolean>(false)
    const [fileList, setFileList] = useState<tabCodeProps[]>([])
    const [tabList, setTabList] = useState<tabCodeProps[]>([])
    const [activeTab, setActiveTab] = useState<string>("")
    const [unTitleCount, setUnTitleCount] = useState(1)

    const [hintShow, setHintShow] = useState<boolean>(false)
    const [hintFile, setHintFile] = useState<string>("")
    const [hintIndex, setHintIndex] = useState<number>(0)

    const [renameHint, setRenameHint] = useState<boolean>(false)
    const [renameIndex, setRenameIndex] = useState<number>(-1)
    const [renameFlag, setRenameFlag] = useState<boolean>(false)
    const [renameCache, setRenameCache] = useState<string>("")

    const [fullScreen, setFullScreen] = useState<boolean>(false)

    const [errors, setErrors] = useState<string[]>([])
    const [executing, setExecuting] = useState(false)
    const [outputEncoding, setOutputEncoding] = useState<"utf8" | "latin1">("utf8")
    const xtermAsideRef = useRef(null)
    const xtermRef = useRef(null)
    const timer = useRef<any>(null)

    const [extraParams, setExtraParams] = useState("")

    // trigger for updating
    const [triggerForUpdatingHistory, setTriggerForUpdatingHistory] = useState<any>(0)

    const addFileTab = useMemoizedFn((res: any) => {
        const {name, code} = res

        const tab: tabCodeProps = {
            tab: `${name}.yak`,
            code: code,
            suffix: "yak",
            isFile: false
        }
        setActiveTab(`${tabList.length}`)
        setTabList(tabList.concat([tab]))
        setUnTitleCount(unTitleCount + 1)
    })

    useEffect(() => {
        ipcRenderer.on("fetch-send-to-yak-running", (e, res: any) => addFileTab(res))
        return () => ipcRenderer.removeAllListeners("fetch-send-to-yak-running")
    }, [])

    // 自动保存
    const autoSave = useMemoizedFn(() => {
        for (let tabInfo of tabList) {
            if (tabInfo.isFile) {
                ipcRenderer.invoke("write-file", {
                    route: tabInfo.route,
                    data: tabInfo.code
                })
            }
        }
    })
    // 保存近期文件内的15个
    const saveFiliList = useMemoizedFn(() => {
        let files = cloneDeep(fileList).reverse()
        files.splice(14)
        files = files.reverse()
        ipcRenderer.invoke("set-value", RecentFileList, files)
    })

    // 获取和保存近期打开文件信息,同时展示打开默认内容
    useEffect(() => {
        let time: any = null
        let timer: any = null
        setLoading(true)
        ipcRenderer
            .invoke("get-value", RecentFileList)
            .then((value: any) => {
                if ((value || []).length !== 0) {
                    setFileList(value)
                } else {
                    const tab: tabCodeProps = {
                        tab: `Untitle-${unTitleCount}.yak`,
                        code: "# input your yak code\nprintln(`Hello Yak World!`)",
                        suffix: "yak",
                        isFile: false
                    }
                    setActiveTab(`${tabList.length}`)
                    setTabList([tab])
                    setUnTitleCount(unTitleCount + 1)
                }
            })
            .catch(() => {})
            .finally(() => {
                setTimeout(() => setLoading(false), 300)
                time = setInterval(() => {
                    autoSave()
                }, 2000)
                timer = setInterval(() => {
                    saveFiliList()
                }, 5000)
            })

        return () => {
            saveFiliList()
            if (time) clearInterval(time)
            if (timer) clearInterval(timer)
        }
    }, [])

    // 全局监听重命名事件是否被打断
    useEffect(() => {
        document.onmousedown = (e) => {
            // @ts-ignore
            if (e.path[0].id !== "rename-input" && renameFlag) {
                renameCode(renameIndex)
                setRenameFlag(false)
            }
        }
    }, [renameFlag])

    // 打开文件
    const addFile = useMemoizedFn((file: any) => {
        const isExists = fileList.filter((item) => item.tab === file.name && item.route === file.path).length === 1

        if (isExists) {
            for (let index in tabList) {
                const item = tabList[index]
                if (item.tab === file.name && item.route === file.path) {
                    setActiveTab(`${index}`)
                    return false
                }
            }
        }
        ipcRenderer
            .invoke("fetch-file-content", file.path)
            .then((res) => {
                const tab: tabCodeProps = {
                    tab: file.name,
                    code: res,
                    suffix: file.name.split(".").pop() === "yak" ? "yak" : "http",
                    isFile: true,
                    route: file.path,
                    extraParams: file.extraParams
                }
                setActiveTab(`${tabList.length}`)
                if (!isExists) setFileList(fileList.concat([tab]))
                setTabList(tabList.concat([tab]))
            })
            .catch(() => {
                failed("无法获取该文件内容,请检查后后重试!")
                const files = cloneDeep(fileList)
                for (let i in files) if (files[i].route === file.path) files.splice(i, 1)
                setFileList(files)
            })
        return false
    })
    // 新建文件
    const newFile = useMemoizedFn(() => {
        const tab: tabCodeProps = {
            tab: `Untitle-${unTitleCount}.yak`,
            code: "# input your yak code\nprintln(`Hello Yak World!`)",
            suffix: "yak",
            isFile: false
        }
        setActiveTab(`${tabList.length}`)
        setTabList(tabList.concat([tab]))
        setUnTitleCount(unTitleCount + 1)
    })
    //修改文件
    const modifyCode = useMemoizedFn((value: string, index: number) => {
        const tabs = cloneDeep(tabList)
        tabs[index].code = value
        setTabList(tabs)
    })
    // 保存文件
    const saveCode = useMemoizedFn((info: tabCodeProps, index: number) => {
        if (info.isFile) {
            ipcRenderer.invoke("write-file", {
                route: info.route,
                data: info.code
            })
        } else {
            ipcRenderer.invoke("show-save-dialog", `${codePath}${codePath ? '/' : ''}${info.tab}`).then((res) => {
                if (res.canceled) return

                const path = res.filePath
                const name = res.name
                ipcRenderer
                    .invoke("write-file", {
                        route: res.filePath,
                        data: info.code
                    })
                    .then(() => {
                        const suffix = name.split(".").pop()

                        var tabs = cloneDeep(tabList)
                        var active = null
                        tabs = tabs.filter((item) => item.route !== path)
                        tabs = tabs.map((item, index) => {
                            if (!item.route && item.tab === info.tab) {
                                active = index
                                item.tab = name
                                item.isFile = true
                                item.suffix = suffix === "yak" ? suffix : "http"
                                item.route = path
                                return item
                            }
                            return item
                        })
                        if (active !== null) setActiveTab(`${active}`)
                        setTabList(tabs)
                        const file: tabCodeProps = {
                            tab: name,
                            code: info.code,
                            isFile: true,
                            suffix: suffix === "yak" ? suffix : "http",
                            route: res.filePath,
                            extraParams: info.extraParams
                        }
                        for (let item of fileList) {
                            if (item.route === file.route) {
                                return
                            }
                        }
                        setFileList(fileList.concat([file]))
                    })
            })
        }
    })
    //关闭文件
    const closeCode = useMemoizedFn((index, isFileList: boolean) => {
        const tabInfo = isFileList ? fileList[+index] : tabList[+index]
        if (isFileList) {
            for (let i in tabList) {
                if (tabList[i].tab === tabInfo.tab && tabList[i].route === tabInfo.route) {
                    const tabs = cloneDeep(tabList)
                    tabs.splice(i, 1)
                    setTabList(tabs)
                    setActiveTab(tabs.length >= 1 ? `0` : "")
                }
            }
            const files = cloneDeep(fileList)
            files.splice(+index, 1)
            setFileList(files)
        } else {
            setActiveTab(index)

            if (!tabInfo.isFile) {
                setHintFile(tabInfo.tab)
                setHintIndex(index)
                setHintShow(true)
            } else {
                const tabs = cloneDeep(tabList)
                tabs.splice(+index, 1)
                setTabList(tabs)
                setActiveTab(tabs.length >= 1 ? `0` : "")
            }
        }
    })
    // 关闭虚拟文件不保存
    const ownCloseCode = useMemoizedFn(() => {
        const tabs = cloneDeep(tabList)
        tabs.splice(hintIndex, 1)
        setTabList(tabs)
        setHintShow(false)
        setActiveTab(tabs.length >= 1 ? `0` : "")
    })
    // 删除文件
    const delCode = useMemoizedFn((index) => {
        const fileInfo = fileList[index]

        ipcRenderer
            .invoke("delelte-code-file", fileInfo.route)
            .then(() => {
                for (let i in tabList) {
                    if (tabList[i].tab === fileInfo.tab && tabList[i].route === fileInfo.route) {
                        const tabs = cloneDeep(tabList)
                        tabs.splice(i, 1)
                        setTabList(tabs)
                        setActiveTab(tabs.length >= 1 ? `0` : "")
                    }
                }
                const arr = cloneDeep(fileList)
                arr.splice(index === undefined ? hintIndex : index, 1)
                setFileList(arr)
            })
            .catch(() => {
                failed("文件删除失败!")
            })
    })
    //重命名操作
    const renameCode = useMemoizedFn((index: number) => {
        const tabInfo = fileList[index]

        if (renameCache === tabInfo.tab) return
        if (!renameCache) return

        if (!tabInfo.route) return
        const flagStr = tabInfo.route?.indexOf("/") > -1 ? "/" : "\\"
        const routes = tabInfo.route?.split(flagStr)
        routes?.pop()
        ipcRenderer
            .invoke("is-exists-file", routes?.concat([renameCache]).join(flagStr))
            .then(() => {
                const newRoute = routes?.concat([renameCache]).join(flagStr)
                if (!tabInfo.route || !newRoute) return
                renameFile(index, renameCache, tabInfo.route, newRoute)
            })
            .catch(() => {
                setRenameHint(true)
            })
    })
    // 重命名文件
    const renameFile = useMemoizedFn(
        (index: number, rename: string, oldRoute: string, newRoute: string, callback?: () => void) => {
            ipcRenderer.invoke("rename-file", {old: oldRoute, new: newRoute}).then(() => {
                const suffix = rename.split(".").pop()

                var files = cloneDeep(fileList)
                var tabs = cloneDeep(tabList)
                var active = null
                files = files.filter((item) => item.route !== newRoute)
                tabs = tabs.filter((item) => item.route !== newRoute)

                files = files.map((item) => {
                    if (item.route === oldRoute) {
                        item.tab = rename
                        item.suffix = suffix === "yak" ? suffix : "http"
                        item.route = newRoute
                        return item
                    }
                    return item
                })
                tabs = tabs.map((item, index) => {
                    if (item.route === oldRoute) {
                        active = index
                        item.tab = rename
                        item.suffix = suffix === "yak" ? suffix : "http"
                        item.route = newRoute
                        return item
                    }
                    return item
                })
                if (active !== null) setActiveTab(`${active}`)
                setFileList(files)
                setTabList(tabs)

                if (callback) callback()
            })
        }
    )

    const fileFunction = (kind: string, index: string, isFileList: boolean) => {
        const tabCodeInfo = isFileList ? fileList[index] : tabList[index]

        switch (kind) {
            case "own":
                closeCode(index, isFileList)
                return
            case "other":
                const tabInfo: tabCodeProps = cloneDeep(tabList[index])
                for (let i in tabList) {
                    if (i !== index && !tabList[i].isFile) {
                        const arr: tabCodeProps[] =
                            +i > +index
                                ? [tabInfo].concat(tabList.splice(+i, tabList.length))
                                : tabList.splice(+i, tabList.length)
                        const num = +i > +index ? 1 : 0

                        setActiveTab(`${num}`)
                        setTabList(arr)
                        setHintFile(arr[num].tab)
                        setHintIndex(num)
                        setHintShow(true)
                        return
                    }
                }
                const code = cloneDeep(tabList[index])
                setTabList([code])
                setActiveTab(`0`)
                return
            case "all":
                for (let i in tabList) {
                    if (!tabList[i].isFile) {
                        const arr = tabList.splice(+i, tabList.length)
                        setActiveTab("0")
                        setTabList(arr)
                        setHintFile(arr[0].tab)
                        setHintIndex(0)
                        setHintShow(true)
                        return
                    }
                }
                setActiveTab("")
                setTabList([])
                return
            case "remove":
                closeCode(index, isFileList)
                return
            case "delete":
                delCode(index)
                return
            case "rename":
                setRenameIndex(+index)
                setRenameFlag(true)
                setRenameCache(tabCodeInfo.tab)
                return
        }
    }

    const openFileLayout = (file: any) => {
        addFile(file)
    }

    useEffect(() => {
        ipcRenderer.invoke("fetch-code-path")
            .then((path: string) => {
                ipcRenderer.invoke("is-exists-file", path)
                    .then(() => {
                        setCodePath("")
                    })
                    .catch(() => {
                        setCodePath(path)
                    })
            })
    }, [])

    useEffect(() => {
        if (tabList.length === 0) setFullScreen(false)
    }, [tabList])

    useEffect(() => {
        if (!xtermRef) {
            return
        }
        // let buffer = "";
        ipcRenderer.on("client-yak-error", async (e: any, data) => {
            failed(`FoundError: ${JSON.stringify(data)}`)
            if (typeof data === "object") {
                setErrors([...errors, `${JSON.stringify(data)}`])
            } else if (typeof data === "string") {
                setErrors([...errors, data])
            } else {
                setErrors([...errors, `${data}`])
            }
        })
        ipcRenderer.on("client-yak-end", () => {
            info("Yak 代码执行完毕")
            setTriggerForUpdatingHistory(getRandomInt(100000))
            setTimeout(() => {
                setExecuting(false)
            }, 300)
        })
        ipcRenderer.on("client-yak-data", async (e: any, data: ExecResult) => {
            if (data.IsMessage) {
                // alert(Buffer.from(data.Message).toString("utf8"))
            }
            if (data?.Raw) {
                writeExecResultXTerm(xtermRef, data, outputEncoding)
                // writeXTerm(xtermRef, Buffer.from(data.Raw).toString(outputEncoding).replaceAll("\n", "\r\n"))
                // monacoEditorWrite(currentOutputEditor, )
            }
        })
        return () => {
            ipcRenderer.removeAllListeners("client-yak-data")
            ipcRenderer.removeAllListeners("client-yak-end")
            ipcRenderer.removeAllListeners("client-yak-error")
        }
    }, [xtermRef])

    const bars = (props: any, TabBarDefault: any) => {
        return (
            <TabBarDefault
                {...props}
                children={(barNode: React.ReactElement) => {
                    return (
                        <Dropdown
                            overlay={CustomMenu(barNode.key, false, tabMenu, fileFunction)}
                            trigger={["contextMenu"]}
                        >
                            {barNode}
                        </Dropdown>
                    )
                }}
            />
        )
    }

    return (
        <AutoCard
            className={"yak-executor-body"}
            // title={"Yak Runner"}
            headStyle={{minHeight: 0}}
            bodyStyle={{padding: 0, overflow: "hidden"}}
        >
            <div
                style={{width: "100%", height: "100%", display: "flex", backgroundColor: "#E8E9E8"}}
                tabIndex={0}
                onKeyDown={(e) => {
                    if (e.keyCode === 78 && (e.ctrlKey || e.metaKey)) {
                        newFile()
                    }
                    if (e.keyCode === 83 && (e.ctrlKey || e.metaKey) && activeTab) {
                        saveCode(tabList[+activeTab], +activeTab)
                    }
                }}
            >
                <div style={{width: `${fullScreen ? 0 : 15}%`}}>
                    <AutoSpin spinning={loading}>
                        <ExecutorFileList
                            lists={fileList}
                            activeFile={tabList[+activeTab]?.route || ""}
                            renameFlag={renameFlag}
                            renameIndex={renameIndex}
                            renameCache={renameCache}
                            setRenameCache={setRenameCache}
                            addFile={addFile}
                            newFile={newFile}
                            openFile={openFileLayout}
                            fileFunction={fileFunction}
                        />
                    </AutoSpin>
                </div>
                <div style={{width: `${fullScreen ? 100 : 85}%`}} className='executor-right-body'>
                    {tabList.length > 0 && (
                        <ResizeBox
                            isVer
                            firstNode={
                                <Tabs
                                    className={"right-editor"}
                                    style={{height: "100%"}}
                                    type='editable-card'
                                    activeKey={activeTab}
                                    hideAdd={true}
                                    onChange={(activeTab) => setActiveTab(activeTab)}
                                    onEdit={(key, event: "add" | "remove") => {
                                        switch (event) {
                                            case "remove":
                                                closeCode(key, false)
                                                return
                                            case "add":
                                                return
                                        }
                                    }}
                                    renderTabBar={(props, TabBarDefault) => {
                                        return bars(props, TabBarDefault)
                                    }}
                                    tabBarExtraContent={
                                        tabList.length && (
                                            <Space style={{marginRight: 5}} size={0}>
                                                <Button
                                                    style={{height: 25}}
                                                    type={"link"}
                                                    size={"small"}
                                                    disabled={
                                                        tabList[+activeTab] && tabList[+activeTab].suffix !== "yak"
                                                    }
                                                    onClick={(e) => {
                                                        let m = showDrawer({
                                                            width: "60%",
                                                            placement: "left",
                                                            title: "选择你的 Yak 模块执行特定功能",
                                                            content: (
                                                                <>
                                                                    <YakScriptManagerPage
                                                                        type={"yak"}
                                                                        onLoadYakScript={(s) => {
                                                                            const tab: tabCodeProps = {
                                                                                tab: `Untitle-${unTitleCount}.yak`,
                                                                                code: s.Content,
                                                                                suffix: "yak",
                                                                                isFile: false
                                                                            }
                                                                            info(`加载 Yak 模块:${s.ScriptName}`)
                                                                            xtermClear(xtermRef)
                                                                            setActiveTab(`${tabList.length}`)
                                                                            setTabList(tabList.concat([tab]))
                                                                            setUnTitleCount(unTitleCount + 1)
                                                                            m.destroy()
                                                                        }}
                                                                    />
                                                                </>
                                                            )
                                                        })
                                                    }}
                                                >
                                                    Yak脚本模板
                                                </Button>

                                                <Button
                                                    icon={
                                                        fullScreen ? (
                                                            <FullscreenExitOutlined style={{fontSize: 15}} />
                                                        ) : (
                                                            <FullscreenOutlined style={{fontSize: 15}} />
                                                        )
                                                    }
                                                    type={"link"}
                                                    size={"small"}
                                                    style={{width: 30, height: 25}}
                                                    onClick={() => setFullScreen(!fullScreen)}
                                                />
                                                <Popover
                                                    trigger={["click"]}
                                                    title={"设置命令行额外参数"}
                                                    placement="bottomRight"
                                                    content={
                                                        <Space style={{width: 400}}>
                                                            <div>yak {tabList[+activeTab]?.tab || "[file]"}</div>
                                                            <Divider type={"vertical"} />
                                                            <Paragraph
                                                                style={{width: 200, marginBottom: 0}}
                                                                editable={{
                                                                    icon: <Space>
                                                                        <EditOutlined />
                                                                        <SaveOutlined onClick={(e) => {
                                                                            e.stopPropagation()
                                                                            tabList[+activeTab].extraParams = extraParams
                                                                            setTabList(tabList)
                                                                            if(tabList[+activeTab].isFile){
                                                                                const files = fileList.map(item => {
                                                                                    if(item.route === tabList[+activeTab].route){
                                                                                        item.extraParams = extraParams
                                                                                        return item
                                                                                    }
                                                                                    return item
                                                                                })
                                                                                setFileList(files)
                                                                            }
                                                                            success("保存成功")
                                                                        }} 
                                                                    /></Space>,
                                                                    tooltip: '编辑/保存为该文件默认参数',
                                                                    onChange: setExtraParams
                                                                }}
                                                            >
                                                                {extraParams}
                                                            </Paragraph>
                                                        </Space>
                                                    }
                                                >
                                                    <Button type={"link"} icon={<EllipsisOutlined />} onClick={() => {
                                                        setExtraParams(tabList[+activeTab]?.extraParams || "")
                                                    }} />
                                                </Popover>
                                                {executing ? (
                                                    <Button
                                                        icon={<PoweroffOutlined style={{fontSize: 15}} />}
                                                        type={"link"}
                                                        danger={true}
                                                        size={"small"}
                                                        style={{width: 30, height: 25}}
                                                        onClick={() => ipcRenderer.invoke("cancel-yak")}
                                                    />
                                                ) : (
                                                    <Button
                                                        icon={<CaretRightOutlined style={{fontSize: 15}} />}
                                                        type={"link"}
                                                        ghost={true}
                                                        size={"small"}
                                                        style={{width: 30, height: 25}}
                                                        disabled={
                                                            tabList[+activeTab] && tabList[+activeTab].suffix !== "yak"
                                                        }
                                                        onClick={() => {
                                                            setErrors([])
                                                            setExecuting(true)
                                                            ipcRenderer.invoke("exec-yak", {
                                                                Script: tabList[+activeTab].code,
                                                                Params: [],
                                                                RunnerParamRaw: extraParams
                                                            })
                                                        }}
                                                    />
                                                )}
                                            </Space>
                                        )
                                    }
                                >
                                    {tabList.map((item, index) => {
                                        return (
                                            <TabPane tab={item.tab} key={`${index}`}>
                                                <div style={{height: "100%"}}>
                                                    <AutoSpin spinning={executing}>
                                                        <div style={{height: "100%"}}>
                                                            <YakEditor
                                                                type={item.suffix}
                                                                value={item.code}
                                                                setValue={(value) => {
                                                                    modifyCode(value, index)
                                                                }}
                                                            />
                                                        </div>
                                                    </AutoSpin>
                                                </div>
                                            </TabPane>
                                        )
                                    })}
                                </Tabs>
                            }
                            firstRatio='70%'
                            secondNode={
                                <div
                                    ref={xtermAsideRef}
                                    style={{
                                        width: "100%",
                                        height: "100%",
                                        overflow: "hidden",
                                        borderTop: "1px solid #dfdfdf"
                                    }}
                                >
                                    <Tabs
                                        style={{height: "100%"}}
                                        className={"right-xterm"}
                                        size={"small"}
                                        tabBarExtraContent={
                                            <Space>
                                                <SelectOne
                                                    formItemStyle={{marginBottom: 0}}
                                                    value={outputEncoding}
                                                    setValue={setOutputEncoding}
                                                    size={"small"}
                                                    data={[
                                                        {text: "GBxxx编码", value: "latin1"},
                                                        {text: "UTF-8编码", value: "utf8"}
                                                    ]}
                                                />
                                                <Button
                                                    size={"small"}
                                                    icon={<DeleteOutlined />}
                                                    type={"link"}
                                                    onClick={(e) => {
                                                        xtermClear(xtermRef)
                                                    }}
                                                />
                                            </Space>
                                        }
                                    >
                                        <TabPane
                                            tab={<div style={{width: 50, textAlign: "center"}}>输出</div>}
                                            key={"output"}
                                        >
                                            <div style={{width: "100%", height: "100%"}}>
                                                <CVXterm
                                                    ref={xtermRef}
                                                    options={{
                                                        convertEol: true,
                                                        theme: {
                                                            foreground: "#536870",
                                                            background: "#E8E9E8",
                                                            cursor: "#536870",

                                                            black: "#002831",
                                                            brightBlack: "#001e27",

                                                            red: "#d11c24",
                                                            brightRed: "#bd3613",

                                                            green: "#738a05",
                                                            brightGreen: "#475b62",

                                                            yellow: "#a57706",
                                                            brightYellow: "#536870",

                                                            blue: "#2176c7",
                                                            brightBlue: "#708284",

                                                            magenta: "#c61c6f",
                                                            brightMagenta: "#5956ba",

                                                            cyan: "#259286",
                                                            brightCyan: "#819090",

                                                            white: "#eae3cb",
                                                            brightWhite: "#fcf4dc"
                                                        }
                                                    }}
                                                />
                                            </div>
                                        </TabPane>
                                        <TabPane
                                            tab={
                                                <div style={{width: 50, textAlign: "center"}} key={"terminal"}>
                                                    终端(监修中)
                                                </div>
                                            }
                                            disabled
                                        >
                                            <Terminal />
                                        </TabPane>
                                    </Tabs>
                                </div>
                            }
                            secondRatio='30%'
                        />
                    )}
                    {tabList.length === 0 && (
                        <Empty className='right-empty' description={<p>请点击左侧打开或新建文件</p>}></Empty>
                    )}
                </div>

                <Modal
                    visible={hintShow}
                    onCancel={() => setHintShow(false)}
                    footer={[
                        <Button key='link' onClick={() => setHintShow(false)}>
                            取消
                        </Button>,
                        <Button key='submit' onClick={() => ownCloseCode()}>
                            不保存
                        </Button>,
                        <Button key='back' type='primary' onClick={() => saveCode(tabList[hintIndex], hintIndex)}>
                            保存
                        </Button>
                    ]}
                >
                    <div style={{height: 40}}>
                        <ExclamationCircleOutlined style={{fontSize: 22, color: "#faad14"}} />
                        <span style={{fontSize: 18, marginLeft: 15}}>文件未保存</span>
                    </div>
                    <p style={{fontSize: 15, marginLeft: 37}}>{`是否要保存${hintFile}里面的内容吗?`}</p>
                </Modal>

                <Modal
                    visible={renameHint}
                    onCancel={() => setHintShow(false)}
                    footer={[
                        <Button key='link' onClick={() => setRenameHint(false)}>
                            取消
                        </Button>,
                        <Button
                            key='back'
                            type='primary'
                            onClick={() => {
                                const oldRoute = tabList[renameIndex].route
                                if (!oldRoute) return
                                const flagStr = oldRoute?.indexOf("/") > -1 ? "/" : "\\"
                                const routes = oldRoute?.split(flagStr)
                                routes?.pop()
                                const newRoute = routes?.concat([renameCache]).join(flagStr)
                                if (!oldRoute || !newRoute) return
                                renameFile(renameIndex, renameCache, oldRoute, newRoute, () => {
                                    setRenameHint(false)
                                })
                            }}
                        >
                            确定
                        </Button>
                    ]}
                >
                    <div style={{height: 40}}>
                        <ExclamationCircleOutlined style={{fontSize: 22, color: "#faad14"}} />
                        <span style={{fontSize: 18, marginLeft: 15}}>文件已存在</span>
                    </div>
                    <p style={{fontSize: 15, marginLeft: 37}}>{`是否要覆盖已存在的文件吗?`}</p>
                </Modal>
            </div>
        </AutoCard>
    )
}