Signed-off-by: Anirudh Oppiliappan anirudh@tangled.sh
+12
-14
appview/db/timeline.go
+12
-14
appview/db/timeline.go
···
20
*FollowStats
21
}
22
23
-
const Limit = 50
24
-
25
// TODO: this gathers heterogenous events from different sources and aggregates
26
// them in code; if we did this entirely in sql, we could order and limit and paginate easily
27
-
func MakeTimeline(e Execer) ([]TimelineEvent, error) {
28
var events []TimelineEvent
29
30
-
repos, err := getTimelineRepos(e)
31
if err != nil {
32
return nil, err
33
}
34
35
-
stars, err := getTimelineStars(e)
36
if err != nil {
37
return nil, err
38
}
39
40
-
follows, err := getTimelineFollows(e)
41
if err != nil {
42
return nil, err
43
}
···
51
})
52
53
// Limit the slice to 100 events
54
-
if len(events) > Limit {
55
-
events = events[:Limit]
56
}
57
58
return events, nil
59
}
60
61
-
func getTimelineRepos(e Execer) ([]TimelineEvent, error) {
62
-
repos, err := GetRepos(e, Limit)
63
if err != nil {
64
return nil, err
65
}
···
104
return events, nil
105
}
106
107
-
func getTimelineStars(e Execer) ([]TimelineEvent, error) {
108
-
stars, err := GetStars(e, Limit)
109
if err != nil {
110
return nil, err
111
}
···
131
return events, nil
132
}
133
134
-
func getTimelineFollows(e Execer) ([]TimelineEvent, error) {
135
-
follows, err := GetFollows(e, Limit)
136
if err != nil {
137
return nil, err
138
}
···
20
*FollowStats
21
}
22
23
// TODO: this gathers heterogenous events from different sources and aggregates
24
// them in code; if we did this entirely in sql, we could order and limit and paginate easily
25
+
func MakeTimeline(e Execer, limit int) ([]TimelineEvent, error) {
26
var events []TimelineEvent
27
28
+
repos, err := getTimelineRepos(e, limit)
29
if err != nil {
30
return nil, err
31
}
32
33
+
stars, err := getTimelineStars(e, limit)
34
if err != nil {
35
return nil, err
36
}
37
38
+
follows, err := getTimelineFollows(e, limit)
39
if err != nil {
40
return nil, err
41
}
···
49
})
50
51
// Limit the slice to 100 events
52
+
if len(events) > limit {
53
+
events = events[:limit]
54
}
55
56
return events, nil
57
}
58
59
+
func getTimelineRepos(e Execer, limit int) ([]TimelineEvent, error) {
60
+
repos, err := GetRepos(e, limit)
61
if err != nil {
62
return nil, err
63
}
···
102
return events, nil
103
}
104
105
+
func getTimelineStars(e Execer, limit int) ([]TimelineEvent, error) {
106
+
stars, err := GetStars(e, limit)
107
if err != nil {
108
return nil, err
109
}
···
129
return events, nil
130
}
131
132
+
func getTimelineFollows(e Execer, limit int) ([]TimelineEvent, error) {
133
+
follows, err := GetFollows(e, limit)
134
if err != nil {
135
return nil, err
136
}
+4
appview/pages/pages.go
+4
appview/pages/pages.go
···
1299
return p.execute("strings/string", w, params)
1300
}
1301
1302
+
func (p *Pages) Home(w io.Writer, params TimelineParams) error {
1303
+
return p.execute("timeline/home", w, params)
1304
+
}
1305
+
1306
func (p *Pages) Static() http.Handler {
1307
if p.dev {
1308
return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static")))
+116
appview/pages/templates/timeline/fragments/timeline.html
+116
appview/pages/templates/timeline/fragments/timeline.html
···
···
1
+
{{ define "timeline/fragments/timeline" }}
2
+
<div class="py-4">
3
+
<div class="px-6 pb-4">
4
+
<p class="text-xl font-bold dark:text-white">Timeline</p>
5
+
</div>
6
+
7
+
<div class="flex flex-col gap-4">
8
+
{{ range $i, $e := .Timeline }}
9
+
<div class="relative">
10
+
{{ if ne $i 0 }}
11
+
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
12
+
{{ end }}
13
+
{{ with $e }}
14
+
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
15
+
{{ if .Repo }}
16
+
{{ template "timeline/fragments/repoEvent" (list $ .Repo .Source) }}
17
+
{{ else if .Star }}
18
+
{{ template "timeline/fragments/starEvent" (list $ .Star) }}
19
+
{{ else if .Follow }}
20
+
{{ template "timeline/fragments/followEvent" (list $ .Follow .Profile .FollowStats) }}
21
+
{{ end }}
22
+
</div>
23
+
{{ end }}
24
+
</div>
25
+
{{ end }}
26
+
</div>
27
+
</div>
28
+
{{ end }}
29
+
30
+
{{ define "timeline/fragments/repoEvent" }}
31
+
{{ $root := index . 0 }}
32
+
{{ $repo := index . 1 }}
33
+
{{ $source := index . 2 }}
34
+
{{ $userHandle := resolve $repo.Did }}
35
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
36
+
{{ template "user/fragments/picHandleLink" $repo.Did }}
37
+
{{ with $source }}
38
+
{{ $sourceDid := resolve .Did }}
39
+
forked
40
+
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
41
+
{{ $sourceDid }}/{{ .Name }}
42
+
</a>
43
+
to
44
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
45
+
{{ else }}
46
+
created
47
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
48
+
{{ $repo.Name }}
49
+
</a>
50
+
{{ end }}
51
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
52
+
</div>
53
+
{{ with $repo }}
54
+
{{ template "user/fragments/repoCard" (list $root . true) }}
55
+
{{ end }}
56
+
{{ end }}
57
+
58
+
{{ define "timeline/fragments/starEvent" }}
59
+
{{ $root := index . 0 }}
60
+
{{ $star := index . 1 }}
61
+
{{ with $star }}
62
+
{{ $starrerHandle := resolve .StarredByDid }}
63
+
{{ $repoOwnerHandle := resolve .Repo.Did }}
64
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
65
+
{{ template "user/fragments/picHandleLink" $starrerHandle }}
66
+
starred
67
+
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
68
+
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
69
+
</a>
70
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
71
+
</div>
72
+
{{ with .Repo }}
73
+
{{ template "user/fragments/repoCard" (list $root . true) }}
74
+
{{ end }}
75
+
{{ end }}
76
+
{{ end }}
77
+
78
+
{{ define "timeline/fragments/followEvent" }}
79
+
{{ $root := index . 0 }}
80
+
{{ $follow := index . 1 }}
81
+
{{ $profile := index . 2 }}
82
+
{{ $stat := index . 3 }}
83
+
84
+
{{ $userHandle := resolve $follow.UserDid }}
85
+
{{ $subjectHandle := resolve $follow.SubjectDid }}
86
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
87
+
{{ template "user/fragments/picHandleLink" $userHandle }}
88
+
followed
89
+
{{ template "user/fragments/picHandleLink" $subjectHandle }}
90
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
91
+
</div>
92
+
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
93
+
<div class="flex-shrink-0 max-h-full w-24 h-24">
94
+
<img alt="" class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
95
+
</div>
96
+
97
+
<div class="flex-1 min-h-0 justify-around flex flex-col">
98
+
<a href="/{{ $subjectHandle }}">
99
+
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
100
+
</a>
101
+
{{ with $profile }}
102
+
{{ with .Description }}
103
+
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
104
+
{{ end }}
105
+
{{ end }}
106
+
{{ with $stat }}
107
+
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
108
+
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
109
+
<span id="followers"><a href="/{{ $subjectHandle }}?tab=followers">{{ .Followers }} followers</a></span>
110
+
<span class="select-none after:content-['·']"></span>
111
+
<span id="following"><a href="/{{ $subjectHandle }}?tab=following">{{ .Following }} following</a></span>
112
+
</div>
113
+
{{ end }}
114
+
</div>
115
+
</div>
116
+
{{ end }}
+25
appview/pages/templates/timeline/fragments/trending.html
+25
appview/pages/templates/timeline/fragments/trending.html
···
···
1
+
{{ define "timeline/fragments/trending" }}
2
+
<div class="w-full md:mx-0 py-4">
3
+
<div class="px-6 pb-4">
4
+
<h3 class="text-xl font-bold dark:text-white flex items-center gap-2">
5
+
Trending
6
+
{{ i "trending-up" "size-4 flex-shrink-0" }}
7
+
</h3>
8
+
</div>
9
+
<div class="flex gap-4 overflow-x-auto scrollbar-hide items-stretch">
10
+
{{ range $index, $repo := .Repos }}
11
+
<div class="flex-none h-full border border-gray-200 dark:border-gray-700 rounded-sm w-96">
12
+
{{ template "user/fragments/repoCard" (list $ $repo true) }}
13
+
</div>
14
+
{{ else }}
15
+
<div class="py-8 px-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-sm">
16
+
<div class="text-sm text-gray-500 dark:text-gray-400 text-center">
17
+
No trending repositories this week
18
+
</div>
19
+
</div>
20
+
{{ end }}
21
+
</div>
22
+
</div>
23
+
{{ end }}
24
+
25
+
+118
appview/pages/templates/timeline/home.html
+118
appview/pages/templates/timeline/home.html
···
···
1
+
{{ define "title" }}tangled · tightly-knit social coding{{ end }}
2
+
3
+
{{ define "extrameta" }}
4
+
<meta property="og:title" content="timeline · tangled" />
5
+
<meta property="og:type" content="object" />
6
+
<meta property="og:url" content="https://tangled.sh" />
7
+
<meta property="og:description" content="tightly-knit social coding" />
8
+
{{ end }}
9
+
10
+
11
+
{{ define "content" }}
12
+
<div class="flex flex-col gap-4">
13
+
{{ block "hero" $ }}{{ end }}
14
+
{{ block "features" $ }}{{ end }}
15
+
{{ block "timeline/fragments/trending" $ }}{{ end }}
16
+
{{ block "timeline/fragments/timeline" $ }}{{ end }}
17
+
</div>
18
+
{{ end }}
19
+
20
+
21
+
{{ define "hero" }}
22
+
<div class="mx-auto max-w-[100rem] flex flex-col text-black dark:text-white px-6 py-4 gap-6 items-center md:flex-row">
23
+
<div class="flex flex-col gap-6">
24
+
<h1 class="font-bold text-4xl">tightly-knit<br>social coding.</h1>
25
+
26
+
<p class="text-lg">
27
+
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
28
+
</p>
29
+
<p class="text-lg">
30
+
we envision a place where developers have complete ownership of their
31
+
code, open source communities can freely self-govern and most
32
+
importantly, coding can be social and fun again.
33
+
</p>
34
+
35
+
<div class="flex gap-6 items-center">
36
+
<a href="/signup" class="no-underline hover:no-underline ">
37
+
<button class="btn-create flex gap-2 px-4 items-center">
38
+
join now {{ i "arrow-right" "size-4" }}
39
+
</button>
40
+
</a>
41
+
</div>
42
+
</div>
43
+
44
+
<figure class="w-full hidden md:block md:w-auto">
45
+
<a href="https://tangled.sh/@tangled.sh/core" class="block">
46
+
<img src="https://assets.tangled.network/hero-repo.png" alt="Screenshot of the Tangled monorepo." class="max-w-md mx-auto md:max-w-none w-full md:w-[30vw] h-auto shadow-sm rounded hover:shadow-md transition-shadow" />
47
+
</a>
48
+
<figcaption class="text-sm text-gray-600 dark:text-gray-400 mt-2 text-center">
49
+
Monorepo for Tangled, built in the open with the community.
50
+
</figcaption>
51
+
</figure>
52
+
</div>
53
+
{{ end }}
54
+
55
+
{{ define "feature" }}
56
+
{{ $info := index . 0 }}
57
+
{{ $bullets := index . 1 }}
58
+
<div class="flex flex-col items-top gap-6 md:flex-row md:gap-12">
59
+
<div class="flex-1">
60
+
<h2 class="text-2xl font-bold text-black dark:text-white mb-6">{{ $info.title }}</h2>
61
+
<ul class="leading-normal">
62
+
{{ range $bullets }}
63
+
<li><p>{{ escapeHtml . }}</p></li>
64
+
{{ end }}
65
+
</ul>
66
+
</div>
67
+
<div class="flex-shrink-0 w-96 md:w-1/3">
68
+
<a href="{{ $info.image }}">
69
+
<img src="{{ $info.image }}" alt="{{ $info.alt }}" class="w-full h-auto rounded" />
70
+
</a>
71
+
</div>
72
+
</div>
73
+
{{ end }}
74
+
75
+
{{ define "features" }}
76
+
<div class="prose dark:text-gray-200 space-y-12 px-6 py-4">
77
+
{{ template "feature" (list
78
+
(dict
79
+
"title" "lightweight git repo hosting"
80
+
"image" "https://assets.tangled.network/what-is-tangled-repo.png"
81
+
"alt" "A repository hosted on Tangled"
82
+
)
83
+
(list
84
+
"Host your repositories on your own infrastructure using <em>knots</em>—tiny, headless servers that facilitate git operations."
85
+
"Add friends to your knot or invite collaborators to your repository."
86
+
"Guarded by fine-grained role-based access control."
87
+
"Use SSH to push and pull."
88
+
)
89
+
) }}
90
+
91
+
{{ template "feature" (list
92
+
(dict
93
+
"title" "improved pull request model"
94
+
"image" "https://assets.tangled.network/pulls.png"
95
+
"alt" "Round-based pull requests."
96
+
)
97
+
(list
98
+
"An intuitive and effective round-based pull request flow, with inter-diffing between rounds."
99
+
"Stacked pull requests using Jujutsu's change IDs."
100
+
"Paste a <code>git diff</code> or <code>git format-patch</code> for quick drive-by changes."
101
+
)
102
+
) }}
103
+
104
+
{{ template "feature" (list
105
+
(dict
106
+
"title" "run pipelines using spindles"
107
+
"image" "https://assets.tangled.network/pipelines.png"
108
+
"alt" "CI pipeline running on spindle"
109
+
)
110
+
(list
111
+
"Run pipelines on your own infrastructure using <em>spindles</em>—lightweight CI runners."
112
+
"Natively supports Nix for package management."
113
+
"Easily extended to support different execution backends."
114
+
)
115
+
) }}
116
+
</div>
117
+
{{ end }}
118
+
+6
-172
appview/pages/templates/timeline/timeline.html
+6
-172
appview/pages/templates/timeline/timeline.html
···
8
{{ end }}
9
10
{{ define "content" }}
11
-
{{ if .LoggedInUser }}
12
-
{{ else }}
13
-
{{ block "hero" $ }}{{ end }}
14
-
{{ end }}
15
-
16
-
{{ block "trending" $ }}{{ end }}
17
-
{{ block "timeline" $ }}{{ end }}
18
-
{{ end }}
19
-
20
-
{{ define "hero" }}
21
-
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
22
-
<div class="font-bold text-4xl">tightly-knit<br>social coding.</div>
23
-
24
-
<p class="text-lg">
25
-
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
26
-
</p>
27
-
<p class="text-lg">
28
-
we envision a place where developers have complete ownership of their
29
-
code, open source communities can freely self-govern and most
30
-
importantly, coding can be social and fun again.
31
-
</p>
32
-
33
-
<div class="flex gap-6 items-center">
34
-
<a href="/signup" class="no-underline hover:no-underline ">
35
-
<button class="btn-create flex gap-2 px-4 items-center">
36
-
join now {{ i "arrow-right" "size-4" }}
37
-
</button>
38
-
</a>
39
-
</div>
40
-
</div>
41
-
{{ end }}
42
-
43
-
{{ define "trending" }}
44
-
<div class="w-full md:mx-0 py-4">
45
-
<div class="px-6 pb-4">
46
-
<h3 class="text-xl font-bold dark:text-white flex items-center gap-2">
47
-
Trending
48
-
{{ i "trending-up" "size-4 flex-shrink-0" }}
49
-
</h3>
50
-
</div>
51
-
<div class="flex gap-4 overflow-x-auto scrollbar-hide items-stretch">
52
-
{{ range $index, $repo := .Repos }}
53
-
<div class="flex-none h-full border border-gray-200 dark:border-gray-700 rounded-sm w-96">
54
-
{{ template "user/fragments/repoCard" (list $ $repo true) }}
55
-
</div>
56
-
{{ else }}
57
-
<div class="py-8 px-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-sm">
58
-
<div class="text-sm text-gray-500 dark:text-gray-400 text-center">
59
-
No trending repositories this week
60
-
</div>
61
-
</div>
62
-
{{ end }}
63
-
</div>
64
-
</div>
65
-
{{ end }}
66
-
67
-
{{ define "timeline" }}
68
-
<div class="py-4">
69
-
<div class="px-6 pb-4">
70
-
<p class="text-xl font-bold dark:text-white">Timeline</p>
71
-
</div>
72
-
73
-
<div class="flex flex-col gap-4">
74
-
{{ range $i, $e := .Timeline }}
75
-
<div class="relative">
76
-
{{ if ne $i 0 }}
77
-
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
78
-
{{ end }}
79
-
{{ with $e }}
80
-
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
81
-
{{ if .Repo }}
82
-
{{ block "repoEvent" (list $ .Repo .Source) }} {{ end }}
83
-
{{ else if .Star }}
84
-
{{ block "starEvent" (list $ .Star) }} {{ end }}
85
-
{{ else if .Follow }}
86
-
{{ block "followEvent" (list $ .Follow .Profile .FollowStats) }} {{ end }}
87
-
{{ end }}
88
-
</div>
89
-
{{ end }}
90
-
</div>
91
-
{{ end }}
92
-
</div>
93
-
</div>
94
-
{{ end }}
95
-
96
-
{{ define "repoEvent" }}
97
-
{{ $root := index . 0 }}
98
-
{{ $repo := index . 1 }}
99
-
{{ $source := index . 2 }}
100
-
{{ $userHandle := resolve $repo.Did }}
101
-
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
102
-
{{ template "user/fragments/picHandleLink" $repo.Did }}
103
-
{{ with $source }}
104
-
{{ $sourceDid := resolve .Did }}
105
-
forked
106
-
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
107
-
{{ $sourceDid }}/{{ .Name }}
108
-
</a>
109
-
to
110
-
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
111
-
{{ else }}
112
-
created
113
-
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
114
-
{{ $repo.Name }}
115
-
</a>
116
-
{{ end }}
117
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
118
-
</div>
119
-
{{ with $repo }}
120
-
{{ template "user/fragments/repoCard" (list $root . true) }}
121
-
{{ end }}
122
-
{{ end }}
123
-
124
-
{{ define "starEvent" }}
125
-
{{ $root := index . 0 }}
126
-
{{ $star := index . 1 }}
127
-
{{ with $star }}
128
-
{{ $starrerHandle := resolve .StarredByDid }}
129
-
{{ $repoOwnerHandle := resolve .Repo.Did }}
130
-
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
131
-
{{ template "user/fragments/picHandleLink" $starrerHandle }}
132
-
starred
133
-
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
134
-
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
135
-
</a>
136
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
137
-
</div>
138
-
{{ with .Repo }}
139
-
{{ template "user/fragments/repoCard" (list $root . true) }}
140
-
{{ end }}
141
-
{{ end }}
142
-
{{ end }}
143
-
144
-
145
-
{{ define "followEvent" }}
146
-
{{ $root := index . 0 }}
147
-
{{ $follow := index . 1 }}
148
-
{{ $profile := index . 2 }}
149
-
{{ $stat := index . 3 }}
150
-
151
-
{{ $userHandle := resolve $follow.UserDid }}
152
-
{{ $subjectHandle := resolve $follow.SubjectDid }}
153
-
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
154
-
{{ template "user/fragments/picHandleLink" $userHandle }}
155
-
followed
156
-
{{ template "user/fragments/picHandleLink" $subjectHandle }}
157
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
158
-
</div>
159
-
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
160
-
<div class="flex-shrink-0 max-h-full w-24 h-24">
161
-
<img alt="" class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
162
-
</div>
163
-
164
-
<div class="flex-1 min-h-0 justify-around flex flex-col">
165
-
<a href="/{{ $subjectHandle }}">
166
-
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
167
-
</a>
168
-
{{ with $profile }}
169
-
{{ with .Description }}
170
-
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
171
-
{{ end }}
172
-
{{ end }}
173
-
{{ with $stat }}
174
-
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
175
-
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
176
-
<span id="followers"><a href="/{{ $subjectHandle }}?tab=followers">{{ .Followers }} followers</a></span>
177
-
<span class="select-none after:content-['·']"></span>
178
-
<span id="following"><a href="/{{ $subjectHandle }}?tab=following">{{ .Following }} following</a></span>
179
-
</div>
180
-
{{ end }}
181
-
</div>
182
-
</div>
183
{{ end }}
+2
-1
appview/state/router.go
+2
-1
appview/state/router.go
+33
-1
appview/state/state.go
+33
-1
appview/state/state.go
···
192
})
193
}
194
195
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
196
user := s.oauth.GetUser(r)
197
198
-
timeline, err := db.MakeTimeline(s.db)
199
if err != nil {
200
log.Println(err)
201
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
215
})
216
}
217
218
func (s *State) Keys(w http.ResponseWriter, r *http.Request) {
219
user := chi.URLParam(r, "user")
220
user = strings.TrimPrefix(user, "@")
···
192
})
193
}
194
195
+
func (s *State) HomeOrTimeline(w http.ResponseWriter, r *http.Request) {
196
+
if s.oauth.GetUser(r) != nil {
197
+
s.Timeline(w, r)
198
+
return
199
+
}
200
+
s.Home(w, r)
201
+
}
202
+
203
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
204
user := s.oauth.GetUser(r)
205
206
+
timeline, err := db.MakeTimeline(s.db, 50)
207
if err != nil {
208
log.Println(err)
209
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
223
})
224
}
225
226
+
func (s *State) Home(w http.ResponseWriter, r *http.Request) {
227
+
timeline, err := db.MakeTimeline(s.db, 15)
228
+
if err != nil {
229
+
log.Println(err)
230
+
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
231
+
return
232
+
}
233
+
234
+
repos, err := db.GetTopStarredReposLastWeek(s.db)
235
+
if err != nil {
236
+
log.Println(err)
237
+
s.pages.Notice(w, "topstarredrepos", "Unable to load.")
238
+
return
239
+
}
240
+
241
+
timeline = timeline[:5]
242
+
243
+
s.pages.Home(w, pages.TimelineParams{
244
+
LoggedInUser: nil,
245
+
Timeline: timeline,
246
+
Repos: repos,
247
+
})
248
+
}
249
+
250
func (s *State) Keys(w http.ResponseWriter, r *http.Request) {
251
user := chi.URLParam(r, "user")
252
user = strings.TrimPrefix(user, "@")