mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-07 13:22:54 +00:00
[ui] Remove NIP-71 authoring sections from upload/edit modals (#58)
bitvid authors kind-30078 and MIRRORS to NIP-71; it never authors NIP-71 directly. Verified before removing: the My Videos mirror (buildNip71MirrorEvent) derives everything from the bitvid note itself (duration/dims are auto-captured at upload, contentWarning comes from the NSFW toggle, imeta is built from the video), and the only consumer of the form's NIP-71 metadata (publishNip71Video) is gated behind FEATURE_PUBLISH_NIP71: false — the fields fed a dead path and confused uploaders. Removed from the upload modal: "NIP-71 Technical" (content warning, duration, summary + Customize toggle) and the IMETA variant editor. Removed from the edit modal: kind (21/22) selector, published_at, alt, duration, content warning, summary, IMETA, text tracks, segments, participants, references. KEPT in both: hashtags (they feed hashtag feeds, the suggestion chips, and the mirror's t tags) and the web seeds / torrent (xs) inputs (bitvid-note fields, not NIP-71). All the JS plumbing is missing-DOM tolerant, so no wiring changes were needed to collect. Compatibility: existing videos' NIP-71 extras survive a save. EditModal keeps the video's full stored metadata (storedNip71Metadata) and merges the edited hashtags into it on submit instead of replacing it with the reduced form's empty output (t mirror key kept in sync). Also fixes a latent pre-existing bug the reduction exposed: nip71Edited compared the submit-side copy AFTER publishedAt normalization (string→timestamp, delete-empty) against an UN-normalized original, so any video with publishedAt made every save look "edited". Both sides now share normalizeCollectedNip71. Tests: +2 in edit-modal-submit-state (stored extras survive a hashtag edit; untouched save keeps nip71Edited false). Modal/payload/mirror suites green (39 + 7). Lint + build green. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
84cec15483
commit
5466d97544
5 files changed
+220
-626
No files matched your search
@@ -101,6 +101,11 @@ export class EditModal {
|
||||
this.nip71SectionKey = "edit";
|
||||
this.originalNip71Metadata = null;
|
||||
this.originalNip71MetadataJson = null;
|
||||
// Full stored NIP-71 metadata for the active video. The form now edits only
|
||||
// hashtags (the rest of the NIP-71 section was removed for a cleaner UI), so
|
||||
// legacy extras (imeta, text tracks, participants, …) must be merged back in
|
||||
// on save rather than replaced by the reduced form's empty output.
|
||||
this.storedNip71Metadata = null;
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options) {
|
||||
@@ -385,6 +390,7 @@ export class EditModal {
|
||||
this.nip71FormManager.resetSection(this.nip71SectionKey);
|
||||
this.originalNip71Metadata = null;
|
||||
this.originalNip71MetadataJson = null;
|
||||
this.storedNip71Metadata = null;
|
||||
this.setSubmitState({ pending: false });
|
||||
return;
|
||||
}
|
||||
@@ -430,6 +436,7 @@ export class EditModal {
|
||||
this.nip71FormManager.resetSection(this.nip71SectionKey);
|
||||
this.originalNip71Metadata = null;
|
||||
this.originalNip71MetadataJson = null;
|
||||
this.storedNip71Metadata = null;
|
||||
this.activeVideo = null;
|
||||
this.setSubmitState({ pending: false });
|
||||
}
|
||||
@@ -511,7 +518,19 @@ export class EditModal {
|
||||
|
||||
const initialNip71 = this.nip71FormManager.collectSection(this.nip71SectionKey);
|
||||
this.originalNip71Metadata = this.cloneNip71Metadata(initialNip71);
|
||||
// Apply the SAME normalization submit applies to its collected copy, so the
|
||||
// nip71Edited JSON comparison is between identically-shaped objects. Without
|
||||
// this, submit's publishedAt string→timestamp / delete-empty step made every
|
||||
// save look "edited" even when nothing changed.
|
||||
this.normalizeCollectedNip71(this.originalNip71Metadata);
|
||||
this.originalNip71MetadataJson = JSON.stringify(this.originalNip71Metadata);
|
||||
// Keep the video's FULL stored NIP-71 metadata (pre-form): the reduced form
|
||||
// only round-trips hashtags, and submit merges them into this so legacy
|
||||
// extras survive a save.
|
||||
this.storedNip71Metadata =
|
||||
video.nip71 && typeof video.nip71 === "object"
|
||||
? this.cloneNip71Metadata(video.nip71)
|
||||
: null;
|
||||
this.activeVideo = editContext;
|
||||
|
||||
if (this.root) {
|
||||
@@ -888,6 +907,28 @@ export class EditModal {
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize a collectSection() result in place: convert the datetime-local
|
||||
// publishedAt string back to unix seconds and drop it when empty/invalid.
|
||||
// Applied to BOTH the open-time original and the submit-time copy so the
|
||||
// nip71Edited comparison sees identically-shaped objects.
|
||||
normalizeCollectedNip71(metadata) {
|
||||
if (!metadata || typeof metadata.publishedAt !== "string") {
|
||||
return metadata;
|
||||
}
|
||||
const dateStr = metadata.publishedAt;
|
||||
if (dateStr) {
|
||||
const dt = new Date(dateStr);
|
||||
if (!isNaN(dt.getTime())) {
|
||||
metadata.publishedAt = Math.floor(dt.getTime() / 1000);
|
||||
} else {
|
||||
delete metadata.publishedAt;
|
||||
}
|
||||
} else {
|
||||
delete metadata.publishedAt;
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
if (this.pendingSubmit) {
|
||||
return;
|
||||
@@ -996,21 +1037,7 @@ export class EditModal {
|
||||
|
||||
const rawNip71 = this.nip71FormManager.collectSection(this.nip71SectionKey);
|
||||
const currentNip71 = this.cloneNip71Metadata(rawNip71);
|
||||
|
||||
// Convert publishedAt back to Unix timestamp (seconds)
|
||||
if (currentNip71 && typeof currentNip71.publishedAt === "string") {
|
||||
const dateStr = currentNip71.publishedAt;
|
||||
if (dateStr) {
|
||||
const dt = new Date(dateStr);
|
||||
if (!isNaN(dt.getTime())) {
|
||||
currentNip71.publishedAt = Math.floor(dt.getTime() / 1000);
|
||||
} else {
|
||||
delete currentNip71.publishedAt;
|
||||
}
|
||||
} else {
|
||||
delete currentNip71.publishedAt;
|
||||
}
|
||||
}
|
||||
this.normalizeCollectedNip71(currentNip71);
|
||||
const hasImetaSource = Array.isArray(currentNip71?.imeta)
|
||||
? currentNip71.imeta.some((variant) => {
|
||||
if (!variant || typeof variant !== "object") {
|
||||
@@ -1170,7 +1197,25 @@ export class EditModal {
|
||||
|
||||
const currentNip71Json = JSON.stringify(currentNip71);
|
||||
const nip71Edited = currentNip71Json !== this.originalNip71MetadataJson;
|
||||
updatedData.nip71 = currentNip71;
|
||||
// The form now edits ONLY hashtags. Merge them into the video's full stored
|
||||
// NIP-71 metadata so legacy extras (imeta, text tracks, participants, …) are
|
||||
// preserved on save instead of being replaced by the reduced form's empty
|
||||
// fields. (Both sides of the nip71Edited comparison round-trip through the
|
||||
// same reduced form, so it still fires exactly on hashtag changes.)
|
||||
let finalNip71 = currentNip71;
|
||||
if (this.storedNip71Metadata && typeof this.storedNip71Metadata === "object") {
|
||||
const preserved = this.cloneNip71Metadata(this.storedNip71Metadata) || {};
|
||||
const editedHashtags = Array.isArray(currentNip71?.hashtags)
|
||||
? currentNip71.hashtags
|
||||
: [];
|
||||
preserved.hashtags = editedHashtags;
|
||||
if (Array.isArray(preserved.t)) {
|
||||
// Some stored payloads mirror hashtags under `t`; keep them in sync.
|
||||
preserved.t = editedHashtags;
|
||||
}
|
||||
finalNip71 = preserved;
|
||||
}
|
||||
updatedData.nip71 = finalNip71;
|
||||
updatedData.nip71Edited = nip71Edited;
|
||||
|
||||
const originalEvent = {
|
||||
|
||||
Reference in new issue
Block a user