Monorepo for Tangled tangled.org

Compare changes

Choose any two refs to compare.

Changed files
+236 -340
appview
issues
knots
pages
templates
fragments
layouts
fragments
repo
fragments
issues
pulls
fragments
settings
fragments
user
pulls
repo
settings
spindles
state
docs
nix
modules
+8 -9
appview/issues/issues.go
··· 129 } 130 131 rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 132 - LoggedInUser: user, 133 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 134 - Issue: issue, 135 - CommentList: issue.CommentList(), 136 - Backlinks: backlinks, 137 - OrderedReactionKinds: models.OrderedReactionKinds, 138 - Reactions: reactionMap, 139 - UserReacted: userReactions, 140 - LabelDefs: defs, 141 }) 142 } 143
··· 129 } 130 131 rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 132 + LoggedInUser: user, 133 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 134 + Issue: issue, 135 + CommentList: issue.CommentList(), 136 + Backlinks: backlinks, 137 + Reactions: reactionMap, 138 + UserReacted: userReactions, 139 + LabelDefs: defs, 140 }) 141 } 142
-15
appview/knots/knots.go
··· 40 Knotstream *eventconsumer.Consumer 41 } 42 43 - type tab = map[string]any 44 - 45 - var ( 46 - knotsTabs []tab = []tab{ 47 - {"Name": "profile", "Icon": "user"}, 48 - {"Name": "keys", "Icon": "key"}, 49 - {"Name": "emails", "Icon": "mail"}, 50 - {"Name": "notifications", "Icon": "bell"}, 51 - {"Name": "knots", "Icon": "volleyball"}, 52 - {"Name": "spindles", "Icon": "spool"}, 53 - } 54 - ) 55 - 56 func (k *Knots) Router() http.Handler { 57 r := chi.NewRouter() 58 ··· 84 k.Pages.Knots(w, pages.KnotsParams{ 85 LoggedInUser: user, 86 Registrations: registrations, 87 - Tabs: knotsTabs, 88 Tab: "knots", 89 }) 90 } ··· 148 Members: members, 149 Repos: repoMap, 150 IsOwner: true, 151 - Tabs: knotsTabs, 152 Tab: "knots", 153 }) 154 }
··· 40 Knotstream *eventconsumer.Consumer 41 } 42 43 func (k *Knots) Router() http.Handler { 44 r := chi.NewRouter() 45 ··· 71 k.Pages.Knots(w, pages.KnotsParams{ 72 LoggedInUser: user, 73 Registrations: registrations, 74 Tab: "knots", 75 }) 76 } ··· 134 Members: members, 135 Repos: repoMap, 136 IsOwner: true, 137 Tab: "knots", 138 }) 139 }
+22
appview/pages/funcmap.go
··· 32 "tangled.org/core/crypto" 33 ) 34 35 func (p *Pages) funcMap() template.FuncMap { 36 return template.FuncMap{ 37 "split": func(s string) []string { ··· 384 return "error" 385 } 386 return fp 387 }, 388 } 389 }
··· 32 "tangled.org/core/crypto" 33 ) 34 35 + type tab map[string]string 36 + 37 func (p *Pages) funcMap() template.FuncMap { 38 return template.FuncMap{ 39 "split": func(s string) []string { ··· 386 return "error" 387 } 388 return fp 389 + }, 390 + // constant values used to define a template 391 + "const": func() map[string]any { 392 + return map[string]any{ 393 + "OrderedReactionKinds": models.OrderedReactionKinds, 394 + // would be great to have ordered maps right about now 395 + "UserSettingsTabs": []tab{ 396 + {"Name": "profile", "Icon": "user"}, 397 + {"Name": "keys", "Icon": "key"}, 398 + {"Name": "emails", "Icon": "mail"}, 399 + {"Name": "notifications", "Icon": "bell"}, 400 + {"Name": "knots", "Icon": "volleyball"}, 401 + {"Name": "spindles", "Icon": "spool"}, 402 + }, 403 + "RepoSettingsTabs": []tab{ 404 + {"Name": "general", "Icon": "sliders-horizontal"}, 405 + {"Name": "access", "Icon": "users"}, 406 + {"Name": "pipelines", "Icon": "layers-2"}, 407 + }, 408 + } 409 }, 410 } 411 }
+23 -42
appview/pages/pages.go
··· 336 337 type UserProfileSettingsParams struct { 338 LoggedInUser *oauth.User 339 - Tabs []map[string]any 340 Tab string 341 } 342 ··· 375 type UserKeysSettingsParams struct { 376 LoggedInUser *oauth.User 377 PubKeys []models.PublicKey 378 - Tabs []map[string]any 379 Tab string 380 } 381 ··· 386 type UserEmailsSettingsParams struct { 387 LoggedInUser *oauth.User 388 Emails []models.Email 389 - Tabs []map[string]any 390 Tab string 391 } 392 ··· 397 type UserNotificationSettingsParams struct { 398 LoggedInUser *oauth.User 399 Preferences *models.NotificationPreferences 400 - Tabs []map[string]any 401 Tab string 402 } 403 ··· 417 type KnotsParams struct { 418 LoggedInUser *oauth.User 419 Registrations []models.Registration 420 - Tabs []map[string]any 421 Tab string 422 } 423 ··· 431 Members []string 432 Repos map[string][]models.Repo 433 IsOwner bool 434 - Tabs []map[string]any 435 Tab string 436 } 437 ··· 450 type SpindlesParams struct { 451 LoggedInUser *oauth.User 452 Spindles []models.Spindle 453 - Tabs []map[string]any 454 Tab string 455 } 456 ··· 460 461 type SpindleListingParams struct { 462 models.Spindle 463 - Tabs []map[string]any 464 - Tab string 465 } 466 467 func (p *Pages) SpindleListing(w io.Writer, params SpindleListingParams) error { ··· 473 Spindle models.Spindle 474 Members []string 475 Repos map[string][]models.Repo 476 - Tabs []map[string]any 477 Tab string 478 } 479 ··· 612 } 613 614 type FollowFragmentParams struct { 615 - UserDid string 616 - FollowStatus models.FollowStatus 617 - FollowersCount int64 618 } 619 620 func (p *Pages) FollowFragment(w io.Writer, params FollowFragmentParams) error { 621 - return p.executePlain("user/fragments/follow-oob", w, params) 622 } 623 624 type EditBioParams struct { ··· 649 IsStarred bool 650 SubjectAt syntax.ATURI 651 StarCount int 652 - HxSwapOob bool 653 } 654 655 func (p *Pages) StarBtnFragment(w io.Writer, params StarBtnFragmentParams) error { 656 - params.HxSwapOob = true 657 - return p.executePlain("fragments/starBtn", w, params) 658 } 659 660 type RepoIndexParams struct { ··· 884 SubscribedLabels map[string]struct{} 885 ShouldSubscribeAll bool 886 Active string 887 - Tabs []map[string]any 888 Tab string 889 Branches []types.Branch 890 } ··· 898 LoggedInUser *oauth.User 899 RepoInfo repoinfo.RepoInfo 900 Active string 901 - Tabs []map[string]any 902 Tab string 903 Collaborators []Collaborator 904 } ··· 912 LoggedInUser *oauth.User 913 RepoInfo repoinfo.RepoInfo 914 Active string 915 - Tabs []map[string]any 916 Tab string 917 Spindles []string 918 CurrentSpindle string ··· 950 Backlinks []models.RichReferenceLink 951 LabelDefs map[string]*models.LabelDefinition 952 953 - OrderedReactionKinds []models.ReactionKind 954 - Reactions map[models.ReactionKind]models.ReactionDisplayData 955 - UserReacted map[models.ReactionKind]bool 956 } 957 958 func (p *Pages) RepoSingleIssue(w io.Writer, params RepoSingleIssueParams) error { ··· 1107 ResubmitCheck ResubmitResult 1108 Pipelines map[string]models.Pipeline 1109 1110 - OrderedReactionKinds []models.ReactionKind 1111 - Reactions map[models.ReactionKind]models.ReactionDisplayData 1112 - UserReacted map[models.ReactionKind]bool 1113 1114 LabelDefs map[string]*models.LabelDefinition 1115 } ··· 1120 } 1121 1122 type RepoPullPatchParams struct { 1123 - LoggedInUser *oauth.User 1124 - RepoInfo repoinfo.RepoInfo 1125 - Pull *models.Pull 1126 - Stack models.Stack 1127 - Diff *types.NiceDiff 1128 - Round int 1129 - Submission *models.PullSubmission 1130 - OrderedReactionKinds []models.ReactionKind 1131 - DiffOpts types.DiffOpts 1132 } 1133 1134 // this name is a mouthful ··· 1137 } 1138 1139 type RepoPullInterdiffParams struct { 1140 - LoggedInUser *oauth.User 1141 - RepoInfo repoinfo.RepoInfo 1142 - Pull *models.Pull 1143 - Round int 1144 - Interdiff *patchutil.InterdiffResult 1145 - OrderedReactionKinds []models.ReactionKind 1146 - DiffOpts types.DiffOpts 1147 } 1148 1149 // this name is a mouthful
··· 336 337 type UserProfileSettingsParams struct { 338 LoggedInUser *oauth.User 339 Tab string 340 } 341 ··· 374 type UserKeysSettingsParams struct { 375 LoggedInUser *oauth.User 376 PubKeys []models.PublicKey 377 Tab string 378 } 379 ··· 384 type UserEmailsSettingsParams struct { 385 LoggedInUser *oauth.User 386 Emails []models.Email 387 Tab string 388 } 389 ··· 394 type UserNotificationSettingsParams struct { 395 LoggedInUser *oauth.User 396 Preferences *models.NotificationPreferences 397 Tab string 398 } 399 ··· 413 type KnotsParams struct { 414 LoggedInUser *oauth.User 415 Registrations []models.Registration 416 Tab string 417 } 418 ··· 426 Members []string 427 Repos map[string][]models.Repo 428 IsOwner bool 429 Tab string 430 } 431 ··· 444 type SpindlesParams struct { 445 LoggedInUser *oauth.User 446 Spindles []models.Spindle 447 Tab string 448 } 449 ··· 453 454 type SpindleListingParams struct { 455 models.Spindle 456 + Tab string 457 } 458 459 func (p *Pages) SpindleListing(w io.Writer, params SpindleListingParams) error { ··· 465 Spindle models.Spindle 466 Members []string 467 Repos map[string][]models.Repo 468 Tab string 469 } 470 ··· 603 } 604 605 type FollowFragmentParams struct { 606 + UserDid string 607 + FollowStatus models.FollowStatus 608 } 609 610 func (p *Pages) FollowFragment(w io.Writer, params FollowFragmentParams) error { 611 + return p.executePlain("user/fragments/follow", w, params) 612 } 613 614 type EditBioParams struct { ··· 639 IsStarred bool 640 SubjectAt syntax.ATURI 641 StarCount int 642 } 643 644 func (p *Pages) StarBtnFragment(w io.Writer, params StarBtnFragmentParams) error { 645 + return p.executePlain("fragments/starBtn-oob", w, params) 646 } 647 648 type RepoIndexParams struct { ··· 872 SubscribedLabels map[string]struct{} 873 ShouldSubscribeAll bool 874 Active string 875 Tab string 876 Branches []types.Branch 877 } ··· 885 LoggedInUser *oauth.User 886 RepoInfo repoinfo.RepoInfo 887 Active string 888 Tab string 889 Collaborators []Collaborator 890 } ··· 898 LoggedInUser *oauth.User 899 RepoInfo repoinfo.RepoInfo 900 Active string 901 Tab string 902 Spindles []string 903 CurrentSpindle string ··· 935 Backlinks []models.RichReferenceLink 936 LabelDefs map[string]*models.LabelDefinition 937 938 + Reactions map[models.ReactionKind]models.ReactionDisplayData 939 + UserReacted map[models.ReactionKind]bool 940 } 941 942 func (p *Pages) RepoSingleIssue(w io.Writer, params RepoSingleIssueParams) error { ··· 1091 ResubmitCheck ResubmitResult 1092 Pipelines map[string]models.Pipeline 1093 1094 + Reactions map[models.ReactionKind]models.ReactionDisplayData 1095 + UserReacted map[models.ReactionKind]bool 1096 1097 LabelDefs map[string]*models.LabelDefinition 1098 } ··· 1103 } 1104 1105 type RepoPullPatchParams struct { 1106 + LoggedInUser *oauth.User 1107 + RepoInfo repoinfo.RepoInfo 1108 + Pull *models.Pull 1109 + Stack models.Stack 1110 + Diff *types.NiceDiff 1111 + Round int 1112 + Submission *models.PullSubmission 1113 + DiffOpts types.DiffOpts 1114 } 1115 1116 // this name is a mouthful ··· 1119 } 1120 1121 type RepoPullInterdiffParams struct { 1122 + LoggedInUser *oauth.User 1123 + RepoInfo repoinfo.RepoInfo 1124 + Pull *models.Pull 1125 + Round int 1126 + Interdiff *patchutil.InterdiffResult 1127 + DiffOpts types.DiffOpts 1128 } 1129 1130 // this name is a mouthful
+5
appview/pages/templates/fragments/starBtn-oob.html
···
··· 1 + {{ define "fragments/starBtn-oob" }} 2 + <div hx-swap-oob='outerHTML:#starBtn[data-star-subject-at="{{ .SubjectAt }}"]'> 3 + {{ template "fragments/starBtn" . }} 4 + </div> 5 + {{ end }}
-1
appview/pages/templates/fragments/starBtn.html
··· 9 {{ else }} 10 hx-post="/star?subject={{ .SubjectAt }}&countHint={{ .StarCount }}" 11 {{ end }} 12 - {{ if .HxSwapOob }}hx-swap-oob='outerHTML:#starBtn[data-star-subject-at="{{ .SubjectAt }}"]'{{ end }} 13 14 hx-trigger="click" 15 hx-disabled-elt="#starBtn"
··· 9 {{ else }} 10 hx-post="/star?subject={{ .SubjectAt }}&countHint={{ .StarCount }}" 11 {{ end }} 12 13 hx-trigger="click" 14 hx-disabled-elt="#starBtn"
+2 -2
appview/pages/templates/layouts/fragments/footer.html
··· 47 48 <!-- Right section --> 49 <div class="text-right"> 50 - <div class="text-xs">&copy; 2026 Tangled Labs Oy. All rights reserved.</div> 51 </div> 52 </div> 53 ··· 93 </div> 94 95 <div class="text-center"> 96 - <div class="text-xs">&copy; 2026 Tangled Labs Oy. All rights reserved.</div> 97 </div> 98 </div> 99 </div>
··· 47 48 <!-- Right section --> 49 <div class="text-right"> 50 + <div class="text-xs">&copy; 2025 Tangled Labs Oy. All rights reserved.</div> 51 </div> 52 </div> 53 ··· 93 </div> 94 95 <div class="text-center"> 96 + <div class="text-xs">&copy; 2025 Tangled Labs Oy. All rights reserved.</div> 97 </div> 98 </div> 99 </div>
+50
appview/pages/templates/repo/fragments/reactions.html
···
··· 1 + {{ define "repo/fragments/reactions" }} 2 + <div class="flex flex-wrap items-center gap-2"> 3 + {{- $reactions := .Reactions -}} 4 + {{- $userReacted := .UserReacted -}} 5 + {{- $threadAt := .ThreadAt -}} 6 + 7 + {{ template "reactionsPopup" }} 8 + {{ range $kind := const.OrderedReactionKinds }} 9 + {{ $reactionData := index $reactions $kind }} 10 + {{ template "repo/fragments/reaction" 11 + (dict 12 + "Kind" $kind 13 + "Count" $reactionData.Count 14 + "IsReacted" (index $userReacted $kind) 15 + "ThreadAt" $threadAt 16 + "Users" $reactionData.Users) }} 17 + {{ end }} 18 + </div> 19 + {{ end }} 20 + 21 + {{ define "reactionsPopup" }} 22 + <details 23 + id="reactionsPopUp" 24 + class="relative inline-block" 25 + > 26 + <summary 27 + class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700 28 + hover:bg-gray-50 29 + hover:border-gray-300 30 + dark:hover:bg-gray-700 31 + dark:hover:border-gray-600 32 + cursor-pointer list-none" 33 + > 34 + {{ i "smile" "size-4" }} 35 + </summary> 36 + <div 37 + class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg" 38 + > 39 + {{ range $kind := const.OrderedReactionKinds }} 40 + <button 41 + id="reactBtn-{{ $kind }}" 42 + class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700" 43 + hx-on:click="this.parentElement.parentElement.removeAttribute('open')" 44 + > 45 + {{ $kind }} 46 + </button> 47 + {{ end }} 48 + </div> 49 + </details> 50 + {{ end }}
-30
appview/pages/templates/repo/fragments/reactionsPopUp.html
··· 1 - {{ define "repo/fragments/reactionsPopUp" }} 2 - <details 3 - id="reactionsPopUp" 4 - class="relative inline-block" 5 - > 6 - <summary 7 - class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700 8 - hover:bg-gray-50 9 - hover:border-gray-300 10 - dark:hover:bg-gray-700 11 - dark:hover:border-gray-600 12 - cursor-pointer list-none" 13 - > 14 - {{ i "smile" "size-4" }} 15 - </summary> 16 - <div 17 - class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg" 18 - > 19 - {{ range $kind := . }} 20 - <button 21 - id="reactBtn-{{ $kind }}" 22 - class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700" 23 - hx-on:click="this.parentElement.parentElement.removeAttribute('open')" 24 - > 25 - {{ $kind }} 26 - </button> 27 - {{ end }} 28 - </div> 29 - </details> 30 - {{ end }}
···
+5 -21
appview/pages/templates/repo/issues/issue.html
··· 35 {{ if .Issue.Body }} 36 <article id="body" class="mt-4 prose dark:prose-invert">{{ .Issue.Body | markdown }}</article> 37 {{ end }} 38 - <div class="flex flex-wrap gap-2 items-stretch mt-4"> 39 - {{ template "issueReactions" . }} 40 </div> 41 </section> 42 {{ end }} ··· 106 {{ i "loader-circle" "size-3 animate-spin hidden group-[.htmx-request]:inline" }} 107 </a> 108 {{ end }} 109 - 110 - {{ define "issueReactions" }} 111 - <div class="flex items-center gap-2"> 112 - {{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }} 113 - {{ range $kind := .OrderedReactionKinds }} 114 - {{ $reactionData := index $.Reactions $kind }} 115 - {{ 116 - template "repo/fragments/reaction" 117 - (dict 118 - "Kind" $kind 119 - "Count" $reactionData.Count 120 - "IsReacted" (index $.UserReacted $kind) 121 - "ThreadAt" $.Issue.AtUri 122 - "Users" $reactionData.Users) 123 - }} 124 - {{ end }} 125 - </div> 126 - {{ end }} 127 - 128 129 {{ define "repoAfter" }} 130 <div class="flex flex-col gap-4 mt-4">
··· 35 {{ if .Issue.Body }} 36 <article id="body" class="mt-4 prose dark:prose-invert">{{ .Issue.Body | markdown }}</article> 37 {{ end }} 38 + <div class="mt-4"> 39 + {{ template "repo/fragments/reactions" 40 + (dict "Reactions" .Reactions 41 + "UserReacted" .UserReacted 42 + "ThreadAt" .Issue.AtUri) }} 43 </div> 44 </section> 45 {{ end }} ··· 109 {{ i "loader-circle" "size-3 animate-spin hidden group-[.htmx-request]:inline" }} 110 </a> 111 {{ end }} 112 113 {{ define "repoAfter" }} 114 <div class="flex flex-col gap-4 mt-4">
+5 -16
appview/pages/templates/repo/pulls/fragments/pullHeader.html
··· 64 </article> 65 {{ end }} 66 67 - {{ with .OrderedReactionKinds }} 68 - <div class="flex items-center gap-2 mt-2"> 69 - {{ template "repo/fragments/reactionsPopUp" . }} 70 - {{ range $kind := . }} 71 - {{ $reactionData := index $.Reactions $kind }} 72 - {{ 73 - template "repo/fragments/reaction" 74 - (dict 75 - "Kind" $kind 76 - "Count" $reactionData.Count 77 - "IsReacted" (index $.UserReacted $kind) 78 - "ThreadAt" $.Pull.AtUri 79 - "Users" $reactionData.Users) 80 - }} 81 - {{ end }} 82 </div> 83 - {{ end }} 84 </section> 85 86
··· 64 </article> 65 {{ end }} 66 67 + <div class="mt-2"> 68 + {{ template "repo/fragments/reactions" 69 + (dict "Reactions" .Reactions 70 + "UserReacted" .UserReacted 71 + "ThreadAt" .Pull.AtUri) }} 72 </div> 73 </section> 74 75
+1 -2
appview/pages/templates/repo/settings/fragments/sidebar.html
··· 1 {{ define "repo/settings/fragments/sidebar" }} 2 {{ $active := .Tab }} 3 - {{ $tabs := .Tabs }} 4 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 5 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 6 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 7 - {{ range $tabs }} 8 <a href="/{{ $.RepoInfo.FullName }}/settings?tab={{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 9 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 10 {{ i .Icon "size-4" }}
··· 1 {{ define "repo/settings/fragments/sidebar" }} 2 {{ $active := .Tab }} 3 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 4 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 5 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 6 + {{ range const.RepoSettingsTabs }} 7 <a href="/{{ $.RepoInfo.FullName }}/settings?tab={{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 8 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 9 {{ i .Icon "size-4" }}
-6
appview/pages/templates/user/fragments/follow-oob.html
··· 1 - {{ define "user/fragments/follow-oob" }} 2 - {{ template "user/fragments/follow" . }} 3 - <span hx-swap-oob='innerHTML:[data-followers-did="{{ .UserDid }}"]'> 4 - <a href="/{{ resolve .UserDid }}?tab=followers">{{ .FollowersCount }} followers</a> 5 - </span> 6 - {{ end }}
···
+3 -5
appview/pages/templates/user/fragments/followCard.html
··· 9 <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-2 w-full min-w-0"> 10 <div class="flex-1 min-h-0 justify-around flex flex-col"> 11 <a href="/{{ $userIdent }}"> 12 - <span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ 13 - $userIdent | truncateAt30 }}</span> 14 </a> 15 {{ with .Profile }} 16 <p class="text-sm pb-2 md:pb-2 break-words">{{.Description}}</p> 17 {{ end }} 18 <div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 19 <span class="flex-shrink-0">{{ i "users" "size-4" }}</span> 20 - <span id="followers" data-followers-did="{{ .UserDid }}"><a href="/{{ $userIdent }}?tab=followers">{{ 21 - .FollowersCount }} followers</a></span> 22 <span class="select-none after:content-['ยท']"></span> 23 <span id="following"><a href="/{{ $userIdent }}?tab=following">{{ .FollowingCount }} following</a></span> 24 </div> ··· 31 </div> 32 </div> 33 </div> 34 - {{ end }}
··· 9 <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-2 w-full min-w-0"> 10 <div class="flex-1 min-h-0 justify-around flex flex-col"> 11 <a href="/{{ $userIdent }}"> 12 + <span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $userIdent | truncateAt30 }}</span> 13 </a> 14 {{ with .Profile }} 15 <p class="text-sm pb-2 md:pb-2 break-words">{{.Description}}</p> 16 {{ end }} 17 <div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 18 <span class="flex-shrink-0">{{ i "users" "size-4" }}</span> 19 + <span id="followers"><a href="/{{ $userIdent }}?tab=followers">{{ .FollowersCount }} followers</a></span> 20 <span class="select-none after:content-['ยท']"></span> 21 <span id="following"><a href="/{{ $userIdent }}?tab=following">{{ .FollowingCount }} following</a></span> 22 </div> ··· 29 </div> 30 </div> 31 </div> 32 + {{ end }}
+99 -97
appview/pages/templates/user/fragments/profileCard.html
··· 1 {{ define "user/fragments/profileCard" }} 2 - {{ $userIdent := resolve .UserDid }} 3 - <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 - <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 - <div class="w-3/4 aspect-square relative"> 6 - <img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" /> 7 - </div> 8 - </div> 9 - <div class="col-span-2"> 10 - <div class="flex items-center flex-row flex-nowrap gap-2"> 11 - <p title="{{ $userIdent }}" 12 - class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap"> 13 - {{ $userIdent }} 14 - </p> 15 - {{ with .Profile }} 16 - {{ if .Pronouns }} 17 - <p class="text-gray-500 dark:text-gray-400">{{ .Pronouns }}</p> 18 - {{ end }} 19 - {{ end }} 20 - </div> 21 22 - <div class="md:hidden"> 23 - {{ block "followerFollowing" (list . $userIdent) }} {{ end }} 24 - </div> 25 - </div> 26 - <div class="col-span-3 md:col-span-full"> 27 - <div id="profile-bio" class="text-sm"> 28 - {{ $profile := .Profile }} 29 - {{ with .Profile }} 30 31 - {{ if .Description }} 32 - <p class="text-base pb-4 md:pb-2">{{ .Description }}</p> 33 - {{ end }} 34 35 - <div class="hidden md:block"> 36 - {{ block "followerFollowing" (list $ $userIdent) }} {{ end }} 37 - </div> 38 39 - <div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 40 - {{ if .Location }} 41 - <div class="flex items-center gap-2"> 42 - <span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span> 43 - <span>{{ .Location }}</span> 44 - </div> 45 - {{ end }} 46 - {{ if .IncludeBluesky }} 47 - <div class="flex items-center gap-2"> 48 - <span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" 49 - }}</span> 50 - <a id="bluesky-link" href="https://bsky.app/profile/{{ $.UserDid }}">{{ $userIdent }}</a> 51 - </div> 52 - {{ end }} 53 - {{ range $link := .Links }} 54 - {{ if $link }} 55 - <div class="flex items-center gap-2"> 56 - <span class="flex-shrink-0">{{ i "link" "size-4" }}</span> 57 - <a href="{{ $link }}">{{ $link }}</a> 58 - </div> 59 - {{ end }} 60 - {{ end }} 61 - {{ if not $profile.IsStatsEmpty }} 62 - <div class="flex items-center justify-evenly gap-2 py-2"> 63 - {{ range $stat := .Stats }} 64 - {{ if $stat.Kind }} 65 - <div class="flex flex-col items-center gap-2"> 66 - <span class="text-xl font-bold">{{ $stat.Value }}</span> 67 - <span>{{ $stat.Kind.String }}</span> 68 </div> 69 {{ end }} 70 - {{ end }} 71 - </div> 72 - {{ end }} 73 - </div> 74 - {{ end }} 75 76 - <div class="flex mt-2 items-center gap-2"> 77 - {{ if ne .FollowStatus.String "IsSelf" }} 78 - {{ template "user/fragments/follow" . }} 79 - {{ else }} 80 - <button id="editBtn" class="btn w-full flex items-center gap-2 group" hx-target="#profile-bio" 81 - hx-get="/profile/edit-bio" hx-swap="innerHTML"> 82 - {{ i "pencil" "w-4 h-4" }} 83 - edit 84 - {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 85 - </button> 86 - {{ end }} 87 88 - <a class="btn text-sm no-underline hover:no-underline flex items-center gap-2 group" 89 - href="/{{ $userIdent }}/feed.atom"> 90 - {{ i "rss" "size-4" }} 91 - </a> 92 - </div> 93 94 </div> 95 - <div id="update-profile" class="text-red-400 dark:text-red-500"></div> 96 - </div> 97 - </div> 98 {{ end }} 99 100 {{ define "followerFollowing" }} 101 - {{ $root := index . 0 }} 102 - {{ $userIdent := index . 1 }} 103 - {{ with $root }} 104 - <div class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm"> 105 - <span class="flex-shrink-0">{{ i "users" "size-4" }}</span> 106 - <span id="followers" data-followers-did="{{ .UserDid }}"><a href="/{{ $userIdent }}?tab=followers">{{ 107 - .Stats.FollowersCount }} followers</a></span> 108 - <span class="select-none after:content-['ยท']"></span> 109 - <span id="following"><a href="/{{ $userIdent }}?tab=following">{{ .Stats.FollowingCount }} following</a></span> 110 - </div> 111 {{ end }} 112 - {{ end }}
··· 1 {{ define "user/fragments/profileCard" }} 2 + {{ $userIdent := resolve .UserDid }} 3 + <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 + <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 + <div class="w-3/4 aspect-square relative"> 6 + <img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" /> 7 + </div> 8 + </div> 9 + <div class="col-span-2"> 10 + <div class="flex items-center flex-row flex-nowrap gap-2"> 11 + <p title="{{ $userIdent }}" 12 + class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap"> 13 + {{ $userIdent }} 14 + </p> 15 + {{ with .Profile }} 16 + {{ if .Pronouns }} 17 + <p class="text-gray-500 dark:text-gray-400">{{ .Pronouns }}</p> 18 + {{ end }} 19 + {{ end }} 20 + </div> 21 22 + <div class="md:hidden"> 23 + {{ block "followerFollowing" (list . $userIdent) }} {{ end }} 24 + </div> 25 + </div> 26 + <div class="col-span-3 md:col-span-full"> 27 + <div id="profile-bio" class="text-sm"> 28 + {{ $profile := .Profile }} 29 + {{ with .Profile }} 30 31 + {{ if .Description }} 32 + <p class="text-base pb-4 md:pb-2">{{ .Description }}</p> 33 + {{ end }} 34 35 + <div class="hidden md:block"> 36 + {{ block "followerFollowing" (list $ $userIdent) }} {{ end }} 37 + </div> 38 39 + <div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 40 + {{ if .Location }} 41 + <div class="flex items-center gap-2"> 42 + <span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span> 43 + <span>{{ .Location }}</span> 44 + </div> 45 + {{ end }} 46 + {{ if .IncludeBluesky }} 47 + <div class="flex items-center gap-2"> 48 + <span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}</span> 49 + <a id="bluesky-link" href="https://bsky.app/profile/{{ $.UserDid }}">{{ $userIdent }}</a> 50 + </div> 51 + {{ end }} 52 + {{ range $link := .Links }} 53 + {{ if $link }} 54 + <div class="flex items-center gap-2"> 55 + <span class="flex-shrink-0">{{ i "link" "size-4" }}</span> 56 + <a href="{{ $link }}">{{ $link }}</a> 57 + </div> 58 + {{ end }} 59 + {{ end }} 60 + {{ if not $profile.IsStatsEmpty }} 61 + <div class="flex items-center justify-evenly gap-2 py-2"> 62 + {{ range $stat := .Stats }} 63 + {{ if $stat.Kind }} 64 + <div class="flex flex-col items-center gap-2"> 65 + <span class="text-xl font-bold">{{ $stat.Value }}</span> 66 + <span>{{ $stat.Kind.String }}</span> 67 + </div> 68 + {{ end }} 69 + {{ end }} 70 + </div> 71 + {{ end }} 72 </div> 73 {{ end }} 74 75 + <div class="flex mt-2 items-center gap-2"> 76 + {{ if ne .FollowStatus.String "IsSelf" }} 77 + {{ template "user/fragments/follow" . }} 78 + {{ else }} 79 + <button id="editBtn" 80 + class="btn w-full flex items-center gap-2 group" 81 + hx-target="#profile-bio" 82 + hx-get="/profile/edit-bio" 83 + hx-swap="innerHTML"> 84 + {{ i "pencil" "w-4 h-4" }} 85 + edit 86 + {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 87 + </button> 88 + {{ end }} 89 90 + <a class="btn text-sm no-underline hover:no-underline flex items-center gap-2 group" 91 + href="/{{ $userIdent }}/feed.atom"> 92 + {{ i "rss" "size-4" }} 93 + </a> 94 + </div> 95 96 + </div> 97 + <div id="update-profile" class="text-red-400 dark:text-red-500"></div> 98 + </div> 99 </div> 100 {{ end }} 101 102 {{ define "followerFollowing" }} 103 + {{ $root := index . 0 }} 104 + {{ $userIdent := index . 1 }} 105 + {{ with $root }} 106 + <div class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm"> 107 + <span class="flex-shrink-0">{{ i "users" "size-4" }}</span> 108 + <span id="followers"><a href="/{{ $userIdent }}?tab=followers">{{ .Stats.FollowersCount }} followers</a></span> 109 + <span class="select-none after:content-['ยท']"></span> 110 + <span id="following"><a href="/{{ $userIdent }}?tab=following">{{ .Stats.FollowingCount }} following</a></span> 111 + </div> 112 + {{ end }} 113 {{ end }} 114 +
+2 -3
appview/pages/templates/user/settings/fragments/sidebar.html
··· 1 {{ define "user/settings/fragments/sidebar" }} 2 {{ $active := .Tab }} 3 - {{ $tabs := .Tabs }} 4 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 5 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 6 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 7 - {{ range $tabs }} 8 <a href="/settings/{{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 9 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 10 {{ i .Icon "size-4" }} ··· 13 </a> 14 {{ end }} 15 </div> 16 - {{ end }}
··· 1 {{ define "user/settings/fragments/sidebar" }} 2 {{ $active := .Tab }} 3 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 4 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 5 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 6 + {{ range const.UserSettingsTabs }} 7 <a href="/settings/{{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 8 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 9 {{ i .Icon "size-4" }} ··· 12 </a> 13 {{ end }} 14 </div> 15 + {{ end }}
+7 -19
appview/pulls/pulls.go
··· 1 package pulls 2 3 import ( 4 - "bytes" 5 - "compress/gzip" 6 "context" 7 "database/sql" 8 "encoding/json" 9 "errors" 10 "fmt" 11 - "io" 12 "log" 13 "log/slog" 14 "net/http" ··· 247 ResubmitCheck: resubmitResult, 248 Pipelines: m, 249 250 - OrderedReactionKinds: models.OrderedReactionKinds, 251 - Reactions: reactionMap, 252 - UserReacted: userReactions, 253 254 LabelDefs: defs, 255 }) ··· 1244 return 1245 } 1246 1247 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 1248 if err != nil { 1249 log.Println("failed to upload patch", err) 1250 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1338 // apply all record creations at once 1339 var writes []*comatproto.RepoApplyWrites_Input_Writes_Elem 1340 for _, p := range stack { 1341 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(p.LatestPatch())) 1342 if err != nil { 1343 log.Println("failed to upload patch blob", err) 1344 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1888 return 1889 } 1890 1891 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 1892 if err != nil { 1893 log.Println("failed to upload patch blob", err) 1894 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2030 return 2031 } 2032 2033 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 2034 if err != nil { 2035 log.Println("failed to upload patch blob", err) 2036 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2072 return 2073 } 2074 2075 - blob, err := comatproto.RepoUploadBlob(r.Context(), client, gz(patch)) 2076 if err != nil { 2077 log.Println("failed to upload patch blob", err) 2078 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2455 2456 return stack, nil 2457 } 2458 - 2459 - func gz(s string) io.Reader { 2460 - var b bytes.Buffer 2461 - w := gzip.NewWriter(&b) 2462 - w.Write([]byte(s)) 2463 - w.Close() 2464 - return &b 2465 - }
··· 1 package pulls 2 3 import ( 4 "context" 5 "database/sql" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "log" 10 "log/slog" 11 "net/http" ··· 244 ResubmitCheck: resubmitResult, 245 Pipelines: m, 246 247 + Reactions: reactionMap, 248 + UserReacted: userReactions, 249 250 LabelDefs: defs, 251 }) ··· 1240 return 1241 } 1242 1243 + blob, err := comatproto.RepoUploadBlob(r.Context(), client, strings.NewReader(patch)) 1244 if err != nil { 1245 log.Println("failed to upload patch", err) 1246 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1334 // apply all record creations at once 1335 var writes []*comatproto.RepoApplyWrites_Input_Writes_Elem 1336 for _, p := range stack { 1337 + blob, err := comatproto.RepoUploadBlob(r.Context(), client, strings.NewReader(p.LatestPatch())) 1338 if err != nil { 1339 log.Println("failed to upload patch blob", err) 1340 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") ··· 1884 return 1885 } 1886 1887 + blob, err := comatproto.RepoUploadBlob(r.Context(), client, strings.NewReader(patch)) 1888 if err != nil { 1889 log.Println("failed to upload patch blob", err) 1890 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2026 return 2027 } 2028 2029 + blob, err := comatproto.RepoUploadBlob(r.Context(), client, strings.NewReader(patch)) 2030 if err != nil { 2031 log.Println("failed to upload patch blob", err) 2032 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2068 return 2069 } 2070 2071 + blob, err := comatproto.RepoUploadBlob(r.Context(), client, strings.NewReader(patch)) 2072 if err != nil { 2073 log.Println("failed to upload patch blob", err) 2074 s.pages.Notice(w, "resubmit-error", "Failed to update pull request on the PDS. Try again later.") ··· 2451 2452 return stack, nil 2453 }
-14
appview/repo/settings.go
··· 22 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 23 ) 24 25 - type tab = map[string]any 26 - 27 - var ( 28 - // would be great to have ordered maps right about now 29 - settingsTabs []tab = []tab{ 30 - {"Name": "general", "Icon": "sliders-horizontal"}, 31 - {"Name": "access", "Icon": "users"}, 32 - {"Name": "pipelines", "Icon": "layers-2"}, 33 - } 34 - ) 35 - 36 func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { 37 l := rp.logger.With("handler", "SetDefaultBranch") 38 ··· 262 DefaultLabels: defaultLabels, 263 SubscribedLabels: subscribedLabels, 264 ShouldSubscribeAll: shouldSubscribeAll, 265 - Tabs: settingsTabs, 266 Tab: "general", 267 }) 268 } ··· 308 rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{ 309 LoggedInUser: user, 310 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 311 - Tabs: settingsTabs, 312 Tab: "access", 313 Collaborators: collaborators, 314 }) ··· 369 rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{ 370 LoggedInUser: user, 371 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 372 - Tabs: settingsTabs, 373 Tab: "pipelines", 374 Spindles: spindles, 375 CurrentSpindle: f.Spindle,
··· 22 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 23 ) 24 25 func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { 26 l := rp.logger.With("handler", "SetDefaultBranch") 27 ··· 251 DefaultLabels: defaultLabels, 252 SubscribedLabels: subscribedLabels, 253 ShouldSubscribeAll: shouldSubscribeAll, 254 Tab: "general", 255 }) 256 } ··· 296 rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{ 297 LoggedInUser: user, 298 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 299 Tab: "access", 300 Collaborators: collaborators, 301 }) ··· 356 rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{ 357 LoggedInUser: user, 358 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 359 Tab: "pipelines", 360 Spindles: spindles, 361 CurrentSpindle: f.Spindle,
-17
appview/settings/settings.go
··· 35 Config *config.Config 36 } 37 38 - type tab = map[string]any 39 - 40 - var ( 41 - settingsTabs []tab = []tab{ 42 - {"Name": "profile", "Icon": "user"}, 43 - {"Name": "keys", "Icon": "key"}, 44 - {"Name": "emails", "Icon": "mail"}, 45 - {"Name": "notifications", "Icon": "bell"}, 46 - {"Name": "knots", "Icon": "volleyball"}, 47 - {"Name": "spindles", "Icon": "spool"}, 48 - } 49 - ) 50 - 51 func (s *Settings) Router() http.Handler { 52 r := chi.NewRouter() 53 ··· 85 86 s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{ 87 LoggedInUser: user, 88 - Tabs: settingsTabs, 89 Tab: "profile", 90 }) 91 } ··· 104 s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{ 105 LoggedInUser: user, 106 Preferences: prefs, 107 - Tabs: settingsTabs, 108 Tab: "notifications", 109 }) 110 } ··· 146 s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{ 147 LoggedInUser: user, 148 PubKeys: pubKeys, 149 - Tabs: settingsTabs, 150 Tab: "keys", 151 }) 152 } ··· 161 s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{ 162 LoggedInUser: user, 163 Emails: emails, 164 - Tabs: settingsTabs, 165 Tab: "emails", 166 }) 167 }
··· 35 Config *config.Config 36 } 37 38 func (s *Settings) Router() http.Handler { 39 r := chi.NewRouter() 40 ··· 72 73 s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{ 74 LoggedInUser: user, 75 Tab: "profile", 76 }) 77 } ··· 90 s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{ 91 LoggedInUser: user, 92 Preferences: prefs, 93 Tab: "notifications", 94 }) 95 } ··· 131 s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{ 132 LoggedInUser: user, 133 PubKeys: pubKeys, 134 Tab: "keys", 135 }) 136 } ··· 145 s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{ 146 LoggedInUser: user, 147 Emails: emails, 148 Tab: "emails", 149 }) 150 }
-15
appview/spindles/spindles.go
··· 39 Logger *slog.Logger 40 } 41 42 - type tab = map[string]any 43 - 44 - var ( 45 - spindlesTabs []tab = []tab{ 46 - {"Name": "profile", "Icon": "user"}, 47 - {"Name": "keys", "Icon": "key"}, 48 - {"Name": "emails", "Icon": "mail"}, 49 - {"Name": "notifications", "Icon": "bell"}, 50 - {"Name": "knots", "Icon": "volleyball"}, 51 - {"Name": "spindles", "Icon": "spool"}, 52 - } 53 - ) 54 - 55 func (s *Spindles) Router() http.Handler { 56 r := chi.NewRouter() 57 ··· 83 s.Pages.Spindles(w, pages.SpindlesParams{ 84 LoggedInUser: user, 85 Spindles: all, 86 - Tabs: spindlesTabs, 87 Tab: "spindles", 88 }) 89 } ··· 143 Spindle: spindle, 144 Members: members, 145 Repos: repoMap, 146 - Tabs: spindlesTabs, 147 Tab: "spindles", 148 }) 149 }
··· 39 Logger *slog.Logger 40 } 41 42 func (s *Spindles) Router() http.Handler { 43 r := chi.NewRouter() 44 ··· 70 s.Pages.Spindles(w, pages.SpindlesParams{ 71 LoggedInUser: user, 72 Spindles: all, 73 Tab: "spindles", 74 }) 75 } ··· 129 Spindle: spindle, 130 Members: members, 131 Repos: repoMap, 132 Tab: "spindles", 133 }) 134 }
+4 -16
appview/state/follow.go
··· 75 76 s.notifier.NewFollow(r.Context(), follow) 77 78 - followStats, err := db.GetFollowerFollowingCount(s.db, subjectIdent.DID.String()) 79 - if err != nil { 80 - log.Println("failed to get follow stats", err) 81 - } 82 - 83 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 84 - UserDid: subjectIdent.DID.String(), 85 - FollowStatus: models.IsFollowing, 86 - FollowersCount: followStats.Followers, 87 }) 88 89 return ··· 112 // this is not an issue, the firehose event might have already done this 113 } 114 115 - followStats, err := db.GetFollowerFollowingCount(s.db, subjectIdent.DID.String()) 116 - if err != nil { 117 - log.Println("failed to get follow stats", err) 118 - } 119 - 120 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 121 - UserDid: subjectIdent.DID.String(), 122 - FollowStatus: models.IsNotFollowing, 123 - FollowersCount: followStats.Followers, 124 }) 125 126 s.notifier.DeleteFollow(r.Context(), follow)
··· 75 76 s.notifier.NewFollow(r.Context(), follow) 77 78 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 79 + UserDid: subjectIdent.DID.String(), 80 + FollowStatus: models.IsFollowing, 81 }) 82 83 return ··· 106 // this is not an issue, the firehose event might have already done this 107 } 108 109 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 110 + UserDid: subjectIdent.DID.String(), 111 + FollowStatus: models.IsNotFollowing, 112 }) 113 114 s.notifier.DeleteFollow(r.Context(), follow)
-3
docs/DOCS.md
··· 663 nixpkgs: 664 - nodejs 665 - go 666 - # unstable 667 - nixpkgs/nixpkgs-unstable: 668 - - bun 669 # custom registry 670 git+https://tangled.org/@example.com/my_pkg: 671 - my_pkg
··· 663 nixpkgs: 664 - nodejs 665 - go 666 # custom registry 667 git+https://tangled.org/@example.com/my_pkg: 668 - my_pkg
-4
input.css
··· 133 disabled:before:bg-green-400 dark:disabled:before:bg-green-600; 134 } 135 136 - .prose { 137 - overflow-wrap: anywhere; 138 - } 139 - 140 .prose hr { 141 @apply my-2; 142 }
··· 133 disabled:before:bg-green-400 dark:disabled:before:bg-green-600; 134 } 135 136 .prose hr { 137 @apply my-2; 138 }
-3
nix/modules/appview.nix
··· 1 { 2 - pkgs, 3 config, 4 lib, 5 ... ··· 260 after = ["redis-appview.service" "network-online.target"]; 261 requires = ["redis-appview.service"]; 262 wants = ["network-online.target"]; 263 - 264 - path = [pkgs.diffutils]; 265 266 serviceConfig = { 267 Type = "simple";
··· 1 { 2 config, 3 lib, 4 ... ··· 259 after = ["redis-appview.service" "network-online.target"]; 260 requires = ["redis-appview.service"]; 261 wants = ["network-online.target"]; 262 263 serviceConfig = { 264 Type = "simple";