Write on the margins of the internet. Powered by the AT Protocol. margin.at
extension web atproto comments

fix not being able to delete collections and preferences lexicon

+49 -35
+5 -1
backend/internal/api/preferences.go
··· 88 89 var xrpcLabelers []xrpc.LabelerSubscription 90 for _, l := range input.SubscribedLabelers { 91 - xrpcLabelers = append(xrpcLabelers, xrpc.LabelerSubscription{DID: l.DID}) 92 } 93 var xrpcLabelPrefs []xrpc.LabelPreference 94 for _, lp := range input.LabelPreferences { 95 xrpcLabelPrefs = append(xrpcLabelPrefs, xrpc.LabelPreference{ 96 LabelerDID: lp.LabelerDID, 97 Label: lp.Label, 98 Visibility: lp.Visibility,
··· 88 89 var xrpcLabelers []xrpc.LabelerSubscription 90 for _, l := range input.SubscribedLabelers { 91 + xrpcLabelers = append(xrpcLabelers, xrpc.LabelerSubscription{ 92 + Type: "at.margin.preferences#labelerSubscription", 93 + DID: l.DID, 94 + }) 95 } 96 var xrpcLabelPrefs []xrpc.LabelPreference 97 for _, lp := range input.LabelPreferences { 98 xrpcLabelPrefs = append(xrpcLabelPrefs, xrpc.LabelPreference{ 99 + Type: "at.margin.preferences#labelPreference", 100 LabelerDID: lp.LabelerDID, 101 Label: lp.Label, 102 Visibility: lp.Visibility,
+3 -1
backend/internal/xrpc/records.go
··· 462 } 463 464 type LabelerSubscription struct { 465 - DID string `json:"did"` 466 } 467 468 type LabelPreference struct { 469 LabelerDID string `json:"labelerDid"` 470 Label string `json:"label"` 471 Visibility string `json:"visibility"`
··· 462 } 463 464 type LabelerSubscription struct { 465 + Type string `json:"$type,omitempty"` 466 + DID string `json:"did"` 467 } 468 469 type LabelPreference struct { 470 + Type string `json:"$type,omitempty"` 471 LabelerDID string `json:"labelerDid"` 472 Label string `json:"label"` 473 Visibility string `json:"visibility"`
+1 -1
backend/internal/xrpc/utils.go
··· 18 19 var ( 20 didPattern = regexp.MustCompile(`^did:[a-z]+:[a-zA-Z0-9._:%-]+$`) 21 - nsidPattern = regexp.MustCompile(`^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$`) 22 rkeyPattern = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) 23 ) 24
··· 18 19 var ( 20 didPattern = regexp.MustCompile(`^did:[a-z]+:[a-zA-Z0-9._:%-]+$`) 21 + nsidPattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9]*(\.[a-zA-Z][a-zA-Z0-9]*)+$`) 22 rkeyPattern = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) 23 ) 24
+33 -25
lexicons/at/margin/preferences.json
··· 23 "type": "array", 24 "description": "List of labeler services the user subscribes to for content moderation.", 25 "items": { 26 - "type": "object", 27 - "required": ["did"], 28 - "properties": { 29 - "did": { 30 - "type": "string", 31 - "description": "DID of the labeler service." 32 - } 33 - } 34 }, 35 "maxLength": 50 36 }, ··· 38 "type": "array", 39 "description": "Per-label visibility preferences for subscribed labelers.", 40 "items": { 41 - "type": "object", 42 - "required": ["labelerDid", "label", "visibility"], 43 - "properties": { 44 - "labelerDid": { 45 - "type": "string", 46 - "description": "DID of the labeler service." 47 - }, 48 - "label": { 49 - "type": "string", 50 - "description": "The label identifier (e.g. sexual, violence, spam)." 51 - }, 52 - "visibility": { 53 - "type": "string", 54 - "description": "How to handle content with this label: hide, warn, or ignore.", 55 - "knownValues": ["hide", "warn", "ignore"] 56 - } 57 - } 58 }, 59 "maxLength": 500 60 }, ··· 62 "type": "string", 63 "format": "datetime" 64 } 65 } 66 } 67 }
··· 23 "type": "array", 24 "description": "List of labeler services the user subscribes to for content moderation.", 25 "items": { 26 + "type": "ref", 27 + "ref": "#labelerSubscription" 28 }, 29 "maxLength": 50 30 }, ··· 32 "type": "array", 33 "description": "Per-label visibility preferences for subscribed labelers.", 34 "items": { 35 + "type": "ref", 36 + "ref": "#labelPreference" 37 }, 38 "maxLength": 500 39 }, ··· 41 "type": "string", 42 "format": "datetime" 43 } 44 + } 45 + } 46 + }, 47 + "labelerSubscription": { 48 + "type": "object", 49 + "required": ["did"], 50 + "properties": { 51 + "did": { 52 + "type": "string", 53 + "description": "DID of the labeler service." 54 + } 55 + } 56 + }, 57 + "labelPreference": { 58 + "type": "object", 59 + "required": ["labelerDid", "label", "visibility"], 60 + "properties": { 61 + "labelerDid": { 62 + "type": "string", 63 + "description": "DID of the labeler service." 64 + }, 65 + "label": { 66 + "type": "string", 67 + "description": "The label identifier (e.g. sexual, violence, spam)." 68 + }, 69 + "visibility": { 70 + "type": "string", 71 + "description": "How to handle content with this label: hide, warn, or ignore.", 72 + "knownValues": ["hide", "warn", "ignore"] 73 } 74 } 75 }
+7 -7
web/src/views/profile/Profile.tsx
··· 138 ]); 139 140 const merged: UserProfile = { 141 - did: bskyData?.did || marginData?.did || did, 142 - handle: bskyData?.handle || marginData?.handle || "", 143 - displayName: bskyData?.displayName || marginData?.displayName, 144 - avatar: bskyData?.avatar || marginData?.avatar, 145 - description: bskyData?.description || marginData?.description, 146 - banner: bskyData?.banner || marginData?.banner, 147 website: marginData?.website, 148 links: marginData?.links || [], 149 followersCount: ··· 429 </div> 430 431 {profile.description && ( 432 - <p className="text-surface-600 dark:text-surface-300 text-sm mt-3 whitespace-pre-line"> 433 <RichText text={profile.description} /> 434 </p> 435 )}
··· 138 ]); 139 140 const merged: UserProfile = { 141 + did: marginData?.did || bskyData?.did || did, 142 + handle: marginData?.handle || bskyData?.handle || "", 143 + displayName: marginData?.displayName || bskyData?.displayName, 144 + avatar: marginData?.avatar || bskyData?.avatar, 145 + description: marginData?.description || bskyData?.description, 146 + banner: marginData?.banner || bskyData?.banner, 147 website: marginData?.website, 148 links: marginData?.links || [], 149 followersCount: ··· 429 </div> 430 431 {profile.description && ( 432 + <p className="text-surface-600 dark:text-surface-300 text-sm mt-3 whitespace-pre-line break-words"> 433 <RichText text={profile.description} /> 434 </p> 435 )}