fastcomments-react-native-sdk
Version:
React Native FastComments Components. Add live commenting to any React Native application.
153 lines (152 loc) • 5.93 kB
JavaScript
import { none } from "@hookstate/core";
// We used to use a doubly linked list but it was a huge pain.
export function graphToListStateWithNewlines(nodes) {
const result = [];
for (const node of nodes) {
result.push(node);
if (node.children) {
node.children.forEach(function (child) {
result.push(child);
});
}
}
return result;
}
export function graphToListStateWithoutNewlines(nodes) {
const result = [];
for (const node of nodes) {
if (node.children) {
node.children.forEach(function (child) {
result.push(child);
});
}
}
return result;
}
export function graphToListWithNewlines(nodes) {
const result = [];
for (const node of nodes) {
result.push(node);
if (node.children) {
node.children.forEach(function (child) {
result.push(child);
});
}
}
return result;
}
// just easier type system wise if this is its own thing
export function graphToListWithoutNewlines(nodes) {
const result = [];
for (const node of nodes) {
if (node.children) {
node.children.forEach(function (child) {
result.push(child);
});
}
}
return result;
}
export function getStatePrev(nodes, id) {
const list = graphToListStateWithoutNewlines(nodes);
const index = list.findIndex((searchingNode) => searchingNode.id.get() === id);
// without this check - weird behavior in delete flow
if (index - 1 < 0) {
return null;
}
return list[index - 1];
}
export function getStateNext(nodes, id) {
const list = graphToListStateWithoutNewlines(nodes);
const index = list.findIndex((searchingNode) => searchingNode.id.get() === id);
// without this check - weird behavior in delete flow
if (index + 1 > list.length - 1) {
return null;
}
return list[index + 1];
}
// we should always have a node (at least a text node) so this should never return null! otherwise is a bug.
export function getStateLast(nodes) {
let newlineCount = nodes.length;
while (newlineCount--) {
const line = nodes[newlineCount];
if (line && line !== none && line.children && line.children.get().length > 0) {
// @ts-ignore fuck typescript
return line.children[line.children.length - 1];
}
}
throw new Error('getStateLast could not find a visible node other than a newline! This should not happen.');
}
// we should always have a node (at least a text node) so this should never return null! otherwise is a bug.
export function getLast(nodes) {
let newlineCount = nodes.length;
while (newlineCount--) {
const line = nodes[newlineCount];
if (line && line !== none && line.children && line.children.length > 0) {
// @ts-ignore fuck typescript
return line.children[line.children.length - 1];
}
}
throw new Error('getLast could not find a visible node other than a newline! This should not happen.');
}
export function getNext(nodes, id) {
const list = graphToListWithoutNewlines(nodes);
const index = list.findIndex((searchingNode) => searchingNode.id === id);
// without this check - weird behavior in delete flow
if (index + 1 > list.length - 1) {
return null;
}
return list[index + 1];
}
export function getPrev(nodes, id) {
const list = graphToListWithoutNewlines(nodes);
const index = list.findIndex((searchingNode) => searchingNode.id === id);
// without this check - weird behavior in delete flow
if (index - 1 < 0) {
return null;
}
return list[index - 1];
}
export function getStateByIdFromMap(nodes, id) {
return nodes[id];
}
export function getLastFocused(graph) {
// MAYBE OPTIMIZE: we had a ton of problems with keeping track of the last selected node with storing references to a raw js object or State<>
// due to hookstatejs (or maybe not using it correctly). Maybe a React expert can help us :)
// UPDATE: Probably way to do it is editorState = { lastNode?: Node } - this way optionals are supported via usehookstate
const hasBeenFocused = graphToListWithoutNewlines(graph);
if (hasBeenFocused.length === 0) {
// it really feels like we are using the library wrong if we have to cast like this?
const children = graph[0].children; // we ALWAYS have a root node
if (children && children.length > 0) {
return children[0];
}
else {
throw new Error('Could not determine current node!!!'); // if this happens it's a bug.
}
}
hasBeenFocused.sort((a, b) => {
return b.lastFocusTime - a.lastFocusTime;
});
return hasBeenFocused[0];
}
export function getLastFocusedState(graph) {
// MAYBE OPTIMIZE: we had a ton of problems with keeping track of the last selected node with storing references to a raw js object or State<>
// due to hookstatejs (or maybe not using it correctly). Maybe a React expert can help us :)
// UPDATE: Probably way to do it is editorState = { lastNode?: Node } - this way optionals are supported via usehookstate
const hasBeenFocused = graphToListStateWithoutNewlines(graph);
if (hasBeenFocused.length === 0) {
// it really feels like we are using the library wrong if we have to cast like this?
const children = graph[0].children; // we ALWAYS have a root node
if (children && children.length > 0) {
return children[0];
}
else {
throw new Error('Could not determine current node!!!'); // if this happens it's a bug.
}
}
hasBeenFocused.sort((a, b) => {
return b.lastFocusTime.get({ stealth: true }) - a.lastFocusTime.get({ stealth: true });
});
return hasBeenFocused[0];
}