diff --git a/api/tangled/actorprofile.go b/api/tangled/actorprofile.go index 1279952e..c9a130a8 100644 --- a/api/tangled/actorprofile.go +++ b/api/tangled/actorprofile.go @@ -28,4 +28,5 @@ type ActorProfile struct { // pinnedRepositories: Any ATURI, it is up to appviews to validate these fields. PinnedRepositories []string `json:"pinnedRepositories,omitempty" cborgen:"pinnedRepositories,omitempty"` Stats []string `json:"stats,omitempty" cborgen:"stats,omitempty"` + Pronouns *string `json:"pronouns,omitempty" cborgen:"pronouns,omitempty"` } diff --git a/appview/db/db.go b/appview/db/db.go index 21f2c20c..f61490c7 100644 --- a/appview/db/db.go +++ b/appview/db/db.go @@ -1106,6 +1106,13 @@ func Make(ctx context.Context, dbPath string) (*DB, error) { return err }) + runMigration(conn, logger, "add-pronouns-profile", func(tx *sql.Tx) error { + _, err := tx.Exec(` + alter table profile add column pronouns text; + `) + return err + }) + return &DB{ db, logger, diff --git a/appview/db/profile.go b/appview/db/profile.go index 7eb5ba83..426e973a 100644 --- a/appview/db/profile.go +++ b/appview/db/profile.go @@ -129,13 +129,15 @@ func UpsertProfile(tx *sql.Tx, profile *models.Profile) error { did, description, include_bluesky, - location + location, + pronouns ) - values (?, ?, ?, ?)`, + values (?, ?, ?, ?, ?)`, profile.Did, profile.Description, includeBskyValue, profile.Location, + profile.Pronouns, ) if err != nil { @@ -216,7 +218,8 @@ func GetProfiles(e Execer, filters ...filter) (map[string]*models.Profile, error did, description, include_bluesky, - location + location, + pronouns from profile %s`, @@ -231,8 +234,9 @@ func GetProfiles(e Execer, filters ...filter) (map[string]*models.Profile, error for rows.Next() { var profile models.Profile var includeBluesky int + var pronouns sql.Null[string] - err = rows.Scan(&profile.ID, &profile.Did, &profile.Description, &includeBluesky, &profile.Location) + err = rows.Scan(&profile.ID, &profile.Did, &profile.Description, &includeBluesky, &profile.Location, &pronouns) if err != nil { return nil, err } @@ -241,6 +245,10 @@ func GetProfiles(e Execer, filters ...filter) (map[string]*models.Profile, error profile.IncludeBluesky = true } + if pronouns.Valid { + profile.Pronouns = pronouns.V + } + profileMap[profile.Did] = &profile } if err = rows.Err(); err != nil { @@ -302,13 +310,16 @@ func GetProfiles(e Execer, filters ...filter) (map[string]*models.Profile, error func GetProfile(e Execer, did string) (*models.Profile, error) { var profile models.Profile + var pronouns sql.Null[string] + profile.Did = did includeBluesky := 0 + err := e.QueryRow( - `select description, include_bluesky, location from profile where did = ?`, + `select description, include_bluesky, location, pronouns from profile where did = ?`, did, - ).Scan(&profile.Description, &includeBluesky, &profile.Location) + ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns) if err == sql.ErrNoRows { profile := models.Profile{} profile.Did = did @@ -323,6 +334,10 @@ func GetProfile(e Execer, did string) (*models.Profile, error) { profile.IncludeBluesky = true } + if pronouns.Valid { + profile.Pronouns = pronouns.V + } + rows, err := e.Query(`select link from profile_links where did = ?`, did) if err != nil { return nil, err @@ -414,6 +429,11 @@ func ValidateProfile(e Execer, profile *models.Profile) error { return fmt.Errorf("Entered location is too long.") } + // ensure pronouns are not too long + if len(profile.Pronouns) > 40 { + return fmt.Errorf("Entered pronouns are too long.") + } + // ensure links are in order err := validateLinks(profile) if err != nil { diff --git a/appview/ingester.go b/appview/ingester.go index 547233fe..1c5d6d0a 100644 --- a/appview/ingester.go +++ b/appview/ingester.go @@ -291,6 +291,11 @@ func (i *Ingester) ingestProfile(e *jmodels.Event) error { includeBluesky := record.Bluesky + pronouns := "" + if record.Pronouns != nil { + pronouns = *record.Pronouns + } + location := "" if record.Location != nil { location = *record.Location @@ -325,6 +330,7 @@ func (i *Ingester) ingestProfile(e *jmodels.Event) error { Links: links, Stats: stats, PinnedRepos: pinned, + Pronouns: pronouns, } ddb, ok := i.Db.Execer.(*db.DB) diff --git a/appview/models/profile.go b/appview/models/profile.go index 0890a766..70fb646b 100644 --- a/appview/models/profile.go +++ b/appview/models/profile.go @@ -19,6 +19,7 @@ type Profile struct { Links [5]string Stats [2]VanityStat PinnedRepos [6]syntax.ATURI + Pronouns string } func (p Profile) IsLinksEmpty() bool { diff --git a/appview/pages/templates/user/fragments/editBio.html b/appview/pages/templates/user/fragments/editBio.html index 7c2730c6..7615da91 100644 --- a/appview/pages/templates/user/fragments/editBio.html +++ b/appview/pages/templates/user/fragments/editBio.html @@ -19,6 +19,17 @@ placeholder="write a bio">{{ $description }} +
{{ .Pronouns }}
+ {{ end }} + {{ end }} {{ i "rss" "size-4" }}