@umbra-privacy/ceremony 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +68 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ import { createWriteStream } from "fs";
|
|
|
33
33
|
import { readFile, unlink } from "fs/promises";
|
|
34
34
|
import { pipeline } from "stream/promises";
|
|
35
35
|
import { Readable } from "stream";
|
|
36
|
-
var DEFAULT_API_URL = "
|
|
36
|
+
var DEFAULT_API_URL = "https://ceremony.api.umbraprivacy.com";
|
|
37
37
|
var BASE = (process.env["CEREMONY_API_URL"] ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
38
38
|
async function request(path, options = {}) {
|
|
39
39
|
const res = await fetch(`${BASE}${path}`, {
|
|
@@ -690,11 +690,15 @@ function Attestation({ contribution }) {
|
|
|
690
690
|
|
|
691
691
|
// src/components/App.tsx
|
|
692
692
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
693
|
-
|
|
693
|
+
var NAME_MAX_LEN = 100;
|
|
694
|
+
var NAME_VALID_RE = /^[\p{L}\p{N} _.\-]*$/u;
|
|
695
|
+
function App({ ceremonyId: initialCeremonyId, displayName: initialDisplayName }) {
|
|
694
696
|
const { exit } = useApp();
|
|
695
697
|
const [activeCeremonyId, setActiveCeremonyId] = useState4(initialCeremonyId);
|
|
698
|
+
const [displayName2, setDisplayName] = useState4(initialDisplayName ?? "anonymous");
|
|
699
|
+
const [nameSet, setNameSet] = useState4(initialDisplayName !== void 0);
|
|
696
700
|
const [screen, setScreen] = useState4(
|
|
697
|
-
initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
701
|
+
initialDisplayName === void 0 ? { name: "name-input", value: "" } : initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
698
702
|
);
|
|
699
703
|
const [ceremony, setCeremony] = useState4(null);
|
|
700
704
|
const [session, setSession] = useState4(null);
|
|
@@ -702,12 +706,13 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
702
706
|
const [selectedIdx, setSelectedIdx] = useState4(0);
|
|
703
707
|
const [tab, setTab] = useState4(0);
|
|
704
708
|
useEffect4(() => {
|
|
709
|
+
if (!nameSet) return;
|
|
705
710
|
if (!initialCeremonyId) {
|
|
706
711
|
loadCeremonies();
|
|
707
712
|
} else {
|
|
708
713
|
boot(initialCeremonyId);
|
|
709
714
|
}
|
|
710
|
-
}, []);
|
|
715
|
+
}, [nameSet]);
|
|
711
716
|
async function loadCeremonies() {
|
|
712
717
|
try {
|
|
713
718
|
const { ceremonies } = await api.listCeremonies();
|
|
@@ -739,6 +744,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
739
744
|
setScreen({ name: "error", message: "No tracks found in this ceremony.", recoverable: false });
|
|
740
745
|
return;
|
|
741
746
|
}
|
|
747
|
+
setSelectedIdx(0);
|
|
742
748
|
setScreen({ name: "tracks", tracks });
|
|
743
749
|
} catch (e) {
|
|
744
750
|
if (e.code === "INVALID_SESSION" || e.status === 401) {
|
|
@@ -751,6 +757,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
751
757
|
setScreen({ name: "error", message: "No tracks found in this ceremony.", recoverable: false });
|
|
752
758
|
return;
|
|
753
759
|
}
|
|
760
|
+
setSelectedIdx(0);
|
|
754
761
|
setScreen({ name: "tracks", tracks });
|
|
755
762
|
} catch (e2) {
|
|
756
763
|
setScreen({ name: "error", message: e2.message ?? "Failed to load tracks.", recoverable: false });
|
|
@@ -760,6 +767,22 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
760
767
|
setScreen({ name: "error", message: e.message ?? "Failed to load tracks.", recoverable: false });
|
|
761
768
|
}
|
|
762
769
|
}
|
|
770
|
+
function commitName(raw) {
|
|
771
|
+
const trimmed = raw.trim();
|
|
772
|
+
if (trimmed.length === 0) return;
|
|
773
|
+
setDisplayName(trimmed);
|
|
774
|
+
setNameSet(true);
|
|
775
|
+
setScreen(
|
|
776
|
+
initialCeremonyId ? { name: "loading" } : { name: "ceremony-picker", ceremonies: [], loading: true }
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
function randomAnonName() {
|
|
780
|
+
const hex = Array.from(
|
|
781
|
+
{ length: 6 },
|
|
782
|
+
() => Math.floor(Math.random() * 16).toString(16)
|
|
783
|
+
).join("");
|
|
784
|
+
return `anon-${hex}`;
|
|
785
|
+
}
|
|
763
786
|
async function joinTrack(track) {
|
|
764
787
|
if (!session) return;
|
|
765
788
|
setScreen({ name: "joining" });
|
|
@@ -795,6 +818,29 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
795
818
|
}, [screen.name]);
|
|
796
819
|
useInput2((input, key) => {
|
|
797
820
|
const q = input.toLowerCase();
|
|
821
|
+
if (screen.name === "name-input") {
|
|
822
|
+
if (key.escape) {
|
|
823
|
+
exit();
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
if (key.tab) {
|
|
827
|
+
commitName(randomAnonName());
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (key.return) {
|
|
831
|
+
commitName(screen.value);
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
if (key.backspace || key.delete) {
|
|
835
|
+
setScreen({ name: "name-input", value: screen.value.slice(0, -1) });
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
if (input && input.length === 1 && NAME_VALID_RE.test(input)) {
|
|
839
|
+
if (screen.value.length >= NAME_MAX_LEN) return;
|
|
840
|
+
setScreen({ name: "name-input", value: screen.value + input });
|
|
841
|
+
}
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
798
844
|
if (q === "q" && screen.name !== "entropy") {
|
|
799
845
|
if (screen.name === "queue" && session) {
|
|
800
846
|
clearQueueCleanup();
|
|
@@ -866,6 +912,23 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
866
912
|
goHome();
|
|
867
913
|
}
|
|
868
914
|
});
|
|
915
|
+
if (screen.name === "name-input") {
|
|
916
|
+
const { value } = screen;
|
|
917
|
+
const canSubmit = value.trim().length > 0;
|
|
918
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
919
|
+
/* @__PURE__ */ jsx6(Header, { ceremony: null }),
|
|
920
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, gap: 1, children: [
|
|
921
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, children: "Who are you contributing as?" }),
|
|
922
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Your display name appears next to your contributions in the public transcript. Pick anything \u2014 your real name, a handle, or hit Tab for a random anonymous name." }),
|
|
923
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
924
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: " > " }),
|
|
925
|
+
/* @__PURE__ */ jsx6(Text6, { children: value }),
|
|
926
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", inverse: true, children: " " })
|
|
927
|
+
] }),
|
|
928
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: canSubmit ? "Enter to continue \xB7 Tab for random \xB7 \u232B backspace \xB7 Esc to quit" : "Type a name, or Tab for a random anonymous name \xB7 Esc to quit" })
|
|
929
|
+
] })
|
|
930
|
+
] });
|
|
931
|
+
}
|
|
869
932
|
if (screen.name === "ceremony-picker") {
|
|
870
933
|
const { ceremonies, loading } = screen;
|
|
871
934
|
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
@@ -1125,7 +1188,7 @@ function App({ ceremonyId: initialCeremonyId, displayName: displayName2 = "anony
|
|
|
1125
1188
|
// src/index.tsx
|
|
1126
1189
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1127
1190
|
var ceremonyId = process.env["CEREMONY_ID"] ?? "";
|
|
1128
|
-
var displayName = process.env["CONTRIBUTOR_NAME"]
|
|
1191
|
+
var displayName = process.env["CONTRIBUTOR_NAME"];
|
|
1129
1192
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
1130
1193
|
function restoreScreen() {
|
|
1131
1194
|
process.stdout.write("\x1B[?1049l");
|