clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / tinyclient / repo_navigation.go
repo_navigation.go 3.3K
1package tinyclient23import (4 "fmt"5 "net/url"6 "strings"7 "time"8)910type repoCrumb struct{ Label, URL string }1112// repoHandle is the owner segment for links from the current page: the13// resolved handle when the page carries one, else the owner as given.14func repoHandle(query url.Values) string {15 if handle := query.Get("handle"); handle != "" {16 return handle17 }18 return query.Get("owner")19}2021// repoURL links a view of the current repository, keeping the branch and22// nothing else from the current query.23func repoURL(query url.Values, view, item string) string {24 keep := url.Values{}25 if ref := query.Get("ref"); ref != "" && view != "commit" {26 keep.Set("ref", ref)27 }28 return repoPath(repoHandle(query), query.Get("repo"), view, item, keep)29}3031func repoCommitURL(query url.Values, oid string) string {32 return repoPath(repoHandle(query), query.Get("repo"), "commit", oid, nil)33}3435// repoPagePath is the current repository page without its query, the36// action for forms that rebuild the query from their fields.37func repoPagePath(query url.Values) string {38 item := query.Get("path")39 if view := repoView(query); view == "issue" || view == "pr" || view == "commit" {40 item = query.Get("id")41 }42 return repoPath(repoHandle(query), query.Get("repo"), repoView(query), item, nil)43}4445// repoPageURL is the current repository page with one query value changed.46func repoPageURL(query url.Values, field string, value any) string {47 values := transientQuery(query)48 values.Set(field, fmt.Sprint(value))49 item := query.Get("path")50 if view := repoView(query); view == "issue" || view == "pr" || view == "commit" {51 item = query.Get("id")52 }53 return repoPath(repoHandle(query), query.Get("repo"), repoView(query), item, values)54}5556// repoHref links a repository by its owner handle, for lists.57func repoHref(handle, repo, view, item string) string {58 return repoPath(handle, repo, view, item, nil)59}6061func hasNextOffset(value any) bool {62 switch offset := value.(type) {63 case int:64 return offset >= 065 case float64:66 return offset >= 067 default:68 return false69 }70}7172func repoBreadcrumbs(query url.Values) []repoCrumb {73 crumbs := []repoCrumb{{Label: query.Get("repo"), URL: repoURL(query, "tree", "")}}74 if query.Get("path") == "" {75 return crumbs76 }77 parts := strings.Split(query.Get("path"), "/")78 for index, label := range parts {79 crumbs = append(crumbs, repoCrumb{Label: label, URL: repoURL(query, "tree", strings.Join(parts[:index+1], "/"))})80 }81 crumbs[len(crumbs)-1].URL = ""82 return crumbs83}8485// browsePageURL is a list page with one query value changed. Values the86// page derives from its path are not written back.87func browsePageURL(route string, query url.Values, field string, value any) string {88 values := transientQuery(query)89 values.Set(field, fmt.Sprint(value))90 if value == "" || value == nil {91 values.Del(field)92 }93 if len(values) == 0 {94 return route95 }96 return route + "?" + values.Encode()97}9899func shortID(value any) string {100 text, ok := value.(string)101 if !ok {102 return ""103 }104 if len(text) > 12 {105 return text[:12]106 }107 return text108}109110func repoDate(value any) string {111 var seconds int64112 switch value := value.(type) {113 case float64:114 seconds = int64(value)115 case int64:116 seconds = value117 }118 if seconds == 0 {119 return ""120 }121 return time.Unix(seconds, 0).UTC().Format("Jan. 2, 2006")122}