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 88 89 89 var xrpcLabelers []xrpc.LabelerSubscription 90 90 for _, l := range input.SubscribedLabelers { 91 - xrpcLabelers = append(xrpcLabelers, xrpc.LabelerSubscription{DID: l.DID}) 91 + xrpcLabelers = append(xrpcLabelers, xrpc.LabelerSubscription{ 92 + Type: "at.margin.preferences#labelerSubscription", 93 + DID: l.DID, 94 + }) 92 95 } 93 96 var xrpcLabelPrefs []xrpc.LabelPreference 94 97 for _, lp := range input.LabelPreferences { 95 98 xrpcLabelPrefs = append(xrpcLabelPrefs, xrpc.LabelPreference{ 99 + Type: "at.margin.preferences#labelPreference", 96 100 LabelerDID: lp.LabelerDID, 97 101 Label: lp.Label, 98 102 Visibility: lp.Visibility,
+3 -1
backend/internal/xrpc/records.go
··· 462 462 } 463 463 464 464 type LabelerSubscription struct { 465 - DID string `json:"did"` 465 + Type string `json:"$type,omitempty"` 466 + DID string `json:"did"` 466 467 } 467 468 468 469 type LabelPreference struct { 470 + Type string `json:"$type,omitempty"` 469 471 LabelerDID string `json:"labelerDid"` 470 472 Label string `json:"label"` 471 473 Visibility string `json:"visibility"`
+1 -1
backend/internal/xrpc/utils.go
··· 18 18 19 19 var ( 20 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]*)+$`) 21 + nsidPattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9]*(\.[a-zA-Z][a-zA-Z0-9]*)+$`) 22 22 rkeyPattern = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) 23 23 ) 24 24
+33 -25
lexicons/at/margin/preferences.json
··· 23 23 "type": "array", 24 24 "description": "List of labeler services the user subscribes to for content moderation.", 25 25 "items": { 26 - "type": "object", 27 - "required": ["did"], 28 - "properties": { 29 - "did": { 30 - "type": "string", 31 - "description": "DID of the labeler service." 32 - } 33 - } 26 + "type": "ref", 27 + "ref": "#labelerSubscription" 34 28 }, 35 29 "maxLength": 50 36 30 }, ··· 38 32 "type": "array", 39 33 "description": "Per-label visibility preferences for subscribed labelers.", 40 34 "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 - } 35 + "type": "ref", 36 + "ref": "#labelPreference" 58 37 }, 59 38 "maxLength": 500 60 39 }, ··· 62 41 "type": "string", 63 42 "format": "datetime" 64 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"] 65 73 } 66 74 } 67 75 }
+7 -7
web/src/views/profile/Profile.tsx
··· 138 138 ]); 139 139 140 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, 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 147 website: marginData?.website, 148 148 links: marginData?.links || [], 149 149 followersCount: ··· 429 429 </div> 430 430 431 431 {profile.description && ( 432 - <p className="text-surface-600 dark:text-surface-300 text-sm mt-3 whitespace-pre-line"> 432 + <p className="text-surface-600 dark:text-surface-300 text-sm mt-3 whitespace-pre-line break-words"> 433 433 <RichText text={profile.description} /> 434 434 </p> 435 435 )}