semantic-ui-react#Progress TypeScript Examples

The following examples show how to use semantic-ui-react#Progress. 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: FileShare.tsx    From FLECT_Amazon_Chime_Meeting with Apache License 2.0 6 votes vote down vote up
sendingStatus = () =>{
        const props = this.props as any
        const appState = props.appState as AppState
        if(appState.focusedMeeting !== NO_FOCUSED){
            const statuses = appState.joinedMeetings[appState.focusedMeeting].fileTransferStatus.sendingStatusStatuses.map(s =>{
                const allNum   = s.partNum
                const num      = s.transferredIndex
                const percent  = Math.ceil((num / allNum) * 100)
                const filename = s.filename
                if (s.done){
                    return(<div/>)
                }
                return(
                    <div>
                        Sending({filename}) <Progress percent={percent} indicating />
                    </div>
                )
            })
            return statuses
        }
    }
Example #2
Source File: FileShare.tsx    From FLECT_Amazon_Chime_Meeting with Apache License 2.0 6 votes vote down vote up
receivingStatus = () =>{
        const props = this.props as any
        const appState = props.appState as AppState
        if(appState.focusedMeeting !== NO_FOCUSED){

            const statuses = appState.joinedMeetings[appState.focusedMeeting].fileTransferStatus.recievingStatuses.map(s =>{
                const allNum   = s.partNum
                const num      = s.recievedIndex
                const percent  = Math.ceil((num / allNum) * 100)
                const filename = s.filename
                if (s.available){
                    return(<div/>)
                }
                return(
                    <div>
                        Receiving({filename}) <Progress percent={percent} indicating />
                    </div>
                )
            })
            return statuses
        }
    }
Example #3
Source File: App.tsx    From watchparty with MIT License 4 votes vote down vote up
render() {
    const sharer = this.state.participants.find((p) => p.isScreenShare);
    const controls = (
      <Controls
        key={this.state.controlsTimestamp}
        togglePlay={this.togglePlay}
        onSeek={this.onSeek}
        fullScreen={this.fullScreen}
        toggleMute={this.toggleMute}
        toggleSubtitle={this.toggleSubtitle}
        setVolume={this.setVolume}
        jumpToLeader={this.jumpToLeader}
        paused={this.state.currentMediaPaused}
        muted={this.isMuted()}
        subtitled={this.isSubtitled()}
        currentTime={this.getCurrentTime()}
        duration={this.getDuration()}
        disabled={!this.haveLock()}
        leaderTime={this.isHttp() ? this.getLeaderTime() : undefined}
        isPauseDisabled={this.isPauseDisabled()}
      />
    );
    const subscribeButton = (
      <SubscribeButton
        user={this.props.user}
        isSubscriber={this.props.isSubscriber}
        isCustomer={this.props.isCustomer}
      />
    );
    const displayRightContent =
      this.state.showRightBar || this.state.fullScreen;
    const rightBar = (
      <Grid.Column
        width={displayRightContent ? 4 : 1}
        style={{ display: 'flex', flexDirection: 'column' }}
        className={`${
          this.state.fullScreen
            ? 'fullHeightColumnFullscreen'
            : 'fullHeightColumn'
        }`}
      >
        <Input
          inverted
          fluid
          label={'My name is:'}
          value={this.state.myName}
          onChange={this.updateName}
          style={{ visibility: displayRightContent ? '' : 'hidden' }}
          icon={
            <Icon
              onClick={() => this.updateName(null, { value: generateName() })}
              name="refresh"
              inverted
              circular
              link
            />
          }
        />
        {
          <Menu
            inverted
            widths={3}
            style={{
              marginTop: '4px',
              marginBottom: '4px',
              visibility: displayRightContent ? '' : 'hidden',
            }}
          >
            <Menu.Item
              name="chat"
              active={this.state.currentTab === 'chat'}
              onClick={() => {
                this.setState({ currentTab: 'chat', unreadCount: 0 });
              }}
              as="a"
            >
              Chat
              {this.state.unreadCount > 0 && (
                <Label circular color="red">
                  {this.state.unreadCount}
                </Label>
              )}
            </Menu.Item>
            <Menu.Item
              name="people"
              active={this.state.currentTab === 'people'}
              onClick={() => this.setState({ currentTab: 'people' })}
              as="a"
            >
              People
              <Label
                circular
                color={
                  getColorForString(
                    this.state.participants.length.toString()
                  ) as SemanticCOLORS
                }
              >
                {this.state.participants.length}
              </Label>
            </Menu.Item>
            <Menu.Item
              name="settings"
              active={this.state.currentTab === 'settings'}
              onClick={() => this.setState({ currentTab: 'settings' })}
              as="a"
            >
              {/* <Icon name="setting" /> */}
              Settings
            </Menu.Item>
          </Menu>
        }
        <Chat
          chat={this.state.chat}
          nameMap={this.state.nameMap}
          pictureMap={this.state.pictureMap}
          socket={this.socket}
          scrollTimestamp={this.state.scrollTimestamp}
          getMediaDisplayName={this.getMediaDisplayName}
          hide={this.state.currentTab !== 'chat' || !displayRightContent}
          isChatDisabled={this.state.isChatDisabled}
          owner={this.state.owner}
          user={this.props.user}
          ref={this.chatRef}
        />
        {this.state.state === 'connected' && (
          <VideoChat
            socket={this.socket}
            participants={this.state.participants}
            nameMap={this.state.nameMap}
            pictureMap={this.state.pictureMap}
            tsMap={this.state.tsMap}
            rosterUpdateTS={this.state.rosterUpdateTS}
            hide={this.state.currentTab !== 'people' || !displayRightContent}
            owner={this.state.owner}
            user={this.props.user}
          />
        )}
        <SettingsTab
          hide={this.state.currentTab !== 'settings' || !displayRightContent}
          user={this.props.user}
          roomLock={this.state.roomLock}
          setRoomLock={this.setRoomLock}
          socket={this.socket}
          isSubscriber={this.props.isSubscriber}
          roomId={this.state.roomId}
          isChatDisabled={this.state.isChatDisabled}
          setIsChatDisabled={this.setIsChatDisabled}
          owner={this.state.owner}
          setOwner={this.setOwner}
          vanity={this.state.vanity}
          setVanity={this.setVanity}
          roomLink={this.state.roomLink}
          password={this.state.password}
          setPassword={this.setPassword}
          clearChat={this.clearChat}
          roomTitle={this.state.roomTitle}
          setRoomTitle={this.setRoomTitle}
          roomDescription={this.state.roomDescription}
          setRoomDescription={this.setRoomDescription}
          roomTitleColor={this.state.roomTitleColor}
          setRoomTitleColor={this.setRoomTitleColor}
          mediaPath={this.state.mediaPath}
          setMediaPath={this.setMediaPath}
        />
      </Grid.Column>
    );
    return (
      <React.Fragment>
        {!this.state.isAutoPlayable && (
          <Modal inverted basic open>
            <div style={{ display: 'flex', justifyContent: 'center' }}>
              <Button
                primary
                size="large"
                onClick={() => {
                  this.setState({ isAutoPlayable: true });
                  this.setMute(false);
                  this.setVolume(1);
                }}
                icon
                labelPosition="left"
              >
                <Icon name="volume up" />
                Click to unmute
              </Button>
            </div>
          </Modal>
        )}
        {this.state.multiStreamSelection && (
          <MultiStreamModal
            streams={this.state.multiStreamSelection}
            setMedia={this.setMedia}
            resetMultiSelect={this.resetMultiSelect}
          />
        )}
        {this.state.isVBrowserModalOpen && (
          <VBrowserModal
            isSubscriber={this.props.isSubscriber}
            subscribeButton={subscribeButton}
            closeModal={() => this.setState({ isVBrowserModalOpen: false })}
            startVBrowser={this.startVBrowser}
            user={this.props.user}
            beta={this.props.beta}
          />
        )}
        {this.state.isScreenShareModalOpen && (
          <ScreenShareModal
            closeModal={() => this.setState({ isScreenShareModalOpen: false })}
            startScreenShare={this.setupScreenShare}
          />
        )}
        {this.state.isFileShareModalOpen && (
          <FileShareModal
            closeModal={() => this.setState({ isFileShareModalOpen: false })}
            startFileShare={this.setupFileShare}
          />
        )}
        {this.state.isSubtitleModalOpen && (
          <SubtitleModal
            closeModal={() => this.setState({ isSubtitleModalOpen: false })}
            socket={this.socket}
            currentSubtitle={this.state.currentSubtitle}
            src={this.state.currentMedia}
            haveLock={this.haveLock}
            getMediaDisplayName={this.getMediaDisplayName}
            beta={this.props.beta}
          />
        )}
        {this.state.error && <ErrorModal error={this.state.error} />}
        {this.state.isErrorAuth && (
          <PasswordModal
            savedPasswords={this.state.savedPasswords}
            roomId={this.state.roomId}
          />
        )}
        {this.state.errorMessage && (
          <Message
            negative
            header="Error"
            content={this.state.errorMessage}
            style={{
              position: 'fixed',
              bottom: '10px',
              right: '10px',
              zIndex: 1000,
            }}
          ></Message>
        )}
        {this.state.successMessage && (
          <Message
            positive
            header="Success"
            content={this.state.successMessage}
            style={{
              position: 'fixed',
              bottom: '10px',
              right: '10px',
              zIndex: 1000,
            }}
          ></Message>
        )}
        <TopBar
          user={this.props.user}
          isCustomer={this.props.isCustomer}
          isSubscriber={this.props.isSubscriber}
          roomTitle={this.state.roomTitle}
          roomDescription={this.state.roomDescription}
          roomTitleColor={this.state.roomTitleColor}
        />
        {
          <Grid stackable celled="internally">
            <Grid.Row id="theaterContainer">
              <Grid.Column
                width={this.state.showRightBar ? 12 : 15}
                className={
                  this.state.fullScreen
                    ? 'fullHeightColumnFullscreen'
                    : 'fullHeightColumn'
                }
              >
                <div
                  style={{
                    display: 'flex',
                    flexDirection: 'column',
                    height: '100%',
                  }}
                >
                  {!this.state.fullScreen && (
                    <React.Fragment>
                      <ComboBox
                        setMedia={this.setMedia}
                        playlistAdd={this.playlistAdd}
                        playlistDelete={this.playlistDelete}
                        playlistMove={this.playlistMove}
                        currentMedia={this.state.currentMedia}
                        getMediaDisplayName={this.getMediaDisplayName}
                        launchMultiSelect={this.launchMultiSelect}
                        streamPath={this.props.streamPath}
                        mediaPath={this.state.mediaPath}
                        disabled={!this.haveLock()}
                        playlist={this.state.playlist}
                      />
                      <Separator />
                      <div
                        className="mobileStack"
                        style={{ display: 'flex', gap: '4px' }}
                      >
                        {this.screenShareStream && (
                          <Button
                            fluid
                            className="toolButton"
                            icon
                            labelPosition="left"
                            color="red"
                            onClick={this.stopScreenShare}
                            disabled={sharer?.id !== this.socket?.id}
                          >
                            <Icon name="cancel" />
                            Stop Share
                          </Button>
                        )}
                        {!this.screenShareStream &&
                          !sharer &&
                          !this.isVBrowser() && (
                            <Popup
                              content={`Share a tab or an application. Make sure to check "Share audio" for best results.`}
                              trigger={
                                <Button
                                  fluid
                                  className="toolButton"
                                  disabled={!this.haveLock()}
                                  icon
                                  labelPosition="left"
                                  color={'instagram'}
                                  onClick={() => {
                                    this.setState({
                                      isScreenShareModalOpen: true,
                                    });
                                  }}
                                >
                                  <Icon name={'slideshare'} />
                                  Screenshare
                                </Button>
                              }
                            />
                          )}
                        {!this.screenShareStream &&
                          !sharer &&
                          !this.isVBrowser() && (
                            <Popup
                              content="Launch a shared virtual browser"
                              trigger={
                                <Button
                                  fluid
                                  className="toolButton"
                                  disabled={!this.haveLock()}
                                  icon
                                  labelPosition="left"
                                  color="green"
                                  onClick={() => {
                                    this.setState({
                                      isVBrowserModalOpen: true,
                                    });
                                  }}
                                >
                                  <Icon name="desktop" />
                                  VBrowser
                                </Button>
                              }
                            />
                          )}
                        {this.isVBrowser() && (
                          <Popup
                            content="Choose the person controlling the VBrowser"
                            trigger={
                              <Dropdown
                                icon="keyboard"
                                labeled
                                className="icon"
                                style={{ height: '36px' }}
                                button
                                value={this.state.controller}
                                placeholder="No controller"
                                clearable
                                onChange={this.changeController}
                                selection
                                disabled={!this.haveLock()}
                                options={this.state.participants.map((p) => ({
                                  text: this.state.nameMap[p.id] || p.id,
                                  value: p.id,
                                }))}
                              ></Dropdown>
                            }
                          />
                        )}
                        {this.isVBrowser() && (
                          <Dropdown
                            icon="desktop"
                            labeled
                            className="icon"
                            style={{ height: '36px' }}
                            button
                            disabled={!this.haveLock()}
                            value={this.state.vBrowserResolution}
                            onChange={(_e, data) =>
                              this.setState({
                                vBrowserResolution: data.value as string,
                              })
                            }
                            selection
                            options={[
                              {
                                text: '1080p (Plus only)',
                                value: '1920x1080@30',
                                disabled: !this.state.isVBrowserLarge,
                              },
                              {
                                text: '720p',
                                value: '1280x720@30',
                              },
                              {
                                text: '576p',
                                value: '1024x576@60',
                              },
                              {
                                text: '486p',
                                value: '864x486@60',
                              },
                              {
                                text: '360p',
                                value: '640x360@60',
                              },
                            ]}
                          ></Dropdown>
                        )}
                        {this.isVBrowser() && (
                          <Button
                            fluid
                            className="toolButton"
                            icon
                            labelPosition="left"
                            color="red"
                            disabled={!this.haveLock()}
                            onClick={this.stopVBrowser}
                          >
                            <Icon name="cancel" />
                            Stop VBrowser
                          </Button>
                        )}
                        {!this.screenShareStream &&
                          !sharer &&
                          !this.isVBrowser() && (
                            <Popup
                              content="Stream your own video file"
                              trigger={
                                <Button
                                  fluid
                                  className="toolButton"
                                  disabled={!this.haveLock()}
                                  icon
                                  labelPosition="left"
                                  onClick={() => {
                                    this.setState({
                                      isFileShareModalOpen: true,
                                    });
                                  }}
                                >
                                  <Icon name="file" />
                                  File
                                </Button>
                              }
                            />
                          )}
                        {false && (
                          <SearchComponent
                            setMedia={this.setMedia}
                            playlistAdd={this.playlistAdd}
                            type={'youtube'}
                            streamPath={this.props.streamPath}
                            disabled={!this.haveLock()}
                          />
                        )}
                        {Boolean(this.props.streamPath) && (
                          <SearchComponent
                            setMedia={this.setMedia}
                            playlistAdd={this.playlistAdd}
                            type={'stream'}
                            streamPath={this.props.streamPath}
                            launchMultiSelect={this.launchMultiSelect}
                            disabled={!this.haveLock()}
                          />
                        )}
                      </div>
                      <Separator />
                    </React.Fragment>
                  )}
                  <div style={{ flexGrow: 1 }}>
                    <div id="playerContainer">
                      {(this.state.loading ||
                        !this.state.currentMedia ||
                        this.state.nonPlayableMedia) && (
                        <div
                          id="loader"
                          className="videoContent"
                          style={{
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                          }}
                        >
                          {this.state.loading && (
                            <Dimmer active>
                              <Loader>
                                {this.isVBrowser()
                                  ? 'Launching virtual browser. This can take up to a minute.'
                                  : ''}
                              </Loader>
                            </Dimmer>
                          )}
                          {!this.state.loading && !this.state.currentMedia && (
                            <Message
                              color="yellow"
                              icon="hand point up"
                              header="You're not watching anything!"
                              content="Pick something to watch above."
                            />
                          )}
                          {!this.state.loading &&
                            this.state.nonPlayableMedia && (
                              <Message
                                color="red"
                                icon="frown"
                                header="It doesn't look like this is a media file!"
                                content="Maybe you meant to launch a VBrowser if you're trying to visit a web page?"
                              />
                            )}
                        </div>
                      )}
                      <iframe
                        style={{
                          display:
                            this.isYouTube() && !this.state.loading
                              ? 'block'
                              : 'none',
                        }}
                        title="YouTube"
                        id="leftYt"
                        className="videoContent"
                        allowFullScreen
                        frameBorder="0"
                        allow="autoplay"
                        src="https://www.youtube.com/embed/?enablejsapi=1&controls=0&rel=0"
                      />
                      {this.isVBrowser() &&
                      this.getVBrowserPass() &&
                      this.getVBrowserHost() ? (
                        <VBrowser
                          username={this.socket.id}
                          password={this.getVBrowserPass()}
                          hostname={this.getVBrowserHost()}
                          controlling={this.state.controller === this.socket.id}
                          setLoadingFalse={this.setLoadingFalse}
                          resolution={this.state.vBrowserResolution}
                          doPlay={this.doPlay}
                          setResolution={(data: string) =>
                            this.setState({ vBrowserResolution: data })
                          }
                        />
                      ) : (
                        <video
                          style={{
                            display:
                              (this.isVideo() && !this.state.loading) ||
                              this.state.fullScreen
                                ? 'block'
                                : 'none',
                            width: '100%',
                            maxHeight:
                              'calc(100vh - 62px - 36px - 36px - 8px - 41px - 16px)',
                          }}
                          id="leftVideo"
                          onEnded={this.onVideoEnded}
                          playsInline
                        ></video>
                      )}
                    </div>
                  </div>
                  {this.state.currentMedia && controls}
                  {Boolean(this.state.total) && (
                    <div>
                      <Progress
                        size="tiny"
                        color="green"
                        inverted
                        value={this.state.downloaded}
                        total={this.state.total}
                        // indicating
                        label={
                          Math.min(
                            (this.state.downloaded / this.state.total) * 100,
                            100
                          ).toFixed(2) +
                          '% - ' +
                          formatSpeed(this.state.speed) +
                          ' - ' +
                          this.state.connections +
                          ' connections'
                        }
                      ></Progress>
                    </div>
                  )}
                </div>
                <Button
                  style={{
                    position: 'absolute',
                    top: '50%',
                    right: 'calc(0% - 18px)',
                    zIndex: 900,
                  }}
                  circular
                  size="mini"
                  icon={this.state.showRightBar ? 'angle right' : 'angle left'}
                  onClick={() =>
                    this.setState({ showRightBar: !this.state.showRightBar })
                  }
                />
              </Grid.Column>
              {rightBar}
            </Grid.Row>
          </Grid>
        }
      </React.Fragment>
    );
  }
Example #4
Source File: Controls.tsx    From watchparty with MIT License 4 votes vote down vote up
render() {
    const {
      togglePlay,
      onSeek,
      fullScreen,
      toggleMute,
      toggleSubtitle,
      jumpToLeader,
      currentTime,
      duration,
      leaderTime,
      isPauseDisabled,
      disabled,
      subtitled,
      paused,
    } = this.props;
    const { muted, volume } = this.state;
    const isBehind = leaderTime && leaderTime - currentTime > 5;
    return (
      <div className="controls">
        <Icon
          size="large"
          onClick={() => {
            togglePlay();
          }}
          className="control action"
          disabled={disabled || isPauseDisabled}
          name={paused ? 'play' : 'pause'}
        />
        <Popup
          content={
            (isBehind ? "We've detected that your stream is behind. " : '') +
            'Click to sync to leader.'
          }
          trigger={
            <Icon
              size="large"
              onClick={jumpToLeader}
              className={`control action ${isBehind ? 'glowing' : ''}`}
              name={'angle double right'}
            />
          }
        />
        <div className="control">{formatTimestamp(currentTime)}</div>
        <Progress
          size="tiny"
          color="blue"
          onClick={
            duration < Infinity && !this.props.disabled ? onSeek : undefined
          }
          onMouseOver={this.onMouseOver}
          onMouseOut={this.onMouseOut}
          onMouseMove={this.onMouseMove}
          className="control action"
          inverted
          style={{
            flexGrow: 1,
            marginTop: 0,
            marginBottom: 0,
            position: 'relative',
            minWidth: '50px',
          }}
          value={currentTime}
          total={duration}
        >
          {duration < Infinity && this.state.showTimestamp && (
            <div
              style={{
                position: 'absolute',
                bottom: '0px',
                left: `calc(${this.state.posTimestamp * 100 + '% - 27px'})`,
                pointerEvents: 'none',
              }}
            >
              <Label basic color="blue" pointing="below">
                <div style={{ width: '34px' }}>
                  {formatTimestamp(this.state.currTimestamp)}
                </div>
              </Label>
            </div>
          )}
        </Progress>
        <div className="control">{formatTimestamp(duration)}</div>
        <Icon
          size="large"
          onClick={() => {
            toggleSubtitle();
          }}
          className="control action"
          name={subtitled ? 'closed captioning' : 'closed captioning outline'}
          title="Captions"
        />
        <Icon
          size="large"
          onClick={() => fullScreen(false)}
          className="control action"
          style={{ transform: 'rotate(90deg)' }}
          name="window maximize outline"
          title="Theater Mode"
        />
        <Icon
          size="large"
          onClick={() => fullScreen(true)}
          className="control action"
          name="expand"
          title="Fullscreen"
        />
        <Icon
          size="large"
          onClick={() => {
            toggleMute();
            this.setState({ muted: !this.state.muted });
          }}
          className="control action"
          name={muted ? 'volume off' : 'volume up'}
          title="Mute"
        />
        <div style={{ width: '100px', marginRight: '10px' }}>
          <Slider
            value={volume}
            color="blue"
            settings={{
              min: 0,
              max: 1,
              step: 0.01,
              onChange: (value: number) => {
                this.setState({ volume: value });
                this.props.setVolume(value);
              },
            }}
          />
        </div>
      </div>
    );
  }
