diff options
| author | s-ol <s+removethis@s-ol.nu> | 2023-11-26 10:39:15 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2023-11-26 10:39:15 +0000 |
| commit | 351f96fce47272b81b3852d6b97462add3f2b35b (patch) | |
| tree | e1cb7278d60f585c61c40b3a8f8bbbb3e46127a6 | |
| parent | react to back button (diff) | |
| download | fedidag-wip.tar.gz fedidag-wip.zip | |
separate out GroupContainerwip
| -rw-r--r-- | client/src/groups.js | 74 | ||||
| -rw-r--r-- | client/src/index.js | 11 | ||||
| -rw-r--r-- | client/src/ui2.js | 88 |
3 files changed, 93 insertions, 80 deletions
diff --git a/client/src/groups.js b/client/src/groups.js new file mode 100644 index 0000000..03f5369 --- /dev/null +++ b/client/src/groups.js @@ -0,0 +1,74 @@ +import { useMemo } from 'preact/hooks'; + +export const GroupContainer = ({ items, first, render }) => { + const groups = useMemo( + () => { + const groupMap = Object.fromEntries( + Object.values(items).map(item => [ + item.id, + { + id: item.id, + items: [item], + next: {}, + depth: {}, + }, + ]), + ); + + for (const item of Object.values(items)) { + const parent = item.inReplyTo.length === 1 && item.inReplyTo[0].id; + + if (parent && items[parent].replies.length === 1) { + const self = groupMap[item.id]; + for (const s of self.items) { + groupMap[parent].items.push(s); + groupMap[s.id] = groupMap[parent]; + } + } + } + + const uniqueGroups = new Set(Object.values(groupMap)); + const groups = {}; + for (const group of uniqueGroups) { + group.next.up = group.items[0].inReplyTo.map(i => groupMap[i.id].id); + group.next.down = group.items[group.items.length-1].replies.map(i => groupMap[i.id].id); + groups[group.items[0].id] = group; + } + + const updateDepth = (group, dir) => { + if (group.depth[dir] !== undefined) { + return group.depth[dir]; + } + + // @TODO: count nodes properly using Set, + // this counts nodes multiple times if subgraphs converge + let count = group.items.length; + for (const id of group.next[dir]) { + // go through groupMap here, since when moving 'up', + // were not hitting only group-headers + count += updateDepth(groupMap[id], dir); + + if (count >= 9) { + count = Infinity; + break; + } + } + + group.depth[dir] = count; + return count; + }; + + for (const group of Object.values(groups)) { + updateDepth(group, 'up'); + updateDepth(group, 'down'); + } + + return groups; + }, + [items] + ); + + first = groups[first].id; + + return render({ groups, first }); +}; diff --git a/client/src/index.js b/client/src/index.js index 4a26f66..d6ac076 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -3,6 +3,7 @@ import 'core-js/stable'; import 'regenerator-runtime/runtime'; import { h, Fragment, Component, render } from 'preact'; import { GraphContainer } from './graph'; +import { GroupContainer } from './groups'; //import { Menu, Discussion, Selection } from './ui'; import { Menu } from './ui/Menu'; import { Discussion } from './ui2'; @@ -123,7 +124,15 @@ if (search.has('document') || search.has('note') || search.has('graph')) { ); } - return <Discussion name={name} items={items} first={first} />; + return ( + <GroupContainer + items={items} + first={first} + render={(props) => ( + <Discussion name={name} {...props} /> + )} + /> + ); /* return ( <SelectionContainer render={({ selection, toggleSelected }) => ( diff --git a/client/src/ui2.js b/client/src/ui2.js index e715d4a..f79ffbb 100644 --- a/client/src/ui2.js +++ b/client/src/ui2.js @@ -1,5 +1,5 @@ import { h } from 'preact'; -import { useState, useEffect, useMemo } from 'preact/hooks'; +import { useState, useEffect } from 'preact/hooks'; import { TransitionGroup, CSSTransition } from 'preact-transitioning' import cn from 'classnames'; import ColorHash from 'color-hash'; @@ -121,26 +121,24 @@ css` const Panel = ({ id, focusDir, activePages, setActivePages, setFocus, groups, className }) => ( <div class={cn('panel', focusDir === 'this' && 'panel-focused', className)}> <PageIndicator - group={groups[id]} dir="up" + pages={groups[id].next.up.map(pid => groups[pid])} active={activePages.up} focused={focusDir === 'this'} attached={focusDir === 'up'} setActivePage={(newId) => setActivePages({ ...activePages, up: newId })} - groups={groups} /> <Group group={groups[id]} onClick={focusDir !== 'this' && setFocus} /> <PageIndicator - group={groups[id]} dir="down" + pages={groups[id].next.down.map(pid => groups[pid])} active={activePages.down} focused={focusDir === 'this'} attached={focusDir === 'down'} setActivePage={(newId) => setActivePages({ ...activePages, down: newId })} - groups={groups} /> </div> ); @@ -293,13 +291,12 @@ css` } `; -const PageIndicator = ({ group: { id, next }, groups, dir, focused, active, attached, setActivePage }) => { - const activeIndex = next[dir].indexOf(active); +const PageIndicator = ({ pages, dir, focused, active, attached, setActivePage }) => { + const activeIndex = pages.findIndex(g => g.id === active); return ( <nav class={cn('page-indicator', `page-indicator-${dir}`, attached && 'page-indicator-attached')}> <ul> - {next[dir].map((id, i) => { - const target = groups[id]; + {pages.map((target, i) => { let num = target.depth[dir]; if (num === Infinity) num = ''; @@ -309,11 +306,11 @@ const PageIndicator = ({ group: { id, next }, groups, dir, focused, active, atta return ( <li key={target.id} - class={cn(active === id && 'active')} + class={cn(active === target.id && 'active')} style={{ '--offset': i - activeIndex }} > <button - onClick={setActivePage ? ((e) => { e.preventDefault(); setActivePage(id); }) : null} + onClick={setActivePage ? ((e) => { e.preventDefault(); setActivePage(target.id); }) : null} disabled={!focused} style={{ '--link-color': color }} > @@ -359,74 +356,7 @@ article.discussion > main { justify-content: center; } ` -export const Discussion = ({ name, items, first }) => { - const groups = useMemo( - () => { - const groupMap = Object.fromEntries( - Object.values(items).map(item => [ - item.id, - { - id: item.id, - items: [item], - next: {}, - depth: {}, - }, - ]), - ); - - for (const item of Object.values(items)) { - const parent = item.inReplyTo.length === 1 && item.inReplyTo[0].id; - - if (parent && items[parent].replies.length === 1) { - const self = groupMap[item.id]; - for (const s of self.items) { - groupMap[parent].items.push(s); - groupMap[s.id] = groupMap[parent]; - } - } - } - - const uniqueGroups = new Set(Object.values(groupMap)); - const groups = {}; - for (const group of uniqueGroups) { - group.next.up = group.items[0].inReplyTo.map(i => groupMap[i.id].id); - group.next.down = group.items[group.items.length-1].replies.map(i => groupMap[i.id].id); - groups[group.items[0].id] = group; - } - - const updateDepth = (group, dir) => { - if (group.depth[dir] !== undefined) { - return group.depth[dir]; - } - - // @TODO: count nodes properly using Set, - // this counts nodes multiple times if subgraphs converge - let count = group.items.length; - for (const id of group.next[dir]) { - // go through groupMap here, since when moving 'up', - // were not hitting only group-headers - count += updateDepth(groupMap[id], dir); - - if (count >= 9) { - count = Infinity; - break; - } - } - - group.depth[dir] = count; - return count; - }; - - for (const group of Object.values(groups)) { - updateDepth(group, 'up'); - updateDepth(group, 'down'); - } - - return groups; - }, - [items] - ); - +export const Discussion = ({ name, groups, first }) => { // save/restore focus state const [focusId, setFocusId] = useState(() => { const id = window.location.hash.slice(1); |
