Compare commits

..

2 commits

10 changed files with 77 additions and 32 deletions

View file

@ -6,8 +6,10 @@ input[type="text"] {
border-radius: 4px; border-radius: 4px;
outline: none; outline: none;
color: var(--fg-3); color: var(--fg-3);
background-color: var(--bg-1); background-color: var(--bg-2);
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
transition: background-color .1s ease-out, color .1s ease-out;
} }
#blogpost { #blogpost {
@ -15,10 +17,10 @@ input[type="text"] {
padding: 1.5em; padding: 1.5em;
border-radius: 8px; border-radius: 8px;
background-color: var(--bg-2); background-color: var(--bg-1);
box-shadow: var(--shadow-lg); box-shadow: var(--shadow-lg);
transition: background .1s ease-out, color .1s ease-out; transition: background-color .1s ease-out, color .1s ease-out;
} }
#blogpost label { #blogpost label {
@ -56,7 +58,8 @@ input[type="text"] {
color: var(--fg-3); color: var(--fg-3);
outline: none; outline: none;
cursor: pointer; cursor: pointer;
transition: background .1s ease-out, border-color .1s ease-out;
transition: background-color .1s ease-out, color .1s ease-out, border-color .1s ease-out;
/*position: relative; outline: none;*/ /*position: relative; outline: none;*/
white-space: pre-wrap; overflow-wrap: break-word; white-space: pre-wrap; overflow-wrap: break-word;
@ -78,9 +81,11 @@ input[type="text"] {
font-size: inherit; font-size: inherit;
border-radius: 4px; border-radius: 4px;
border: none; border: none;
background-color: var(--bg-1); background-color: var(--bg-2);
color: var(--fg-3); color: var(--fg-3);
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
transition: background-color .1s ease-out, color .1s ease-out;
} }
#blogpost textarea { #blogpost textarea {
@ -90,11 +95,13 @@ input[type="text"] {
display: block; display: block;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
background-color: var(--bg-1); background-color: var(--bg-2);
color: var(--fg-3); color: var(--fg-3);
box-shadow: var(--shadow-md); box-shadow: var(--shadow-md);
resize: vertical; resize: vertical;
outline: none; outline: none;
transition: background-color .1s ease-out, color .1s ease-out;
} }
#blogpost #description { #blogpost #description {
@ -107,8 +114,10 @@ input[type="text"] {
border: none; border: none;
border-radius: 10em; border-radius: 10em;
color: var(--fg-3); color: var(--fg-3);
background-color: var(--bg-1); background-color: var(--bg-2);
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
transition: background-color .1s ease-out, color .1s ease-out;
} }
#blogpost .social-post-details { #blogpost .social-post-details {
@ -120,3 +129,12 @@ input[type="text"] {
#blogpost .blog-actions { #blogpost .blog-actions {
margin-top: 1em; margin-top: 1em;
} }
@media (prefers-color-scheme: dark) {
input[type="text"],
#blogpost #publish-date,
#blogpost textarea,
#blogpost select {
background-color: var(--bg-0);
}
}

View file

@ -110,7 +110,7 @@
This action is <strong>irreversible</strong>. This action is <strong>irreversible</strong>.
You will be prompted to confirm this decision. You will be prompted to confirm this decision.
</p> </p>
<button class="delete" id="delete">Delete Release</button> <button class="delete" id="delete">Delete Post</button>
</div> </div>
</main> </main>

View file

