feat(bskyweb): match Pass Designer pass.json + assets literally
This commit is contained in:
@@ -30,30 +30,32 @@ func ThemeBackgroundRGB(theme string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type passField struct {
|
type passField struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
DateStyle string `json:"dateStyle,omitempty"`
|
DateStyle string `json:"dateStyle,omitempty"`
|
||||||
|
TextAlignment string `json:"textAlignment,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// passFields is the iOS <= 26 storeCard/generic layout: header, primary,
|
// genericFields is the iOS <= 26 fallback layout that Pass Designer produces
|
||||||
// secondary, back.
|
// in the `generic` block. Notably no backFields - Pass Designer omits that
|
||||||
type passFields struct {
|
// key in this block.
|
||||||
|
type genericFields struct {
|
||||||
HeaderFields []passField `json:"headerFields"`
|
HeaderFields []passField `json:"headerFields"`
|
||||||
PrimaryFields []passField `json:"primaryFields"`
|
PrimaryFields []passField `json:"primaryFields"`
|
||||||
SecondaryFields []passField `json:"secondaryFields"`
|
SecondaryFields []passField `json:"secondaryFields"`
|
||||||
BackFields []passField `json:"backFields"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// posterFields is the iOS 27 layout used by Pass Designer. Adds auxiliary
|
// posterFields is the iOS 27+ layout in the `posterGeneric` block. All six
|
||||||
// and footer field slots that the classic layout does not have.
|
// field slots present, empty arrays where not used (matches Pass Designer's
|
||||||
|
// output literally).
|
||||||
type posterFields struct {
|
type posterFields struct {
|
||||||
|
AuxiliaryFields []passField `json:"auxiliaryFields"`
|
||||||
|
BackFields []passField `json:"backFields"`
|
||||||
|
FooterFields []passField `json:"footerFields"`
|
||||||
HeaderFields []passField `json:"headerFields"`
|
HeaderFields []passField `json:"headerFields"`
|
||||||
PrimaryFields []passField `json:"primaryFields"`
|
PrimaryFields []passField `json:"primaryFields"`
|
||||||
SecondaryFields []passField `json:"secondaryFields"`
|
SecondaryFields []passField `json:"secondaryFields"`
|
||||||
AuxiliaryFields []passField `json:"auxiliaryFields"`
|
|
||||||
FooterFields []passField `json:"footerFields"`
|
|
||||||
BackFields []passField `json:"backFields"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type barcode struct {
|
type barcode struct {
|
||||||
@@ -64,62 +66,46 @@ type barcode struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pkPass struct {
|
type pkPass struct {
|
||||||
FormatVersion int `json:"formatVersion"`
|
FormatVersion int `json:"formatVersion"`
|
||||||
PassTypeIdentifier string `json:"passTypeIdentifier"`
|
PassTypeIdentifier string `json:"passTypeIdentifier"`
|
||||||
SerialNumber string `json:"serialNumber"`
|
SerialNumber string `json:"serialNumber"`
|
||||||
TeamIdentifier string `json:"teamIdentifier"`
|
TeamIdentifier string `json:"teamIdentifier"`
|
||||||
OrganizationName string `json:"organizationName"`
|
OrganizationName string `json:"organizationName"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
LogoText string `json:"logoText"`
|
ForegroundColor string `json:"foregroundColor"`
|
||||||
ForegroundColor string `json:"foregroundColor"`
|
LabelColor string `json:"labelColor"`
|
||||||
LabelColor string `json:"labelColor"`
|
BackgroundColor string `json:"backgroundColor"`
|
||||||
BackgroundColor string `json:"backgroundColor"`
|
Generic genericFields `json:"generic"`
|
||||||
Generic passFields `json:"generic"`
|
PosterGeneric posterFields `json:"posterGeneric"`
|
||||||
PosterGeneric posterFields `json:"posterGeneric"`
|
SuppressHeaderDarkening bool `json:"suppressHeaderDarkening"`
|
||||||
SuppressHeaderDarkening bool `json:"suppressHeaderDarkening"`
|
UseAutomaticColors bool `json:"useAutomaticColors"`
|
||||||
UseAutomaticColors bool `json:"useAutomaticColors"`
|
Barcodes []barcode `json:"barcodes"`
|
||||||
Barcodes []barcode `json:"barcodes"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const passTypeIdentifier = "pass.xyz.blueskyweb.app"
|
const passTypeIdentifier = "pass.xyz.blueskyweb.app"
|
||||||
|
|
||||||
// BuildPassJSON builds the pkpass JSON for both the iOS <= 26 fallback layout
|
// BuildPassJSON builds the pkpass JSON matching the Pass Designer-exported
|
||||||
// (`generic` block) and the iOS 27 layout (`posterGeneric` block). The two
|
// layout literally: `generic` has handle (primary) + member-since (secondary);
|
||||||
// blocks describe the same fields in the layouts each iOS version expects:
|
// `posterGeneric` adds DID as a footer field and stacks handle + member-since
|
||||||
// the user sees the poster layout on iOS 27+ and the legacy layout below that.
|
// in primaryFields.
|
||||||
//
|
//
|
||||||
// pdsHost is the hostname extracted from the user's DID document
|
// pdsHost and displayName are currently unused - the design landed without
|
||||||
// serviceEndpoint (e.g. "suillus.us-west.host.bsky.network").
|
// them - but their plumbing is retained in callers for a possible future
|
||||||
// createdAt is the user's profile record creation time, used as a rough
|
// design. The token still carries pdsHost.
|
||||||
// stand-in for account creation.
|
|
||||||
func BuildPassJSON(did, handle, displayName, pdsHost, theme, teamID string, createdAt time.Time) ([]byte, error) {
|
func BuildPassJSON(did, handle, displayName, pdsHost, theme, teamID string, createdAt time.Time) ([]byte, error) {
|
||||||
|
_ = displayName
|
||||||
|
_ = pdsHost
|
||||||
|
_ = theme
|
||||||
theme = CoerceTheme(theme)
|
theme = CoerceTheme(theme)
|
||||||
profileURL := "https://bsky.app/profile/" + handle
|
profileURL := "https://bsky.app/profile/" + handle
|
||||||
atHandle := "@" + handle
|
|
||||||
memberName := displayName
|
|
||||||
if memberName == "" {
|
|
||||||
memberName = atHandle
|
|
||||||
}
|
|
||||||
if pdsHost == "" {
|
|
||||||
pdsHost = "bsky.social"
|
|
||||||
}
|
|
||||||
createdAtISO := ""
|
createdAtISO := ""
|
||||||
if !createdAt.IsZero() {
|
if !createdAt.IsZero() {
|
||||||
createdAtISO = createdAt.UTC().Format(time.RFC3339)
|
createdAtISO = createdAt.UTC().Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid an unused variable when displayName is empty - we keep memberName
|
|
||||||
// computed for a possible future design, but the current layout uses
|
|
||||||
// handle directly.
|
|
||||||
_ = memberName
|
|
||||||
|
|
||||||
pdsField := passField{Key: "pds", Label: "PDS", Value: pdsHost}
|
|
||||||
handleField := passField{Key: "handle", Label: "Handle", Value: handle}
|
handleField := passField{Key: "handle", Label: "Handle", Value: handle}
|
||||||
sinceField := passField{Key: "since", Label: "Member Since", Value: createdAtISO, DateStyle: "PKDateStyleShort"}
|
sinceField := passField{Key: "since", Label: "Member Since", Value: createdAtISO, DateStyle: "PKDateStyleShort"}
|
||||||
backFields := []passField{
|
didField := passField{Key: "did", Label: "DID", Value: did, TextAlignment: "PKTextAlignmentNatural"}
|
||||||
{Key: "about", Label: "About", Value: "Scan the QR code to view this Bluesky profile."},
|
|
||||||
{Key: "url", Label: "Profile URL", Value: profileURL},
|
|
||||||
}
|
|
||||||
|
|
||||||
p := pkPass{
|
p := pkPass{
|
||||||
FormatVersion: 1,
|
FormatVersion: 1,
|
||||||
@@ -127,29 +113,24 @@ func BuildPassJSON(did, handle, displayName, pdsHost, theme, teamID string, crea
|
|||||||
SerialNumber: did + "-" + theme + "-v1",
|
SerialNumber: did + "-" + theme + "-v1",
|
||||||
TeamIdentifier: teamID,
|
TeamIdentifier: teamID,
|
||||||
OrganizationName: "Bluesky",
|
OrganizationName: "Bluesky",
|
||||||
Description: "Bluesky profile - " + atHandle,
|
Description: "Atmosphere Account",
|
||||||
// logoText omitted - the logo image already carries the "Bluesky"
|
ForegroundColor: "rgb(255,255,255)",
|
||||||
// wordmark; setting both would render the brand name twice.
|
LabelColor: "rgb(255,255,255)",
|
||||||
LogoText: "",
|
// Matches Pass Designer's exported backgroundColor. Theme parameter
|
||||||
ForegroundColor: "rgb(255, 255, 255)",
|
// kept in the signature for the URL/serial but no longer affects color.
|
||||||
LabelColor: "rgb(255, 255, 255)",
|
BackgroundColor: "rgb(44,103,244)",
|
||||||
BackgroundColor: ThemeBackgroundRGB(theme),
|
Generic: genericFields{
|
||||||
// iOS <= 26 fallback: handle as primary, since as secondary (stacked).
|
HeaderFields: []passField{},
|
||||||
Generic: passFields{
|
|
||||||
HeaderFields: []passField{pdsField},
|
|
||||||
PrimaryFields: []passField{handleField},
|
PrimaryFields: []passField{handleField},
|
||||||
SecondaryFields: []passField{sinceField},
|
SecondaryFields: []passField{sinceField},
|
||||||
BackFields: backFields,
|
|
||||||
},
|
},
|
||||||
// iOS 27+: handle and since side-by-side in primaryFields, matching
|
|
||||||
// what Pass Designer exports.
|
|
||||||
PosterGeneric: posterFields{
|
PosterGeneric: posterFields{
|
||||||
HeaderFields: []passField{pdsField},
|
AuxiliaryFields: []passField{},
|
||||||
|
BackFields: []passField{},
|
||||||
|
FooterFields: []passField{didField},
|
||||||
|
HeaderFields: []passField{},
|
||||||
PrimaryFields: []passField{handleField, sinceField},
|
PrimaryFields: []passField{handleField, sinceField},
|
||||||
SecondaryFields: []passField{},
|
SecondaryFields: []passField{},
|
||||||
AuxiliaryFields: []passField{},
|
|
||||||
FooterFields: []passField{},
|
|
||||||
BackFields: backFields,
|
|
||||||
},
|
},
|
||||||
SuppressHeaderDarkening: false,
|
SuppressHeaderDarkening: false,
|
||||||
UseAutomaticColors: false,
|
UseAutomaticColors: false,
|
||||||
|
|||||||
+14
-43
@@ -4,19 +4,12 @@
|
|||||||
"serialNumber": "did:plc:abc123-dawn-v1",
|
"serialNumber": "did:plc:abc123-dawn-v1",
|
||||||
"teamIdentifier": "TEAMID00",
|
"teamIdentifier": "TEAMID00",
|
||||||
"organizationName": "Bluesky",
|
"organizationName": "Bluesky",
|
||||||
"description": "Bluesky profile - @alice.bsky.social",
|
"description": "Atmosphere Account",
|
||||||
"logoText": "",
|
"foregroundColor": "rgb(255,255,255)",
|
||||||
"foregroundColor": "rgb(255, 255, 255)",
|
"labelColor": "rgb(255,255,255)",
|
||||||
"labelColor": "rgb(255, 255, 255)",
|
"backgroundColor": "rgb(44,103,244)",
|
||||||
"backgroundColor": "rgb(255, 109, 190)",
|
|
||||||
"generic": {
|
"generic": {
|
||||||
"headerFields": [
|
"headerFields": [],
|
||||||
{
|
|
||||||
"key": "pds",
|
|
||||||
"label": "PDS",
|
|
||||||
"value": "alice.host.bsky.network"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -31,28 +24,20 @@
|
|||||||
"value": "2026-01-25T23:59:05Z",
|
"value": "2026-01-25T23:59:05Z",
|
||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"posterGeneric": {
|
"posterGeneric": {
|
||||||
"headerFields": [
|
"auxiliaryFields": [],
|
||||||
|
"backFields": [],
|
||||||
|
"footerFields": [
|
||||||
{
|
{
|
||||||
"key": "pds",
|
"key": "did",
|
||||||
"label": "PDS",
|
"label": "DID",
|
||||||
"value": "alice.host.bsky.network"
|
"value": "did:plc:abc123",
|
||||||
|
"textAlignment": "PKTextAlignmentNatural"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"headerFields": [],
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -66,21 +51,7 @@
|
|||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"secondaryFields": [],
|
"secondaryFields": []
|
||||||
"auxiliaryFields": [],
|
|
||||||
"footerFields": [],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"suppressHeaderDarkening": false,
|
"suppressHeaderDarkening": false,
|
||||||
"useAutomaticColors": false,
|
"useAutomaticColors": false,
|
||||||
|
|||||||
+14
-43
@@ -4,19 +4,12 @@
|
|||||||
"serialNumber": "did:plc:abc123-day-v1",
|
"serialNumber": "did:plc:abc123-day-v1",
|
||||||
"teamIdentifier": "TEAMID00",
|
"teamIdentifier": "TEAMID00",
|
||||||
"organizationName": "Bluesky",
|
"organizationName": "Bluesky",
|
||||||
"description": "Bluesky profile - @alice.bsky.social",
|
"description": "Atmosphere Account",
|
||||||
"logoText": "",
|
"foregroundColor": "rgb(255,255,255)",
|
||||||
"foregroundColor": "rgb(255, 255, 255)",
|
"labelColor": "rgb(255,255,255)",
|
||||||
"labelColor": "rgb(255, 255, 255)",
|
"backgroundColor": "rgb(44,103,244)",
|
||||||
"backgroundColor": "rgb(117, 175, 255)",
|
|
||||||
"generic": {
|
"generic": {
|
||||||
"headerFields": [
|
"headerFields": [],
|
||||||
{
|
|
||||||
"key": "pds",
|
|
||||||
"label": "PDS",
|
|
||||||
"value": "alice.host.bsky.network"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -31,28 +24,20 @@
|
|||||||
"value": "2026-01-25T23:59:05Z",
|
"value": "2026-01-25T23:59:05Z",
|
||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"posterGeneric": {
|
"posterGeneric": {
|
||||||
"headerFields": [
|
"auxiliaryFields": [],
|
||||||
|
"backFields": [],
|
||||||
|
"footerFields": [
|
||||||
{
|
{
|
||||||
"key": "pds",
|
"key": "did",
|
||||||
"label": "PDS",
|
"label": "DID",
|
||||||
"value": "alice.host.bsky.network"
|
"value": "did:plc:abc123",
|
||||||
|
"textAlignment": "PKTextAlignmentNatural"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"headerFields": [],
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -66,21 +51,7 @@
|
|||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"secondaryFields": [],
|
"secondaryFields": []
|
||||||
"auxiliaryFields": [],
|
|
||||||
"footerFields": [],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"suppressHeaderDarkening": false,
|
"suppressHeaderDarkening": false,
|
||||||
"useAutomaticColors": false,
|
"useAutomaticColors": false,
|
||||||
|
|||||||
+14
-43
@@ -4,19 +4,12 @@
|
|||||||
"serialNumber": "did:plc:abc123-dusk-v1",
|
"serialNumber": "did:plc:abc123-dusk-v1",
|
||||||
"teamIdentifier": "TEAMID00",
|
"teamIdentifier": "TEAMID00",
|
||||||
"organizationName": "Bluesky",
|
"organizationName": "Bluesky",
|
||||||
"description": "Bluesky profile - @alice.bsky.social",
|
"description": "Atmosphere Account",
|
||||||
"logoText": "",
|
"foregroundColor": "rgb(255,255,255)",
|
||||||
"foregroundColor": "rgb(255, 255, 255)",
|
"labelColor": "rgb(255,255,255)",
|
||||||
"labelColor": "rgb(255, 255, 255)",
|
"backgroundColor": "rgb(44,103,244)",
|
||||||
"backgroundColor": "rgb(177, 90, 162)",
|
|
||||||
"generic": {
|
"generic": {
|
||||||
"headerFields": [
|
"headerFields": [],
|
||||||
{
|
|
||||||
"key": "pds",
|
|
||||||
"label": "PDS",
|
|
||||||
"value": "alice.host.bsky.network"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -31,28 +24,20 @@
|
|||||||
"value": "2026-01-25T23:59:05Z",
|
"value": "2026-01-25T23:59:05Z",
|
||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"posterGeneric": {
|
"posterGeneric": {
|
||||||
"headerFields": [
|
"auxiliaryFields": [],
|
||||||
|
"backFields": [],
|
||||||
|
"footerFields": [
|
||||||
{
|
{
|
||||||
"key": "pds",
|
"key": "did",
|
||||||
"label": "PDS",
|
"label": "DID",
|
||||||
"value": "alice.host.bsky.network"
|
"value": "did:plc:abc123",
|
||||||
|
"textAlignment": "PKTextAlignmentNatural"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"headerFields": [],
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -66,21 +51,7 @@
|
|||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"secondaryFields": [],
|
"secondaryFields": []
|
||||||
"auxiliaryFields": [],
|
|
||||||
"footerFields": [],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"suppressHeaderDarkening": false,
|
"suppressHeaderDarkening": false,
|
||||||
"useAutomaticColors": false,
|
"useAutomaticColors": false,
|
||||||
|
|||||||
+14
-43
@@ -4,19 +4,12 @@
|
|||||||
"serialNumber": "did:plc:abc123-night-v1",
|
"serialNumber": "did:plc:abc123-night-v1",
|
||||||
"teamIdentifier": "TEAMID00",
|
"teamIdentifier": "TEAMID00",
|
||||||
"organizationName": "Bluesky",
|
"organizationName": "Bluesky",
|
||||||
"description": "Bluesky profile - @alice.bsky.social",
|
"description": "Atmosphere Account",
|
||||||
"logoText": "",
|
"foregroundColor": "rgb(255,255,255)",
|
||||||
"foregroundColor": "rgb(255, 255, 255)",
|
"labelColor": "rgb(255,255,255)",
|
||||||
"labelColor": "rgb(255, 255, 255)",
|
"backgroundColor": "rgb(44,103,244)",
|
||||||
"backgroundColor": "rgb(0, 21, 51)",
|
|
||||||
"generic": {
|
"generic": {
|
||||||
"headerFields": [
|
"headerFields": [],
|
||||||
{
|
|
||||||
"key": "pds",
|
|
||||||
"label": "PDS",
|
|
||||||
"value": "alice.host.bsky.network"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -31,28 +24,20 @@
|
|||||||
"value": "2026-01-25T23:59:05Z",
|
"value": "2026-01-25T23:59:05Z",
|
||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"posterGeneric": {
|
"posterGeneric": {
|
||||||
"headerFields": [
|
"auxiliaryFields": [],
|
||||||
|
"backFields": [],
|
||||||
|
"footerFields": [
|
||||||
{
|
{
|
||||||
"key": "pds",
|
"key": "did",
|
||||||
"label": "PDS",
|
"label": "DID",
|
||||||
"value": "alice.host.bsky.network"
|
"value": "did:plc:abc123",
|
||||||
|
"textAlignment": "PKTextAlignmentNatural"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"headerFields": [],
|
||||||
"primaryFields": [
|
"primaryFields": [
|
||||||
{
|
{
|
||||||
"key": "handle",
|
"key": "handle",
|
||||||
@@ -66,21 +51,7 @@
|
|||||||
"dateStyle": "PKDateStyleShort"
|
"dateStyle": "PKDateStyleShort"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"secondaryFields": [],
|
"secondaryFields": []
|
||||||
"auxiliaryFields": [],
|
|
||||||
"footerFields": [],
|
|
||||||
"backFields": [
|
|
||||||
{
|
|
||||||
"key": "about",
|
|
||||||
"label": "About",
|
|
||||||
"value": "Scan the QR code to view this Bluesky profile."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "url",
|
|
||||||
"label": "Profile URL",
|
|
||||||
"value": "https://bsky.app/profile/alice.bsky.social"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"suppressHeaderDarkening": false,
|
"suppressHeaderDarkening": false,
|
||||||
"useAutomaticColors": false,
|
"useAutomaticColors": false,
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 6.3 KiB |
Reference in New Issue
Block a user