Example #5
Source File: playertools.tsx    From website with MIT License 4 votes vote down vote up
PlayerToolsPanes = (props: PlayerToolsPanesProps) => {
	const { playerData, strippedPlayerData, voyageData, eventData, activeCrew, dataSource,
			allCrew, allItems, requestShowForm, requestClearData } = props;

	const [showIfStale, setShowIfStale] = useStateWithStorage('tools/showStale', true);

	const [showShare, setShowShare] = useStateWithStorage(playerData.player.dbid+'/tools/showShare', true, { rememberForever: true, onInitialize: variableReady });
	const [profileAutoUpdate, setProfileAutoUpdate] = useStateWithStorage(playerData.player.dbid+'/tools/profileAutoUpdate', false, { rememberForever: true });
	const [profileUploaded, setProfileUploaded] = React.useState(false);
	const [profileUploading, setProfileUploading] = React.useState(false);
	const [profileShared, setProfileShared] = useStateWithStorage('tools/profileShared', false);

	const [varsReady, setVarsReady] = React.useState(false);
	const [activeTool, setActiveTool] = React.useState('voyage');

	React.useEffect(() => {
		if (dataSource == 'input' && profileAutoUpdate && !profileUploaded) {
			console.log('Uploading profile');
			shareProfile();
		}
	}, [profileAutoUpdate, strippedPlayerData]);

	const tools = playerTools;
	React.useEffect(() => {
		const urlParams = new URLSearchParams(window.location.search);
		if (urlParams.has('tool') && tools[urlParams.get('tool')])
			setActiveTool(urlParams.get('tool'));
	}, [window.location.search]);

	const StaleMessage = () => {
		const STALETHRESHOLD = 3;	// in hours
		if (showIfStale && new Date().getTime()-playerData.calc.lastModified.getTime() > STALETHRESHOLD*60*60*1000) {
			return (
				<Message
					warning
					icon='clock'
					header='Update your player data'
					content="It's been a few hours since you last updated your player data. We recommend that you update now to make sure our tools are providing you recent information about your crew."
					onDismiss={() => setShowIfStale(false)}
				/>
			);
		}
		else {
			return (<></>);
		}
	};

	const ShareMessage = () => {
		if (!showShare) return (<></>);

		// The option to auto-share profile only appears after a profile is uploaded or if previously set to auto-update
		const bShowUploaded = profileUploaded || profileAutoUpdate;

		return (
			<Message icon onDismiss={() => setShowShare(false)}>
				<Icon name='share alternate' />
				<Message.Content>
					<Message.Header>Share your player profile!</Message.Header>
					{!bShowUploaded && (
						<div>
							<p>
								Click here to{' '}
								<Button size='small' color='green' onClick={() => shareProfile()}>
									{profileUploading && <Icon loading name='spinner' />}share your profile
									</Button>{' '}
									and unlock more tools and export options for items and ships. More details:
							</p>
							<Message.List>
								<Message.Item>
									Once shared, the profile will be publicly accessible, will be accessible by your DBID link, and linked on related pages (such as fleet pages & event pages)
									</Message.Item>
								<Message.Item>
									There is no private information included in the player profile; information being shared is limited to:{' '}
									<b>captain name, level, vip level, fleet name and role, achievements, completed missions, your crew, items and ships.</b>
								</Message.Item>
							</Message.List>
						</div>
					)}
					{bShowUploaded && (
						<Form.Group>
							<p>
								Your profile was uploaded. Share the link:{' '}
								<a
									href={`${process.env.GATSBY_DATACORE_URL}profile/?dbid=${playerData.player.dbid}`}
									target='_blank'>{`${process.env.GATSBY_DATACORE_URL}profile/?dbid=${playerData.player.dbid}`}</a>
							</p>
							<Form.Field
								control={Checkbox}
								label='Automatically share profile after every import'
								checked={profileAutoUpdate}
								onChange={(e, { checked }) => setProfileAutoUpdate(checked)}
							/>
						</Form.Group>
					)}
				</Message.Content>
			</Message>
		);
	};

	if (!varsReady)
		return (<PlayerToolsLoading />);

	const PlayerLevelProgress = () => {
		const endingValue = playerData.player.character.xp_for_next_level - playerData.player.character.xp_for_current_level;
		const currentValue = playerData.player.character.xp - playerData.player.character.xp_for_current_level;
		const percent = (currentValue / endingValue) * 100;
		return (
		  <Progress
			percent={percent.toPrecision(3)}
			label={`Level ${playerData.player.character.level}: ${playerData.player.character.xp} / ${playerData.player.character.xp_for_next_level}`}
			progress
		  />
		);
	 };

	return (
		<Layout title='Player tools'>
			<Header as='h4'>Hello, {playerData.player.character.display_name}</Header>
			<PlayerLevelProgress />
			<StaleMessage />
			<Menu compact stackable>
				<Menu.Item>
					Last imported: {playerData.calc.lastModified.toLocaleString()}
				</Menu.Item>
				<Dropdown item text='Profile options'>
					<Dropdown.Menu>
						<Dropdown.Item onClick={() => requestShowForm(true)}>Update now...</Dropdown.Item>
						{!showShare && (<Dropdown.Item onClick={() => setShowShare(true)}>Share profile...</Dropdown.Item>)}
						<Dropdown.Item onClick={() => requestClearData()}>Clear player data</Dropdown.Item>
					</Dropdown.Menu>
				</Dropdown>
			  <Dropdown item text='Export'>
				<Dropdown.Menu>
					<Popup basic content='Download crew data as traditional comma delimited CSV file' trigger={
						<Dropdown.Item onClick={() => exportCrewTool()} content='Download CSV...' />
					} />
					<Popup basic content='Copy crew data to clipboard in Google Sheets format' trigger={
						<Dropdown.Item onClick={() => exportCrewToClipboard()} content='Copy to clipboard' />
					} />
				</Dropdown.Menu>
			</Dropdown>
			</Menu>

			<React.Fragment>
				<ShareMessage />
				<Header as='h3'>{tools[activeTool].title}</Header>
				{tools[activeTool].render(props)}
			</React.Fragment>
		</Layout>
	);

	function variableReady(keyName: string) {
		setVarsReady(true);
	}

	function shareProfile() {
		setProfileUploading(true);

		let jsonBody = JSON.stringify({
			dbid: playerData.player.dbid,
			player_data: strippedPlayerData
		});

		fetch(`${process.env.GATSBY_DATACORE_URL}api/post_profile`, {
			method: 'post',
			headers: {
				'Content-Type': 'application/json'
			},
			body: jsonBody
		}).then(() => {
			if (!profileAutoUpdate) window.open(`${process.env.GATSBY_DATACORE_URL}profile/?dbid=${playerData.player.dbid}`, '_blank');
			setProfileUploading(false);
			setProfileUploaded(true);
			setProfileShared(true);
		});
	}

	function exportCrewTool() {
		let text = exportCrew(playerData.player.character.crew.concat(playerData.player.character.unOwnedCrew));
		downloadData(`data:text/csv;charset=utf-8,${encodeURIComponent(text)}`, 'crew.csv');
	}

	function exportCrewToClipboard() {
		let text = exportCrew(playerData.player.character.crew.concat(playerData.player.character.unOwnedCrew), '\t');
		navigator.clipboard.writeText(text);
	}
}