-
-
-
-
+
+
+
>
);
diff --git a/src/timelines/RegularToot.tsx b/src/timelines/RegularToot.tsx
index 63ef7c1..84c1c38 100644
--- a/src/timelines/RegularToot.tsx
+++ b/src/timelines/RegularToot.tsx
@@ -4,7 +4,6 @@ import {
type Component,
type JSX,
Show,
- createRenderEffect,
createSignal,
type Setter,
createContext,
diff --git a/src/timelines/TootList.tsx b/src/timelines/TootList.tsx
index b35dcce..35986a5 100644
--- a/src/timelines/TootList.tsx
+++ b/src/timelines/TootList.tsx
@@ -7,6 +7,7 @@ import {
Index,
createMemo,
For,
+ createUniqueId,
} from "solid-js";
import { type mastodon } from "masto";
import { vibrate } from "~platform/hardware";
@@ -21,6 +22,7 @@ import cardStyle from "~material/cards.module.css";
import type { ThreadNode } from "../masto/timelines";
import { useNavigator } from "~platform/StackedRouter";
import { ANIM_CURVE_STD } from "~material/theme";
+import { useItemSelection } from "./toots/ItemSelectionProvider";
function durationOf(rect0: DOMRect, rect1: DOMRect) {
const distancelt = Math.sqrt(
@@ -45,6 +47,9 @@ function positionTootInThread(index: number, threadLength: number) {
return "middle";
}
+/**
+ * Full-feature toot list.
+ */
const TootList: Component<{
ref?: Ref
;
id?: string;
@@ -53,7 +58,7 @@ const TootList: Component<{
onChangeToot: (id: string, value: mastodon.v1.Status) => void;
}> = (props) => {
const session = useDefaultSession();
- const [expandedThreadId, setExpandedThreadId] = createSignal();
+ const [isExpanded, setExpanded] = useItemSelection();
const { push } = useNavigator();
const onBookmark = async (status: mastodon.v1.Status) => {
@@ -190,7 +195,7 @@ const TootList: Component<{
event.currentTarget,
);
- if (actionableElement && checkIsExpended(status)) {
+ if (actionableElement && isExpanded(event.currentTarget.id)) {
if (actionableElement.dataset.action === "acct") {
event.stopPropagation();
@@ -214,18 +219,13 @@ const TootList: Component<{
}
// else if (!actionableElement || !checkIsExpended(status) || )
- if (status.id !== expandedThreadId()) {
- setExpandedThreadId((x) => (x ? undefined : status.id));
+ if (!isExpanded(event.currentTarget.id)) {
+ setExpanded(event.currentTarget.id);
} else {
openFullScreenToot(status, event.currentTarget as HTMLElement);
}
};
- const checkIsExpendedId = createSelector(expandedThreadId);
-
- const checkIsExpended = (status: mastodon.v1.Status) =>
- checkIsExpendedId(status.id);
-
const reply = (
status: mastodon.v1.Status,
event: { currentTarget: HTMLElement },
@@ -234,10 +234,7 @@ const TootList: Component<{
openFullScreenToot(status, element, true);
};
- const vote = async (
- status: mastodon.v1.Status,
- votes: readonly number[]
- ) => {
+ const vote = async (status: mastodon.v1.Status, votes: readonly number[]) => {
const client = session()?.client;
if (!client) return;
@@ -271,13 +268,15 @@ const TootList: Component<{
return Oops: {String(err)}
;
}}
>
-
+
{(threadId, threadIdx) => {
@@ -291,11 +290,13 @@ const TootList: Component<{
{(threadNode, index) => {
const status = () => threadNode().value;
+ const id = createUniqueId();
return (
1
@@ -303,8 +304,8 @@ const TootList: Component<{
: undefined
}
class={cardStyle.card}
- evaluated={checkIsExpended(status())}
- actionable={checkIsExpended(status())}
+ evaluated={isExpanded(id)}
+ actionable={isExpanded(id)}
onClick={[onItemClick, status()]}
/>
);
diff --git a/src/timelines/toots/ItemSelectionProvider.ts b/src/timelines/toots/ItemSelectionProvider.ts
new file mode 100644
index 0000000..e19e024
--- /dev/null
+++ b/src/timelines/toots/ItemSelectionProvider.ts
@@ -0,0 +1,35 @@
+import {
+ createContext,
+ createSelector,
+ createSignal,
+ useContext,
+ type Accessor,
+} from "solid-js";
+
+export type ItemSelectionState = [(value: T) => boolean, (value: T) => void];
+
+const ItemSelectionContext = /* @__PURE__ */ createContext<
+ ItemSelectionState
+>([() => false, () => undefined]);
+
+export function createSingluarItemSelection(
+ intial?: T,
+): readonly [Accessor, ItemSelectionState] {
+ const [value, setValue] = createSignal(intial);
+
+ const select = createSelector(value, (a, b) =>
+ typeof b !== "undefined" ? a === b : false,
+ );
+
+ const toggle = (v: T | undefined) => {
+ setValue((o) => (o ? undefined : v));
+ };
+
+ return [value, [select, toggle]];
+}
+
+export function useItemSelection() {
+ return useContext(ItemSelectionContext);
+}
+
+export default ItemSelectionContext.Provider;