Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/{pages,repo}: show previews for image/ and video/ mimetypes

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

authored by

Anirudh Oppiliappan and committed by
Tangled
49393144 9afbb415

+79 -23
+2 -2
appview/pages/markup/camo.go
··· 9 9 "github.com/yuin/goldmark/ast" 10 10 ) 11 11 12 - func generateCamoURL(baseURL, secret, imageURL string) string { 12 + func GenerateCamoURL(baseURL, secret, imageURL string) string { 13 13 h := hmac.New(sha256.New, []byte(secret)) 14 14 h.Write([]byte(imageURL)) 15 15 signature := hex.EncodeToString(h.Sum(nil)) ··· 24 24 } 25 25 26 26 if rctx.CamoUrl != "" && rctx.CamoSecret != "" { 27 - return generateCamoURL(rctx.CamoUrl, rctx.CamoSecret, dst) 27 + return GenerateCamoURL(rctx.CamoUrl, rctx.CamoSecret, dst) 28 28 } 29 29 30 30 return dst
+4
appview/pages/pages.go
··· 624 624 LoggedInUser *oauth.User 625 625 RepoInfo repoinfo.RepoInfo 626 626 Active string 627 + Unsupported bool 628 + IsImage bool 629 + IsVideo bool 630 + ContentSrc string 627 631 BreadCrumbs [][]string 628 632 ShowRendered bool 629 633 RenderToggle bool
+19 -6
appview/pages/templates/repo/blob.html
··· 5 5 6 6 {{ $title := printf "%s at %s &middot; %s" .Path .Ref .RepoInfo.FullName }} 7 7 {{ $url := printf "https://tangled.sh/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }} 8 - 8 + 9 9 {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }} 10 - 10 + 11 11 {{ end }} 12 12 13 13 {{ define "repoContent" }} ··· 44 44 <a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a> 45 45 {{ if .RenderToggle }} 46 46 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 47 - <a 48 - href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}" 47 + <a 48 + href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}" 49 49 hx-boost="true" 50 50 >view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}</a> 51 51 {{ end }} 52 52 </div> 53 53 </div> 54 54 </div> 55 - {{ if .IsBinary }} 55 + {{ if and .IsBinary .Unsupported }} 56 56 <p class="text-center text-gray-400 dark:text-gray-500"> 57 - This is a binary file and will not be displayed. 57 + Previews are not supported for this file type. 58 58 </p> 59 + {{ else if .IsBinary }} 60 + <div class="text-center"> 61 + {{ if .IsImage }} 62 + <img src="{{ .ContentSrc }}" 63 + alt="{{ .Path }}" 64 + class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" /> 65 + {{ else if .IsVideo }} 66 + <video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded"> 67 + <source src="{{ .ContentSrc }}"> 68 + Your browser does not support the video tag. 69 + </video> 70 + {{ end }} 71 + </div> 59 72 {{ else }} 60 73 <div class="overflow-auto relative"> 61 74 {{ if .ShowRendered }}
+54 -15
appview/repo/repo.go
··· 10 10 "log" 11 11 "net/http" 12 12 "net/url" 13 + "path/filepath" 13 14 "slices" 14 15 "strconv" 15 16 "strings" ··· 533 532 showRendered = r.URL.Query().Get("code") != "true" 534 533 } 535 534 535 + var unsupported bool 536 + var isImage bool 537 + var isVideo bool 538 + var contentSrc string 539 + 540 + if result.IsBinary { 541 + ext := strings.ToLower(filepath.Ext(result.Path)) 542 + switch ext { 543 + case ".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp": 544 + isImage = true 545 + case ".mp4", ".webm", ".ogg", ".mov", ".avi": 546 + isVideo = true 547 + default: 548 + unsupported = true 549 + } 550 + 551 + // fetch the actual binary content like in RepoBlobRaw 552 + 553 + blobURL := fmt.Sprintf("%s://%s/%s/%s/raw/%s/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref, filePath) 554 + contentSrc = blobURL 555 + if !rp.config.Core.Dev { 556 + contentSrc = markup.GenerateCamoURL(rp.config.Camo.Host, rp.config.Camo.SharedSecret, blobURL) 557 + } 558 + } 559 + 536 560 user := rp.oauth.GetUser(r) 537 561 rp.pages.RepoBlob(w, pages.RepoBlobParams{ 538 562 LoggedInUser: user, ··· 566 540 BreadCrumbs: breadcrumbs, 567 541 ShowRendered: showRendered, 568 542 RenderToggle: renderToggle, 543 + Unsupported: unsupported, 544 + IsImage: isImage, 545 + IsVideo: isVideo, 546 + ContentSrc: contentSrc, 569 547 }) 570 548 } 571 549 ··· 577 547 f, err := rp.repoResolver.Resolve(r) 578 548 if err != nil { 579 549 log.Println("failed to get repo and knot", err) 550 + w.WriteHeader(http.StatusBadRequest) 580 551 return 581 552 } 582 553 ··· 588 557 if !rp.config.Core.Dev { 589 558 protocol = "https" 590 559 } 591 - resp, err := http.Get(fmt.Sprintf("%s://%s/%s/%s/blob/%s/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref, filePath)) 560 + blobURL := fmt.Sprintf("%s://%s/%s/%s/raw/%s/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref, filePath) 561 + resp, err := http.Get(blobURL) 592 562 if err != nil { 593 - log.Println("failed to reach knotserver", err) 563 + log.Println("failed to reach knotserver:", err) 564 + rp.pages.Error503(w) 565 + return 566 + } 567 + defer resp.Body.Close() 568 + 569 + if resp.StatusCode != http.StatusOK { 570 + log.Printf("knotserver returned non-OK status for raw blob %s: %d", blobURL, resp.StatusCode) 571 + w.WriteHeader(resp.StatusCode) 572 + _, _ = io.Copy(w, resp.Body) 594 573 return 595 574 } 596 575 576 + contentType := resp.Header.Get("Content-Type") 597 577 body, err := io.ReadAll(resp.Body) 598 578 if err != nil { 599 - log.Printf("Error reading response body: %v", err) 579 + log.Printf("error reading response body from knotserver: %v", err) 580 + w.WriteHeader(http.StatusInternalServerError) 600 581 return 601 582 } 602 583 603 - var result types.RepoBlobResponse 604 - err = json.Unmarshal(body, &result) 605 - if err != nil { 606 - log.Println("failed to parse response:", err) 607 - return 608 - } 609 - 610 - if result.IsBinary { 611 - w.Header().Set("Content-Type", "application/octet-stream") 584 + if strings.Contains(contentType, "text/plain") { 585 + w.Header().Set("Content-Type", "text/plain; charset=utf-8") 612 586 w.Write(body) 587 + } else if strings.HasPrefix(contentType, "image/") || strings.HasPrefix(contentType, "video/") { 588 + w.Header().Set("Content-Type", contentType) 589 + w.Write(body) 590 + } else { 591 + w.WriteHeader(http.StatusUnsupportedMediaType) 592 + w.Write([]byte("unsupported content type")) 613 593 return 614 594 } 615 - 616 - w.Header().Set("Content-Type", "text/plain; charset=utf-8") 617 - w.Write([]byte(result.Contents)) 618 595 } 619 596 620 597 // modify the spindle configured for this repo