Skip to content

Commit dc13af1

Browse files
committed
feat: added reading indicator
1 parent c2d7855 commit dc13af1

File tree

4 files changed

+138
-33
lines changed

4 files changed

+138
-33
lines changed

src/LinkDotNet.Blog.Web/Features/ShowBlogPost/Components/CommentSection.razor

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@
1818

1919
@code {
2020
private bool MultipleCommentPlugins => AppConfiguration.IsDisqusEnabled && AppConfiguration.IsGiscusEnabled;
21-
2221
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
@inject IJSRuntime JSRuntime
2+
3+
<div class="progress-container">
4+
<svg class="progress-circle" viewBox="0 0 36 36">
5+
<circle class="progress-bg" cx="18" cy="18" r="15.91549431" />
6+
<circle class="progress-bar" id="progressBar" cx="18" cy="18" r="15.91549431" />
7+
</svg>
8+
</div>
9+
10+
<style>
11+
.progress-container {
12+
position: fixed;
13+
bottom: 20px;
14+
right: 20px;
15+
z-index: 1000;
16+
opacity: 0;
17+
transition: opacity 0.5s;
18+
}
19+
20+
.progress-container.visible {
21+
opacity: 1;
22+
}
23+
24+
@@keyframes fadeOut {
25+
to {
26+
opacity: 0;
27+
}
28+
}
29+
30+
.progress-circle {
31+
width: 50px;
32+
height: 50px;
33+
}
34+
35+
.progress-bg {
36+
fill: none;
37+
stroke: #f3f3f3;
38+
stroke-width: 4;
39+
}
40+
41+
.progress-bar {
42+
fill: none;
43+
stroke: #4caf50;
44+
stroke-width: 4;
45+
stroke-linecap: round;
46+
transform-origin: center;
47+
transform: rotate(-90deg);
48+
stroke-dasharray: 100, 100;
49+
stroke-dashoffset: 100;
50+
}
51+
52+
</style>
53+
54+
@code {
55+
protected override async Task OnAfterRenderAsync(bool firstRender)
56+
{
57+
if (firstRender)
58+
{
59+
await using var _ = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Features/ShowBlogPost/Components/ReadingIndicator.razor.js");
60+
await JSRuntime.InvokeVoidAsync("initCircularReadingProgress");
61+
}
62+
}
63+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
let progressTimeout;
2+
3+
function getContentHeight() {
4+
const content = document.querySelector(".blog-inner-content");
5+
if (!content) {
6+
return 0;
7+
}
8+
const contentRect = content.getBoundingClientRect();
9+
return contentRect.height;
10+
}
11+
12+
function showProgressIndicator(progressContainer) {
13+
progressContainer.classList.add("visible");
14+
progressContainer.style.animation = "none";
15+
}
16+
17+
function hideProgressIndicator(progressContainer) {
18+
progressContainer.style.animation = "fadeOut 0.5s forwards";
19+
}
20+
21+
window.initCircularReadingProgress = () => {
22+
const progressBar = document.getElementById("progressBar");
23+
const progressContainer = progressBar.closest(".progress-container");
24+
25+
window.addEventListener("scroll", () => {
26+
clearTimeout(progressTimeout);
27+
28+
const contentHeight = getContentHeight();
29+
const windowHeight = document.documentElement.clientHeight;
30+
const scrollAmount = document.documentElement.scrollTop;
31+
const maxScrollAmount = contentHeight - windowHeight;
32+
const progress = Math.max(0, Math.min(100, (scrollAmount / maxScrollAmount) * 100));
33+
progressBar.style.strokeDashoffset = 100 - progress;
34+
35+
showProgressIndicator(progressContainer);
36+
37+
progressTimeout = setTimeout(() => {
38+
hideProgressIndicator(progressContainer);
39+
}, 2000);
40+
});
41+
};

src/LinkDotNet.Blog.Web/Features/ShowBlogPost/ShowBlogPostPage.razor

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,42 @@ else
1919
AbsolutePreviewImageUrl="@OgDataImage"
2020
Description="@(Markdown.ToPlainText(BlogPost.ShortDescription))"
2121
Keywords="@Tags"></OgData>
22-
<div class="d-flex justify-content-center pt-2 blog-outer-box">
23-
<div class="content blog-container">
24-
<div>
25-
<header class="text-center">
26-
<h1>@BlogPost.Title</h1></header>
27-
<div class="blogpost-metainformation d-flex flex-row flex-wrap gap-2">
28-
<div><span class="date"></span><span class="ms-1">@BlogPost.UpdatedDate.ToString("dd/MM/yyyy")</span></div>
29-
@if (BlogPost.Tags != null && BlogPost.Tags.Any())
30-
{
31-
<span class="blogpost-tag d-inline-block">
32-
@foreach (var tag in BlogPost.Tags.Select(t => t.Content))
33-
{
34-
<a class="goto-tag ms-1" href="/searchByTag/@(Uri.EscapeDataString(tag))">@tag</a>
35-
}
36-
</span>
37-
}
38-
</div>
22+
<div class="d-flex justify-content-center pt-2 blog-outer-box">
23+
<div class="content blog-container">
24+
<div class="blog-inner-content">
25+
<header class="text-center">
26+
<h1>@BlogPost.Title</h1></header>
27+
<div class="blogpost-metainformation d-flex flex-row flex-wrap gap-2">
28+
<div><span class="date"></span><span class="ms-1">@BlogPost.UpdatedDate.ToString("dd/MM/yyyy")</span></div>
29+
@if (BlogPost.Tags != null && BlogPost.Tags.Any())
30+
{
31+
<span class="blogpost-tag d-inline-block">
32+
@foreach (var tag in BlogPost.Tags.Select(t => t.Content))
33+
{
34+
<a class="goto-tag ms-1" href="/searchByTag/@(Uri.EscapeDataString(tag))">@tag</a>
35+
}
36+
</span>
37+
}
38+
</div>
3939

40-
<div class="admin-action">
41-
<BlogPostAdminActions BlogPostId="@BlogPostId"></BlogPostAdminActions>
42-
</div>
40+
<div class="admin-action">
41+
<BlogPostAdminActions BlogPostId="@BlogPostId"></BlogPostAdminActions>
42+
</div>
4343

44-
<div class="blogpost-content">
45-
@(MarkdownConverter.ToMarkupString(BlogPost.Content))
46-
</div>
47-
</div>
48-
<div class="d-flex justify-content-between py-2">
49-
<Like BlogPost="@BlogPost" OnBlogPostLiked="@UpdateLikes"></Like>
50-
<ShareBlogPost></ShareBlogPost>
51-
</div>
52-
<DonationSection></DonationSection>
53-
<CommentSection></CommentSection>
54-
</div>
55-
</div>
44+
<div class="blogpost-content">
45+
@(MarkdownConverter.ToMarkupString(BlogPost.Content))
46+
</div>
47+
</div>
48+
<div class="d-flex justify-content-between py-2">
49+
<Like BlogPost="@BlogPost" OnBlogPostLiked="@UpdateLikes"></Like>
50+
<ShareBlogPost></ShareBlogPost>
51+
</div>
52+
<DonationSection></DonationSection>
53+
<CommentSection></CommentSection>
54+
</div>
55+
</div>
56+
57+
<ReadingIndicator />
5658
}
5759

5860
@code {

0 commit comments

Comments
 (0)