aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2025-03-25 14:17:58 +0800
committerGitHub <noreply@github.com>2025-03-25 06:17:58 +0000
commit41c946a66faa06e1a39f91ff6900f05106d0695a (patch)
treeb70dc8f41f4132c923509c048c0a0dda9ca6a59d
parent32258e0f22e6e9d0564c353b9fe596389be0edbc (diff)
downloadgitea-41c946a66faa06e1a39f91ff6900f05106d0695a.tar.gz
gitea-41c946a66faa06e1a39f91ff6900f05106d0695a.zip
Prepare common tmpl functions in a middleware (#33957)
Fix the TODO in `routers/web/web.go`, and avoid the unnecessary `GetActiveStopwatch` SQL query in non-related route handlers.
-rw-r--r--routers/common/pagetmpl.go75
-rw-r--r--routers/web/repo/issue_stopwatch.go38
-rw-r--r--routers/web/user/notification.go27
-rw-r--r--routers/web/web.go4
-rw-r--r--templates/base/head_navbar.tmpl25
-rw-r--r--templates/user/notification/notification_div.tmpl2
6 files changed, 91 insertions, 80 deletions
diff --git a/routers/common/pagetmpl.go b/routers/common/pagetmpl.go
new file mode 100644
index 0000000000..52c9fceba3
--- /dev/null
+++ b/routers/common/pagetmpl.go
@@ -0,0 +1,75 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package common
+
+import (
+ goctx "context"
+ "errors"
+
+ activities_model "code.gitea.io/gitea/models/activities"
+ "code.gitea.io/gitea/models/db"
+ issues_model "code.gitea.io/gitea/models/issues"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/services/context"
+)
+
+// StopwatchTmplInfo is a view on a stopwatch specifically for template rendering
+type StopwatchTmplInfo struct {
+ IssueLink string
+ RepoSlug string
+ IssueIndex int64
+ Seconds int64
+}
+
+func getActiveStopwatch(goCtx goctx.Context) *StopwatchTmplInfo {
+ ctx := context.GetWebContext(goCtx)
+ if ctx.Doer == nil {
+ return nil
+ }
+
+ _, sw, issue, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
+ if err != nil {
+ if !errors.Is(err, goctx.Canceled) {
+ log.Error("Unable to HasUserStopwatch for user:%-v: %v", ctx.Doer, err)
+ }
+ return nil
+ }
+
+ if sw == nil || sw.ID == 0 {
+ return nil
+ }
+
+ return &StopwatchTmplInfo{
+ issue.Link(),
+ issue.Repo.FullName(),
+ issue.Index,
+ sw.Seconds() + 1, // ensure time is never zero in ui
+ }
+}
+
+func notificationUnreadCount(goCtx goctx.Context) int64 {
+ ctx := context.GetWebContext(goCtx)
+ if ctx.Doer == nil {
+ return 0
+ }
+ count, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{
+ UserID: ctx.Doer.ID,
+ Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread},
+ })
+ if err != nil {
+ if !errors.Is(err, goctx.Canceled) {
+ log.Error("Unable to find notification for user:%-v: %v", ctx.Doer, err)
+ }
+ return 0
+ }
+ return count
+}
+
+func PageTmplFunctions(ctx *context.Context) {
+ if ctx.IsSigned {
+ // defer the function call to the last moment when the tmpl renders
+ ctx.Data["NotificationUnreadCount"] = notificationUnreadCount
+ ctx.Data["GetActiveStopwatch"] = getActiveStopwatch
+ }
+}
diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go
index 73e279e0a6..5a8d203771 100644
--- a/routers/web/repo/issue_stopwatch.go
+++ b/routers/web/repo/issue_stopwatch.go
@@ -4,8 +4,6 @@
package repo
import (
- "strings"
-
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/eventsource"
@@ -72,39 +70,3 @@ func CancelStopwatch(c *context.Context) {
c.JSONRedirect("")
}
-
-// GetActiveStopwatch is the middleware that sets .ActiveStopwatch on context
-func GetActiveStopwatch(ctx *context.Context) {
- if strings.HasPrefix(ctx.Req.URL.Path, "/api") {
- return
- }
-
- if !ctx.IsSigned {
- return
- }
-
- _, sw, issue, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
- if err != nil {
- ctx.ServerError("HasUserStopwatch", err)
- return
- }
-
- if sw == nil || sw.ID == 0 {
- return
- }
-
- ctx.Data["ActiveStopwatch"] = StopwatchTmplInfo{
- issue.Link(),
- issue.Repo.FullName(),
- issue.Index,
- sw.Seconds() + 1, // ensure time is never zero in ui
- }
-}
-
-// StopwatchTmplInfo is a view on a stopwatch specifically for template rendering
-type StopwatchTmplInfo struct {
- IssueLink string
- RepoSlug string
- IssueIndex int64
- Seconds int64
-}
diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go
index 1c91ff6364..f0c4390852 100644
--- a/routers/web/user/notification.go
+++ b/routers/web/user/notification.go
@@ -4,7 +4,6 @@
package user
import (
- goctx "context"
"errors"
"fmt"
"net/http"
@@ -35,32 +34,6 @@ const (
tplNotificationSubscriptions templates.TplName = "user/notification/notification_subscriptions"
)
-// GetNotificationCount is the middleware that sets the notification count in the context
-func GetNotificationCount(ctx *context.Context) {
- if strings.HasPrefix(ctx.Req.URL.Path, "/api") {
- return
- }
-
- if !ctx.IsSigned {
- return
- }
-
- ctx.Data["NotificationUnreadCount"] = func() int64 {
- count, err := db.Count[activities_model.Notification](ctx, activities_model.FindNotificationOptions{
- UserID: ctx.Doer.ID,
- Status: []activities_model.NotificationStatus{activities_model.NotificationStatusUnread},
- })
- if err != nil {
- if err != goctx.Canceled {
- log.Error("Unable to GetNotificationCount for user:%-v: %v", ctx.Doer, err)
- }
- return -1
- }
-
- return count
- }
-}
-
// Notifications is the notifications page
func Notifications(ctx *context.Context) {
getNotifications(ctx)
diff --git a/routers/web/web.go b/routers/web/web.go
index 463f486250..4d635f04f0 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -280,10 +280,8 @@ func Routes() *web.Router {
routes.Get("/api/swagger", append(mid, misc.Swagger)...) // Render V1 by default
}
- // TODO: These really seem like things that could be folded into Contexter or as helper functions
- mid = append(mid, user.GetNotificationCount)
- mid = append(mid, repo.GetActiveStopwatch)
mid = append(mid, goGet)
+ mid = append(mid, common.PageTmplFunctions)
others := web.NewRouter()
others.Use(mid...)
diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl
index eab6c00840..35e14d38d3 100644
--- a/templates/base/head_navbar.tmpl
+++ b/templates/base/head_navbar.tmpl
@@ -1,8 +1,11 @@
{{$notificationUnreadCount := 0}}
{{if and .IsSigned .NotificationUnreadCount}}
- {{$notificationUnreadCount = call .NotificationUnreadCount}}
+ {{$notificationUnreadCount = call .NotificationUnreadCount ctx}}
+{{end}}
+{{$activeStopwatch := NIL}}
+{{if and .IsSigned EnableTimetracking .GetActiveStopwatch}}
+ {{$activeStopwatch = call .GetActiveStopwatch ctx}}
{{end}}
-
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
<div class="navbar-left">
<!-- the logo -->
@@ -12,8 +15,8 @@
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu navbar-mobile-right only-mobile">
- {{if and .IsSigned EnableTimetracking .ActiveStopwatch}}
- <a id="mobile-stopwatch-icon" class="active-stopwatch item" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{.ActiveStopwatch.Seconds}}">
+ {{if $activeStopwatch}}
+ <a id="mobile-stopwatch-icon" class="active-stopwatch item" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
<div class="tw-relative">
{{svg "octicon-stopwatch"}}
<span class="header-stopwatch-dot"></span>
@@ -82,8 +85,8 @@
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else if .IsSigned}}
- {{if and EnableTimetracking .ActiveStopwatch}}
- <a class="item not-mobile active-stopwatch" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{.ActiveStopwatch.Seconds}}">
+ {{if $activeStopwatch}}
+ <a class="item not-mobile active-stopwatch" href="{{$activeStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{$activeStopwatch.Seconds}}">
<div class="tw-relative">
{{svg "octicon-stopwatch"}}
<span class="header-stopwatch-dot"></span>
@@ -186,15 +189,15 @@
{{end}}
</div><!-- end full right menu -->
- {{if and .IsSigned EnableTimetracking .ActiveStopwatch}}
+ {{if $activeStopwatch}}
<div class="active-stopwatch-popup tippy-target">
<div class="tw-flex tw-items-center tw-gap-2 tw-p-3">
- <a class="stopwatch-link tw-flex tw-items-center tw-gap-2 muted" href="{{.ActiveStopwatch.IssueLink}}">
+ <a class="stopwatch-link tw-flex tw-items-center tw-gap-2 muted" href="{{$activeStopwatch.IssueLink}}">
{{svg "octicon-issue-opened" 16}}
- <span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span>
+ <span class="stopwatch-issue">{{$activeStopwatch.RepoSlug}}#{{$activeStopwatch.IssueIndex}}</span>
</a>
<div class="tw-flex tw-gap-1">
- <form class="stopwatch-commit form-fetch-action" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle">
+ <form class="stopwatch-commit form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/toggle">
{{.CsrfTokenHtml}}
<button
type="submit"
@@ -202,7 +205,7 @@
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}"
>{{svg "octicon-square-fill"}}</button>
</form>
- <form class="stopwatch-cancel form-fetch-action" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel">
+ <form class="stopwatch-cancel form-fetch-action" method="post" action="{{$activeStopwatch.IssueLink}}/times/stopwatch/cancel">
{{.CsrfTokenHtml}}
<button
type="submit"
diff --git a/templates/user/notification/notification_div.tmpl b/templates/user/notification/notification_div.tmpl
index 0d2371a358..9af2cd53b3 100644
--- a/templates/user/notification/notification_div.tmpl
+++ b/templates/user/notification/notification_div.tmpl
@@ -1,6 +1,6 @@
<div role="main" aria-label="{{.Title}}" class="page-content user notification" id="notification_div" data-sequence-number="{{.SequenceNumber}}">
<div class="ui container">
- {{$notificationUnreadCount := call .NotificationUnreadCount}}
+ {{$notificationUnreadCount := call .NotificationUnreadCount ctx}}
<div class="tw-flex tw-items-center tw-justify-between tw-mb-[--page-spacing]">
<div class="small-menu-items ui compact tiny menu">
<a class="{{if eq .Status 1}}active {{end}}item" href="{{AppSubUrl}}/notifications?q=unread">