Monorepo for Tangled tangled.org
2

Configure Feed

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

appview/pages: UI bits for focus mode

Signed-off-by: oppiliappan <me@oppi.li>

author
oppiliappan
committer
Tangled
date (Jun 15, 2026, 5:28 PM +0300) commit 5c97f1cc parent 778a7a5a change-id qlvkvttt
+396 -301
+5 -5
appview/issues/issues.go
··· 166 166 } 167 167 168 168 err = rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 169 - BaseParams: pages.BaseParamsFromContext(r.Context()), 169 + BaseParams: pages.BaseParamsFromContext(r.Context()), 170 170 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 171 171 Issue: issue, 172 172 CommentList: models.NewCommentList(issue.Comments), ··· 196 196 case http.MethodGet: 197 197 rp.pages.EditIssueFragment(w, pages.EditIssueParams{ 198 198 BaseParams: pages.BaseParamsFromContext(r.Context()), 199 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 200 - Issue: issue, 199 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 200 + Issue: issue, 201 201 }) 202 202 case http.MethodPost: 203 203 noticeId := "issues" ··· 632 632 } 633 633 baseFilterQuery := strings.Join(baseFilterParts, " ") 634 634 rp.pages.RepoIssues(w, pages.RepoIssuesParams{ 635 - BaseParams: pages.BaseParamsFromContext(r.Context()), 635 + BaseParams: pages.BaseParamsFromContext(r.Context()), 636 636 RepoInfo: repoInfo, 637 637 Issues: issues, 638 638 IssueCount: totalIssues, ··· 661 661 case http.MethodGet: 662 662 rp.pages.RepoNewIssue(w, pages.RepoNewIssueParams{ 663 663 BaseParams: pages.BaseParamsFromContext(r.Context()), 664 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 664 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 665 665 }) 666 666 case http.MethodPost: 667 667 body := r.FormValue("body")
+2 -2
appview/knots/knots.go
··· 90 90 91 91 k.Pages.Knots(w, pages.KnotsParams{ 92 92 BaseParams: pages.BaseParamsFromContext(r.Context()), 93 - Knots: knots, 93 + Knots: knots, 94 94 }) 95 95 } 96 96 ··· 141 141 } 142 142 143 143 k.Pages.Knot(w, pages.KnotParams{ 144 - BaseParams: pages.BaseParamsFromContext(r.Context()), 144 + BaseParams: pages.BaseParamsFromContext(r.Context()), 145 145 Registration: &registration, 146 146 Members: members, 147 147 Repos: repoMap,
+14 -2
appview/notifications/notifications.go
··· 152 152 l.Error("failed to count social unread", "err", err) 153 153 } 154 154 155 + focusCount, err := db.CountFocusNotifs(n.db, user.Did) 156 + if err != nil { 157 + l.Error("failed to count focus notifs", "err", err) 158 + } 159 + 155 160 err = n.pages.Notifications(w, pages.NotificationsParams{ 156 - BaseParams: pages.BaseParamsFromContext(r.Context()), 161 + BaseParams: pages.BaseParamsFromContext(r.Context()), 157 162 MobileGroups: pages.GroupNotificationsByDate(notifications), 158 163 WorkGroups: pages.GroupNotificationsByDate(workNotifications), 159 164 SocialGroups: pages.GroupNotificationsByDate(socialNotifications), ··· 163 168 Total: total, 164 169 ReadFilter: readFilter, 165 170 CategoryFilter: categoryFilter, 171 + CanFocus: focusCount > 1, 166 172 }) 167 173 if err != nil { 168 174 l.Error("failed to render page", "err", err) ··· 186 192 return 187 193 } 188 194 195 + focusCount, err := db.CountFocusNotifs(n.db, user.Did) 196 + if err != nil { 197 + l.Error("failed to count focus notifs", "err", err) 198 + } 199 + 189 200 err = n.pages.NotificationPreview(w, pages.NotificationPreviewParams{ 190 - BaseParams: pages.BaseParamsFromContext(r.Context()), 201 + BaseParams: pages.BaseParamsFromContext(r.Context()), 191 202 Notifications: notifications, 192 203 ReadFilter: readFilter, 193 204 CategoryFilter: categoryFilter, 205 + CanFocus: focusCount > 1, 194 206 }) 195 207 if err != nil { 196 208 l.Error("failed to render notification preview", "err", err)
+4
appview/pages/funcmap.go
··· 77 77 "resolve": func(s string) string { 78 78 return p.DisplayHandle(context.Background(), s) 79 79 }, 80 + "resolver": func() *idresolver.Resolver { 81 + return p.resolver 82 + }, 80 83 "primaryHandle": func(s string) string { 81 84 return primaryHandle(p.resolver, s) 82 85 }, ··· 383 386 // returns false for other "zero" values 384 387 return t == nil 385 388 }, 389 + "hasPrefix": strings.HasPrefix, 386 390 "list": func(args ...any) []any { 387 391 return args 388 392 },
+144 -132
appview/pages/pages.go
··· 42 42 43 43 type BaseParams struct { 44 44 LoggedInUser *oauth.MultiAccountUser 45 + FocusParams FocusParams 46 + } 47 + 48 + type FocusParams struct { 49 + Focusing bool 50 + FocusLink string 51 + FocusNotificationID int64 52 + CurrentPath string // r.URL.Path, for off-focus detection in templates 53 + FocusCount int // total unread focus-eligible items remaining 54 + } 55 + 56 + func (p *Pages) Resolver() *idresolver.Resolver { 57 + return p.resolver 45 58 } 46 59 47 60 func BaseParamsIntoContext(ctx context.Context, bp BaseParams) context.Context { ··· 384 397 385 398 type PrivacyPolicyParams struct { 386 399 BaseParams 387 - Content template.HTML 400 + Content template.HTML 388 401 } 389 402 390 403 func (p *Pages) PrivacyPolicy(w io.Writer, params PrivacyPolicyParams) error { ··· 458 471 459 472 type GoodFirstIssuesParams struct { 460 473 BaseParams 461 - Issues []models.Issue 462 - RepoGroups []*models.RepoGroup 463 - LabelDefs map[string]*models.LabelDefinition 464 - GfiLabel *models.LabelDefinition 465 - Page pagination.Page 474 + Issues []models.Issue 475 + RepoGroups []*models.RepoGroup 476 + LabelDefs map[string]*models.LabelDefinition 477 + GfiLabel *models.LabelDefinition 478 + Page pagination.Page 466 479 } 467 480 468 481 func (p *Pages) GoodFirstIssues(w io.Writer, params GoodFirstIssuesParams) error { ··· 550 563 return p.executePlain("notifications/fragments/preview", w, params) 551 564 } 552 565 553 - 554 566 type UserKeysSettingsParams struct { 555 567 BaseParams 556 - PubKeys []models.PublicKey 557 - Tab string 568 + PubKeys []models.PublicKey 569 + Tab string 558 570 } 559 571 560 572 func (p *Pages) UserKeysSettings(w io.Writer, params UserKeysSettingsParams) error { ··· 564 576 565 577 type UserEmailsSettingsParams struct { 566 578 BaseParams 567 - Emails []models.Email 568 - Tab string 579 + Emails []models.Email 580 + Tab string 569 581 } 570 582 571 583 func (p *Pages) UserEmailsSettings(w io.Writer, params UserEmailsSettingsParams) error { ··· 575 587 576 588 type UserNotificationSettingsParams struct { 577 589 BaseParams 578 - Preferences *models.NotificationPreferences 579 - Tab string 590 + Preferences *models.NotificationPreferences 591 + Tab string 580 592 } 581 593 582 594 func (p *Pages) UserNotificationSettings(w io.Writer, params UserNotificationSettingsParams) error { ··· 620 632 621 633 type KnotsParams struct { 622 634 BaseParams 623 - Knots []KnotListingParams 624 - Tab string 635 + Knots []KnotListingParams 636 + Tab string 625 637 } 626 638 627 639 func (p *Pages) Knots(w io.Writer, params KnotsParams) error { ··· 654 666 655 667 type SpindlesParams struct { 656 668 BaseParams 657 - Spindles []models.Spindle 658 - Tab string 669 + Spindles []models.Spindle 670 + Tab string 659 671 } 660 672 661 673 func (p *Pages) Spindles(w io.Writer, params SpindlesParams) error { ··· 674 686 675 687 type SpindleDashboardParams struct { 676 688 BaseParams 677 - Spindle models.Spindle 678 - Members []string 679 - Repos map[string][]models.Repo 680 - Tab string 689 + Spindle models.Spindle 690 + Members []string 691 + Repos map[string][]models.Repo 692 + Tab string 681 693 } 682 694 683 695 func (p *Pages) SpindleDashboard(w io.Writer, params SpindleDashboardParams) error { ··· 686 698 687 699 type NewRepoParams struct { 688 700 BaseParams 689 - Knots []string 701 + Knots []string 690 702 } 691 703 692 704 func (p *Pages) NewRepo(w io.Writer, params NewRepoParams) error { ··· 695 707 696 708 type ForkRepoParams struct { 697 709 BaseParams 698 - Knots []string 699 - RepoInfo repoinfo.RepoInfo 710 + Knots []string 711 + RepoInfo repoinfo.RepoInfo 700 712 } 701 713 702 714 func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error { ··· 767 779 768 780 type ProfileStarredParams struct { 769 781 BaseParams 770 - Repos []models.Repo 771 - Card *ProfileCard 772 - Page pagination.Page 773 - Total int 774 - Active string 782 + Repos []models.Repo 783 + Card *ProfileCard 784 + Page pagination.Page 785 + Total int 786 + Active string 775 787 } 776 788 777 789 func (p *Pages) ProfileStarred(w io.Writer, params ProfileStarredParams) error { ··· 781 793 782 794 type ProfileStringsParams struct { 783 795 BaseParams 784 - Strings []models.String 785 - Card *ProfileCard 786 - Active string 796 + Strings []models.String 797 + Card *ProfileCard 798 + Active string 787 799 } 788 800 789 801 func (p *Pages) ProfileStrings(w io.Writer, params ProfileStringsParams) error { ··· 809 821 } 810 822 811 823 type FollowCard struct { 812 - UserDid string 824 + UserDid string 813 825 BaseParams 814 826 FollowStatus models.FollowStatus 815 827 FollowersCount int64 ··· 819 831 820 832 type ProfileFollowersParams struct { 821 833 BaseParams 822 - Followers []FollowCard 823 - Card *ProfileCard 824 - Active string 834 + Followers []FollowCard 835 + Card *ProfileCard 836 + Active string 825 837 } 826 838 827 839 func (p *Pages) ProfileFollowers(w io.Writer, params ProfileFollowersParams) error { ··· 831 843 832 844 type ProfileFollowingParams struct { 833 845 BaseParams 834 - Following []FollowCard 835 - Card *ProfileCard 836 - Active string 846 + Following []FollowCard 847 + Card *ProfileCard 848 + Active string 837 849 } 838 850 839 851 func (p *Pages) ProfileFollowing(w io.Writer, params ProfileFollowingParams) error { ··· 871 883 872 884 type EditBioParams struct { 873 885 BaseParams 874 - Profile *models.Profile 875 - AlsoKnownAs []string 886 + Profile *models.Profile 887 + AlsoKnownAs []string 876 888 } 877 889 878 890 func (p *Pages) EditBioFragment(w io.Writer, params EditBioParams) error { ··· 881 893 882 894 type EditPinsParams struct { 883 895 BaseParams 884 - Profile *models.Profile 885 - AllRepos []PinnedRepo 896 + Profile *models.Profile 897 + AllRepos []PinnedRepo 886 898 } 887 899 888 900 type PinnedRepo struct { ··· 980 992 981 993 type RepoCommitParams struct { 982 994 BaseParams 983 - RepoInfo repoinfo.RepoInfo 984 - Active string 985 - EmailToDid map[string]string 986 - Pipeline *models.Pipeline 987 - DiffOpts types.DiffOpts 995 + RepoInfo repoinfo.RepoInfo 996 + Active string 997 + EmailToDid map[string]string 998 + Pipeline *models.Pipeline 999 + DiffOpts types.DiffOpts 988 1000 989 1001 // singular because it's always going to be just one 990 1002 VerifiedCommit commitverify.VerifiedCommits ··· 1061 1073 1062 1074 type RepoBranchesParams struct { 1063 1075 BaseParams 1064 - RepoInfo repoinfo.RepoInfo 1065 - Active string 1076 + RepoInfo repoinfo.RepoInfo 1077 + Active string 1066 1078 types.RepoBranchesResponse 1067 1079 } 1068 1080 ··· 1073 1085 1074 1086 type RepoTagsParams struct { 1075 1087 BaseParams 1076 - RepoInfo repoinfo.RepoInfo 1077 - Active string 1088 + RepoInfo repoinfo.RepoInfo 1089 + Active string 1078 1090 types.RepoTagsResponse 1079 1091 ArtifactMap map[plumbing.Hash][]models.Artifact 1080 1092 DanglingArtifacts []models.Artifact ··· 1087 1099 1088 1100 type RepoTagParams struct { 1089 1101 BaseParams 1090 - RepoInfo repoinfo.RepoInfo 1091 - Active string 1102 + RepoInfo repoinfo.RepoInfo 1103 + Active string 1092 1104 types.RepoTagResponse 1093 1105 ArtifactMap map[plumbing.Hash][]models.Artifact 1094 1106 DanglingArtifacts []models.Artifact ··· 1101 1113 1102 1114 type RepoArtifactParams struct { 1103 1115 BaseParams 1104 - RepoInfo repoinfo.RepoInfo 1105 - Artifact models.Artifact 1116 + RepoInfo repoinfo.RepoInfo 1117 + Artifact models.Artifact 1106 1118 } 1107 1119 1108 1120 func (p *Pages) RepoArtifactFragment(w io.Writer, params RepoArtifactParams) error { ··· 1217 1229 1218 1230 type WebhookDeliveriesListParams struct { 1219 1231 BaseParams 1220 - RepoInfo repoinfo.RepoInfo 1221 - Webhook *models.Webhook 1222 - Deliveries []models.WebhookDelivery 1232 + RepoInfo repoinfo.RepoInfo 1233 + Webhook *models.Webhook 1234 + Deliveries []models.WebhookDelivery 1223 1235 } 1224 1236 1225 1237 func (p *Pages) WebhookDeliveriesList(w io.Writer, params WebhookDeliveriesListParams) error { ··· 1269 1281 1270 1282 type RepoSingleIssueParams struct { 1271 1283 BaseParams 1272 - RepoInfo repoinfo.RepoInfo 1273 - Active string 1274 - Issue *models.Issue 1275 - CommentList []models.CommentListItem 1276 - Backlinks []models.RichReferenceLink 1277 - LabelDefs map[string]*models.LabelDefinition 1284 + RepoInfo repoinfo.RepoInfo 1285 + Active string 1286 + Issue *models.Issue 1287 + CommentList []models.CommentListItem 1288 + Backlinks []models.RichReferenceLink 1289 + LabelDefs map[string]*models.LabelDefinition 1278 1290 1279 1291 Reactions map[syntax.ATURI]map[models.ReactionKind]models.ReactionDisplayData 1280 1292 UserReacted map[syntax.ATURI]map[models.ReactionKind]bool ··· 1288 1300 1289 1301 type EditIssueParams struct { 1290 1302 BaseParams 1291 - RepoInfo repoinfo.RepoInfo 1292 - Issue *models.Issue 1293 - Action string 1303 + RepoInfo repoinfo.RepoInfo 1304 + Issue *models.Issue 1305 + Action string 1294 1306 } 1295 1307 1296 1308 func (p *Pages) EditIssueFragment(w io.Writer, params EditIssueParams) error { ··· 1313 1325 1314 1326 type RepoNewIssueParams struct { 1315 1327 BaseParams 1316 - RepoInfo repoinfo.RepoInfo 1317 - Issue *models.Issue // existing issue if any -- passed when editing 1318 - Active string 1319 - Action string 1328 + RepoInfo repoinfo.RepoInfo 1329 + Issue *models.Issue // existing issue if any -- passed when editing 1330 + Active string 1331 + Action string 1320 1332 } 1321 1333 1322 1334 func (p *Pages) RepoNewIssue(w io.Writer, params RepoNewIssueParams) error { ··· 1468 1480 1469 1481 type PullNewCommentParams struct { 1470 1482 BaseParams 1471 - RepoInfo repoinfo.RepoInfo 1472 - Pull *models.Pull 1473 - RoundNumber int 1483 + RepoInfo repoinfo.RepoInfo 1484 + Pull *models.Pull 1485 + RoundNumber int 1474 1486 } 1475 1487 1476 1488 func (p *Pages) PullNewCommentFragment(w io.Writer, params PullNewCommentParams) error { ··· 1479 1491 1480 1492 type RepoCompareParams struct { 1481 1493 BaseParams 1482 - RepoInfo repoinfo.RepoInfo 1483 - Forks []models.Repo 1484 - Branches []types.Branch 1485 - Tags []*types.TagReference 1486 - Base string 1487 - Head string 1488 - Diff *types.NiceDiff 1489 - DiffOpts types.DiffOpts 1494 + RepoInfo repoinfo.RepoInfo 1495 + Forks []models.Repo 1496 + Branches []types.Branch 1497 + Tags []*types.TagReference 1498 + Base string 1499 + Head string 1500 + Diff *types.NiceDiff 1501 + DiffOpts types.DiffOpts 1490 1502 1491 1503 Active string 1492 1504 } ··· 1498 1510 1499 1511 type RepoCompareNewParams struct { 1500 1512 BaseParams 1501 - RepoInfo repoinfo.RepoInfo 1502 - Forks []models.Repo 1503 - Branches []types.Branch 1504 - Tags []*types.TagReference 1505 - Base string 1506 - Head string 1513 + RepoInfo repoinfo.RepoInfo 1514 + Forks []models.Repo 1515 + Branches []types.Branch 1516 + Tags []*types.TagReference 1517 + Base string 1518 + Head string 1507 1519 1508 1520 Active string 1509 1521 } ··· 1515 1527 1516 1528 type RepoCompareAllowPullParams struct { 1517 1529 BaseParams 1518 - RepoInfo repoinfo.RepoInfo 1519 - Base string 1520 - Head string 1530 + RepoInfo repoinfo.RepoInfo 1531 + Base string 1532 + Head string 1521 1533 } 1522 1534 1523 1535 func (p *Pages) RepoCompareAllowPullFragment(w io.Writer, params RepoCompareAllowPullParams) error { ··· 1535 1547 1536 1548 type LabelPanelParams struct { 1537 1549 BaseParams 1538 - RepoInfo repoinfo.RepoInfo 1539 - Defs map[string]*models.LabelDefinition 1540 - Subject string 1541 - State models.LabelState 1550 + RepoInfo repoinfo.RepoInfo 1551 + Defs map[string]*models.LabelDefinition 1552 + Subject string 1553 + State models.LabelState 1542 1554 } 1543 1555 1544 1556 func (p *Pages) LabelPanel(w io.Writer, params LabelPanelParams) error { ··· 1547 1559 1548 1560 type EditLabelPanelParams struct { 1549 1561 BaseParams 1550 - RepoInfo repoinfo.RepoInfo 1551 - Defs map[string]*models.LabelDefinition 1552 - Subject string 1553 - State models.LabelState 1554 - Prefix string 1562 + RepoInfo repoinfo.RepoInfo 1563 + Defs map[string]*models.LabelDefinition 1564 + Subject string 1565 + State models.LabelState 1566 + Prefix string 1555 1567 } 1556 1568 1557 1569 func (p *Pages) EditLabelPanel(w io.Writer, params EditLabelPanelParams) error { ··· 1560 1572 1561 1573 type RepoStarsParams struct { 1562 1574 BaseParams 1563 - RepoInfo repoinfo.RepoInfo 1564 - Active string 1565 - Starrers []models.Star 1566 - Page pagination.Page 1567 - TotalCount int 1575 + RepoInfo repoinfo.RepoInfo 1576 + Active string 1577 + Starrers []models.Star 1578 + Page pagination.Page 1579 + TotalCount int 1568 1580 } 1569 1581 1570 1582 func (p *Pages) RepoStars(w io.Writer, params RepoStarsParams) error { ··· 1574 1586 1575 1587 type RepoForksParams struct { 1576 1588 BaseParams 1577 - RepoInfo repoinfo.RepoInfo 1578 - Active string 1579 - Forks []models.Repo 1580 - Page pagination.Page 1581 - TotalCount int 1589 + RepoInfo repoinfo.RepoInfo 1590 + Active string 1591 + Forks []models.Repo 1592 + Page pagination.Page 1593 + TotalCount int 1582 1594 } 1583 1595 1584 1596 func (p *Pages) RepoForks(w io.Writer, params RepoForksParams) error { ··· 1588 1600 1589 1601 type PipelinesParams struct { 1590 1602 BaseParams 1591 - RepoInfo repoinfo.RepoInfo 1592 - Pipelines []models.Pipeline 1593 - Active string 1594 - FilterKind string 1595 - Total int64 1603 + RepoInfo repoinfo.RepoInfo 1604 + Pipelines []models.Pipeline 1605 + Active string 1606 + FilterKind string 1607 + Total int64 1596 1608 } 1597 1609 1598 1610 func (p *Pages) Pipelines(w io.Writer, params PipelinesParams) error { ··· 1642 1654 1643 1655 type WorkflowParams struct { 1644 1656 BaseParams 1645 - RepoInfo repoinfo.RepoInfo 1646 - Pipeline models.Pipeline 1647 - Workflow string 1648 - LogUrl string 1649 - Active string 1657 + RepoInfo repoinfo.RepoInfo 1658 + Pipeline models.Pipeline 1659 + Workflow string 1660 + LogUrl string 1661 + Active string 1650 1662 } 1651 1663 1652 1664 func (p *Pages) Workflow(w io.Writer, params WorkflowParams) error { ··· 1656 1668 1657 1669 type PutStringParams struct { 1658 1670 BaseParams 1659 - Action string 1671 + Action string 1660 1672 1661 1673 // this is supplied in the case of editing an existing string 1662 1674 String models.String ··· 1668 1680 1669 1681 type StringsDashboardParams struct { 1670 1682 BaseParams 1671 - Card ProfileCard 1672 - Strings []models.String 1683 + Card ProfileCard 1684 + Strings []models.String 1673 1685 } 1674 1686 1675 1687 func (p *Pages) StringsDashboard(w io.Writer, params StringsDashboardParams) error { ··· 1678 1690 1679 1691 type StringTimelineParams struct { 1680 1692 BaseParams 1681 - Strings []models.String 1693 + Strings []models.String 1682 1694 } 1683 1695 1684 1696 func (p *Pages) StringsTimeline(w io.Writer, params StringTimelineParams) error { ··· 1708 1720 1709 1721 type SearchReposParams struct { 1710 1722 BaseParams 1711 - Repos []models.Repo 1712 - Page pagination.Page 1713 - ResultCount int 1714 - FilterQuery string 1715 - SortParam string 1716 - TimeTaken time.Duration 1717 - DocCount int64 1723 + Repos []models.Repo 1724 + Page pagination.Page 1725 + ResultCount int 1726 + FilterQuery string 1727 + SortParam string 1728 + TimeTaken time.Duration 1729 + DocCount int64 1718 1730 } 1719 1731 1720 1732 func (p *Pages) SearchRepos(w io.Writer, params SearchReposParams) error {
+10
appview/pages/templates/focus/fragments/beginButton.html
··· 1 + {{ define "focus/fragments/beginButton" }} 2 + {{ if and .CanFocus (not .FocusParams.Focusing) }} 3 + <form method="POST" action="/focus/begin"> 4 + <button type="submit" 5 + class="flex btn-primary items-center gap-2"> 6 + {{ i "telescope" "size-4" }} Focus &amp; reply 7 + </button> 8 + </form> 9 + {{ end }} 10 + {{ end }}
+52
appview/pages/templates/focus/fragments/pill.html
··· 1 + {{ define "focus/pill" }} 2 + {{ if .Focusing }} 3 + {{ $offFocus := and .FocusLink .CurrentPath (not (hasPrefix .CurrentPath .FocusLink)) }} 4 + <div id="focus-pill" class="fixed bottom-0 left-1/2 -translate-x-1/2 z-50 select-none"> 5 + {{ if $offFocus }}<a href="{{ .FocusLink }}" class="absolute inset-0 z-0 no-underline" aria-label="Return to focus"></a>{{ end }} 6 + <div class="relative flex items-center gap-12 bg-indigo-600 text-sm text-white rounded-t-lg px-4 py-2 shadow-lg"> 7 + 8 + <form method="POST" action="/focus/end" class="relative z-10 inline m-0"> 9 + <button type="submit" class="flex items-center gap-1 text-white hover:text-indigo-200 bg-transparent border-0 p-0 cursor-pointer text-sm"> 10 + {{ i "x" "size-4" }} Exit 11 + </button> 12 + </form> 13 + 14 + {{ $remaining := sub .FocusCount 1 }} 15 + {{ if $offFocus }} 16 + <span class="flex items-center gap-2 whitespace-nowrap animate-pulse"> 17 + {{ i "route-off" "size-4" }} 18 + Off track 19 + {{ if gt $remaining 0 }} 20 + <span class="opacity-75">{{ $remaining }} remaining</span> 21 + {{ end }} 22 + </span> 23 + {{ else }} 24 + <span class="flex items-center gap-2 whitespace-nowrap"> 25 + {{ i "telescope" "size-4" }} 26 + Focusing 27 + {{ if gt $remaining 0 }} 28 + <span class="opacity-75">{{ $remaining }} remaining</span> 29 + {{ end }} 30 + </span> 31 + {{ end }} 32 + 33 + {{ if $offFocus }} 34 + <a href="{{ .FocusLink }}" class="flex items-center gap-1 text-white hover:text-indigo-200 no-underline hover:no-underline bg-transparent border-0 p-0 cursor-pointer text-sm"> 35 + Return {{ i "undo-2" "size-4" }} 36 + </a> 37 + {{ else }} 38 + <form method="POST" action="/focus/next" class="inline m-0"> 39 + <input type="hidden" name="current_id" value="{{ .FocusNotificationID }}"> 40 + <button type="submit" class="flex items-center gap-1 text-white hover:text-indigo-200 bg-transparent border-0 p-0 cursor-pointer text-sm"> 41 + {{ if le .FocusCount 1 }} 42 + {{ i "check" "size-4" }} Finish 43 + {{ else }} 44 + Next {{ i "arrow-right" "size-4" }} 45 + {{ end }} 46 + </button> 47 + </form> 48 + {{ end }} 49 + </div> 50 + </div> 51 + {{ end }} 52 + {{ end }}
+2
appview/pages/templates/layouts/base.html
··· 105 105 {{ template "layouts/fragments/footer" . }} 106 106 </footer> 107 107 {{ end }} 108 + 109 + {{ template "focus/pill" .FocusParams }} 108 110 </body> 109 111 </html> 110 112 {{ end }}
+1 -1
appview/pages/templates/notifications/fragments/count.html
··· 1 1 {{define "notifications/fragments/count"}} 2 2 {{if and .Count (gt .Count 0)}} 3 - <span class="absolute -top-1.5 -right-0.5 min-w-[16px] h-[16px] px-1 bg-red-500 text-white text-xs font-medium rounded-full flex items-center justify-center"> 3 + <span class="absolute -top-1.5 -right-0.5 min-w-[16px] h-[16px] px-1 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center"> 4 4 {{if gt .Count 99}}99+{{else}}{{.Count}}{{end}} 5 5 </span> 6 6 {{end}}
+18 -14
appview/pages/templates/notifications/fragments/preview.html
··· 1 1 {{ define "notifications/fragments/preview" }} 2 - <div class="flex items-center justify-between px-4 py-2 border-b border-gray-200 dark:border-gray-700 flex-wrap gap-2"> 3 - {{ $read := .ReadFilter }} 4 - {{ $cat := .CategoryFilter }} 2 + {{ $read := .ReadFilter }} 3 + {{ $cat := .CategoryFilter }} 5 4 5 + <div class="flex items-center justify-between px-4 py-2 border-b border-gray-200 dark:border-gray-700 flex-wrap gap-2"> 6 6 <div class="flex items-center gap-2 flex-wrap"> 7 7 <div class="btn-group"> 8 8 <a href="#" ··· 30 30 </button> 31 31 </div> 32 32 33 - <div class="btn-group"> 34 - {{ range $k, $label := list "all" "work" "social" }} 35 - <a href="#" 36 - hx-get="/notifications/preview?read={{ $read }}&category={{ $label }}" 37 - hx-target="#notif-popup" 38 - hx-swap="innerHTML" 39 - class="btn-group-item {{ if eq $label $cat }}active{{ end }} capitalize"> 40 - {{ $label }} 41 - </a> 42 - {{ end }} 43 - </div> 33 + {{ if and .CanFocus (not .FocusParams.Focusing) }} 34 + {{ template "focus/fragments/beginButton" . }} 35 + {{ else if not .FocusParams.Focusing }} 36 + <div class="btn-group"> 37 + {{ range $k, $label := list "all" "work" "social" }} 38 + <a href="#" 39 + hx-get="/notifications/preview?read={{ $read }}&category={{ $label }}" 40 + hx-target="#notif-popup" 41 + hx-swap="innerHTML" 42 + class="btn-group-item {{ if eq $label $cat }}active{{ end }} capitalize"> 43 + {{ $label }} 44 + </a> 45 + {{ end }} 46 + </div> 47 + {{ end }} 44 48 45 49 </div> 46 50
+4 -19
appview/pages/templates/notifications/list.html
··· 10 10 (dict "Key" "unread" "Value" "Unread" "Icon" "glasses") 11 11 }} 12 12 13 - {{/* Mobile controls: single row */}} 14 - <div class="md:hidden px-4 pb-4 flex items-center justify-between"> 15 - <div class="flex items-center gap-2"> 16 - {{ template "fragments/tabSelector" (dict "Name" "read" "Values" $readVals "Active" .ReadFilter) }} 17 - <button 18 - hx-post="/notifications/read-all" 19 - hx-swap="none" 20 - hx-on::after-request="window.location.reload()" 21 - class="btn-flat flex items-center gap-2 text-sm"> 22 - {{ i "check-check" "size-4" }} Mark all read 23 - </button> 24 - </div> 25 - <a href="/settings/notifications" class="btn-flat"> 26 - {{ i "cog" "size-5" }} 27 - </a> 28 - </div> 29 - 30 13 {{/* Desktop controls: single row */}} 31 - <div class="hidden md:flex md:px-0 pb-4 items-center justify-between gap-4"> 14 + <div class="flex md:px-0 px-4 pb-4 items-center justify-between gap-4"> 32 15 <div class="flex items-center gap-2"> 33 16 {{ template "fragments/tabSelector" (dict "Name" "read" "Values" $readVals "Active" .ReadFilter) }} 17 + {{ template "focus/fragments/beginButton" . }} 34 18 <button 35 19 hx-post="/notifications/read-all" 36 20 hx-swap="none" ··· 40 24 </button> 41 25 </div> 42 26 <a href="/settings/notifications" class="flex items-center gap-2 text-sm"> 43 - {{ i "cog" "w-4 h-4" }} Preferences 27 + {{ i "cog" "w-4 h-4" }} 28 + <span class="hidden md:inline">Preferences</span> 44 29 </a> 45 30 </div> 46 31
+10 -8
appview/pages/templates/timeline/fragments/notifications.html
··· 1 1 {{ define "timeline/fragments/notifications" }} 2 2 <div class="border border-gray-200 dark:border-gray-700 rounded-sm divide-y divide-gray-200 dark:divide-gray-700"> 3 - <a href="/notifications" class="flex items-center justify-between bg-white/50 dark:bg-gray-800/50 no-underline hover:no-underline"> 4 - <h3 class="text-base dark:text-white flex items-center gap-2 px-4 py-2"> 5 - {{ i "bell" "size-4 flex-shrink-0" }} 6 - Notifications 7 - </h3> 8 - <span class="text-sm font-normal flex items-center gap-1 pr-4"> 3 + <div class="flex items-center justify-between bg-white/50 dark:bg-gray-800/50"> 4 + <a href="/notifications" class="flex items-center gap-2 px-4 py-2 no-underline hover:no-underline flex-1"> 5 + <h3 class="text-base dark:text-white flex items-center gap-2"> 6 + {{ i "bell" "size-4 flex-shrink-0" }} 7 + Notifications 8 + </h3> 9 + </a> 10 + <a href="/notifications" class="text-sm font-normal flex items-center gap-1 pr-4 text-gray-500 dark:text-gray-400 no-underline hover:no-underline"> 9 11 View all {{ i "arrow-right" "size-3.5" }} 10 - </span> 11 - </a> 12 + </a> 13 + </div> 12 14 13 15 {{ if not .LoggedInUser }} 14 16 <div class="px-4 py-8 text-sm text-center text-gray-400 dark:text-gray-500">
+7 -7
appview/pipelines/pipelines.go
··· 120 120 121 121 p.pages.Pipelines(w, pages.PipelinesParams{ 122 122 BaseParams: pages.BaseParamsFromContext(r.Context()), 123 - RepoInfo: p.repoResolver.GetRepoInfo(r, user), 124 - Pipelines: ps, 125 - FilterKind: filterKind, 126 - Total: total, 123 + RepoInfo: p.repoResolver.GetRepoInfo(r, user), 124 + Pipelines: ps, 125 + FilterKind: filterKind, 126 + Total: total, 127 127 }) 128 128 } 129 129 ··· 169 169 170 170 p.pages.Workflow(w, pages.WorkflowParams{ 171 171 BaseParams: pages.BaseParamsFromContext(r.Context()), 172 - RepoInfo: p.repoResolver.GetRepoInfo(r, user), 173 - Pipeline: singlePipeline, 174 - Workflow: workflow, 172 + RepoInfo: p.repoResolver.GetRepoInfo(r, user), 173 + Pipeline: singlePipeline, 174 + Workflow: workflow, 175 175 }) 176 176 } 177 177
+4 -4
appview/pulls/comment.go
··· 37 37 switch r.Method { 38 38 case http.MethodGet: 39 39 s.pages.PullNewCommentFragment(w, pages.PullNewCommentParams{ 40 - BaseParams: pages.BaseParamsFromContext(r.Context()), 41 - RepoInfo: s.repoResolver.GetRepoInfo(r, user), 42 - Pull: pull, 43 - RoundNumber: roundNumber, 40 + BaseParams: pages.BaseParamsFromContext(r.Context()), 41 + RepoInfo: s.repoResolver.GetRepoInfo(r, user), 42 + Pull: pull, 43 + RoundNumber: roundNumber, 44 44 }) 45 45 return 46 46 }
+1 -1
appview/pulls/compose.go
··· 306 306 } 307 307 308 308 return pages.RepoNewPullParams{ 309 - BaseParams: pages.BaseParamsFromContext(r.Context()), 309 + BaseParams: pages.BaseParamsFromContext(r.Context()), 310 310 RepoInfo: repoInfo, 311 311 Branches: branches, 312 312 SourceBranches: sourceBranchList,
+1 -1
appview/pulls/list.go
··· 310 310 } 311 311 312 312 err = s.pages.RepoPulls(w, pages.RepoPullsParams{ 313 - BaseParams: pages.BaseParamsFromContext(r.Context()), 313 + BaseParams: pages.BaseParamsFromContext(r.Context()), 314 314 RepoInfo: repoInfo, 315 315 Pulls: pulls, 316 316 LabelDefs: defs,
+2 -2
appview/pulls/single.go
··· 66 66 } 67 67 68 68 s.pages.PullActionsFragment(w, pages.PullActionsParams{ 69 - BaseParams: pages.BaseParamsFromContext(r.Context()), 69 + BaseParams: pages.BaseParamsFromContext(r.Context()), 70 70 RepoInfo: s.repoResolver.GetRepoInfo(r, user), 71 71 Pull: pull, 72 72 RoundNumber: roundNumber, ··· 251 251 } 252 252 253 253 err = s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{ 254 - BaseParams: pages.BaseParamsFromContext(r.Context()), 254 + BaseParams: pages.BaseParamsFromContext(r.Context()), 255 255 RepoInfo: s.repoResolver.GetRepoInfo(r, user), 256 256 Pull: pull, 257 257 Stack: stack,
+2 -2
appview/repo/artifact.go
··· 128 128 129 129 rp.pages.RepoArtifactFragment(w, pages.RepoArtifactParams{ 130 130 BaseParams: pages.BaseParamsFromContext(r.Context()), 131 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 132 - Artifact: artifact, 131 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 132 + Artifact: artifact, 133 133 }) 134 134 } 135 135
+1 -1
appview/repo/branches.go
··· 38 38 sortBranches(result.Branches) 39 39 user := rp.oauth.GetMultiAccountUser(r) 40 40 rp.pages.RepoBranches(w, pages.RepoBranchesParams{ 41 - BaseParams: pages.BaseParamsFromContext(r.Context()), 41 + BaseParams: pages.BaseParamsFromContext(r.Context()), 42 42 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 43 43 RepoBranchesResponse: result, 44 44 })
+12 -12
appview/repo/compare.go
··· 85 85 86 86 rp.pages.RepoCompareNew(w, pages.RepoCompareNewParams{ 87 87 BaseParams: pages.BaseParamsFromContext(r.Context()), 88 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 89 - Branches: branches, 90 - Tags: tags.Tags, 91 - Base: base, 92 - Head: head, 88 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 89 + Branches: branches, 90 + Tags: tags.Tags, 91 + Base: base, 92 + Head: head, 93 93 }) 94 94 } 95 95 ··· 202 202 203 203 rp.pages.RepoCompare(w, pages.RepoCompareParams{ 204 204 BaseParams: pages.BaseParamsFromContext(r.Context()), 205 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 206 - Branches: branches.Branches, 207 - Tags: tags.Tags, 208 - Base: base, 209 - Head: head, 210 - Diff: &diff, 211 - DiffOpts: diffOpts, 205 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 206 + Branches: branches.Branches, 207 + Tags: tags.Tags, 208 + Base: base, 209 + Head: head, 210 + Diff: &diff, 211 + DiffOpts: diffOpts, 212 212 }) 213 213 214 214 }
+2 -2
appview/repo/index.go
··· 58 58 if err != nil { 59 59 l.Error("failed to build index response", "err", err) 60 60 rp.pages.RepoIndexPage(w, pages.RepoIndexParams{ 61 - BaseParams: pages.BaseParamsFromContext(r.Context()), 61 + BaseParams: pages.BaseParamsFromContext(r.Context()), 62 62 KnotUnreachable: true, 63 63 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 64 64 }) ··· 171 171 } 172 172 173 173 rp.pages.RepoIndexPage(w, pages.RepoIndexParams{ 174 - BaseParams: pages.BaseParamsFromContext(r.Context()), 174 + BaseParams: pages.BaseParamsFromContext(r.Context()), 175 175 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 176 176 TagMap: tagMap, 177 177 RepoIndexResponse: *result,
+2 -2
appview/repo/log.go
··· 185 185 } 186 186 187 187 rp.pages.RepoLog(w, pages.RepoLogParams{ 188 - BaseParams: pages.BaseParamsFromContext(r.Context()), 188 + BaseParams: pages.BaseParamsFromContext(r.Context()), 189 189 TagMap: tagMap, 190 190 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 191 191 RepoLogResponse: xrpcResp, ··· 261 261 } 262 262 263 263 rp.pages.RepoCommit(w, pages.RepoCommitParams{ 264 - BaseParams: pages.BaseParamsFromContext(r.Context()), 264 + BaseParams: pages.BaseParamsFromContext(r.Context()), 265 265 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 266 266 RepoCommitResponse: result, 267 267 EmailToDid: emailToDidMap,
+18 -18
appview/repo/repo.go
··· 665 665 user := rp.oauth.GetMultiAccountUser(r) 666 666 rp.pages.LabelPanel(w, pages.LabelPanelParams{ 667 667 BaseParams: pages.BaseParamsFromContext(r.Context()), 668 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 669 - Defs: defs, 670 - Subject: subject.String(), 671 - State: state, 668 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 669 + Defs: defs, 670 + Subject: subject.String(), 671 + State: state, 672 672 }) 673 673 } 674 674 ··· 713 713 user := rp.oauth.GetMultiAccountUser(r) 714 714 rp.pages.EditLabelPanel(w, pages.EditLabelPanelParams{ 715 715 BaseParams: pages.BaseParamsFromContext(r.Context()), 716 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 717 - Defs: defs, 718 - Subject: subject.String(), 719 - State: state, 716 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 717 + Defs: defs, 718 + Subject: subject.String(), 719 + State: state, 720 720 }) 721 721 } 722 722 ··· 1426 1426 1427 1427 rp.pages.ForkRepo(w, pages.ForkRepoParams{ 1428 1428 BaseParams: pages.BaseParamsFromContext(r.Context()), 1429 - Knots: knots, 1430 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1429 + Knots: knots, 1430 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1431 1431 }) 1432 1432 1433 1433 case http.MethodPost: ··· 1698 1698 1699 1699 rp.pages.RepoStars(w, pages.RepoStarsParams{ 1700 1700 BaseParams: pages.BaseParamsFromContext(r.Context()), 1701 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1702 - Starrers: starrers, 1703 - Page: page, 1704 - TotalCount: totalCount, 1701 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1702 + Starrers: starrers, 1703 + Page: page, 1704 + TotalCount: totalCount, 1705 1705 }) 1706 1706 } 1707 1707 ··· 1734 1734 1735 1735 err = rp.pages.RepoForks(w, pages.RepoForksParams{ 1736 1736 BaseParams: pages.BaseParamsFromContext(r.Context()), 1737 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1738 - Forks: forks, 1739 - Page: page, 1740 - TotalCount: totalCount, 1737 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1738 + Forks: forks, 1739 + Page: page, 1740 + TotalCount: totalCount, 1741 1741 }) 1742 1742 if err != nil { 1743 1743 l.Error("failed to render page", "err", err)
+4 -4
appview/repo/settings.go
··· 241 241 } 242 242 243 243 rp.pages.RepoSiteSettings(w, pages.RepoSiteSettingsParams{ 244 - BaseParams: pages.BaseParamsFromContext(r.Context()), 244 + BaseParams: pages.BaseParamsFromContext(r.Context()), 245 245 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 246 246 Branches: result.Branches, 247 247 SiteConfig: siteConfig, ··· 436 436 } 437 437 438 438 rp.pages.RepoGeneralSettings(w, pages.RepoGeneralSettingsParams{ 439 - BaseParams: pages.BaseParamsFromContext(r.Context()), 439 + BaseParams: pages.BaseParamsFromContext(r.Context()), 440 440 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 441 441 Branches: result.Branches, 442 442 Labels: labels, ··· 459 459 collaborators := rp.acl.Collaborators(r.Context(), f) 460 460 461 461 rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{ 462 - BaseParams: pages.BaseParamsFromContext(r.Context()), 462 + BaseParams: pages.BaseParamsFromContext(r.Context()), 463 463 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 464 464 Collaborators: collaborators, 465 465 CanRemoveCollaborator: knotcompat.KnotHasCapability(r.Context(), f.Knot, rp.config.Core.Dev, consts.CapKnotACL), ··· 519 519 } 520 520 521 521 rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{ 522 - BaseParams: pages.BaseParamsFromContext(r.Context()), 522 + BaseParams: pages.BaseParamsFromContext(r.Context()), 523 523 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 524 524 Spindles: spindles, 525 525 CurrentSpindle: f.Spindle,
+2 -2
appview/repo/tags.go
··· 67 67 user := rp.oauth.GetMultiAccountUser(r) 68 68 69 69 rp.pages.RepoTags(w, pages.RepoTagsParams{ 70 - BaseParams: pages.BaseParamsFromContext(r.Context()), 70 + BaseParams: pages.BaseParamsFromContext(r.Context()), 71 71 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 72 72 RepoTagsResponse: result, 73 73 ArtifactMap: artifactMap, ··· 142 142 143 143 user := rp.oauth.GetMultiAccountUser(r) 144 144 rp.pages.RepoTag(w, pages.RepoTagParams{ 145 - BaseParams: pages.BaseParamsFromContext(r.Context()), 145 + BaseParams: pages.BaseParamsFromContext(r.Context()), 146 146 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 147 147 RepoTagResponse: result, 148 148 ArtifactMap: artifactMap,
+4 -4
appview/repo/webhooks.go
··· 45 45 } 46 46 47 47 rp.pages.RepoWebhooksSettings(w, pages.RepoWebhooksSettingsParams{ 48 - BaseParams: pages.BaseParamsFromContext(r.Context()), 48 + BaseParams: pages.BaseParamsFromContext(r.Context()), 49 49 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 50 50 Webhooks: webhooks, 51 51 WebhookDeliveries: deliveriesMap, ··· 366 366 367 367 rp.pages.WebhookDeliveriesList(w, pages.WebhookDeliveriesListParams{ 368 368 BaseParams: pages.BaseParamsFromContext(r.Context()), 369 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 370 - Webhook: webhook, 371 - Deliveries: deliveries, 369 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 370 + Webhook: webhook, 371 + Deliveries: deliveries, 372 372 }) 373 373 }
+6 -6
appview/settings/settings.go
··· 125 125 isTnglHandle, _ := s.isTnglHandle(r.Context(), syntax.DID(user.Did)) 126 126 127 127 s.Pages.UserSiteSettings(w, pages.UserSiteSettingsParams{ 128 - BaseParams: pages.BaseParamsFromContext(r.Context()), 128 + BaseParams: pages.BaseParamsFromContext(r.Context()), 129 129 Claim: claim, 130 130 SitesDomain: s.Config.Sites.Domain, 131 131 IsTnglHandle: isTnglHandle, ··· 270 270 isDeactivated := s.isAccountDeactivated(r.Context(), syntax.DID(user.Did)) 271 271 272 272 s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{ 273 - BaseParams: pages.BaseParamsFromContext(r.Context()), 273 + BaseParams: pages.BaseParamsFromContext(r.Context()), 274 274 PunchcardPreference: punchcardPreferences, 275 275 IsTnglSh: isTnglSh, 276 276 IsDeactivated: isDeactivated, ··· 289 289 } 290 290 291 291 s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{ 292 - BaseParams: pages.BaseParamsFromContext(r.Context()), 293 - Preferences: prefs, 292 + BaseParams: pages.BaseParamsFromContext(r.Context()), 293 + Preferences: prefs, 294 294 }) 295 295 } 296 296 ··· 330 330 331 331 s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{ 332 332 BaseParams: pages.BaseParamsFromContext(r.Context()), 333 - PubKeys: pubKeys, 333 + PubKeys: pubKeys, 334 334 }) 335 335 } 336 336 ··· 343 343 344 344 s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{ 345 345 BaseParams: pages.BaseParamsFromContext(r.Context()), 346 - Emails: emails, 346 + Emails: emails, 347 347 }) 348 348 } 349 349
+6 -6
appview/spindles/spindles.go
··· 70 70 71 71 s.Pages.Spindles(w, pages.SpindlesParams{ 72 72 BaseParams: pages.BaseParamsFromContext(r.Context()), 73 - Spindles: all, 74 - Tab: "spindles", 73 + Spindles: all, 74 + Tab: "spindles", 75 75 }) 76 76 } 77 77 ··· 127 127 128 128 s.Pages.SpindleDashboard(w, pages.SpindleDashboardParams{ 129 129 BaseParams: pages.BaseParamsFromContext(r.Context()), 130 - Spindle: spindle, 131 - Members: members, 132 - Repos: repoMap, 133 - Tab: "spindles", 130 + Spindle: spindle, 131 + Members: members, 132 + Repos: repoMap, 133 + Tab: "spindles", 134 134 }) 135 135 } 136 136
+8 -8
appview/state/gfi.go
··· 36 36 if len(repoLabels) == 0 { 37 37 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{ 38 38 BaseParams: pages.BaseParamsFromContext(r.Context()), 39 - RepoGroups: []*models.RepoGroup{}, 40 - LabelDefs: make(map[string]*models.LabelDefinition), 41 - Page: page, 42 - GfiLabel: gfiLabelDef, 39 + RepoGroups: []*models.RepoGroup{}, 40 + LabelDefs: make(map[string]*models.LabelDefinition), 41 + Page: page, 42 + GfiLabel: gfiLabelDef, 43 43 }) 44 44 return 45 45 } ··· 145 145 146 146 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{ 147 147 BaseParams: pages.BaseParamsFromContext(r.Context()), 148 - RepoGroups: paginatedGroups, 149 - LabelDefs: labelDefsMap, 150 - Page: page, 151 - GfiLabel: gfiLabelDef, 148 + RepoGroups: paginatedGroups, 149 + LabelDefs: labelDefsMap, 150 + Page: page, 151 + GfiLabel: gfiLabelDef, 152 152 }) 153 153 }
+20 -20
appview/state/profile.go
··· 187 187 } 188 188 189 189 err = s.pages.ProfileOverview(w, pages.ProfileOverviewParams{ 190 - BaseParams: pages.BaseParamsFromContext(r.Context()), 190 + BaseParams: pages.BaseParamsFromContext(r.Context()), 191 191 Card: profile, 192 192 Repos: pinnedRepos, 193 193 CollaboratingRepos: pinnedCollaboratingRepos, ··· 336 336 } 337 337 338 338 err = s.pages.ProfileRepos(w, pages.ProfileReposParams{ 339 - BaseParams: pages.BaseParamsFromContext(r.Context()), 339 + BaseParams: pages.BaseParamsFromContext(r.Context()), 340 340 Repos: repos, 341 341 StarStatuses: starStatuses, 342 342 Card: profile, ··· 376 376 377 377 err = s.pages.ProfileStarred(w, pages.ProfileStarredParams{ 378 378 BaseParams: pages.BaseParamsFromContext(r.Context()), 379 - Repos: repos, 380 - Total: int(profile.Stats.StarredCount), 381 - Card: profile, 382 - Page: page, 379 + Repos: repos, 380 + Total: int(profile.Stats.StarredCount), 381 + Card: profile, 382 + Page: page, 383 383 }) 384 384 if err != nil { 385 385 l.Error("failed to render", "err", err) ··· 406 406 407 407 err = s.pages.ProfileStrings(w, pages.ProfileStringsParams{ 408 408 BaseParams: pages.BaseParamsFromContext(r.Context()), 409 - Strings: strings, 410 - Card: profile, 409 + Strings: strings, 410 + Card: profile, 411 411 }) 412 412 } 413 413 ··· 502 502 } 503 503 504 504 err = s.pages.ProfileVouches(w, pages.ProfileVouchesParams{ 505 - BaseParams: pages.BaseParamsFromContext(r.Context()), 505 + BaseParams: pages.BaseParamsFromContext(r.Context()), 506 506 Vouches: vouches, 507 507 Suggestions: suggestions, 508 508 Card: profile, ··· 596 596 profile.Did = did 597 597 } 598 598 followCards[i] = pages.FollowCard{ 599 - BaseParams: pages.BaseParamsFromContext(r.Context()), 599 + BaseParams: pages.BaseParamsFromContext(r.Context()), 600 600 UserDid: did, 601 601 FollowStatus: followStatus, 602 602 FollowersCount: followStats.Followers, ··· 619 619 620 620 s.pages.ProfileFollowers(w, pages.ProfileFollowersParams{ 621 621 BaseParams: pages.BaseParamsFromContext(r.Context()), 622 - Followers: followPage.Follows, 623 - Card: followPage.Card, 622 + Followers: followPage.Follows, 623 + Card: followPage.Card, 624 624 }) 625 625 } 626 626 ··· 633 633 634 634 s.pages.ProfileFollowing(w, pages.ProfileFollowingParams{ 635 635 BaseParams: pages.BaseParamsFromContext(r.Context()), 636 - Following: followPage.Follows, 637 - Card: followPage.Card, 636 + Following: followPage.Follows, 637 + Card: followPage.Card, 638 638 }) 639 639 } 640 640 ··· 1008 1008 } 1009 1009 1010 1010 s.pages.ProfilePopoverFragment(w, pages.ProfilePopoverParams{ 1011 - BaseParams: pages.BaseParamsFromContext(r.Context()), 1011 + BaseParams: pages.BaseParamsFromContext(r.Context()), 1012 1012 UserDid: did, 1013 1013 Profile: profile, 1014 1014 FollowStatus: followStatus, ··· 1039 1039 } 1040 1040 1041 1041 s.pages.EditBioFragment(w, pages.EditBioParams{ 1042 - BaseParams: pages.BaseParamsFromContext(r.Context()), 1043 - Profile: profile, 1044 - AlsoKnownAs: alsoKnownAs, 1042 + BaseParams: pages.BaseParamsFromContext(r.Context()), 1043 + Profile: profile, 1044 + AlsoKnownAs: alsoKnownAs, 1045 1045 }) 1046 1046 } 1047 1047 ··· 1084 1084 1085 1085 s.pages.EditPinsFragment(w, pages.EditPinsParams{ 1086 1086 BaseParams: pages.BaseParamsFromContext(r.Context()), 1087 - Profile: profile, 1088 - AllRepos: allRepos, 1087 + Profile: profile, 1088 + AllRepos: allRepos, 1089 1089 }) 1090 1090 } 1091 1091
+8 -8
appview/state/search.go
··· 142 142 } 143 143 144 144 err = s.pages.SearchRepos(w, pages.SearchReposParams{ 145 - BaseParams: pages.BaseParamsFromContext(r.Context()), 146 - Repos: repos, 147 - Page: page, 148 - FilterQuery: query.String(), 149 - SortParam: sortParam, 150 - TimeTaken: searchDuration, 151 - ResultCount: resultCount, 152 - DocCount: docCount, 145 + BaseParams: pages.BaseParamsFromContext(r.Context()), 146 + Repos: repos, 147 + Page: page, 148 + FilterQuery: query.String(), 149 + SortParam: sortParam, 150 + TimeTaken: searchDuration, 151 + ResultCount: resultCount, 152 + DocCount: docCount, 153 153 }) 154 154 if err != nil { 155 155 l.Error("failed to render page", "err", err)
+1 -1
appview/state/state.go
··· 456 456 457 457 s.pages.NewRepo(w, pages.NewRepoParams{ 458 458 BaseParams: pages.BaseParamsFromContext(r.Context()), 459 - Knots: knots, 459 + Knots: knots, 460 460 }) 461 461 462 462 case http.MethodPost:
+5 -5
appview/strings/strings.go
··· 80 80 81 81 s.Pages.StringsTimeline(w, pages.StringTimelineParams{ 82 82 BaseParams: pages.BaseParamsFromContext(r.Context()), 83 - Strings: strings, 83 + Strings: strings, 84 84 }) 85 85 } 86 86 ··· 192 192 } 193 193 194 194 err = s.Pages.SingleString(w, pages.SingleStringParams{ 195 - BaseParams: pages.BaseParamsFromContext(r.Context()), 195 + BaseParams: pages.BaseParamsFromContext(r.Context()), 196 196 RenderToggle: renderToggle, 197 197 ShowRendered: showRendered, 198 198 String: &string, ··· 264 264 // return the form with prefilled fields 265 265 s.Pages.PutString(w, pages.PutStringParams{ 266 266 BaseParams: pages.BaseParamsFromContext(r.Context()), 267 - Action: "edit", 268 - String: first, 267 + Action: "edit", 268 + String: first, 269 269 }) 270 270 case http.MethodPost: 271 271 fail := func(msg string, err error) { ··· 349 349 case http.MethodGet: 350 350 s.Pages.PutString(w, pages.PutStringParams{ 351 351 BaseParams: pages.BaseParamsFromContext(r.Context()), 352 - Action: "new", 352 + Action: "new", 353 353 }) 354 354 case http.MethodPost: 355 355 fail := func(msg string, err error) {
+1 -1
appview/timeline/home.go
··· 26 26 } 27 27 28 28 t.pages.Home(w, pages.TimelineParams{ 29 - BaseParams: pages.BaseParamsFromContext(r.Context()), 29 + BaseParams: pages.BaseParamsFromContext(r.Context()), 30 30 Timeline: timeline, 31 31 BlueskyPosts: blueskyPosts, 32 32 RecentBlogPosts: t.recentPosts,
+13 -1
input.css
··· 217 217 @apply hover:bg-gray-50 dark:hover:bg-gray-700 218 218 hover:before:shadow-[inset_0_-2px_0_0_theme(colors.gray.300)] dark:hover:before:shadow-[inset_0_-2px_0_0_theme(colors.gray.800)] 219 219 active:before:shadow-[inset_0_2px_2px_0_theme(colors.gray.200)] dark:active:before:shadow-[inset_0_2px_2px_0_theme(colors.gray.900)] 220 + active:translate-y-0.5 220 221 disabled:cursor-not-allowed disabled:opacity-50; 221 222 } 222 223 223 224 .btn-flat { 224 225 @apply inline-flex items-center justify-center 225 - min-h-7 px-2 py-[6px] 226 + min-h-[30px] px-2 py-[6px] 226 227 rounded 227 228 text-sm text-gray-900 dark:text-gray-100 cursor-pointer 228 229 transition-colors duration-150 ease-in-out ··· 249 250 before:shadow-none 250 251 hover:before:shadow-none 251 252 active:before:shadow-none; 253 + } 254 + 255 + .btn-primary { 256 + @apply btn text-white 257 + bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600 258 + border border-indigo-700 hover:border-indigo-800 dark:border-indigo-600 dark:hover:border-indigo-700 259 + focus-visible:outline-indigo-500 260 + disabled:bg-indigo-400 dark:disabled:bg-indigo-400 261 + before:shadow-[inset_0_-2px_0_0_theme(colors.gray.900/25%)] 262 + hover:before:shadow-[inset_0_-2px_0_0_theme(colors.gray.900/25%)] 263 + active:before:shadow-[inset_0_2px_2px_0_theme(colors.gray.900/50%)]; 252 264 } 253 265 254 266 .btn-cancel {