diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json
index f8b2bcd0f6..cc06102c46 100644
--- a/options/locale_next/locale_en-US.json
+++ b/options/locale_next/locale_en-US.json
@@ -1,4 +1,9 @@
{
+ "home.welcome.no_activity": "No activity",
+ "home.welcome.activity_hint": "There is nothing in your feed yet. Your actions and activity from repositories that you watch will show up here.",
+ "home.explore_repos": "Explore repositories",
+ "home.explore_users": "Explore users",
+ "home.explore_orgs": "Explore organizations",
"repo.pulls.merged_title_desc": {
"one": "merged %[1]d commit from %[2]s
into %[3]s
%[4]s",
"other": "merged %[1]d commits from %[2]s
into %[3]s
%[4]s"
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index 2c98da1383..a0841c0227 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -90,6 +90,8 @@ func Dashboard(ctx *context.Context) {
cnt, _ := organization.GetOrganizationCount(ctx, ctxUser)
ctx.Data["UserOrgsCount"] = cnt
ctx.Data["MirrorsEnabled"] = setting.Mirror.Enabled
+ ctx.Data["UsersPageIsDisabled"] = setting.Service.Explore.DisableUsersPage
+ ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
ctx.Data["Date"] = date
var uid int64
diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl
index 5dc46dc0a5..3ce3c1eb73 100644
--- a/templates/user/dashboard/dashboard.tmpl
+++ b/templates/user/dashboard/dashboard.tmpl
@@ -5,7 +5,11 @@
{{template "base/alert" .}}
{{template "user/heatmap" .}}
- {{template "user/dashboard/feeds" .}}
+ {{if .Feeds}}
+ {{template "user/dashboard/feeds" .}}
+ {{else}}
+ {{template "user/dashboard/guide" .}}
+ {{end}}
{{template "user/dashboard/repolist" .}}
diff --git a/templates/user/dashboard/guide.tmpl b/templates/user/dashboard/guide.tmpl
new file mode 100644
index 0000000000..a80c211030
--- /dev/null
+++ b/templates/user/dashboard/guide.tmpl
@@ -0,0 +1,16 @@
+
+ {{svg "octicon-inbox" 64 "tw-text-placeholder-text"}}
+
{{ctx.Locale.Tr "home.welcome.no_activity"}}
+
{{ctx.Locale.Tr "home.welcome.activity_hint"}}
+
+
diff --git a/tests/integration/user_dashboard_test.go b/tests/integration/user_dashboard_test.go
index 0ed5193c48..6621caca9b 100644
--- a/tests/integration/user_dashboard_test.go
+++ b/tests/integration/user_dashboard_test.go
@@ -1,5 +1,5 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-3.0-or-later
package integration
@@ -38,6 +38,25 @@ func TestUserDashboardActionLinks(t *testing.T) {
assert.EqualValues(t, locale.TrString("new_org.link"), strings.TrimSpace(links.Find("a[href='/org/create']").Text()))
}
+func TestUserDashboardFeedWelcome(t *testing.T) {
+ require.NoError(t, unittest.PrepareTestDatabase())
+
+ // User2 has some activity in feed
+ session := loginUser(t, "user2")
+ page := NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK).Body)
+ testUserDashboardFeedType(t, page, false)
+
+ // User1 doesn't have any activity in feed
+ session = loginUser(t, "user1")
+ page = NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK).Body)
+ testUserDashboardFeedType(t, page, true)
+}
+
+func testUserDashboardFeedType(t *testing.T, page *HTMLDoc, isEmpty bool) {
+ page.AssertElement(t, "#activity-feed", !isEmpty)
+ page.AssertElement(t, "#empty-feed", isEmpty)
+}
+
func TestDashboardTitleRendering(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
diff --git a/web_src/css/dashboard.css b/web_src/css/dashboard.css
index 4bb9fa38bf..3a1fc34ed3 100644
--- a/web_src/css/dashboard.css
+++ b/web_src/css/dashboard.css
@@ -79,3 +79,7 @@
.dashboard .secondary-nav .ui.dropdown {
max-width: 100%;
}
+
+.dashboard .help {
+ color: var(--color-secondary-dark-8);
+}