Skip to content

Commit f622d4e

Browse files
committed
fix: revert to old version
1 parent 2cdec58 commit f622d4e

4 files changed

Lines changed: 106 additions & 62 deletions

File tree

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
@inject IJSRuntime JSRuntime
22

3-
<div class="reading-progress" @ref="progressContainer" aria-hidden="true">
4-
<div class="reading-progress-bar" @ref="progressBar"></div>
3+
<div class="progress-container" @ref="progressContainer">
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>
58
</div>
69

10+
711
@code {
812
[Parameter, EditorRequired]
913
public required string ContainerCssSelector { get; set; }
1014

1115
private ElementReference progressContainer;
12-
private ElementReference progressBar;
1316

1417
protected override async Task OnAfterRenderAsync(bool firstRender)
1518
{
1619
if (firstRender)
1720
{
18-
await using var module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Features/ShowBlogPost/Components/ReadingIndicator.razor.js");
19-
await module.InvokeVoidAsync("initReadingProgress", ContainerCssSelector, progressContainer, progressBar);
21+
await using var _ = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Features/ShowBlogPost/Components/ReadingIndicator.razor.js");
22+
await JSRuntime.InvokeVoidAsync("initCircularReadingProgress", ContainerCssSelector, progressContainer);
2023
}
2124
}
2225
}
Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,52 @@
1-
let cleanup = null;
1+
let progressTimeout;
2+
let rafId;
3+
4+
function getContentHeight(className) {
5+
const content = document.querySelector(className);
6+
if (!content) {
7+
return 0;
8+
}
9+
const contentRect = content.getBoundingClientRect();
10+
return contentRect.height;
11+
}
212

3-
export function initReadingProgress(containerSelector, progressContainer, progressBar) {
4-
// Re-init (e.g. Blazor re-render) tears down any previous listeners first.
5-
cleanup?.();
13+
function showProgressIndicator(progressContainer) {
14+
progressContainer.classList.add("visible");
15+
progressContainer.style.animation = 'none';
16+
}
617

7-
let hideTimeout;
8-
let ticking = false;
18+
function hideProgressIndicator(progressContainer) {
19+
progressContainer.style.animation = 'fadeOut 0.5s forwards';
20+
setTimeout(() => {
21+
progressContainer.classList.remove('visible');
22+
}, 500);
23+
}
924

10-
const update = () => {
11-
ticking = false;
12-
const container = document.querySelector(containerSelector);
13-
if (!container) {
14-
return;
15-
}
25+
window.initCircularReadingProgress = (parentContainer, progressContainer) => {
26+
if (window.circularProgressScrollListenerAdded) {
27+
return;
28+
}
1629

17-
const contentHeight = container.getBoundingClientRect().height;
18-
const windowHeight = document.documentElement.clientHeight;
19-
const scrolled = document.documentElement.scrollTop;
20-
const maxScroll = contentHeight - windowHeight;
21-
const progress = maxScroll <= 0 ? 1 : Math.min(1, Math.max(0, scrolled / maxScroll));
30+
const progressBar = document.getElementById('progressBar');
2231

23-
progressBar.style.transform = `scaleX(${progress})`;
32+
const onScroll = () => {
33+
clearTimeout(progressTimeout);
2434

25-
progressContainer.classList.add('visible');
26-
clearTimeout(hideTimeout);
27-
hideTimeout = setTimeout(() => progressContainer.classList.remove('visible'), 2000);
28-
};
35+
const contentHeight = getContentHeight(parentContainer);
36+
const windowHeight = document.documentElement.clientHeight;
37+
const scrollAmount = document.documentElement.scrollTop;
38+
const maxScrollAmount = contentHeight - windowHeight;
39+
const progress = Math.max(0, Math.min(100, (scrollAmount / maxScrollAmount) * 100));
40+
progressBar.style.strokeDashoffset = 100 - progress;
2941

30-
const onScroll = () => {
31-
if (!ticking) {
32-
ticking = true;
33-
requestAnimationFrame(update);
34-
}
35-
};
42+
showProgressIndicator(progressContainer);
3643

37-
window.addEventListener('scroll', onScroll, { passive: true });
38-
window.addEventListener('resize', onScroll, { passive: true });
44+
progressTimeout = setTimeout(() => {
45+
hideProgressIndicator(progressContainer);
46+
}, 2000);
3947

40-
cleanup = () => {
41-
window.removeEventListener('scroll', onScroll);
42-
window.removeEventListener('resize', onScroll);
43-
clearTimeout(hideTimeout);
48+
rafId = null;
4449
};
45-
}
50+
51+
window.addEventListener('scroll', onScroll);
52+
};

src/LinkDotNet.Blog.Web/wwwroot/css/basic.css

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -594,37 +594,50 @@ code {
594594
/*#endregion */
595595

596596
/*#region ReadingIndicator.razor */
597-
.reading-progress {
597+
.progress-container {
598598
position: fixed;
599-
inset: 0 0 auto 0;
600-
height: 3px;
601-
z-index: 1030;
599+
bottom: 20px;
600+
right: 20px;
601+
z-index: 1000;
602602
opacity: 0;
603-
pointer-events: none;
604-
transition: opacity 0.4s ease;
603+
transition: opacity 1.5s;
605604
}
606605

607-
.reading-progress.visible {
606+
.progress-container.visible {
608607
opacity: 1;
609608
}
610609

611-
.reading-progress-bar {
612-
height: 100%;
613-
width: 100%;
614-
transform: scaleX(0);
615-
transform-origin: left center;
616-
background: var(--bs-primary);
617-
box-shadow: 0 0 10px rgba(var(--bs-primary-rgb), 0.6);
618-
transition: transform 0.12s ease-out;
619-
will-change: transform;
620-
}
621-
622-
@media (prefers-reduced-motion: reduce) {
623-
.reading-progress,
624-
.reading-progress-bar {
625-
transition: none;
610+
@keyframes fadeOut {
611+
to {
612+
opacity: 0;
626613
}
627614
}
615+
616+
.progress-circle {
617+
width: 50px;
618+
height: 50px;
619+
}
620+
621+
.progress-bg {
622+
fill: none;
623+
stroke: #f3f3f3;
624+
stroke-width: 4;
625+
}
626+
627+
.progress-bar {
628+
fill: none;
629+
stroke: #4caf50;
630+
stroke-width: 4;
631+
stroke-linecap: round;
632+
transform-origin: center;
633+
transform: rotate(-90deg);
634+
stroke-dasharray: 100, 100;
635+
stroke-dashoffset: 100;
636+
}
637+
638+
[data-bs-theme='light'] .progress-bg {
639+
stroke: #444444;
640+
}
628641
/*#endregion */
629642

630643
/*region ShowBlogPostPage.razor */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Linq;
2+
using LinkDotNet.Blog.Web.Features.ShowBlogPost.Components;
3+
4+
namespace LinkDotNet.Blog.UnitTests.Web.Features.ShowBlogPost.Components;
5+
6+
public class ReadingIndicatorTests : BunitContext
7+
{
8+
[Fact]
9+
public void ShouldLoadJavascript()
10+
{
11+
JSInterop.SetupModule("./Features/ShowBlogPost/Components/ReadingIndicator.razor.js");
12+
JSInterop.Mode = JSRuntimeMode.Loose;
13+
14+
Render<ReadingIndicator>(parameters => parameters
15+
.Add(p => p.ContainerCssSelector, ".blog-inner-content"));
16+
17+
var init = JSInterop.Invocations.SingleOrDefault(i => i.Identifier == "initCircularReadingProgress");
18+
19+
init.Arguments.ShouldContain(".blog-inner-content");
20+
}
21+
}

0 commit comments

Comments
 (0)