Profile: support wide page
This commit is contained in:
		
							parent
							
								
									bb3ba32dc5
								
							
						
					
					
						commit
						66d0bc8d84
					
				
					 3 changed files with 347 additions and 302 deletions
				
			
		| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
.StackedPage {
 | 
			
		||||
  contain: layout style;
 | 
			
		||||
  container: StackedPage / size;
 | 
			
		||||
  display: contents;
 | 
			
		||||
  max-width: 100vw;
 | 
			
		||||
  max-width: 100dvw;
 | 
			
		||||
  contain: strict;
 | 
			
		||||
  container: StackedPage / inline-size;
 | 
			
		||||
  width: 100vw;
 | 
			
		||||
  width: 100dvw;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  height: 100dvh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dialog.StackedPage {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,6 +115,44 @@
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@container StackedPage (inline-size >=960px) {
 | 
			
		||||
  .Profile {
 | 
			
		||||
    display: grid;
 | 
			
		||||
    grid-template-columns: auto 560px;
 | 
			
		||||
    grid-template-rows: min-content 1fr;
 | 
			
		||||
    height: 100cqh;
 | 
			
		||||
 | 
			
		||||
    >.topbar {
 | 
			
		||||
      grid-column: 1 / 3;
 | 
			
		||||
      grid-row: 1 /2;
 | 
			
		||||
 | 
			
		||||
      .MuiToolbar-root {
 | 
			
		||||
        padding-right: calc(560px + 24px);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    > .details {
 | 
			
		||||
      height: 100%;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-flow: column nowrap;
 | 
			
		||||
 | 
			
		||||
      > .intro {
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    >.recent-toots {
 | 
			
		||||
      overflow-y: auto;
 | 
			
		||||
      margin-top: calc(-1 * var(--scaffold-topbar-height));
 | 
			
		||||
      z-index: calc(var(--tutu-zidx-nav, 1) + 1);
 | 
			
		||||
 | 
			
		||||
      >.toot-list-toolbar {
 | 
			
		||||
        top: 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Profile__page-title {
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,315 +237,321 @@ const Profile: Component = () => {
 | 
			
		|||
      }
 | 
			
		||||
      class="Profile"
 | 
			
		||||
    >
 | 
			
		||||
      <Menu
 | 
			
		||||
        id={optMenuId}
 | 
			
		||||
        open={menuOpen()}
 | 
			
		||||
        onClose={[setMenuOpen, false]}
 | 
			
		||||
        anchor={() =>
 | 
			
		||||
          document.getElementById(menuButId)!.getBoundingClientRect()
 | 
			
		||||
        }
 | 
			
		||||
        aria-label="Options for the Profile"
 | 
			
		||||
      >
 | 
			
		||||
        <Show when={session().account}>
 | 
			
		||||
          <MenuItem>
 | 
			
		||||
            <ListItemAvatar>
 | 
			
		||||
              <Avatar src={session().account?.inf?.avatar} />
 | 
			
		||||
            </ListItemAvatar>
 | 
			
		||||
            <ListItemText secondary={"Default account"}>
 | 
			
		||||
              <span ref={useSessionDisplayName}></span>
 | 
			
		||||
            </ListItemText>
 | 
			
		||||
            {/* <ArrowRight /> // for future */}
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
        </Show>
 | 
			
		||||
        <Show when={session().account && profile()}>
 | 
			
		||||
          <Show
 | 
			
		||||
            when={isCurrentSessionProfile()}
 | 
			
		||||
            fallback={
 | 
			
		||||
              <MenuItem
 | 
			
		||||
                onClick={(event) => {
 | 
			
		||||
                  const { left, right, top } =
 | 
			
		||||
                    event.currentTarget.getBoundingClientRect();
 | 
			
		||||
                  openSubscribeMenu({
 | 
			
		||||
                    left,
 | 
			
		||||
                    right,
 | 
			
		||||
                    top,
 | 
			
		||||
                    e: 1,
 | 
			
		||||
                  });
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <ListItemIcon>
 | 
			
		||||
                  <PlaylistAdd />
 | 
			
		||||
                </ListItemIcon>
 | 
			
		||||
                <ListItemText>Subscribe...</ListItemText>
 | 
			
		||||
              </MenuItem>
 | 
			
		||||
            }
 | 
			
		||||
          >
 | 
			
		||||
            <MenuItem disabled>
 | 
			
		||||
              <ListItemIcon>
 | 
			
		||||
                <Edit />
 | 
			
		||||
              </ListItemIcon>
 | 
			
		||||
              <ListItemText>Edit...</ListItemText>
 | 
			
		||||
      <div class="details">
 | 
			
		||||
        <Menu
 | 
			
		||||
          id={optMenuId}
 | 
			
		||||
          open={menuOpen()}
 | 
			
		||||
          onClose={[setMenuOpen, false]}
 | 
			
		||||
          anchor={() =>
 | 
			
		||||
            document.getElementById(menuButId)!.getBoundingClientRect()
 | 
			
		||||
          }
 | 
			
		||||
          aria-label="Options for the Profile"
 | 
			
		||||
        >
 | 
			
		||||
          <Show when={session().account}>
 | 
			
		||||
            <MenuItem>
 | 
			
		||||
              <ListItemAvatar>
 | 
			
		||||
                <Avatar src={session().account?.inf?.avatar} />
 | 
			
		||||
              </ListItemAvatar>
 | 
			
		||||
              <ListItemText secondary={"Default account"}>
 | 
			
		||||
                <span ref={useSessionDisplayName}></span>
 | 
			
		||||
              </ListItemText>
 | 
			
		||||
              {/* <ArrowRight /> // for future */}
 | 
			
		||||
            </MenuItem>
 | 
			
		||||
          </Show>
 | 
			
		||||
          <Divider />
 | 
			
		||||
        </Show>
 | 
			
		||||
        <MenuItem disabled>
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <Group />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Followers</ListItemText>
 | 
			
		||||
          <ListItemSecondaryAction>
 | 
			
		||||
            <span aria-label="The number of the account follower">
 | 
			
		||||
              {profile()?.followersCount ?? ""}
 | 
			
		||||
            </span>
 | 
			
		||||
          </ListItemSecondaryAction>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
        <MenuItem disabled>
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <Subject />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Following</ListItemText>
 | 
			
		||||
          <ListItemSecondaryAction>
 | 
			
		||||
            <span aria-label="The number the account following">
 | 
			
		||||
              {profile()?.followingCount ?? ""}
 | 
			
		||||
            </span>
 | 
			
		||||
          </ListItemSecondaryAction>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
        <MenuItem disabled>
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <PersonOff />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Blocklist</ListItemText>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
        <MenuItem disabled>
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <Send />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Mention in...</ListItemText>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
        <Divider />
 | 
			
		||||
        <MenuItem
 | 
			
		||||
          component={"a"}
 | 
			
		||||
          href={profile()?.url}
 | 
			
		||||
          target="_blank"
 | 
			
		||||
          rel="noopener noreferrer"
 | 
			
		||||
        >
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <OpenInBrowser />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Open in browser...</ListItemText>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
        <MenuItem onClick={() => share({ url: profile()?.url })}>
 | 
			
		||||
          <ListItemIcon>
 | 
			
		||||
            <Share />
 | 
			
		||||
          </ListItemIcon>
 | 
			
		||||
          <ListItemText>Share...</ListItemText>
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
      </Menu>
 | 
			
		||||
      <div
 | 
			
		||||
        style={{
 | 
			
		||||
          height: `${268 * (Math.min(560, windowSize.width) / 560)}px`,
 | 
			
		||||
        }}
 | 
			
		||||
        class="banner"
 | 
			
		||||
        role="presentation"
 | 
			
		||||
      >
 | 
			
		||||
        <img
 | 
			
		||||
          ref={(e) => obx.observe(e)}
 | 
			
		||||
          src={bannerImg()}
 | 
			
		||||
          crossOrigin="anonymous"
 | 
			
		||||
          alt={`Banner image for ${profile()?.displayName || "the user"}`}
 | 
			
		||||
          onLoad={(event) => {
 | 
			
		||||
            const ins = new FastAverageColor();
 | 
			
		||||
            const colors = ins.getColor(event.currentTarget);
 | 
			
		||||
            setBannerSampledColors({
 | 
			
		||||
              average: colors.hex,
 | 
			
		||||
              text: colors.isDark ? "white" : "black",
 | 
			
		||||
            });
 | 
			
		||||
            ins.destroy();
 | 
			
		||||
          }}
 | 
			
		||||
        ></img>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <Menu {...subscribeMenuState}>
 | 
			
		||||
        <MenuItem
 | 
			
		||||
          onClick={toggleSubscribeHome}
 | 
			
		||||
          aria-label={`${relationship()?.following ? "Unfollow" : "Follow"} on your home timeline`}
 | 
			
		||||
        >
 | 
			
		||||
          <ListItemAvatar>
 | 
			
		||||
            <Avatar src={session().account?.inf?.avatar}></Avatar>
 | 
			
		||||
          </ListItemAvatar>
 | 
			
		||||
          <ListItemText
 | 
			
		||||
            secondary={
 | 
			
		||||
              relationship()?.following
 | 
			
		||||
                ? undefined
 | 
			
		||||
                : profile()?.locked
 | 
			
		||||
                  ? "A request will be sent"
 | 
			
		||||
                  : undefined
 | 
			
		||||
            }
 | 
			
		||||
          >
 | 
			
		||||
            <span ref={useSessionDisplayName}></span>
 | 
			
		||||
            <span>'s Home</span>
 | 
			
		||||
          </ListItemText>
 | 
			
		||||
 | 
			
		||||
          <Checkbox checked={relationship()?.following ?? false} />
 | 
			
		||||
        </MenuItem>
 | 
			
		||||
      </Menu>
 | 
			
		||||
 | 
			
		||||
      <div
 | 
			
		||||
        class="intro"
 | 
			
		||||
        style={{
 | 
			
		||||
          "background-color": bannerSampledColors()?.average,
 | 
			
		||||
          color: bannerSampledColors()?.text,
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <section class="acct-grp">
 | 
			
		||||
          <Avatar
 | 
			
		||||
            src={avatarImg()}
 | 
			
		||||
            alt={`${profile()?.displayName || "the user"}'s avatar`}
 | 
			
		||||
            sx={{
 | 
			
		||||
              marginTop: "calc(-16px - 72px / 2)",
 | 
			
		||||
              width: "72px",
 | 
			
		||||
              height: "72px",
 | 
			
		||||
            }}
 | 
			
		||||
          ></Avatar>
 | 
			
		||||
          <div class="name-grp">
 | 
			
		||||
            <div class="display-name">
 | 
			
		||||
              <Show when={profile()?.bot}>
 | 
			
		||||
                <SmartToySharp class="acct-mark" aria-label="Bot" />
 | 
			
		||||
              </Show>
 | 
			
		||||
              <Show when={profile()?.locked}>
 | 
			
		||||
                <Lock class="acct-mark" aria-label="Locked" />
 | 
			
		||||
              </Show>
 | 
			
		||||
              <Body2
 | 
			
		||||
                component="span"
 | 
			
		||||
                ref={(e: HTMLElement) =>
 | 
			
		||||
                  createRenderEffect(() => (e.innerHTML = displayName()))
 | 
			
		||||
                }
 | 
			
		||||
                aria-label="Display name"
 | 
			
		||||
              ></Body2>
 | 
			
		||||
            </div>
 | 
			
		||||
            <span aria-label="Complete username" class="username">{fullUsername()}</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div role="presentation">
 | 
			
		||||
            <Switch>
 | 
			
		||||
              <Match
 | 
			
		||||
                when={
 | 
			
		||||
                  !session().account ||
 | 
			
		||||
                  profileUncaught.loading ||
 | 
			
		||||
                  profileUncaught.error
 | 
			
		||||
                }
 | 
			
		||||
              >
 | 
			
		||||
                {<></>}
 | 
			
		||||
              </Match>
 | 
			
		||||
              <Match when={isCurrentSessionProfile()}>
 | 
			
		||||
                <IconButton color="inherit">
 | 
			
		||||
                  <Edit />
 | 
			
		||||
                </IconButton>
 | 
			
		||||
              </Match>
 | 
			
		||||
              <Match when={true}>
 | 
			
		||||
                <Button
 | 
			
		||||
                  variant="contained"
 | 
			
		||||
                  color="secondary"
 | 
			
		||||
          <Show when={session().account && profile()}>
 | 
			
		||||
            <Show
 | 
			
		||||
              when={isCurrentSessionProfile()}
 | 
			
		||||
              fallback={
 | 
			
		||||
                <MenuItem
 | 
			
		||||
                  onClick={(event) => {
 | 
			
		||||
                    openSubscribeMenu(
 | 
			
		||||
                      event.currentTarget.getBoundingClientRect(),
 | 
			
		||||
                    );
 | 
			
		||||
                    const { left, right, top } =
 | 
			
		||||
                      event.currentTarget.getBoundingClientRect();
 | 
			
		||||
                    openSubscribeMenu({
 | 
			
		||||
                      left,
 | 
			
		||||
                      right,
 | 
			
		||||
                      top,
 | 
			
		||||
                      e: 1,
 | 
			
		||||
                    });
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  {relationship()?.following ? "Subscribed" : "Subscribe"}
 | 
			
		||||
                </Button>
 | 
			
		||||
              </Match>
 | 
			
		||||
            </Switch>
 | 
			
		||||
          </div>
 | 
			
		||||
        </section>
 | 
			
		||||
        <section
 | 
			
		||||
          class="description"
 | 
			
		||||
          aria-label={`${profile()?.displayName || "the user"}'s description`}
 | 
			
		||||
          ref={(e) =>
 | 
			
		||||
            createRenderEffect(() => (e.innerHTML = description() || ""))
 | 
			
		||||
          }
 | 
			
		||||
        ></section>
 | 
			
		||||
 | 
			
		||||
        <table
 | 
			
		||||
          class="acct-fields"
 | 
			
		||||
          aria-label={`${profile()?.displayName || "the user"}'s fields`}
 | 
			
		||||
        >
 | 
			
		||||
          <tbody>
 | 
			
		||||
            <For each={profile()?.fields ?? []}>
 | 
			
		||||
              {(item, index) => {
 | 
			
		||||
                return (
 | 
			
		||||
                  <tr data-field-index={index()}>
 | 
			
		||||
                    <td>{item.name}</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                      <Show when={item.verifiedAt}>
 | 
			
		||||
                        <Verified />
 | 
			
		||||
                      </Show>
 | 
			
		||||
                    </td>
 | 
			
		||||
                    <td
 | 
			
		||||
                      ref={(e) => {
 | 
			
		||||
                        createRenderEffect(() => (e.innerHTML = item.value));
 | 
			
		||||
                      }}
 | 
			
		||||
                    ></td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                );
 | 
			
		||||
              }}
 | 
			
		||||
            </For>
 | 
			
		||||
          </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="toot-list-toolbar">
 | 
			
		||||
        <TootFilterButton
 | 
			
		||||
          options={{
 | 
			
		||||
            pinned: "Pinneds",
 | 
			
		||||
            boost: "Boosts",
 | 
			
		||||
            reply: "Replies",
 | 
			
		||||
            original: "Originals",
 | 
			
		||||
          }}
 | 
			
		||||
          applied={recentTootFilter()}
 | 
			
		||||
          onApply={setRecentTootFilter}
 | 
			
		||||
          disabledKeys={["original"]}
 | 
			
		||||
        ></TootFilterButton>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <TimeSourceProvider value={time}>
 | 
			
		||||
        <Show when={recentTootFilter().pinned && pinnedToots.list.length > 0}>
 | 
			
		||||
          <TootList
 | 
			
		||||
            threads={pinnedToots.list}
 | 
			
		||||
            onUnknownThread={pinnedToots.getPath}
 | 
			
		||||
            onChangeToot={pinnedToots.set}
 | 
			
		||||
          />
 | 
			
		||||
                  <ListItemIcon>
 | 
			
		||||
                    <PlaylistAdd />
 | 
			
		||||
                  </ListItemIcon>
 | 
			
		||||
                  <ListItemText>Subscribe...</ListItemText>
 | 
			
		||||
                </MenuItem>
 | 
			
		||||
              }
 | 
			
		||||
            >
 | 
			
		||||
              <MenuItem disabled>
 | 
			
		||||
                <ListItemIcon>
 | 
			
		||||
                  <Edit />
 | 
			
		||||
                </ListItemIcon>
 | 
			
		||||
                <ListItemText>Edit...</ListItemText>
 | 
			
		||||
              </MenuItem>
 | 
			
		||||
            </Show>
 | 
			
		||||
            <Divider />
 | 
			
		||||
          </Show>
 | 
			
		||||
          <MenuItem disabled>
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <Group />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Followers</ListItemText>
 | 
			
		||||
            <ListItemSecondaryAction>
 | 
			
		||||
              <span aria-label="The number of the account follower">
 | 
			
		||||
                {profile()?.followersCount ?? ""}
 | 
			
		||||
              </span>
 | 
			
		||||
            </ListItemSecondaryAction>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
          <MenuItem disabled>
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <Subject />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Following</ListItemText>
 | 
			
		||||
            <ListItemSecondaryAction>
 | 
			
		||||
              <span aria-label="The number the account following">
 | 
			
		||||
                {profile()?.followingCount ?? ""}
 | 
			
		||||
              </span>
 | 
			
		||||
            </ListItemSecondaryAction>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
          <MenuItem disabled>
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <PersonOff />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Blocklist</ListItemText>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
          <MenuItem disabled>
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <Send />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Mention in...</ListItemText>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
          <Divider />
 | 
			
		||||
        </Show>
 | 
			
		||||
        <TootList
 | 
			
		||||
          id={recentTootListId}
 | 
			
		||||
          threads={recentToots.list}
 | 
			
		||||
          onUnknownThread={recentToots.getPath}
 | 
			
		||||
          onChangeToot={recentToots.set}
 | 
			
		||||
        />
 | 
			
		||||
      </TimeSourceProvider>
 | 
			
		||||
 | 
			
		||||
      <Show when={!recentTootChunk()?.done}>
 | 
			
		||||
          <MenuItem
 | 
			
		||||
            component={"a"}
 | 
			
		||||
            href={profile()?.url}
 | 
			
		||||
            target="_blank"
 | 
			
		||||
            rel="noopener noreferrer"
 | 
			
		||||
          >
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <OpenInBrowser />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Open in browser...</ListItemText>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
          <MenuItem onClick={() => share({ url: profile()?.url })}>
 | 
			
		||||
            <ListItemIcon>
 | 
			
		||||
              <Share />
 | 
			
		||||
            </ListItemIcon>
 | 
			
		||||
            <ListItemText>Share...</ListItemText>
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
        </Menu>
 | 
			
		||||
        <div
 | 
			
		||||
          style={{
 | 
			
		||||
            "text-align": "center",
 | 
			
		||||
            "padding-bottom": "var(--safe-area-inset-bottom)",
 | 
			
		||||
            height: `${268 * (Math.min(560, windowSize.width) / 560)}px`,
 | 
			
		||||
          }}
 | 
			
		||||
          class="banner"
 | 
			
		||||
          role="presentation"
 | 
			
		||||
        >
 | 
			
		||||
          <img
 | 
			
		||||
            ref={(e) => obx.observe(e)}
 | 
			
		||||
            src={bannerImg()}
 | 
			
		||||
            crossOrigin="anonymous"
 | 
			
		||||
            alt={`Banner image for ${profile()?.displayName || "the user"}`}
 | 
			
		||||
            onLoad={(event) => {
 | 
			
		||||
              const ins = new FastAverageColor();
 | 
			
		||||
              const colors = ins.getColor(event.currentTarget);
 | 
			
		||||
              setBannerSampledColors({
 | 
			
		||||
                average: colors.hex,
 | 
			
		||||
                text: colors.isDark ? "white" : "black",
 | 
			
		||||
              });
 | 
			
		||||
              ins.destroy();
 | 
			
		||||
            }}
 | 
			
		||||
          ></img>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <Menu {...subscribeMenuState}>
 | 
			
		||||
          <MenuItem
 | 
			
		||||
            onClick={toggleSubscribeHome}
 | 
			
		||||
            aria-label={`${relationship()?.following ? "Unfollow" : "Follow"} on your home timeline`}
 | 
			
		||||
          >
 | 
			
		||||
            <ListItemAvatar>
 | 
			
		||||
              <Avatar src={session().account?.inf?.avatar}></Avatar>
 | 
			
		||||
            </ListItemAvatar>
 | 
			
		||||
            <ListItemText
 | 
			
		||||
              secondary={
 | 
			
		||||
                relationship()?.following
 | 
			
		||||
                  ? undefined
 | 
			
		||||
                  : profile()?.locked
 | 
			
		||||
                    ? "A request will be sent"
 | 
			
		||||
                    : undefined
 | 
			
		||||
              }
 | 
			
		||||
            >
 | 
			
		||||
              <span ref={useSessionDisplayName}></span>
 | 
			
		||||
              <span>'s Home</span>
 | 
			
		||||
            </ListItemText>
 | 
			
		||||
 | 
			
		||||
            <Checkbox checked={relationship()?.following ?? false} />
 | 
			
		||||
          </MenuItem>
 | 
			
		||||
        </Menu>
 | 
			
		||||
 | 
			
		||||
        <div
 | 
			
		||||
          class="intro"
 | 
			
		||||
          style={{
 | 
			
		||||
            "background-color": bannerSampledColors()?.average,
 | 
			
		||||
            color: bannerSampledColors()?.text,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <IconButton
 | 
			
		||||
            aria-label="Load More"
 | 
			
		||||
            aria-controls={recentTootListId}
 | 
			
		||||
            size="large"
 | 
			
		||||
            color="primary"
 | 
			
		||||
            onClick={[refetchRecentToots, "prev"]}
 | 
			
		||||
            disabled={isTootListLoading()}
 | 
			
		||||
          <section class="acct-grp">
 | 
			
		||||
            <Avatar
 | 
			
		||||
              src={avatarImg()}
 | 
			
		||||
              alt={`${profile()?.displayName || "the user"}'s avatar`}
 | 
			
		||||
              sx={{
 | 
			
		||||
                marginTop: "calc(-16px - 72px / 2)",
 | 
			
		||||
                width: "72px",
 | 
			
		||||
                height: "72px",
 | 
			
		||||
              }}
 | 
			
		||||
            ></Avatar>
 | 
			
		||||
            <div class="name-grp">
 | 
			
		||||
              <div class="display-name">
 | 
			
		||||
                <Show when={profile()?.bot}>
 | 
			
		||||
                  <SmartToySharp class="acct-mark" aria-label="Bot" />
 | 
			
		||||
                </Show>
 | 
			
		||||
                <Show when={profile()?.locked}>
 | 
			
		||||
                  <Lock class="acct-mark" aria-label="Locked" />
 | 
			
		||||
                </Show>
 | 
			
		||||
                <Body2
 | 
			
		||||
                  component="span"
 | 
			
		||||
                  ref={(e: HTMLElement) =>
 | 
			
		||||
                    createRenderEffect(() => (e.innerHTML = displayName()))
 | 
			
		||||
                  }
 | 
			
		||||
                  aria-label="Display name"
 | 
			
		||||
                ></Body2>
 | 
			
		||||
              </div>
 | 
			
		||||
              <span aria-label="Complete username" class="username">
 | 
			
		||||
                {fullUsername()}
 | 
			
		||||
              </span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div role="presentation">
 | 
			
		||||
              <Switch>
 | 
			
		||||
                <Match
 | 
			
		||||
                  when={
 | 
			
		||||
                    !session().account ||
 | 
			
		||||
                    profileUncaught.loading ||
 | 
			
		||||
                    profileUncaught.error
 | 
			
		||||
                  }
 | 
			
		||||
                >
 | 
			
		||||
                  {<></>}
 | 
			
		||||
                </Match>
 | 
			
		||||
                <Match when={isCurrentSessionProfile()}>
 | 
			
		||||
                  <IconButton color="inherit">
 | 
			
		||||
                    <Edit />
 | 
			
		||||
                  </IconButton>
 | 
			
		||||
                </Match>
 | 
			
		||||
                <Match when={true}>
 | 
			
		||||
                  <Button
 | 
			
		||||
                    variant="contained"
 | 
			
		||||
                    color="secondary"
 | 
			
		||||
                    onClick={(event) => {
 | 
			
		||||
                      openSubscribeMenu(
 | 
			
		||||
                        event.currentTarget.getBoundingClientRect(),
 | 
			
		||||
                      );
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    {relationship()?.following ? "Subscribed" : "Subscribe"}
 | 
			
		||||
                  </Button>
 | 
			
		||||
                </Match>
 | 
			
		||||
              </Switch>
 | 
			
		||||
            </div>
 | 
			
		||||
          </section>
 | 
			
		||||
          <section
 | 
			
		||||
            class="description"
 | 
			
		||||
            aria-label={`${profile()?.displayName || "the user"}'s description`}
 | 
			
		||||
            ref={(e) =>
 | 
			
		||||
              createRenderEffect(() => (e.innerHTML = description() || ""))
 | 
			
		||||
            }
 | 
			
		||||
          ></section>
 | 
			
		||||
 | 
			
		||||
          <table
 | 
			
		||||
            class="acct-fields"
 | 
			
		||||
            aria-label={`${profile()?.displayName || "the user"}'s fields`}
 | 
			
		||||
          >
 | 
			
		||||
            <Show when={isTootListLoading()} fallback={<ExpandMore />}>
 | 
			
		||||
              <CircularProgress sx={{ width: "24px", height: "24px" }} />
 | 
			
		||||
            </Show>
 | 
			
		||||
          </IconButton>
 | 
			
		||||
            <tbody>
 | 
			
		||||
              <For each={profile()?.fields ?? []}>
 | 
			
		||||
                {(item, index) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <tr data-field-index={index()}>
 | 
			
		||||
                      <td>{item.name}</td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <Show when={item.verifiedAt}>
 | 
			
		||||
                          <Verified />
 | 
			
		||||
                        </Show>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td
 | 
			
		||||
                        ref={(e) => {
 | 
			
		||||
                          createRenderEffect(() => (e.innerHTML = item.value));
 | 
			
		||||
                        }}
 | 
			
		||||
                      ></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                  );
 | 
			
		||||
                }}
 | 
			
		||||
              </For>
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
      </Show>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="recent-toots">
 | 
			
		||||
        <div class="toot-list-toolbar">
 | 
			
		||||
          <TootFilterButton
 | 
			
		||||
            options={{
 | 
			
		||||
              pinned: "Pinneds",
 | 
			
		||||
              boost: "Boosts",
 | 
			
		||||
              reply: "Replies",
 | 
			
		||||
              original: "Originals",
 | 
			
		||||
            }}
 | 
			
		||||
            applied={recentTootFilter()}
 | 
			
		||||
            onApply={setRecentTootFilter}
 | 
			
		||||
            disabledKeys={["original"]}
 | 
			
		||||
          ></TootFilterButton>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <TimeSourceProvider value={time}>
 | 
			
		||||
          <Show when={recentTootFilter().pinned && pinnedToots.list.length > 0}>
 | 
			
		||||
            <TootList
 | 
			
		||||
              threads={pinnedToots.list}
 | 
			
		||||
              onUnknownThread={pinnedToots.getPath}
 | 
			
		||||
              onChangeToot={pinnedToots.set}
 | 
			
		||||
            />
 | 
			
		||||
            <Divider />
 | 
			
		||||
          </Show>
 | 
			
		||||
          <TootList
 | 
			
		||||
            id={recentTootListId}
 | 
			
		||||
            threads={recentToots.list}
 | 
			
		||||
            onUnknownThread={recentToots.getPath}
 | 
			
		||||
            onChangeToot={recentToots.set}
 | 
			
		||||
          />
 | 
			
		||||
        </TimeSourceProvider>
 | 
			
		||||
 | 
			
		||||
        <Show when={!recentTootChunk()?.done}>
 | 
			
		||||
          <div
 | 
			
		||||
            style={{
 | 
			
		||||
              "text-align": "center",
 | 
			
		||||
              "padding-bottom": "var(--safe-area-inset-bottom)",
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <IconButton
 | 
			
		||||
              aria-label="Load More"
 | 
			
		||||
              aria-controls={recentTootListId}
 | 
			
		||||
              size="large"
 | 
			
		||||
              color="primary"
 | 
			
		||||
              onClick={[refetchRecentToots, "prev"]}
 | 
			
		||||
              disabled={isTootListLoading()}
 | 
			
		||||
            >
 | 
			
		||||
              <Show when={isTootListLoading()} fallback={<ExpandMore />}>
 | 
			
		||||
                <CircularProgress sx={{ width: "24px", height: "24px" }} />
 | 
			
		||||
              </Show>
 | 
			
		||||
            </IconButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        </Show>
 | 
			
		||||
      </div>
 | 
			
		||||
    </Scaffold>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue