From c3e462921ee31536e59b37e654ed20e92a37ffe6 Mon Sep 17 00:00:00 2001
From: KN4CK3R <admin@oldschoolhack.me>
Date: Thu, 1 Feb 2024 18:10:16 +0100
Subject: [PATCH] Improve user search display name (#29002)

I tripped over this strange method and I don't think we need that
workaround to fix the value.

old:

![grafik](https://github.com/go-gitea/gitea/assets/1666336/c8b6797b-eb45-4dec-99db-1b0649a34ec5)

new:

![grafik](https://github.com/go-gitea/gitea/assets/1666336/ab1a65ae-de5b-4ce4-9813-3b8b39c7922e)

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
---
 routers/utils/utils.go                    | 8 --------
 routers/utils/utils_test.go               | 6 ------
 routers/web/org/teams.go                  | 3 +--
 routers/web/repo/setting/collaboration.go | 5 ++---
 web_src/css/base.css                      | 4 ++++
 web_src/css/repo.css                      | 8 +++++---
 web_src/js/features/comp/SearchUserBox.js | 9 ++++-----
 web_src/js/features/repo-settings.js      | 4 ++--
 8 files changed, 18 insertions(+), 29 deletions(-)

diff --git a/routers/utils/utils.go b/routers/utils/utils.go
index d6856fceac..1f4d11fd3c 100644
--- a/routers/utils/utils.go
+++ b/routers/utils/utils.go
@@ -11,14 +11,6 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 )
 
-// RemoveUsernameParameterSuffix returns the username parameter without the (fullname) suffix - leaving just the username
-func RemoveUsernameParameterSuffix(name string) string {
-	if index := strings.Index(name, " ("); index >= 0 {
-		name = name[:index]
-	}
-	return name
-}
-
 // SanitizeFlashErrorString will sanitize a flash error string
 func SanitizeFlashErrorString(x string) string {
 	return strings.ReplaceAll(html.EscapeString(x), "\n", "<br>")
diff --git a/routers/utils/utils_test.go b/routers/utils/utils_test.go
index 6d19214c88..440aad87c6 100644
--- a/routers/utils/utils_test.go
+++ b/routers/utils/utils_test.go
@@ -11,12 +11,6 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestRemoveUsernameParameterSuffix(t *testing.T) {
-	assert.Equal(t, "foobar", RemoveUsernameParameterSuffix("foobar (Foo Bar)"))
-	assert.Equal(t, "foobar", RemoveUsernameParameterSuffix("foobar"))
-	assert.Equal(t, "", RemoveUsernameParameterSuffix(""))
-}
-
 func TestIsExternalURL(t *testing.T) {
 	setting.AppURL = "https://try.gitea.io/"
 	type test struct {
diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go
index 9e65c8ba9c..71fe99c97c 100644
--- a/routers/web/org/teams.go
+++ b/routers/web/org/teams.go
@@ -24,7 +24,6 @@ import (
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/web"
-	"code.gitea.io/gitea/routers/utils"
 	shared_user "code.gitea.io/gitea/routers/web/shared/user"
 	"code.gitea.io/gitea/services/convert"
 	"code.gitea.io/gitea/services/forms"
@@ -127,7 +126,7 @@ func TeamsAction(ctx *context.Context) {
 			ctx.Error(http.StatusNotFound)
 			return
 		}
-		uname := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("uname")))
+		uname := strings.ToLower(ctx.FormString("uname"))
 		var u *user_model.User
 		u, err = user_model.GetUserByName(ctx, uname)
 		if err != nil {
diff --git a/routers/web/repo/setting/collaboration.go b/routers/web/repo/setting/collaboration.go
index e217697cc0..c5c2a88c49 100644
--- a/routers/web/repo/setting/collaboration.go
+++ b/routers/web/repo/setting/collaboration.go
@@ -17,7 +17,6 @@ import (
 	"code.gitea.io/gitea/modules/log"
 	repo_module "code.gitea.io/gitea/modules/repository"
 	"code.gitea.io/gitea/modules/setting"
-	"code.gitea.io/gitea/routers/utils"
 	"code.gitea.io/gitea/services/mailer"
 	org_service "code.gitea.io/gitea/services/org"
 	repo_service "code.gitea.io/gitea/services/repository"
@@ -52,7 +51,7 @@ func Collaboration(ctx *context.Context) {
 
 // CollaborationPost response for actions for a collaboration of a repository
 func CollaborationPost(ctx *context.Context) {
-	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("collaborator")))
+	name := strings.ToLower(ctx.FormString("collaborator"))
 	if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
 		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 		return
@@ -144,7 +143,7 @@ func AddTeamPost(ctx *context.Context) {
 		return
 	}
 
-	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("team")))
+	name := strings.ToLower(ctx.FormString("team"))
 	if len(name) == 0 {
 		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 		return
diff --git a/web_src/css/base.css b/web_src/css/base.css
index cc1f6a8397..198e87c0e2 100644
--- a/web_src/css/base.css
+++ b/web_src/css/base.css
@@ -196,10 +196,14 @@ a.label,
 .ui.search > .results {
   background: var(--color-body);
   border-color: var(--color-secondary);
+  overflow-wrap: anywhere; /* allow text to wrap as fomantic limits this to 18em width */
 }
 
 .ui.search > .results .result {
   background: var(--color-body);
+  border-color: var(--color-secondary);
+  display: flex;
+  align-items: center;
 }
 
 .ui.search > .results .result .title {
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index dfe0d6c77f..55c6ec4817 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -2128,14 +2128,16 @@
 }
 
 #search-user-box .results .result .image {
-  float: left;
-  margin-right: 8px;
+  order: 0;
+  margin-right: 12px;
   width: 2em;
   height: 2em;
+  min-width: 2em;
+  min-height: 2em;
 }
 
 #search-user-box .results .result .content {
-  margin: 6px 0; /* this trick is used to align with the sibling avatar image */
+  margin: 0; /* remove margin reserved for avatar because we move it to left via `order: 0` */
 }
 
 .ui.menu .item > img:not(.ui) {
diff --git a/web_src/js/features/comp/SearchUserBox.js b/web_src/js/features/comp/SearchUserBox.js
index 960b787fea..992d4ef020 100644
--- a/web_src/js/features/comp/SearchUserBox.js
+++ b/web_src/js/features/comp/SearchUserBox.js
@@ -17,14 +17,13 @@ export function initCompSearchUserBox() {
         const searchQuery = $searchUserBox.find('input').val();
         const searchQueryUppercase = searchQuery.toUpperCase();
         $.each(response.data, (_i, item) => {
-          let title = item.login;
-          if (item.full_name && item.full_name.length > 0) {
-            title += ` (${htmlEscape(item.full_name)})`;
-          }
           const resultItem = {
-            title,
+            title: item.login,
             image: item.avatar_url
           };
+          if (item.full_name) {
+            resultItem.description = htmlEscape(item.full_name);
+          }
           if (searchQueryUppercase === item.login.toUpperCase()) {
             items.unshift(resultItem);
           } else {
diff --git a/web_src/js/features/repo-settings.js b/web_src/js/features/repo-settings.js
index 04974200bb..75e624a6a7 100644
--- a/web_src/js/features/repo-settings.js
+++ b/web_src/js/features/repo-settings.js
@@ -52,9 +52,9 @@ export function initRepoSettingSearchTeamBox() {
       onResponse(response) {
         const items = [];
         $.each(response.data, (_i, item) => {
-          const title = `${item.name} (${item.permission} access)`;
           items.push({
-            title,
+            title: item.name,
+            description: `${item.permission} access` // TODO: translate this string
           });
         });