Thread: removed
This commit is contained in:
		
							parent
							
								
									5afaf21f4b
								
							
						
					
					
						commit
						17e738e21a
					
				
					 3 changed files with 56 additions and 118 deletions
				
			
		| 
						 | 
				
			
			@ -1,90 +0,0 @@
 | 
			
		|||
import type { mastodon } from "masto";
 | 
			
		||||
import { Index, type Component, type Ref } from "solid-js";
 | 
			
		||||
import RegularToot, { findRootToot } from "./RegularToot";
 | 
			
		||||
import cardStyle from "../material/cards.module.css";
 | 
			
		||||
import { css } from "solid-styled";
 | 
			
		||||
 | 
			
		||||
type TootActionTarget = {
 | 
			
		||||
  client: mastodon.rest.Client;
 | 
			
		||||
  status: mastodon.v1.Status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type TootActions = {
 | 
			
		||||
  onBoost(client: mastodon.rest.Client, status: mastodon.v1.Status): void;
 | 
			
		||||
  onBookmark(client: mastodon.rest.Client, status: mastodon.v1.Status): void;
 | 
			
		||||
  onReply(target: TootActionTarget, element: HTMLElement): void;
 | 
			
		||||
  onFavourite(status: mastodon.v1.Status): void
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type ThreadProps = {
 | 
			
		||||
  ref?: Ref<HTMLElement>;
 | 
			
		||||
  client: mastodon.rest.Client;
 | 
			
		||||
  toots: readonly mastodon.v1.Status[];
 | 
			
		||||
  isExpended: (status: mastodon.v1.Status) => boolean;
 | 
			
		||||
 | 
			
		||||
  onItemClick(status: mastodon.v1.Status, event: MouseEvent): void;
 | 
			
		||||
} & TootActions;
 | 
			
		||||
 | 
			
		||||
const Thread: Component<ThreadProps> = (props) => {
 | 
			
		||||
  const boost = (status: mastodon.v1.Status) => {
 | 
			
		||||
    props.onBoost(props.client, status);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const bookmark = (status: mastodon.v1.Status) => {
 | 
			
		||||
    props.onBookmark(props.client, status);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const reply = (
 | 
			
		||||
    status: mastodon.v1.Status,
 | 
			
		||||
    event: MouseEvent & { currentTarget: HTMLElement },
 | 
			
		||||
  ) => {
 | 
			
		||||
    const element = findRootToot(event.currentTarget);
 | 
			
		||||
    props.onReply({ client: props.client, status }, element);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const threading = () => props.toots.length > 1;
 | 
			
		||||
 | 
			
		||||
  const posThread = (index: number) => {
 | 
			
		||||
    if (!threading()) return;
 | 
			
		||||
 | 
			
		||||
    if (index === 0) {
 | 
			
		||||
      return "top";
 | 
			
		||||
    } else if (index === props.toots.length - 1) {
 | 
			
		||||
      return "bottom";
 | 
			
		||||
    }
 | 
			
		||||
    return "middle";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  css`
 | 
			
		||||
    .thread {
 | 
			
		||||
      user-select: none;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
  return (
 | 
			
		||||
    <article ref={props.ref} class="thread" aria-setsize={props.toots.length}>
 | 
			
		||||
      <Index each={props.toots}>
 | 
			
		||||
        {(status, index) => {
 | 
			
		||||
          return (
 | 
			
		||||
            <RegularToot
 | 
			
		||||
              data-status-id={status().id}
 | 
			
		||||
              data-thread-sort={index}
 | 
			
		||||
              status={status()}
 | 
			
		||||
              thread={posThread(index)}
 | 
			
		||||
              class={cardStyle.card}
 | 
			
		||||
              evaluated={props.isExpended(status())}
 | 
			
		||||
              actionable={props.isExpended(status())}
 | 
			
		||||
              onBookmark={(s) => bookmark(s)}
 | 
			
		||||
              onRetoot={(s) => boost(s)}
 | 
			
		||||
              onFavourite={props.onFavourite}
 | 
			
		||||
              onReply={reply}
 | 
			
		||||
              onClick={[props.onItemClick, status()]}
 | 
			
		||||
            />
 | 
			
		||||
          );
 | 
			
		||||
        }}
 | 
			
		||||
      </Index>
 | 
			
		||||
    </article>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Thread;
 | 
			
		||||
| 
						 | 
				
			
			@ -5,16 +5,30 @@ import {
 | 
			
		|||
  ErrorBoundary,
 | 
			
		||||
  type Ref,
 | 
			
		||||
  createSelector,
 | 
			
		||||
  Index,
 | 
			
		||||
  createMemo,
 | 
			
		||||
} from "solid-js";
 | 
			
		||||
import { type mastodon } from "masto";
 | 
			
		||||
import { vibrate } from "../platform/hardware";
 | 
			
		||||
import Thread from "./Thread.jsx";
 | 
			
		||||
import { useDefaultSession } from "../masto/clients";
 | 
			
		||||
import { useHeroSource } from "../platform/anim";
 | 
			
		||||
import { HERO as BOTTOM_SHEET_HERO } from "../material/BottomSheet";
 | 
			
		||||
import { setCache as setTootBottomSheetCache } from "./TootBottomSheet";
 | 
			
		||||
import { useNavigate } from "@solidjs/router";
 | 
			
		||||
import { findElementActionable } from "./RegularToot";
 | 
			
		||||
import RegularToot, {
 | 
			
		||||
  findElementActionable,
 | 
			
		||||
  findRootToot,
 | 
			
		||||
} from "./RegularToot";
 | 
			
		||||
import cardStyle from "../material/cards.module.css";
 | 
			
		||||
 | 
			
		||||
function positionTootInThread(index: number, threadLength: number) {
 | 
			
		||||
  if (index === 0) {
 | 
			
		||||
    return "top";
 | 
			
		||||
  } else if (index === threadLength - 1) {
 | 
			
		||||
    return "bottom";
 | 
			
		||||
  }
 | 
			
		||||
  return "middle";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TootList: Component<{
 | 
			
		||||
  ref?: Ref<HTMLDivElement>;
 | 
			
		||||
| 
						 | 
				
			
			@ -28,20 +42,20 @@ const TootList: Component<{
 | 
			
		|||
  const [expandedThreadId, setExpandedThreadId] = createSignal<string>();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const onBookmark = async (
 | 
			
		||||
    client: mastodon.rest.Client,
 | 
			
		||||
    status: mastodon.v1.Status,
 | 
			
		||||
  ) => {
 | 
			
		||||
  const onBookmark = async (status: mastodon.v1.Status) => {
 | 
			
		||||
    const client = session()?.client;
 | 
			
		||||
    if (!client) return;
 | 
			
		||||
 | 
			
		||||
    const result = await (status.bookmarked
 | 
			
		||||
      ? client.v1.statuses.$select(status.id).unbookmark()
 | 
			
		||||
      : client.v1.statuses.$select(status.id).bookmark());
 | 
			
		||||
    props.onChangeToot(result.id, result);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const toggleBoost = async (
 | 
			
		||||
    client: mastodon.rest.Client,
 | 
			
		||||
    status: mastodon.v1.Status,
 | 
			
		||||
  ) => {
 | 
			
		||||
  const toggleBoost = async (status: mastodon.v1.Status) => {
 | 
			
		||||
    const client = session()?.client;
 | 
			
		||||
    if (!client) return;
 | 
			
		||||
 | 
			
		||||
    vibrate(50);
 | 
			
		||||
    const rootStatus = status.reblog ? status.reblog : status;
 | 
			
		||||
    const reblogged = rootStatus.reblogged;
 | 
			
		||||
| 
						 | 
				
			
			@ -110,8 +124,11 @@ const TootList: Component<{
 | 
			
		|||
 | 
			
		||||
  const onItemClick = (
 | 
			
		||||
    status: mastodon.v1.Status,
 | 
			
		||||
    event: MouseEvent & { target: HTMLElement; currentTarget: HTMLElement },
 | 
			
		||||
    event: MouseEvent & { target: EventTarget; currentTarget: HTMLElement },
 | 
			
		||||
  ) => {
 | 
			
		||||
    if (!(event.target instanceof HTMLElement)) {
 | 
			
		||||
      throw new Error("target is not an element");
 | 
			
		||||
    }
 | 
			
		||||
    const actionableElement = findElementActionable(
 | 
			
		||||
      event.target,
 | 
			
		||||
      event.currentTarget,
 | 
			
		||||
| 
						 | 
				
			
			@ -153,13 +170,6 @@ const TootList: Component<{
 | 
			
		|||
  const checkIsExpended = (status: mastodon.v1.Status) =>
 | 
			
		||||
    checkIsExpendedId(status.id);
 | 
			
		||||
 | 
			
		||||
  const onReply = (
 | 
			
		||||
    { status }: { status: mastodon.v1.Status },
 | 
			
		||||
    element: HTMLElement,
 | 
			
		||||
  ) => {
 | 
			
		||||
    openFullScreenToot(status, element, true);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const getPath = (itemId: string) => {
 | 
			
		||||
    return props
 | 
			
		||||
      .onUnknownThread(itemId)!
 | 
			
		||||
| 
						 | 
				
			
			@ -176,17 +186,33 @@ const TootList: Component<{
 | 
			
		|||
      <div ref={props.ref} id={props.id} class="toot-list">
 | 
			
		||||
        <For each={props.threads}>
 | 
			
		||||
          {(itemId) => {
 | 
			
		||||
            const toots = createMemo(() => getPath(itemId));
 | 
			
		||||
            return (
 | 
			
		||||
              <Thread
 | 
			
		||||
                toots={getPath(itemId)}
 | 
			
		||||
                onBoost={toggleBoost}
 | 
			
		||||
                onBookmark={onBookmark}
 | 
			
		||||
                onReply={onReply}
 | 
			
		||||
                onFavourite={toggleFavourite}
 | 
			
		||||
                client={session()?.client!}
 | 
			
		||||
                isExpended={checkIsExpended}
 | 
			
		||||
                onItemClick={onItemClick}
 | 
			
		||||
              />
 | 
			
		||||
              <Index each={toots()}>
 | 
			
		||||
                {(status, index) => (
 | 
			
		||||
                  <RegularToot
 | 
			
		||||
                    data-status-id={status().id}
 | 
			
		||||
                    data-thread-sort={index}
 | 
			
		||||
                    status={status()}
 | 
			
		||||
                    thread={
 | 
			
		||||
                      toots().length > 1
 | 
			
		||||
                        ? positionTootInThread(index, toots().length)
 | 
			
		||||
                        : undefined
 | 
			
		||||
                    }
 | 
			
		||||
                    class={cardStyle.card}
 | 
			
		||||
                    evaluated={checkIsExpended(status())}
 | 
			
		||||
                    actionable={checkIsExpended(status())}
 | 
			
		||||
                    onBookmark={onBookmark}
 | 
			
		||||
                    onRetoot={toggleBoost}
 | 
			
		||||
                    onFavourite={toggleFavourite}
 | 
			
		||||
                    onReply={(status, event) => {
 | 
			
		||||
                      const element = findRootToot(event.currentTarget);
 | 
			
		||||
                      openFullScreenToot(status, element, true);
 | 
			
		||||
                    }}
 | 
			
		||||
                    onClick={[onItemClick, status()]}
 | 
			
		||||
                  />
 | 
			
		||||
                )}
 | 
			
		||||
              </Index>
 | 
			
		||||
            );
 | 
			
		||||
          }}
 | 
			
		||||
        </For>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@
 | 
			
		|||
  margin-block: 0;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  contain: content;
 | 
			
		||||
  user-select: none;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
 | 
			
		||||
  &.toot {
 | 
			
		||||
    /* fix composition ordering: I think the css module processor should aware the overriding and behaves, but no */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue