Skip to content

Commit 1df06e3

Browse files
authored
Don't do a full page load when clicking the follow button (#28872)
- Use htmx to perform the button request - `hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}'` to authenticate (we should probably learn to reuse this) - `hx-post="{{.ContextUser.HomeLink}}?action=follow"` to send a POST request to follow the user - `hx-target="#profile-avatar-card"` to target the card div for replacement - `hx-swap="outerHTML"` to replace the card (as opposed to its inner content) with the new card that shows the new follower count and button color - Change the backend response to return a `<div>` tag (the card) instead of a redirect to the user page # Before ![before](https://github.com/go-gitea/gitea/assets/20454870/86899d15-41c9-42ed-bd85-253b9caac7f8) # After ![after](https://github.com/go-gitea/gitea/assets/20454870/59455d96-548c-4a81-a5b0-fab1dc1e87ef) Signed-off-by: Yarden Shoham <git@yardenshoham.com>
1 parent 14f6fcf commit 1df06e3

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

routers/web/user/profile.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"code.gitea.io/gitea/models/db"
1515
repo_model "code.gitea.io/gitea/models/repo"
1616
user_model "code.gitea.io/gitea/models/user"
17+
"code.gitea.io/gitea/modules/base"
1718
"code.gitea.io/gitea/modules/context"
1819
"code.gitea.io/gitea/modules/git"
1920
"code.gitea.io/gitea/modules/log"
@@ -26,6 +27,10 @@ import (
2627
shared_user "code.gitea.io/gitea/routers/web/shared/user"
2728
)
2829

30+
const (
31+
tplProfileBigAvatar base.TplName = "shared/user/profile_big_avatar"
32+
)
33+
2934
// OwnerProfile render profile page for a user or a organization (aka, repo owner)
3035
func OwnerProfile(ctx *context.Context) {
3136
if strings.Contains(ctx.Req.Header.Get("Accept"), "application/rss+xml") {
@@ -309,8 +314,10 @@ func Action(ctx *context.Context) {
309314

310315
if err != nil {
311316
log.Error("Failed to apply action %q: %v", ctx.FormString("action"), err)
312-
ctx.JSONError(fmt.Sprintf("Action %q failed", ctx.FormString("action")))
317+
ctx.Error(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action")))
313318
return
314319
}
315-
ctx.JSONOK()
320+
321+
shared_user.PrepareContextForProfileBigAvatar(ctx)
322+
ctx.HTML(http.StatusOK, tplProfileBigAvatar)
316323
}

templates/shared/user/profile_big_avatar.tmpl

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="ui card">
1+
<div id="profile-avatar-card" class="ui card">
22
<div id="profile-avatar" class="content gt-df">
33
{{if eq .SignedUserID .ContextUser.ID}}
44
<a class="image" href="{{AppSubUrl}}/user/settings" data-tooltip-content="{{ctx.Locale.Tr "user.change_avatar"}}">
@@ -110,13 +110,13 @@
110110
</li>
111111
{{end}}
112112
{{if and .IsSigned (ne .SignedUserID .ContextUser.ID)}}
113-
<li class="follow">
113+
<li class="follow" hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}' hx-target="#profile-avatar-card" hx-swap="outerHTML">
114114
{{if $.IsFollowing}}
115-
<button class="ui basic red button link-action" data-url="{{.ContextUser.HomeLink}}?action=unfollow">
115+
<button hx-post="{{.ContextUser.HomeLink}}?action=unfollow" class="ui basic red button">
116116
{{svg "octicon-person"}} {{ctx.Locale.Tr "user.unfollow"}}
117117
</button>
118118
{{else}}
119-
<button class="ui basic primary button link-action" data-url="{{.ContextUser.HomeLink}}?action=follow">
119+
<button hx-post="{{.ContextUser.HomeLink}}?action=follow" class="ui basic primary button">
120120
{{svg "octicon-person"}} {{ctx.Locale.Tr "user.follow"}}
121121
</button>
122122
{{end}}

0 commit comments

Comments
 (0)