;
+function getComputedStyles(dark = false) {
+ if (!computed) computed = computeStyles(fixedStyles, dark, "code-better");
+ return computed;
+}
+
+class FixedReactDiffViewer extends ReactDiffViewer {
+ static contextType = ColorModeContext;
+
+ // @ts-expect-error
+ constructor(...args) {
+ // @ts-expect-error
+ super(...args);
+ // @ts-expect-error
+ this.computeStyles = () => {
+ // @ts-expect-error
+ return getComputedStyles(this.context.colorMode === "dark");
+ };
+ }
+}
+
+export default function DiffViewer({ oldValue, newValue }: { oldValue: string; newValue: string }) {
+ const { colorMode } = useColorMode();
+
+ return (
+
+ );
+}
diff --git a/src/views/other-stuff/apps.ts b/src/views/other-stuff/apps.ts
index 5ce1c89b4..fdf672b7f 100644
--- a/src/views/other-stuff/apps.ts
+++ b/src/views/other-stuff/apps.ts
@@ -21,6 +21,7 @@ import Users01 from "../../components/icons/users-01";
import Film02 from "../../components/icons/film-02";
import MessageQuestionSquare from "../../components/icons/message-question-square";
import UploadCloud01 from "../../components/icons/upload-cloud-01";
+import Edit04 from "../../components/icons/edit-04";
export const internalApps: App[] = [
{
@@ -113,7 +114,13 @@ export const internalTools: App[] = [
id: "publisher",
to: "/tools/publisher ",
},
- { title: "WoT Test", description: "Just a test for now", icon: Users01, id: "wot-test", to: "/tools/wot-test" },
+ {
+ title: "Corrections Feed",
+ description: "A feed of post edits",
+ icon: Edit04,
+ id: "corrections",
+ to: "/tools/corrections ",
+ },
];
export const externalTools: App[] = [
diff --git a/src/views/tools/corrections/correction-card.tsx b/src/views/tools/corrections/correction-card.tsx
new file mode 100644
index 000000000..447ec0c7e
--- /dev/null
+++ b/src/views/tools/corrections/correction-card.tsx
@@ -0,0 +1,43 @@
+import { Suspense, lazy, useMemo, useState } from "react";
+import { NostrEvent } from "nostr-tools";
+import { Button, ButtonGroup, Spinner, useColorMode } from "@chakra-ui/react";
+
+import { isETag } from "../../../types/nostr-event";
+import useSingleEvent from "../../../hooks/use-single-event";
+import TimelineItem from "../../../components/timeline-page/generic-note-timeline/timeline-item";
+import DiffViewer from "../../../components/diff/diff-viewer";
+
+export default function CorrectionCard({ correction }: { correction: NostrEvent }) {
+ const originalId = correction.tags.find(isETag)?.[1];
+ const original = useSingleEvent(originalId);
+
+ // NOTE: produces an invalid event
+ const modified = useMemo(() => original && { ...original, content: correction.content }, [correction, original]);
+
+ const [show, setShow] = useState("modified");
+ const showEvent = show === "original" ? original : modified;
+
+ return (
+
+
+
+
+
+
+
+ {show === "diff" ? (
+ }>
+
+
+ ) : (
+ showEvent &&
+ )}
+
+ );
+}
diff --git a/src/views/tools/corrections/index.tsx b/src/views/tools/corrections/index.tsx
new file mode 100644
index 000000000..945f230f8
--- /dev/null
+++ b/src/views/tools/corrections/index.tsx
@@ -0,0 +1,44 @@
+import { Flex, Heading } from "@chakra-ui/react";
+
+import VerticalPageLayout from "../../../components/vertical-page-layout";
+import { useReadRelays } from "../../../hooks/use-client-relays";
+import useSubject from "../../../hooks/use-subject";
+import useTimelineLoader from "../../../hooks/use-timeline-loader";
+import PeopleListProvider, { usePeopleListContext } from "../../../providers/local/people-list-provider";
+import BackButton from "../../../components/router/back-button";
+import PeopleListSelection from "../../../components/people-list-selection/people-list-selection";
+import CorrectionCard from "./correction-card";
+
+function CorrectionsPage() {
+ const { listId, filter } = usePeopleListContext();
+ const readRelays = useReadRelays();
+ const timeline = useTimelineLoader(
+ `${listId}-corrections`,
+ readRelays,
+ filter ? [{ kinds: [1010], ...filter }] : undefined,
+ );
+
+ const corrections = useSubject(timeline.timeline);
+
+ return (
+
+
+
+ Corrections
+
+
+
+ {corrections.map((correction) => (
+
+ ))}
+
+ );
+}
+
+export default function CorrectionsFeedView() {
+ return (
+
+
+
+ );
+}
diff --git a/src/views/tools/wot-test.tsx b/src/views/tools/wot-test.tsx
deleted file mode 100644
index d18689a29..000000000
--- a/src/views/tools/wot-test.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { memo, useMemo, useState } from "react";
-import { Button, Flex, Select, SimpleGrid, Text } from "@chakra-ui/react";
-
-import useCurrentAccount from "../../hooks/use-current-account";
-import RequireCurrentAccount from "../../providers/route/require-current-account";
-import { useNetworkConnectionCount } from "../../hooks/use-user-network";
-import UserAvatarLink from "../../components/user/user-avatar-link";
-import UserLink from "../../components/user/user-link";
-import { ChevronLeftIcon } from "../../components/icons";
-import { useNavigate } from "react-router-dom";
-import VerticalPageLayout from "../../components/vertical-page-layout";
-
-const User = memo(({ pubkey, count }: { pubkey: string; count: number }) => (
-
-
-
- ({count})
-
-));
-
-function WotTestPage() {
- const navigate = useNavigate();
- const account = useCurrentAccount()!;
- const [range, setRange] = useState("50-100");
-
- const network = useNetworkConnectionCount(account.pubkey);
- const filteredPubkeys = useMemo(() => {
- if (range.endsWith("+")) {
- const min = parseInt(range.replace("+", ""));
- return network.filter((p) => p.count > min);
- }
- const [min, max] = range.split("-").map((v) => parseInt(v));
- return network.filter((p) => p.count > min && p.count <= max);
- }, [range, network]);
-
- return (
-
-
- } onClick={() => navigate(-1)}>
- Back
-
-
-
-
- {filteredPubkeys.map(({ pubkey, count }) => (
-
- ))}
-
-
- );
-}
-
-export default function WotTestView() {
- return (
-
-
-
- );
-}
diff --git a/src/views/wiki/hooks/use-wiki-topic-timeline.tsx b/src/views/wiki/hooks/use-wiki-topic-timeline.tsx
index 7be452576..25643e26f 100644
--- a/src/views/wiki/hooks/use-wiki-topic-timeline.tsx
+++ b/src/views/wiki/hooks/use-wiki-topic-timeline.tsx
@@ -1,7 +1,12 @@
+import { NostrEvent } from "nostr-tools";
import { WIKI_PAGE_KIND } from "../../../helpers/nostr/wiki";
import { useReadRelays } from "../../../hooks/use-client-relays";
import useTimelineLoader from "../../../hooks/use-timeline-loader";
+function noEmptyEvent(event: NostrEvent) {
+ return event.content.length > 0;
+}
+
export default function useWikiTopicTimeline(topic: string) {
const relays = useReadRelays(["wss://relay.wikifreedia.xyz/"]);
@@ -9,6 +14,6 @@ export default function useWikiTopicTimeline(topic: string) {
`wiki-${topic.toLocaleLowerCase()}-pages`,
relays,
[{ kinds: [WIKI_PAGE_KIND], "#d": [topic.toLocaleLowerCase()] }],
- { eventFilter: (e) => e.content.length > 0 },
+ { eventFilter: noEmptyEvent },
);
}
diff --git a/src/views/wiki/page.tsx b/src/views/wiki/page.tsx
index 3b46111a8..f28ae0d0d 100644
--- a/src/views/wiki/page.tsx
+++ b/src/views/wiki/page.tsx
@@ -1,5 +1,5 @@
import { NostrEvent } from "nostr-tools";
-import { Box, Card, Divider, Flex, Heading, Link, Spinner, Text } from "@chakra-ui/react";
+import { Box, ButtonGroup, Divider, Flex, Heading, Link, Spinner, Text } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import useParamsAddressPointer from "../../hooks/use-params-address-pointer";
@@ -14,6 +14,7 @@ import useSubject from "../../hooks/use-subject";
import useWikiTopicTimeline from "./hooks/use-wiki-topic-timeline";
import WikiPageResult from "./components/wiki-page-result";
import Timestamp from "../../components/timestamp";
+import DebugEventButton from "../../components/debug-modal/debug-event-button";
function WikiPagePage({ page }: { page: NostrEvent }) {
const topic = getPageTopic(page);
@@ -34,6 +35,9 @@ function WikiPagePage({ page }: { page: NostrEvent }) {
+
+
+
{getPageTitle(page)}
by -
diff --git a/yarn.lock b/yarn.lock
index 8892a5a97..9698ce814 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2145,6 +2145,17 @@
"@emotion/weak-memoize" "^0.3.1"
stylis "4.2.0"
+"@emotion/css@^11.11.2":
+ version "11.11.2"
+ resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.2.tgz#e5fa081d0c6e335352e1bc2b05953b61832dca5a"
+ integrity sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==
+ dependencies:
+ "@emotion/babel-plugin" "^11.11.0"
+ "@emotion/cache" "^11.11.0"
+ "@emotion/serialize" "^1.1.2"
+ "@emotion/sheet" "^1.2.2"
+ "@emotion/utils" "^1.2.1"
+
"@emotion/hash@^0.9.1":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
@@ -4102,6 +4113,11 @@ devlop@^1.0.0, devlop@^1.1.0:
dependencies:
dequal "^2.0.0"
+diff@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531"
+ integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -5600,6 +5616,11 @@ mdn-data@2.0.14:
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+memoize-one@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
+ integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
+
meow@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467"
@@ -6439,6 +6460,17 @@ react-clientside-effect@^1.2.6:
dependencies:
"@babel/runtime" "^7.12.13"
+react-diff-viewer-continued@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/react-diff-viewer-continued/-/react-diff-viewer-continued-3.4.0.tgz#0501ffb2b5ab740f88b9ae5f18771aa90d3803c2"
+ integrity sha512-kMZmUyb3Pv5L9vUtCfIGYsdOHs8mUojblGy1U1Sm0D7FhAOEsH9QhnngEIRo5hXWIPNGupNRJls1TJ6Eqx84eg==
+ dependencies:
+ "@emotion/css" "^11.11.2"
+ classnames "^2.3.2"
+ diff "^5.1.0"
+ memoize-one "^6.0.0"
+ prop-types "^15.8.1"
+
react-dnd-html5-backend@^16.0.1:
version "16.0.1"
resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz#87faef15845d512a23b3c08d29ecfd34871688b6"