diff --git a/appview/db/timeline.go b/appview/db/timeline.go
index b2b69dd7..a5907722 100644
--- a/appview/db/timeline.go
+++ b/appview/db/timeline.go
@@ -20,24 +20,22 @@ type TimelineEvent struct {
*FollowStats
}
-const Limit = 50
-
// TODO: this gathers heterogenous events from different sources and aggregates
// them in code; if we did this entirely in sql, we could order and limit and paginate easily
-func MakeTimeline(e Execer) ([]TimelineEvent, error) {
+func MakeTimeline(e Execer, limit int) ([]TimelineEvent, error) {
var events []TimelineEvent
- repos, err := getTimelineRepos(e)
+ repos, err := getTimelineRepos(e, limit)
if err != nil {
return nil, err
}
- stars, err := getTimelineStars(e)
+ stars, err := getTimelineStars(e, limit)
if err != nil {
return nil, err
}
- follows, err := getTimelineFollows(e)
+ follows, err := getTimelineFollows(e, limit)
if err != nil {
return nil, err
}
@@ -51,15 +49,15 @@ func MakeTimeline(e Execer) ([]TimelineEvent, error) {
})
// Limit the slice to 100 events
- if len(events) > Limit {
- events = events[:Limit]
+ if len(events) > limit {
+ events = events[:limit]
}
return events, nil
}
-func getTimelineRepos(e Execer) ([]TimelineEvent, error) {
- repos, err := GetRepos(e, Limit)
+func getTimelineRepos(e Execer, limit int) ([]TimelineEvent, error) {
+ repos, err := GetRepos(e, limit)
if err != nil {
return nil, err
}
@@ -104,8 +102,8 @@ func getTimelineRepos(e Execer) ([]TimelineEvent, error) {
return events, nil
}
-func getTimelineStars(e Execer) ([]TimelineEvent, error) {
- stars, err := GetStars(e, Limit)
+func getTimelineStars(e Execer, limit int) ([]TimelineEvent, error) {
+ stars, err := GetStars(e, limit)
if err != nil {
return nil, err
}
@@ -131,8 +129,8 @@ func getTimelineStars(e Execer) ([]TimelineEvent, error) {
return events, nil
}
-func getTimelineFollows(e Execer) ([]TimelineEvent, error) {
- follows, err := GetFollows(e, Limit)
+func getTimelineFollows(e Execer, limit int) ([]TimelineEvent, error) {
+ follows, err := GetFollows(e, limit)
if err != nil {
return nil, err
}
diff --git a/appview/pages/pages.go b/appview/pages/pages.go
index bec12c1c..b85b2f17 100644
--- a/appview/pages/pages.go
+++ b/appview/pages/pages.go
@@ -1299,6 +1299,10 @@ func (p *Pages) SingleString(w io.Writer, params SingleStringParams) error {
return p.execute("strings/string", w, params)
}
+func (p *Pages) Home(w io.Writer, params TimelineParams) error {
+ return p.execute("timeline/home", w, params)
+}
+
func (p *Pages) Static() http.Handler {
if p.dev {
return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static")))
diff --git a/appview/pages/templates/timeline/fragments/hero.html b/appview/pages/templates/timeline/fragments/hero.html
new file mode 100644
index 00000000..1db31f4f
--- /dev/null
+++ b/appview/pages/templates/timeline/fragments/hero.html
@@ -0,0 +1,34 @@
+{{ define "timeline/fragments/hero" }}
+
+
+
tightly-knit social coding.
+
+
+ tangled is new social-enabled git collaboration platform built on atproto .
+
+
+ we envision a place where developers have complete ownership of their
+ code, open source communities can freely self-govern and most
+ importantly, coding can be social and fun again.
+
+
+
+
+
+
+
+
+
+
+ Monorepo for Tangled, built in the open with the community.
+
+
+
+{{ end }}
+
diff --git a/appview/pages/templates/timeline/fragments/timeline.html b/appview/pages/templates/timeline/fragments/timeline.html
new file mode 100644
index 00000000..5c630dab
--- /dev/null
+++ b/appview/pages/templates/timeline/fragments/timeline.html
@@ -0,0 +1,116 @@
+{{ define "timeline/fragments/timeline" }}
+
+
+
+
+ {{ range $i, $e := .Timeline }}
+
+ {{ if ne $i 0 }}
+
+ {{ end }}
+ {{ with $e }}
+
+ {{ if .Repo }}
+ {{ template "timeline/fragments/repoEvent" (list $ .Repo .Source) }}
+ {{ else if .Star }}
+ {{ template "timeline/fragments/starEvent" (list $ .Star) }}
+ {{ else if .Follow }}
+ {{ template "timeline/fragments/followEvent" (list $ .Follow .Profile .FollowStats) }}
+ {{ end }}
+
+ {{ end }}
+
+ {{ end }}
+
+
+{{ end }}
+
+{{ define "timeline/fragments/repoEvent" }}
+ {{ $root := index . 0 }}
+ {{ $repo := index . 1 }}
+ {{ $source := index . 2 }}
+ {{ $userHandle := resolve $repo.Did }}
+
+ {{ template "user/fragments/picHandleLink" $repo.Did }}
+ {{ with $source }}
+ {{ $sourceDid := resolve .Did }}
+ forked
+
+ {{ $sourceDid }}/{{ .Name }}
+
+ to
+
{{ $repo.Name }}
+ {{ else }}
+ created
+
+ {{ $repo.Name }}
+
+ {{ end }}
+
{{ template "repo/fragments/time" $repo.Created }}
+
+ {{ with $repo }}
+ {{ template "user/fragments/repoCard" (list $root . true) }}
+ {{ end }}
+{{ end }}
+
+{{ define "timeline/fragments/starEvent" }}
+ {{ $root := index . 0 }}
+ {{ $star := index . 1 }}
+ {{ with $star }}
+ {{ $starrerHandle := resolve .StarredByDid }}
+ {{ $repoOwnerHandle := resolve .Repo.Did }}
+
+ {{ template "user/fragments/picHandleLink" $starrerHandle }}
+ starred
+
+ {{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
+
+
{{ template "repo/fragments/time" .Created }}
+
+ {{ with .Repo }}
+ {{ template "user/fragments/repoCard" (list $root . true) }}
+ {{ end }}
+ {{ end }}
+{{ end }}
+
+{{ define "timeline/fragments/followEvent" }}
+ {{ $root := index . 0 }}
+ {{ $follow := index . 1 }}
+ {{ $profile := index . 2 }}
+ {{ $stat := index . 3 }}
+
+ {{ $userHandle := resolve $follow.UserDid }}
+ {{ $subjectHandle := resolve $follow.SubjectDid }}
+
+ {{ template "user/fragments/picHandleLink" $userHandle }}
+ followed
+ {{ template "user/fragments/picHandleLink" $subjectHandle }}
+ {{ template "repo/fragments/time" $follow.FollowedAt }}
+
+
+
+
+
+
+
+
+{{ end }}
diff --git a/appview/pages/templates/timeline/fragments/trending.html b/appview/pages/templates/timeline/fragments/trending.html
new file mode 100644
index 00000000..fb92e74b
--- /dev/null
+++ b/appview/pages/templates/timeline/fragments/trending.html
@@ -0,0 +1,25 @@
+{{ define "timeline/fragments/trending" }}
+
+
+
+ Trending
+ {{ i "trending-up" "size-4 flex-shrink-0" }}
+
+
+
+
+{{ end }}
+
+
diff --git a/appview/pages/templates/timeline/home.html b/appview/pages/templates/timeline/home.html
new file mode 100644
index 00000000..e4207402
--- /dev/null
+++ b/appview/pages/templates/timeline/home.html
@@ -0,0 +1,90 @@
+{{ define "title" }}tangled · tightly-knit social coding{{ end }}
+
+{{ define "extrameta" }}
+
+
+
+
+{{ end }}
+
+
+{{ define "content" }}
+
+ {{ template "timeline/fragments/hero" . }}
+ {{ template "features" . }}
+ {{ template "timeline/fragments/trending" . }}
+ {{ template "timeline/fragments/timeline" . }}
+
+
+{{ end }}
+
+
+{{ define "feature" }}
+ {{ $info := index . 0 }}
+ {{ $bullets := index . 1 }}
+
+
+
{{ $info.title }}
+
+ {{ range $bullets }}
+ {{ escapeHtml . }}
+ {{ end }}
+
+
+
+
+{{ end }}
+
+{{ define "features" }}
+
+ {{ template "feature" (list
+ (dict
+ "title" "lightweight git repo hosting"
+ "image" "https://assets.tangled.network/what-is-tangled-repo.png"
+ "alt" "A repository hosted on Tangled"
+ )
+ (list
+ "Host your repositories on your own infrastructure using knots —tiny, headless servers that facilitate git operations."
+ "Add friends to your knot or invite collaborators to your repository."
+ "Guarded by fine-grained role-based access control."
+ "Use SSH to push and pull."
+ )
+ ) }}
+
+ {{ template "feature" (list
+ (dict
+ "title" "improved pull request model"
+ "image" "https://assets.tangled.network/pulls.png"
+ "alt" "Round-based pull requests."
+ )
+ (list
+ "An intuitive and effective round-based pull request flow, with inter-diffing between rounds."
+ "Stacked pull requests using Jujutsu's change IDs."
+ "Paste a git diff or git format-patch for quick drive-by changes."
+ )
+ ) }}
+
+ {{ template "feature" (list
+ (dict
+ "title" "run pipelines using spindles"
+ "image" "https://assets.tangled.network/pipelines.png"
+ "alt" "CI pipeline running on spindle"
+ )
+ (list
+ "Run pipelines on your own infrastructure using spindles —lightweight CI runners."
+ "Natively supports Nix for package management."
+ "Easily extended to support different execution backends."
+ )
+ ) }}
+
+{{ end }}
+
diff --git a/appview/pages/templates/timeline/timeline.html b/appview/pages/templates/timeline/timeline.html
index 2ae1695b..65f3d84b 100644
--- a/appview/pages/templates/timeline/timeline.html
+++ b/appview/pages/templates/timeline/timeline.html
@@ -8,176 +8,11 @@
{{ end }}
{{ define "content" }}
- {{ if .LoggedInUser }}
- {{ else }}
- {{ block "hero" $ }}{{ end }}
- {{ end }}
+ {{ if .LoggedInUser }}
+ {{ else }}
+ {{ template "timeline/fragments/hero" . }}
+ {{ end }}
- {{ block "trending" $ }}{{ end }}
- {{ block "timeline" $ }}{{ end }}
-{{ end }}
-
-{{ define "hero" }}
-
-
tightly-knit social coding.
-
-
- tangled is new social-enabled git collaboration platform built on atproto .
-
-
- we envision a place where developers have complete ownership of their
- code, open source communities can freely self-govern and most
- importantly, coding can be social and fun again.
-
-
-
-
-{{ end }}
-
-{{ define "trending" }}
-
-
-
- Trending
- {{ i "trending-up" "size-4 flex-shrink-0" }}
-
-
-
-
-{{ end }}
-
-{{ define "timeline" }}
-
-
-
-
- {{ range $i, $e := .Timeline }}
-
- {{ if ne $i 0 }}
-
- {{ end }}
- {{ with $e }}
-
- {{ if .Repo }}
- {{ block "repoEvent" (list $ .Repo .Source) }} {{ end }}
- {{ else if .Star }}
- {{ block "starEvent" (list $ .Star) }} {{ end }}
- {{ else if .Follow }}
- {{ block "followEvent" (list $ .Follow .Profile .FollowStats) }} {{ end }}
- {{ end }}
-
- {{ end }}
-
- {{ end }}
-
-
-{{ end }}
-
-{{ define "repoEvent" }}
- {{ $root := index . 0 }}
- {{ $repo := index . 1 }}
- {{ $source := index . 2 }}
- {{ $userHandle := resolve $repo.Did }}
-
- {{ template "user/fragments/picHandleLink" $repo.Did }}
- {{ with $source }}
- {{ $sourceDid := resolve .Did }}
- forked
-
- {{ $sourceDid }}/{{ .Name }}
-
- to
-
{{ $repo.Name }}
- {{ else }}
- created
-
- {{ $repo.Name }}
-
- {{ end }}
-
{{ template "repo/fragments/time" $repo.Created }}
-
- {{ with $repo }}
- {{ template "user/fragments/repoCard" (list $root . true) }}
- {{ end }}
-{{ end }}
-
-{{ define "starEvent" }}
- {{ $root := index . 0 }}
- {{ $star := index . 1 }}
- {{ with $star }}
- {{ $starrerHandle := resolve .StarredByDid }}
- {{ $repoOwnerHandle := resolve .Repo.Did }}
-
- {{ template "user/fragments/picHandleLink" $starrerHandle }}
- starred
-
- {{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
-
-
{{ template "repo/fragments/time" .Created }}
-
- {{ with .Repo }}
- {{ template "user/fragments/repoCard" (list $root . true) }}
- {{ end }}
- {{ end }}
-{{ end }}
-
-
-{{ define "followEvent" }}
- {{ $root := index . 0 }}
- {{ $follow := index . 1 }}
- {{ $profile := index . 2 }}
- {{ $stat := index . 3 }}
-
- {{ $userHandle := resolve $follow.UserDid }}
- {{ $subjectHandle := resolve $follow.SubjectDid }}
-
- {{ template "user/fragments/picHandleLink" $userHandle }}
- followed
- {{ template "user/fragments/picHandleLink" $subjectHandle }}
- {{ template "repo/fragments/time" $follow.FollowedAt }}
-
-
-
-
-
-
-
-
+ {{ template "timeline/fragments/trending" . }}
+ {{ template "timeline/fragments/timeline" . }}
{{ end }}
diff --git a/appview/state/router.go b/appview/state/router.go
index a41ee4b4..9b48ea96 100644
--- a/appview/state/router.go
+++ b/appview/state/router.go
@@ -111,7 +111,8 @@ func (s *State) StandardRouter(mw *middleware.Middleware) http.Handler {
r.Handle("/static/*", s.pages.Static())
- r.Get("/", s.Timeline)
+ r.Get("/", s.HomeOrTimeline)
+ r.Get("/timeline", s.Timeline)
r.Route("/repo", func(r chi.Router) {
r.Route("/new", func(r chi.Router) {
diff --git a/appview/state/state.go b/appview/state/state.go
index 168e8fd3..c41539fb 100644
--- a/appview/state/state.go
+++ b/appview/state/state.go
@@ -192,10 +192,18 @@ func (s *State) PrivacyPolicy(w http.ResponseWriter, r *http.Request) {
})
}
+func (s *State) HomeOrTimeline(w http.ResponseWriter, r *http.Request) {
+ if s.oauth.GetUser(r) != nil {
+ s.Timeline(w, r)
+ return
+ }
+ s.Home(w, r)
+}
+
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
user := s.oauth.GetUser(r)
- timeline, err := db.MakeTimeline(s.db)
+ timeline, err := db.MakeTimeline(s.db, 50)
if err != nil {
log.Println(err)
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
@@ -215,6 +223,30 @@ func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
})
}
+func (s *State) Home(w http.ResponseWriter, r *http.Request) {
+ timeline, err := db.MakeTimeline(s.db, 15)
+ if err != nil {
+ log.Println(err)
+ s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
+ return
+ }
+
+ repos, err := db.GetTopStarredReposLastWeek(s.db)
+ if err != nil {
+ log.Println(err)
+ s.pages.Notice(w, "topstarredrepos", "Unable to load.")
+ return
+ }
+
+ timeline = timeline[:5]
+
+ s.pages.Home(w, pages.TimelineParams{
+ LoggedInUser: nil,
+ Timeline: timeline,
+ Repos: repos,
+ })
+}
+
func (s *State) Keys(w http.ResponseWriter, r *http.Request) {
user := chi.URLParam(r, "user")
user = strings.TrimPrefix(user, "@")