appview/pages: show mini avatar next to user handle #267

merged
opened by anirudh.fi targeting master from push-ytpxvpknlxun
Changed files
+72 -66
appview
pages
templates
repo
user
fragments
+15 -1
appview/pages/funcmap.go
···
package pages
import (
+
"crypto/hmac"
+
"crypto/sha256"
+
"encoding/hex"
"errors"
"fmt"
"html"
···
"tangled.sh/tangled.sh/core/appview/pages/markup"
)
-
func funcMap() template.FuncMap {
+
func (p *Pages) funcMap() template.FuncMap {
return template.FuncMap{
"split": func(s string) []string {
return strings.Split(s, "\n")
···
u, _ := url.PathUnescape(s)
return u
},
+
+
"tinyAvatar": p.tinyAvatar,
}
}
+
func (p *Pages) tinyAvatar(handle string) string {
+
handle = strings.TrimPrefix(handle, "@")
+
secret := p.avatar.SharedSecret
+
h := hmac.New(sha256.New, []byte(secret))
+
h.Write([]byte(handle))
+
signature := hex.EncodeToString(h.Sum(nil))
+
return fmt.Sprintf("%s/%s/%s?size=tiny", p.avatar.Host, signature, handle)
+
}
+
func icon(name string, classes []string) (template.HTML, error) {
iconPath := filepath.Join("static", "icons", name)
+5 -3
appview/pages/pages.go
···
type Pages struct {
t map[string]*template.Template
+
avatar config.AvatarConfig
dev bool
embedFS embed.FS
templateDir string // Path to templates on disk for dev mode
···
p := &Pages{
t: make(map[string]*template.Template),
dev: config.Core.Dev,
+
avatar: config.Avatar,
embedFS: Files,
rctx: rctx,
templateDir: "appview/pages",
···
name := strings.TrimPrefix(path, "templates/")
name = strings.TrimSuffix(name, ".html")
tmpl, err := template.New(name).
-
Funcs(funcMap()).
+
Funcs(p.funcMap()).
ParseFS(p.embedFS, path)
if err != nil {
log.Fatalf("setting up fragment: %v", err)
···
allPaths = append(allPaths, fragmentPaths...)
allPaths = append(allPaths, path)
tmpl, err := template.New(name).
-
Funcs(funcMap()).
+
Funcs(p.funcMap()).
ParseFS(p.embedFS, allPaths...)
if err != nil {
return fmt.Errorf("setting up template: %w", err)
···
}
// Create a new template
-
tmpl := template.New(name).Funcs(funcMap())
+
tmpl := template.New(name).Funcs(p.funcMap())
// Parse layouts
layoutGlob := filepath.Join(p.templateDir, "templates", "layouts", "*.html")
+21 -23
appview/pages/templates/repo/issues/issue.html
···
{{ define "extrameta" }}
{{ $title := printf "%s · issue #%d · %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
{{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
-
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
···
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
<span class="text-white">{{ .State }}</span>
</div>
-
<span class="text-gray-500 dark:text-gray-400 text-sm">
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
opened by
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
-
<a href="/{{ $owner }}" class="no-underline hover:underline"
-
>{{ $owner }}</a
-
>
-
<span class="px-1 select-none before:content-['\00B7']"></span>
+
{{ template "user/fragments/picHandle" $owner }}
+
<span class="select-none before:content-['\00B7']"></span>
<time title="{{ .Issue.Created | longTimeFmt }}">
{{ .Issue.Created | timeFmt }}
</time>
···
{{ define "newComment" }}
{{ if .LoggedInUser }}
-
<form
-
id="comment-form"
+
<form
+
id="comment-form"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
hx-on::after-request="if(event.detail.successful) this.reset()"
>
···
<div id="issue-comment"></div>
<div id="issue-action" class="error"></div>
</div>
-
+
<div class="flex gap-2 mt-2">
-
<button
+
<button
id="comment-button"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
type="submit"
···
{{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
{{ $isRepoOwner := .RepoInfo.Roles.IsOwner }}
{{ if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "open") }}
-
<button
+
<button
id="close-button"
-
type="button"
+
type="button"
class="btn flex items-center gap-2"
hx-indicator="#close-spinner"
hx-trigger="click"
···
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
</button>
-
<div
-
id="close-with-comment"
-
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
-
hx-trigger="click from:#close-button"
+
<div
+
id="close-with-comment"
+
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
+
hx-trigger="click from:#close-button"
hx-disabled-elt="#close-with-comment"
hx-target="#issue-comment"
hx-indicator="#close-spinner"
···
hx-swap="none"
>
</div>
-
<div
-
id="close-issue"
+
<div
+
id="close-issue"
hx-disabled-elt="#close-issue"
-
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/close"
-
hx-trigger="click from:#close-button"
+
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/close"
+
hx-trigger="click from:#close-button"
hx-target="#issue-action"
hx-indicator="#close-spinner"
hx-swap="none"
···
});
</script>
{{ else if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "closed") }}
-
<button
-
type="button"
+
<button
+
type="button"
class="btn flex items-center gap-2"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/reopen"
hx-indicator="#reopen-spinner"
···
});
</script>
</div>
-
</form>
+
</form>
{{ else }}
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
<a href="/login" class="underline">login</a> to join the discussion
+5 -5
appview/pages/templates/repo/issues/issues.html
···
{{ define "extrameta" }}
{{ $title := "issues"}}
{{ $url := printf "https://tangled.sh/%s/issues" .RepoInfo.FullName }}
-
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
···
<span class="text-gray-500">#{{ .IssueId }}</span>
</a>
</div>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
+
<p class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
{{ $icon := "ban" }}
{{ $state := "closed" }}
···
<span class="text-white dark:text-white">{{ $state }}</span>
</span>
-
<span>
-
{{ $owner := index $.DidHandleMap .OwnerDid }}
-
<a href="/{{ $owner }}">{{ $owner }}</a>
+
<span class="ml-1">
+
{{ $owner := index $.DidHandleMap .OwnerDid }}
+
{{ template "user/fragments/picHandle" $owner }}
</span>
<span class="before:content-['·']">
+2 -4
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
<span class="text-white">{{ .Pull.State.String }}</span>
</div>
-
<span class="text-gray-500 dark:text-gray-400 text-sm">
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
opened by
{{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
-
<a href="/{{ $owner }}" class="no-underline hover:underline"
-
>{{ $owner }}</a
-
>
+
{{ template "user/fragments/picHandle" $owner }}
<span class="select-none before:content-['\00B7']"></span>
<time>{{ .Pull.Created | timeFmt }}</time>
+5 -5
appview/pages/templates/repo/pulls/pulls.html
···
{{ define "extrameta" }}
{{ $title := "pulls"}}
{{ $url := printf "https://tangled.sh/%s/pulls" .RepoInfo.FullName }}
-
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
···
<span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span>
</a>
</div>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
+
<p class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
{{ $owner := index $.DidHandleMap .OwnerDid }}
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
{{ $icon := "ban" }}
···
<span class="text-white">{{ .State.String }}</span>
</span>
-
<span>
-
<a href="/{{ $owner }}" class="dark:text-gray-300">{{ $owner }}</a>
+
<span class="ml-1">
+
{{ template "user/fragments/picHandle" $owner }}
</span>
-
<span class="before:content-['·']">
+
<span>
<time>
{{ .Created | timeFmt }}
</time>
+9 -25
appview/pages/templates/timeline.html
···
{{ if .Repo }}
{{ $userHandle := index $.DidHandleMap .Repo.Did }}
<div class="flex items-center">
-
<p class="text-gray-600 dark:text-gray-300">
-
<a
-
href="/{{ $userHandle }}"
-
class="no-underline hover:underline"
-
>{{ $userHandle | truncateAt30 }}</a
-
>
+
<p class="text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2">
+
{{ template "user/fragments/picHandle" $userHandle }}
{{ if .Source }}
forked
<a
href="/{{ index $.DidHandleMap .Source.Did }}/{{ .Source.Name }}"
class="no-underline hover:underline"
>
-
{{ index $.DidHandleMap .Source.Did }}/{{ .Source.Name }}
-
</a>
+
{{ index $.DidHandleMap .Source.Did }}/{{ .Source.Name }}</a
+
>
to
<a
href="/{{ $userHandle }}/{{ .Repo.Name }}"
···
{{ $userHandle := index $.DidHandleMap .Follow.UserDid }}
{{ $subjectHandle := index $.DidHandleMap .Follow.SubjectDid }}
<div class="flex items-center">
-
<p class="text-gray-600 dark:text-gray-300">
-
<a
-
href="/{{ $userHandle }}"
-
class="no-underline hover:underline"
-
>{{ $userHandle | truncateAt30 }}</a
-
>
+
<p class="text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2">
+
{{ template "user/fragments/picHandle" $userHandle }}
followed
-
<a
-
href="/{{ $subjectHandle }}"
-
class="no-underline hover:underline"
-
>{{ $subjectHandle | truncateAt30 }}</a
-
>
+
{{ template "user/fragments/picHandle" $subjectHandle }}
<time
class="text-gray-700 dark:text-gray-400 text-xs"
>{{ .Follow.FollowedAt | timeFmt }}</time
···
{{ $starrerHandle := index $.DidHandleMap .Star.StarredByDid }}
{{ $repoOwnerHandle := index $.DidHandleMap .Star.Repo.Did }}
<div class="flex items-center">
-
<p class="text-gray-600 dark:text-gray-300">
-
<a
-
href="/{{ $starrerHandle }}"
-
class="no-underline hover:underline"
-
>{{ $starrerHandle | truncateAt30 }}</a
-
>
+
{{ template "user/fragments/picHandle" $starrerHandle }}
+
<p class="text-gray-600 dark:text-gray-300 flex items-center gap-2">
starred
<a
href="/{{ $repoOwnerHandle }}/{{ .Star.Repo.Name }}"
+10
appview/pages/templates/user/fragments/picHandle.html
···
+
{{ define "user/fragments/picHandle" }}
+
<a href="/{{ . }}" class="flex items-center">
+
<img
+
src="{{ tinyAvatar . }}"
+
alt="{{ . }}"
+
class="rounded-full h-6 w-6 mr-1"
+
/>
+
{{ . | truncateAt30 }}
+
</a>
+
{{ end }}