import * as React from "react"; import * as System from "~/components/system"; import * as Actions from "~/common/actions"; import * as Constants from "~/common/constants"; import * as SVG from "~/common/svg"; import { css } from "@emotion/react"; import { TabGroup } from "~/components/core/TabGroup"; import { Boundary } from "~/components/system/components/fragments/Boundary"; import { PopoverNavigation } from "~/components/system/components/PopoverNavigation"; import { ButtonPrimary, ButtonSecondary, } from "~/components/system/components/Buttons"; import ScenePage from "~/components/core/ScenePage"; import ScenePageHeader from "~/components/core/ScenePageHeader"; import EmptyState from "~/components/core/EmptyState"; const STYLES_USER_ENTRY = css` display: grid; grid-template-columns: auto 1fr; align-items: center; font-size: ${Constants.typescale.lvl1}; cursor: pointer; border: 1px solid ${Constants.system.lightBorder}; border-radius: 4px; margin-bottom: 8px; `; const STYLES_USER = css` display: grid; grid-template-columns: auto 1fr; align-items: center; margin: 24px; color: ${Constants.system.brand}; font-family: ${Constants.font.medium}; font-size: ${Constants.typescale.lvl1}; `; const STYLES_BUTTONS = css` justify-self: end; display: flex; flex-direction: row; margin-right: 48px; `; const STYLES_ITEM_BOX = css` position: relative; justify-self: end; display: flex; align-items: center; justify-content: center; padding: 8px; margin-right: 48px; color: ${Constants.system.darkGray}; `; const STYLES_ACTION_BUTTON = css` cursor: pointer; padding: 8px; color: ${Constants.system.brand}; font-family: ${Constants.font.medium}; `; const STYLES_PROFILE_IMAGE = css` background-color: ${Constants.system.foreground}; background-size: cover; background-position: 50% 50%; height: 24px; width: 24px; margin-right: 16px; border-radius: 4px; `; const STYLES_MESSAGE = css` color: ${Constants.system.black}; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @media (max-width: 1000px) { display: none; } `; const STYLES_NAME = css` overflow: hidden; white-space: nowrap; text-overflow: ellipsis; `; function UserEntry({ user, button, onClick, message }) { return (
{user.data.name || `@${user.username}`} {message ? {message} : null}
{button}
); } const STYLES_COPY_INPUT = css` pointer-events: none; position: absolute; opacity: 0; `; export default class SceneDirectory extends React.Component { _ref; state = { copyValue: "", loading: false, tab: 0, contextMenu: null, }; _handleCopy = (e, value) => { e.stopPropagation(); this.setState({ copyValue: value }, () => { this._ref.select(); document.execCommand("copy"); this._handleHide(); }); }; _handleHide = (e) => { this.setState({ contextMenu: null }); }; _handleClick = (e, value) => { e.stopPropagation(); if (this.state.contextMenu === value) { this._handleHide(); } else { this.setState({ contextMenu: value }); } }; _handleDelete = async (e, id) => { this._handleHide(); e.stopPropagation(); const response = await Actions.deleteTrustRelationship({ id: id, }); await this.props.onRehydrate(); }; _handleAccept = async (e, id) => { this._handleHide(); e.stopPropagation(); const response = await Actions.updateTrustRelationship({ userId: id, }); await this.props.onRehydrate(); }; _handleFollow = async (e, id) => { this._handleHide(); e.stopPropagation(); const response = await Actions.createSubscription({ userId: id, }); await this.props.onRehydrate(); }; render() { let requests = this.props.viewer.pendingTrusted .filter((relation) => { return !relation.data.verified; }) .map((relation) => { let button = (
this._handleAccept(e, relation.owner.id)} > Accept { this._handleDelete(e, relation.id); }} > Decline
); return ( { this.props.onAction({ type: "NAVIGATE", value: this.props.sceneId, scene: "PUBLIC_PROFILE", data: relation.owner, }); }} message=" requested to trust you" /> ); }); let trusted = this.props.viewer.pendingTrusted .filter((relation) => { return relation.data.verified; }) .map((relation) => { let button = (
this._handleClick(e, relation.id)} > {this.state.contextMenu === relation.id ? ( this._handleClick(e, relation.id)} > this._handleCopy( e, `https://slate.host/${relation.owner.username}` ), }, { text: "Remove peer", onClick: (e) => this._handleDelete(e, relation.id), }, ]} /> ) : null}
); return ( { this.props.onAction({ type: "NAVIGATE", value: this.props.sceneId, scene: "PUBLIC_PROFILE", data: relation.owner, }); }} /> ); }); if (!trusted) { trusted = []; } trusted.push( ...this.props.viewer.trusted .filter((relation) => { return relation.data.verified; }) .map((relation) => { let button = (
this._handleClick(e, relation.id)} > {this.state.contextMenu === relation.id ? ( this._handleClick(e, relation.id)} > this._handleCopy( e, `https://slate.host/${relation.user.username}` ), }, { text: "Remove peer", onClick: (e) => this._handleDelete(e, relation.id), }, ]} /> ) : null}
); return ( { this.props.onAction({ type: "NAVIGATE", value: this.props.sceneId, scene: "PUBLIC_PROFILE", data: relation.user, }); }} /> ); }) ); let following = this.props.viewer.subscriptions .filter((relation) => { return !!relation.target_user_id; }) .map((relation) => { let button = (
this._handleClick(e, relation.id)} > {this.state.contextMenu === relation.id ? ( this._handleClick(e, relation.id)} > this._handleCopy( e, `https://slate.host/${relation.user.username}` ), }, { text: "Unfollow", onClick: (e) => this._handleFollow(e, relation.user.id), }, ]} /> ) : null}
); return ( { this.props.onAction({ type: "NAVIGATE", value: this.props.sceneId, scene: "PUBLIC_PROFILE", data: relation.user, }); }} /> ); }); let followers = this.props.viewer.subscribers.map((relation) => { let button = (
this._handleClick(e, relation.id)} > {this.state.contextMenu === relation.id ? ( this._handleClick(e, relation.id)} > this._handleCopy( e, `https://slate.host/${relation.owner.username}` ), }, { text: this.props.viewer.subscriptions.filter( (subscription) => { return ( subscription.target_user_id === relation.owner.id ); } ).length ? "Unfollow" : "Follow", onClick: (e) => this._handleFollow(e, relation.owner.id), }, ]} /> ) : null}
); return ( { this.props.onAction({ type: "NAVIGATE", value: this.props.sceneId, scene: "PUBLIC_PROFILE", data: relation.owner, }); }} /> ); }); return ( this.setState({ tab: value })} /> {this.state.tab === 0 ? ( requests && requests.length ? ( requests ) : ( Trust requests that you receive will appear here. ) ) : null} {this.state.tab === 1 ? ( trusted && trusted.length ? ( trusted ) : ( Trusted is for your close friends. ) ) : null} {this.state.tab === 2 ? ( following && following.length ? ( following ) : ( You can follow any user on the network to be updated on their new uploads and slates. ) ) : null} {this.state.tab === 3 ? ( followers && followers.length ? ( followers ) : ( You don't have any followers yet. ) ) : null} { this._ref = c; }} value={this.state.copyValue} tabIndex="-1" css={STYLES_COPY_INPUT} /> ); } }