appview/pages: display home page to logged out users #551

merged
opened by oppi.li targeting master from push-prszwlupsoqz
Changed files
+322 -187
appview
+12 -14
appview/db/timeline.go
···
*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) {
var events []TimelineEvent
-
repos, err := getTimelineRepos(e)
if err != nil {
return nil, err
}
-
stars, err := getTimelineStars(e)
if err != nil {
return nil, err
}
-
follows, err := getTimelineFollows(e)
if err != nil {
return nil, err
}
···
})
// Limit the slice to 100 events
-
if len(events) > Limit {
-
events = events[:Limit]
}
return events, nil
}
-
func getTimelineRepos(e Execer) ([]TimelineEvent, error) {
-
repos, err := GetRepos(e, Limit)
if err != nil {
return nil, err
}
···
return events, nil
}
-
func getTimelineStars(e Execer) ([]TimelineEvent, error) {
-
stars, err := GetStars(e, Limit)
if err != nil {
return nil, err
}
···
return events, nil
}
-
func getTimelineFollows(e Execer) ([]TimelineEvent, error) {
-
follows, err := GetFollows(e, Limit)
if err != nil {
return nil, err
}
···
*FollowStats
}
// 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, limit int) ([]TimelineEvent, error) {
var events []TimelineEvent
+
repos, err := getTimelineRepos(e, limit)
if err != nil {
return nil, err
}
+
stars, err := getTimelineStars(e, limit)
if err != nil {
return nil, err
}
+
follows, err := getTimelineFollows(e, limit)
if err != nil {
return nil, err
}
···
})
// Limit the slice to 100 events
+
if len(events) > limit {
+
events = events[:limit]
}
return events, nil
}
+
func getTimelineRepos(e Execer, limit int) ([]TimelineEvent, error) {
+
repos, err := GetRepos(e, limit)
if err != nil {
return nil, err
}
···
return events, nil
}
+
func getTimelineStars(e Execer, limit int) ([]TimelineEvent, error) {
+
stars, err := GetStars(e, limit)
if err != nil {
return nil, err
}
···
return events, nil
}
+
func getTimelineFollows(e Execer, limit int) ([]TimelineEvent, error) {
+
follows, err := GetFollows(e, limit)
if err != nil {
return nil, err
}
+4
appview/pages/pages.go
···
return p.execute("strings/string", w, params)
}
func (p *Pages) Static() http.Handler {
if p.dev {
return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static")))
···
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")))
+34
appview/pages/templates/timeline/fragments/hero.html
···
···
+
{{ define "timeline/fragments/hero" }}
+
<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">
+
<div class="flex flex-col gap-6">
+
<h1 class="font-bold text-4xl">tightly-knit<br>social coding.</h1>
+
+
<p class="text-lg">
+
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
+
</p>
+
<p class="text-lg">
+
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.
+
</p>
+
+
<div class="flex gap-6 items-center">
+
<a href="/signup" class="no-underline hover:no-underline ">
+
<button class="btn-create flex gap-2 px-4 items-center">
+
join now {{ i "arrow-right" "size-4" }}
+
</button>
+
</a>
+
</div>
+
</div>
+
+
<figure class="w-full hidden md:block md:w-auto">
+
<a href="https://tangled.sh/@tangled.sh/core" class="block">
+
<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" />
+
</a>
+
<figcaption class="text-sm text-gray-600 dark:text-gray-400 mt-2 text-center">
+
Monorepo for Tangled, built in the open with the community.
+
</figcaption>
+
</figure>
+
</div>
+
{{ end }}
+
+116
appview/pages/templates/timeline/fragments/timeline.html
···
···
+
{{ define "timeline/fragments/timeline" }}
+
<div class="py-4">
+
<div class="px-6 pb-4">
+
<p class="text-xl font-bold dark:text-white">Timeline</p>
+
</div>
+
+
<div class="flex flex-col gap-4">
+
{{ range $i, $e := .Timeline }}
+
<div class="relative">
+
{{ if ne $i 0 }}
+
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
+
{{ end }}
+
{{ with $e }}
+
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
+
{{ 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 }}
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+
+
{{ define "timeline/fragments/repoEvent" }}
+
{{ $root := index . 0 }}
+
{{ $repo := index . 1 }}
+
{{ $source := index . 2 }}
+
{{ $userHandle := resolve $repo.Did }}
+
<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">
+
{{ template "user/fragments/picHandleLink" $repo.Did }}
+
{{ with $source }}
+
{{ $sourceDid := resolve .Did }}
+
forked
+
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
+
{{ $sourceDid }}/{{ .Name }}
+
</a>
+
to
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
+
{{ else }}
+
created
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
+
{{ $repo.Name }}
+
</a>
+
{{ end }}
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
+
</div>
+
{{ 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 }}
+
<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">
+
{{ template "user/fragments/picHandleLink" $starrerHandle }}
+
starred
+
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
+
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
+
</a>
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
+
</div>
+
{{ 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 }}
+
<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">
+
{{ template "user/fragments/picHandleLink" $userHandle }}
+
followed
+
{{ template "user/fragments/picHandleLink" $subjectHandle }}
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
+
</div>
+
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
+
<div class="flex-shrink-0 max-h-full w-24 h-24">
+
<img alt="" class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
+
</div>
+
+
<div class="flex-1 min-h-0 justify-around flex flex-col">
+
<a href="/{{ $subjectHandle }}">
+
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
+
</a>
+
{{ with $profile }}
+
{{ with .Description }}
+
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
+
{{ end }}
+
{{ end }}
+
{{ with $stat }}
+
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
+
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
+
<span id="followers"><a href="/{{ $subjectHandle }}?tab=followers">{{ .Followers }} followers</a></span>
+
<span class="select-none after:content-['·']"></span>
+
<span id="following"><a href="/{{ $subjectHandle }}?tab=following">{{ .Following }} following</a></span>
+
</div>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+25
appview/pages/templates/timeline/fragments/trending.html
···
···
+
{{ define "timeline/fragments/trending" }}
+
<div class="w-full md:mx-0 py-4">
+
<div class="px-6 pb-4">
+
<h3 class="text-xl font-bold dark:text-white flex items-center gap-2">
+
Trending
+
{{ i "trending-up" "size-4 flex-shrink-0" }}
+
</h3>
+
</div>
+
<div class="flex gap-4 overflow-x-auto scrollbar-hide items-stretch">
+
{{ range $index, $repo := .Repos }}
+
<div class="flex-none h-full border border-gray-200 dark:border-gray-700 rounded-sm w-96">
+
{{ template "user/fragments/repoCard" (list $ $repo true) }}
+
</div>
+
{{ else }}
+
<div class="py-8 px-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-sm">
+
<div class="text-sm text-gray-500 dark:text-gray-400 text-center">
+
No trending repositories this week
+
</div>
+
</div>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+
+
+90
appview/pages/templates/timeline/home.html
···
···
+
{{ define "title" }}tangled &middot; tightly-knit social coding{{ end }}
+
+
{{ define "extrameta" }}
+
<meta property="og:title" content="timeline · tangled" />
+
<meta property="og:type" content="object" />
+
<meta property="og:url" content="https://tangled.sh" />
+
<meta property="og:description" content="tightly-knit social coding" />
+
{{ end }}
+
+
+
{{ define "content" }}
+
<div class="flex flex-col gap-4">
+
{{ template "timeline/fragments/hero" . }}
+
{{ template "features" . }}
+
{{ template "timeline/fragments/trending" . }}
+
{{ template "timeline/fragments/timeline" . }}
+
<div class="flex justify-end">
+
<a href="/timeline" class="inline-flex items-center gap-2 text-gray-500 dark:text-gray-400">
+
view more
+
{{ i "arrow-right" "size-4" }}
+
</a>
+
</div>
+
</div>
+
{{ end }}
+
+
+
{{ define "feature" }}
+
{{ $info := index . 0 }}
+
{{ $bullets := index . 1 }}
+
<div class="flex flex-col items-top gap-6 md:flex-row md:gap-12">
+
<div class="flex-1">
+
<h2 class="text-2xl font-bold text-black dark:text-white mb-6">{{ $info.title }}</h2>
+
<ul class="leading-normal">
+
{{ range $bullets }}
+
<li><p>{{ escapeHtml . }}</p></li>
+
{{ end }}
+
</ul>
+
</div>
+
<div class="flex-shrink-0 w-96 md:w-1/3">
+
<a href="{{ $info.image }}">
+
<img src="{{ $info.image }}" alt="{{ $info.alt }}" class="w-full h-auto rounded" />
+
</a>
+
</div>
+
</div>
+
{{ end }}
+
+
{{ define "features" }}
+
<div class="prose dark:text-gray-200 space-y-12 px-6 py-4">
+
{{ 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 <em>knots</em>&mdash;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 <code>git diff</code> or <code>git format-patch</code> 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 <em>spindles</em>&mdash;lightweight CI runners."
+
"Natively supports Nix for package management."
+
"Easily extended to support different execution backends."
+
)
+
) }}
+
</div>
+
{{ end }}
+
+6 -171
appview/pages/templates/timeline/timeline.html
···
{{ end }}
{{ define "content" }}
-
{{ if .LoggedInUser }}
-
{{ else }}
-
{{ block "hero" $ }}{{ end }}
-
{{ end }}
-
{{ block "trending" $ }}{{ end }}
-
{{ block "timeline" $ }}{{ end }}
-
{{ end }}
-
-
{{ define "hero" }}
-
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
-
<div class="font-bold text-4xl">tightly-knit<br>social coding.</div>
-
-
<p class="text-lg">
-
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
-
</p>
-
<p class="text-lg">
-
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.
-
</p>
-
-
<div class="flex gap-6 items-center">
-
<a href="/signup" class="no-underline hover:no-underline ">
-
<button class="btn-create flex gap-2 px-4 items-center">
-
join now {{ i "arrow-right" "size-4" }}
-
</button>
-
</a>
-
</div>
-
</div>
-
{{ end }}
-
-
{{ define "trending" }}
-
<div class="w-full md:mx-0 py-4">
-
<div class="px-6 pb-4">
-
<h3 class="text-xl font-bold dark:text-white flex items-center gap-2">
-
Trending
-
{{ i "trending-up" "size-4 flex-shrink-0" }}
-
</h3>
-
</div>
-
<div class="flex gap-4 overflow-x-auto scrollbar-hide items-stretch">
-
{{ range $index, $repo := .Repos }}
-
<div class="flex-none h-full border border-gray-200 dark:border-gray-700 rounded-sm w-96">
-
{{ template "user/fragments/repoCard" (list $ $repo true) }}
-
</div>
-
{{ else }}
-
<div class="py-8 px-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-sm">
-
<div class="text-sm text-gray-500 dark:text-gray-400 text-center">
-
No trending repositories this week
-
</div>
-
</div>
-
{{ end }}
-
</div>
-
</div>
-
{{ end }}
-
-
{{ define "timeline" }}
-
<div class="py-4">
-
<div class="px-6 pb-4">
-
<p class="text-xl font-bold dark:text-white">Timeline</p>
-
</div>
-
-
<div class="flex flex-col gap-4">
-
{{ range $i, $e := .Timeline }}
-
<div class="relative">
-
{{ if ne $i 0 }}
-
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
-
{{ end }}
-
{{ with $e }}
-
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
-
{{ 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 }}
-
</div>
-
{{ end }}
-
</div>
-
{{ end }}
-
</div>
-
</div>
-
{{ end }}
-
-
{{ define "repoEvent" }}
-
{{ $root := index . 0 }}
-
{{ $repo := index . 1 }}
-
{{ $source := index . 2 }}
-
{{ $userHandle := resolve $repo.Did }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $repo.Did }}
-
{{ with $source }}
-
{{ $sourceDid := resolve .Did }}
-
forked
-
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
-
{{ $sourceDid }}/{{ .Name }}
-
</a>
-
to
-
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
-
{{ else }}
-
created
-
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
-
{{ $repo.Name }}
-
</a>
-
{{ end }}
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
-
</div>
-
{{ 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 }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $starrerHandle }}
-
starred
-
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
-
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
-
</a>
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
-
</div>
-
{{ 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 }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $userHandle }}
-
followed
-
{{ template "user/fragments/picHandleLink" $subjectHandle }}
-
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
-
</div>
-
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
-
<div class="flex-shrink-0 max-h-full w-24 h-24">
-
<img alt="" class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
-
</div>
-
-
<div class="flex-1 min-h-0 justify-around flex flex-col">
-
<a href="/{{ $subjectHandle }}">
-
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
-
</a>
-
{{ with $profile }}
-
{{ with .Description }}
-
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
-
{{ end }}
-
{{ end }}
-
{{ with $stat }}
-
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
-
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
-
<span id="followers"><a href="/{{ $subjectHandle }}?tab=followers">{{ .Followers }} followers</a></span>
-
<span class="select-none after:content-['·']"></span>
-
<span id="following"><a href="/{{ $subjectHandle }}?tab=following">{{ .Following }} following</a></span>
-
</div>
-
{{ end }}
-
</div>
-
</div>
{{ end }}
···
{{ end }}
{{ define "content" }}
+
{{ if .LoggedInUser }}
+
{{ else }}
+
{{ template "timeline/fragments/hero" . }}
+
{{ end }}
+
{{ template "timeline/fragments/trending" . }}
+
{{ template "timeline/fragments/timeline" . }}
{{ end }}
+2 -1
appview/state/router.go
···
r.Handle("/static/*", s.pages.Static())
-
r.Get("/", s.Timeline)
r.Route("/repo", func(r chi.Router) {
r.Route("/new", func(r chi.Router) {
···
r.Handle("/static/*", s.pages.Static())
+
r.Get("/", s.HomeOrTimeline)
+
r.Get("/timeline", s.Timeline)
r.Route("/repo", func(r chi.Router) {
r.Route("/new", func(r chi.Router) {
+33 -1
appview/state/state.go
···
})
}
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
user := s.oauth.GetUser(r)
-
timeline, err := db.MakeTimeline(s.db)
if err != nil {
log.Println(err)
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
})
}
func (s *State) Keys(w http.ResponseWriter, r *http.Request) {
user := chi.URLParam(r, "user")
user = strings.TrimPrefix(user, "@")
···
})
}
+
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, 50)
if err != nil {
log.Println(err)
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
···
})
}
+
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, "@")