@ -26,6 +26,7 @@ func GetBlogPost(db *sqlx.DB, id string) (*model.BlogPost, error) {
if strings.Contains(err.Error(), "no rows") { return nil, nil } if strings.Contains(err.Error(), "no rows") { return nil, nil }
return nil, err return nil, err
} }
defer rows.Close()
blueskyActor := sql.NullString{} blueskyActor := sql.NullString{}
blueskyRecord := sql.NullString{} blueskyRecord := sql.NullString{}
@ -84,6 +85,7 @@ func GetBlogPosts(db *sqlx.DB, onlyVisible bool, limit int, offset int) ([]*mode
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close()
for rows.Next() { for rows.Next() {
blog := model.BlogPost{} blog := model.BlogPost{}

View file

@ -11,7 +11,7 @@ import (
const BSKY_API_BASE = "https://public.api.bsky.app" const BSKY_API_BASE = "https://public.api.bsky.app"
func FetchThreadViewPost(actorID string, recordID string) (*model.ThreadViewPost, error) { func FetchThreadViewPost(app *model.AppState, actorID string, recordID string) (*model.ThreadViewPost, error) {
uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", actorID, recordID) uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", actorID, recordID)
req, err := http.NewRequest( req, err := http.NewRequest(
@ -24,7 +24,7 @@ func FetchThreadViewPost(actorID string, recordID string) (*model.ThreadViewPost
req.URL.RawQuery = url.Values{ req.URL.RawQuery = url.Values{
"uri": { uri }, "uri": { uri },
}.Encode() }.Encode()
req.Header.Set("User-Agent", "ari melody [https://arimelody.me]") req.Header.Set("User-Agent", fmt.Sprintf("ari melody [%s]", app.Config.BaseUrl))
req.Header.Set("Accept", "application/json") req.Header.Set("Accept", "application/json")
client := &http.Client{} client := &http.Client{}

View file

@ -339,6 +339,7 @@ func GetReleaseCredits(db *sqlx.DB, releaseID string) ([]*model.Credit, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close()
var credits []*model.Credit var credits []*model.Credit
for rows.Next() { for rows.Next() {

View file

@ -51,7 +51,11 @@ func (b *BlogPost) GetMonth() string {
} }
func (b *BlogPost) PrintDate() string { func (b *BlogPost) PrintDate() string {
return b.PublishDate.Format("2 January 2006, 15:04") return b.PublishDate.Format("02 January 2006, 15:04")
}
func (b *BlogPost) PrintShortDate() string {
return b.PublishDate.Format("2 Jan 2006")
} }
func (b *BlogPost) TextPublishDate() string { func (b *BlogPost) TextPublishDate() string {

View file

@ -6,7 +6,7 @@
} }
main { main {
width: min(calc(100% - 4rem), 1200px); width: min(calc(100% - 4rem), 800px);
margin: 0 auto 1rem auto; margin: 0 auto 1rem auto;
} }
@ -70,24 +70,26 @@ main {
margin: 0; margin: 0;
} }
article#blog p:hover, #blog p:hover,
.comment p:hover { .comment p:hover {
background: inherit; background: inherit;
} }
article#blog { #blog {
font-size: 22px; font-size: 22px;
} }
article#blog h1 { #blog h1 {
margin-bottom: 0; margin-bottom: 0;
font-size: 1.8em; font-size: 1.8em;
} }
#blog h2::before { content: "## " }
#blog h3::before { content: "### " }
.blog-author { .blog-author {
margin: .2em 0; margin: .2em 0;
} }
article#blog .blog-author img { #blog .blog-author img {
width: 1.3em; width: 1.3em;
height: 1.3em; height: 1.3em;
display: inline-block; display: inline-block;
@ -104,11 +106,11 @@ article#blog .blog-author img {
opacity: .75; opacity: .75;
} }
article#blog { #blog {
font-family: 'Lora', serif; font-family: 'Lora', serif;
} }
article#blog header { #blog header {
position: relative; position: relative;
width: auto; width: auto;
font-family: 'Monaspace Argon', monospace; font-family: 'Monaspace Argon', monospace;
@ -117,20 +119,20 @@ article#blog header {
z-index: 0; z-index: 0;
} }
article#blog p { #blog p {
line-height: 1.5em; line-height: 1.25em;
} }
article#blog p.no-content { #blog p.no-content {
font-style: italic; font-style: italic;
opacity: .66; opacity: .66;
} }
article#blog sub { #blog sub {
opacity: .75; opacity: .75;
} }
article#blog pre { #blog pre {
max-height: 15em; max-height: 15em;
padding: .5em; padding: .5em;
font-size: .9em; font-size: .9em;
@ -140,7 +142,7 @@ article#blog pre {
background: var(--background-alt); background: var(--background-alt);
} }
article#blog p code { #blog p code {
padding: .2em .3em; padding: .2em .3em;
font-size: .9em; font-size: .9em;
border: 1px solid #8884; border: 1px solid #8884;
@ -148,20 +150,30 @@ article#blog p code {
background: var(--background-alt); background: var(--background-alt);
} }
article#blog blockquote { #blog blockquote {
margin: 1em 0; margin: 1em 0;
padding: 0 0 0 1em; padding: 0 0 0 1em;
border-left: .2em solid #8888; border-left: .2em solid #8888;
} }
article#blog img { #blog img {
max-height: 50%; max-height: 50%;
max-width: 100%; max-width: 100%;
display: block; display: block;
} }
article#blog i.end-mark { #blog figure {
margin: 1em 0;
padding: 0 1em;
}
#blog figure.quote {
border-left: 4px solid color-mix(in srgb, var(--on-background), transparent 75%);
color: color-mix(in srgb, var(--on-background), transparent 25%);
}
#blog i.end-mark {
width: 1.2em; width: 1.2em;
height: 1.2em; height: 1.2em;
margin-top: -.2em; margin-top: -.2em;
@ -236,7 +248,7 @@ article#blog i.end-mark {
} }
.comment-callout { .comment-callout {
margin: 0 0 0 1em; margin: 0 0 0 .5em;
} }
.comment-callout:hover { .comment-callout:hover {
background: none; background: none;

View file

@ -34,7 +34,7 @@
<h3 class="blog-title"><a href="/blog/{{.ID}}">{{.Title}}</a></h3> <h3 class="blog-title"><a href="/blog/{{.ID}}">{{.Title}}</a></h3>
<p class="blog-meta"> <p class="blog-meta">
<span class="blog-author"><img src="/img/favicon.png" alt="" width="32" height="32"/> {{.Author.DisplayName}}</span> <span class="blog-author"><img src="/img/favicon.png" alt="" width="32" height="32"/> {{.Author.DisplayName}}</span>
<span class="blog-date">&bull; {{.PrintDate}}</span> <span class="blog-date">&bull; {{.PrintShortDate}}</span>
</p> </p>
{{if ne .Description ""}} {{if ne .Description ""}}
<p class="blog-description">{{.Description}}</p> <p class="blog-description">{{.Description}}</p>

View file

@ -85,7 +85,7 @@
<header> <header>
<h1 class="typeout"># {{.Title}}</h1> <h1 class="typeout"># {{.Title}}</h1>
<p class="blog-author">by <a href="/blog?author={{.Author.DisplayName}}">{{.Author.DisplayName}} <img src="/img/favicon.png" alt="" aria-hidden="true" width="32" height="32"/></a></p> <p class="blog-author">by <a href="/blog?author={{.Author.DisplayName}}">{{.Author.DisplayName}} <img src="/img/favicon.png" alt="" aria-hidden="true" width="32" height="32"/></a></p>
<p class="blog-date">posted {{.PrintDate}}</p> <p class="blog-date">Published {{.PrintDate}}</p>
</header> </header>
<hr> <hr>
@ -110,6 +110,7 @@
</div> </div>
{{.Likes}} {{.Likes}}
</a> </a>
<!--
<a href="{{.BlueskyURL}}" class="button boosts" aria-label="{{.Boosts}} boosts"> <a href="{{.BlueskyURL}}" class="button boosts" aria-label="{{.Boosts}} boosts">
<div class="dark-only"> <div class="dark-only">
<img src="/img/blog/boost-dark.svg" alt="" width="32" height="32"> <img src="/img/blog/boost-dark.svg" alt="" width="32" height="32">
@ -119,6 +120,7 @@
</div> </div>
{{.Boosts}} {{.Boosts}}
</a> </a>
-->
<p class="comment-callout"> <p class="comment-callout">
join the conversation on join the conversation on

View file

@ -141,11 +141,17 @@ func ServeBlogPost(app *model.AppState, blogPostID string) http.Handler {
var blueskyURL string var blueskyURL string
var blueskyPost *model.ThreadViewPost var blueskyPost *model.ThreadViewPost
if blog.Bluesky != nil { if blog.Bluesky != nil {
blueskyPost, err = controller.FetchThreadViewPost(blog.Bluesky.ActorDID, blog.Bluesky.RecordID) blueskyPost, err = controller.FetchThreadViewPost(app, blog.Bluesky.ActorDID, blog.Bluesky.RecordID)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog post Bluesky thread: %v\n", err) fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog post Bluesky thread: %v\n", err)
} else { } else {
comments = append(comments, blueskyPost.Replies...) replies := []*model.ThreadViewPost{}
for _, reply := range blueskyPost.Replies {
if reply.Post.Author.DID != blog.Bluesky.ActorDID {
replies = append(replies, reply)
}
}
comments = append(comments, replies...)
likeCount += blueskyPost.Post.LikeCount likeCount += blueskyPost.Post.LikeCount
boostCount += blueskyPost.Post.RepostCount boostCount += blueskyPost.Post.RepostCount
blueskyURL = fmt.Sprintf("https://bsky.app/profile/%s/post/%s", blueskyPost.Post.Author.Handle, blog.Bluesky.RecordID) blueskyURL = fmt.Sprintf("https://bsky.app/profile/%s/post/%s", blueskyPost.Post.Author.Handle, blog.Bluesky.RecordID)