I've included a way to see status as an image. I don't know if I will end-up using that.
This commit is contained in:
parent
003373834f
commit
8a2a048f83
9 changed files with 133 additions and 9 deletions
|
|
@ -15,6 +15,19 @@ section {
|
|||
row-gap: 1em;
|
||||
}
|
||||
|
||||
.status-username {
|
||||
font-weight: bold;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.status-content {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
@media (min-width: 650px) {
|
||||
.cols {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -3,8 +3,11 @@ module status
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/fogleman/gg v1.3.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/lib/pq v1.10.4
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
|
||||
)
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -1,3 +1,7 @@
|
|||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
|
|
@ -8,6 +12,8 @@ github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
|||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ var TplCommonMap = map[string]string{
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>status cafe</title>
|
||||
<title>status ☕</title>
|
||||
<meta name="description" content="your friends' updates">
|
||||
<link rel="stylesheet" href="/assets/style.css"/>
|
||||
{{ template "head" . }}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>status.cafe</h1>
|
||||
<p>status ☕</p>
|
||||
</header>
|
||||
<main>
|
||||
{{ template "content" . }}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http
|
|||
|
||||
router.HandleFunc("/users/{user}", h.showUserView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/users/{user}/status.json", h.showUserStatusView).Methods(http.MethodGet)
|
||||
router.HandleFunc("/users/{user}/status.png", h.showUserStatusImageView).Methods(http.MethodGet)
|
||||
router.PathPrefix("/assets/").Handler(
|
||||
http.StripPrefix("/assets/",
|
||||
http.FileServer(
|
||||
|
|
|
|||
|
|
@ -88,15 +88,18 @@ Are you sure you you want to delete the following status?
|
|||
</div>
|
||||
<br>
|
||||
<input type="submit" value="Submit">
|
||||
<h3>Update status with bookmarklet</h3>
|
||||
<p>Drag to your bookmarks to update from anywhere: <a href="javascript:void(open('https://status.cafe/status-new','status.cafe','resizable,scrollbars,width=360,height=200'))">Set status</a></p>
|
||||
<h3>Display status on your homepage</h3>
|
||||
<p>todo</p>
|
||||
</form>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Status stream</h2>
|
||||
{{ range .statuses }}
|
||||
<article class="status">
|
||||
<div class="username"><a href="/users/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
|
||||
<p>{{ .Content }}</p>
|
||||
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a>'s status, updated {{ .TimeAgo }}</div>
|
||||
<p class="status-content">{{ .Content }}</p>
|
||||
</article>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>status cafe</title>
|
||||
<title>status ☕</title>
|
||||
<meta name="description" content="your friends' updates">
|
||||
<link rel="stylesheet" href="/assets/style.css"/>
|
||||
{{ template "head" . }}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>status.cafe</h1>
|
||||
<p>status ☕</p>
|
||||
</header>
|
||||
<main>
|
||||
{{ template "content" . }}
|
||||
|
|
|
|||
|
|
@ -14,15 +14,18 @@
|
|||
</div>
|
||||
<br>
|
||||
<input type="submit" value="Submit">
|
||||
<h3>Update status with bookmarklet</h3>
|
||||
<p>Drag to your bookmarks to update from anywhere: <a href="javascript:void(open('https://status.cafe/status-new','status.cafe','resizable,scrollbars,width=360,height=200'))">Set status</a></p>
|
||||
<h3>Display status on your homepage</h3>
|
||||
<p>todo</p>
|
||||
</form>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Status stream</h2>
|
||||
{{ range .statuses }}
|
||||
<article class="status">
|
||||
<div class="username"><a href="/users/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
|
||||
<p>{{ .Content }}</p>
|
||||
<div class="status-username"><a href="/users/{{ .User }}">{{ .User }}</a>'s status, updated {{ .TimeAgo }}</div>
|
||||
<p class="status-content">{{ .Content }}</p>
|
||||
</article>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,17 @@ package handler
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/fogleman/gg"
|
||||
"github.com/golang/freetype"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/gofont/goregular"
|
||||
"golang.org/x/image/math/fixed"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
//"image/png"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
|
@ -26,7 +36,7 @@ func (h *Handler) showUserView(w http.ResponseWriter, r *http.Request) {
|
|||
type statusjson struct {
|
||||
Author string `json:"author"`
|
||||
Content string `json:"content"`
|
||||
TimeAgo string `json:"time_ago"`
|
||||
TimeAgo string `json:"timeAgo"`
|
||||
}
|
||||
|
||||
func (h *Handler) showUserStatusView(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -50,3 +60,88 @@ func (h *Handler) showUserStatusView(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
func drawText(canvas *image.RGBA, text string) error {
|
||||
var (
|
||||
fgColor image.Image
|
||||
fontFace *truetype.Font
|
||||
err error
|
||||
fontSize = 12.0
|
||||
)
|
||||
fgColor = image.White
|
||||
fontFace, err = freetype.ParseFont(goregular.TTF)
|
||||
fontDrawer := &font.Drawer{
|
||||
Dst: canvas,
|
||||
Src: fgColor,
|
||||
Face: truetype.NewFace(fontFace, &truetype.Options{
|
||||
Size: fontSize,
|
||||
Hinting: font.HintingFull,
|
||||
}),
|
||||
}
|
||||
//textBounds, _ := fontDrawer.BoundString(text)
|
||||
xPosition := fixed.I(20)
|
||||
//textHeight := textBounds.Max.Y - textBounds.Min.Y
|
||||
yPosition := fixed.I(20)
|
||||
fontDrawer.Dot = fixed.Point26_6{
|
||||
X: xPosition,
|
||||
Y: yPosition,
|
||||
}
|
||||
fontDrawer.DrawString(text)
|
||||
return err
|
||||
}
|
||||
|
||||
func createAvatar(text string) *image.RGBA {
|
||||
bgColor := color.RGBA{
|
||||
R: 255,
|
||||
G: 20,
|
||||
B: 100,
|
||||
A: 255,
|
||||
}
|
||||
background := image.NewRGBA(image.Rect(0, 0, 200, 100))
|
||||
draw.Draw(background, background.Bounds(), &image.Uniform{C: bgColor},
|
||||
image.Point{}, draw.Src)
|
||||
drawText(background, text)
|
||||
return background
|
||||
}
|
||||
|
||||
func (h *Handler) showUserStatusImageView(w http.ResponseWriter, r *http.Request) {
|
||||
user := mux.Vars(r)["user"]
|
||||
if !h.storage.UserExists(user) {
|
||||
notFound(w)
|
||||
return
|
||||
}
|
||||
statuses, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 1, 0)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
//w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
//w.Header().Set("Content-Type", "application/json")
|
||||
var text string
|
||||
if len(statuses) > 0 {
|
||||
text = statuses[0].Content
|
||||
}
|
||||
|
||||
background := "#ffffff"
|
||||
foreground := "#000000"
|
||||
|
||||
if c := r.URL.Query().Get("background"); c != "" {
|
||||
background = "#" + c
|
||||
}
|
||||
|
||||
if c := r.URL.Query().Get("foreground"); c != "" {
|
||||
foreground = "#" + c
|
||||
}
|
||||
|
||||
width := 350
|
||||
dc := gg.NewContext(width, 80)
|
||||
dc.SetHexColor(background)
|
||||
dc.Clear()
|
||||
dc.SetHexColor(foreground)
|
||||
dc.DrawStringWrapped(text, 19, 16, 0, 0, float64(width-(2*16)), 1.5, gg.AlignLeft)
|
||||
dc.EncodePNG(w)
|
||||
//dc.SavePNG("out.png")
|
||||
|
||||
//avatar := createAvatar(text)
|
||||
//png.Encode(w, avatar)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue