(READ ONLY) Margin is an open annotation layer for the internet. Powered by the AT Protocol. margin.at
extension web atproto comments
98
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix not being able to delete collections and preferences lexicon

scanash00 28a3bb2f 77df412c

+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 )}