-
-
Notifications
You must be signed in to change notification settings - Fork 79
Feature: Bookmarks #403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
linkdotnet
merged 29 commits into
linkdotnet:master
from
levinoeninckx:feature/bookmarks
Mar 7, 2025
Merged
Feature: Bookmarks #403
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
5428428
implement bookmarks
4244410
clear storage on startup when in development
b396e1c
add conditional bookmark buttons & use onAfterRender lifecycle hook
a5df71e
move bookmarks link to rss
6bdb0d8
add bookmark button to post page
890744d
remove bookmark icon and change position
720ef5d
remove localStorage.js
9f75386
remove unused dependencies
4a2d9ac
Fix CI/CD build issues
cf5922a
Create & use BookmarkButton, update bookmarkService
9f3b6a1
move bookmarks nav out of rss
3badad6
refactor BookmarkService
a697224
refactor bookmarkservice
220eb5a
update navmenu
8fef145
restyle bookmark button and add icon to navMenu
7233cab
add extra styling to bookmark button
1910223
add padding to bookmarks page
7548d03
add unit tests for BookmarkService
3eeca43
change exception type
91bc212
refactor code
0304be3
move BookmarkButton css to seperate file
71533ae
refactor
e590c40
Only update initially
linkdotnet 52f3a8a
fix: Tests
linkdotnet 7b4c994
Added tests
linkdotnet 22fc52b
Updated bookmark implementation and icons
linkdotnet 910707f
refactor: Remove unused objects
linkdotnet e7468e2
fix: Styling alignments
linkdotnet efa0e0f
fix: Remove debug stuff
linkdotnet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,14 @@ | ||
@using LinkDotNet.Blog.Web.Features.Home.Components | ||
|
||
<CascadingAuthenticationState> | ||
<Router AppAssembly="@typeof(Program).Assembly"> | ||
<Found Context="routeData"> | ||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/> | ||
</Found> | ||
<NotFound> | ||
<LayoutView Layout="@typeof(MainLayout)"> | ||
<ObjectNotFound></ObjectNotFound> | ||
</LayoutView> | ||
</NotFound> | ||
</Router> | ||
<Router AppAssembly="@typeof(Program).Assembly"> | ||
<Found Context="routeData"> | ||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/> | ||
</Found> | ||
<NotFound> | ||
<LayoutView Layout="@typeof(MainLayout)"> | ||
<ObjectNotFound></ObjectNotFound> | ||
</LayoutView> | ||
</NotFound> | ||
</Router> | ||
</CascadingAuthenticationState> |
63 changes: 63 additions & 0 deletions
63
src/LinkDotNet.Blog.Web/Features/Bookmarks/BookmarkService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using LinkDotNet.Blog.Domain; | ||
using LinkDotNet.Blog.Infrastructure.Persistence.Sql; | ||
using LinkDotNet.Blog.Web.Features.Services; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace LinkDotNet.Blog.Web.Features.Bookmarks; | ||
|
||
public class BookmarkService : IBookmarkService | ||
{ | ||
private readonly ILocalStorageService localStorageService; | ||
|
||
public BookmarkService(ILocalStorageService localStorageService) | ||
{ | ||
this.localStorageService = localStorageService; | ||
} | ||
|
||
public async Task<bool> IsBookmarked(string postId) | ||
{ | ||
ArgumentException.ThrowIfNullOrEmpty(postId); | ||
await InitializeIfNotExists(); | ||
var bookmarks = await localStorageService.GetItemAsync<HashSet<string>>("bookmarks"); | ||
|
||
return bookmarks.Contains(postId); | ||
} | ||
|
||
public async Task<IReadOnlyList<string>> GetBookmarkedPostIds() | ||
{ | ||
await InitializeIfNotExists(); | ||
return await localStorageService.GetItemAsync<IReadOnlyList<string>>("bookmarks"); | ||
} | ||
|
||
public async Task SetBookmark(string postId, bool isBookmarked) | ||
{ | ||
ArgumentException.ThrowIfNullOrEmpty(postId); | ||
await InitializeIfNotExists(); | ||
|
||
var bookmarks = await localStorageService.GetItemAsync<HashSet<string>>("bookmarks"); | ||
|
||
if (!isBookmarked) | ||
{ | ||
bookmarks.Remove(postId); | ||
} | ||
else | ||
{ | ||
bookmarks.Add(postId); | ||
} | ||
|
||
await localStorageService.SetItemAsync("bookmarks", bookmarks); | ||
|
||
} | ||
|
||
private async Task InitializeIfNotExists() | ||
{ | ||
if (!(await localStorageService.ContainKeyAsync("bookmarks"))) | ||
{ | ||
await localStorageService.SetItemAsync("bookmarks", new List<string>()); | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/LinkDotNet.Blog.Web/Features/Bookmarks/Bookmarks.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
@page "/bookmarks" | ||
@using LinkDotNet.Blog.Domain | ||
@using LinkDotNet.Blog.Infrastructure.Persistence | ||
@inject IBookmarkService BookmarkService | ||
@inject IRepository<BlogPost> BlogPostRepository; | ||
|
||
<div class="container"> | ||
<h3 class="pb-3 fw-bold">Bookmarks</h3> | ||
@if (bookmarkedPosts.Count <= 0) | ||
{ | ||
<div class="alert alert-info" role="alert"> | ||
<h4 class="alert-heading">No bookmarks yet!</h4> | ||
<p>You can bookmark posts while browsing by clicking the bookmark icon <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi text-secondary" viewBox="0 0 16 16"> | ||
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> | ||
</svg> that appears on each post.</p> | ||
<hr> | ||
<p class="mb-0">Bookmarks are stored in your browser's local storage and are not synchronized across devices or browsers.</p> | ||
</div> | ||
} | ||
else | ||
{ | ||
@foreach (var post in bookmarkedPosts) | ||
{ | ||
<ShortBlogPost BlogPost="post" /> | ||
} | ||
} | ||
</div> | ||
|
||
@code { | ||
private IReadOnlyList<BlogPost> bookmarkedPosts = []; | ||
|
||
protected override async Task OnAfterRenderAsync(bool firstRender) | ||
{ | ||
if (firstRender) | ||
{ | ||
var ids = await BookmarkService.GetBookmarkedPostIds(); | ||
|
||
if (ids.Any()) | ||
{ | ||
bookmarkedPosts = await BlogPostRepository.GetAllByProjectionAsync(post => post, post => ids.Contains(post.Id)); | ||
StateHasChanged(); | ||
} | ||
} | ||
} | ||
|
||
} |
17 changes: 17 additions & 0 deletions
17
src/LinkDotNet.Blog.Web/Features/Bookmarks/Components/BookmarkButton.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<button type="button" class="btn btn-sm bg-transparent border-0" @onclick="OnBookmarkClicked" title="@(IsBookmarked ? "Remove bookmark" : "Add bookmark")"> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="@(IsBookmarked ? "text-warning" : "text-secondary")" viewBox="0 0 16 16"> | ||
<path d="@(IsBookmarked ? | ||
"M2 2v13.5a.5.5 0 0 0 .74.439L8 13.069l5.26 2.87A.5.5 0 0 0 14 15.5V2a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2z" : | ||
"M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z")"/> | ||
</svg> | ||
</button> | ||
|
||
@code { | ||
[Parameter] public bool IsBookmarked { get; set; } | ||
[Parameter] public EventCallback Bookmarked { get; set; } | ||
|
||
private async Task OnBookmarkClicked() | ||
{ | ||
await Bookmarked.InvokeAsync(); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/LinkDotNet.Blog.Web/Features/Bookmarks/IBookmarkService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
|
||
namespace LinkDotNet.Blog.Web.Features.Bookmarks; | ||
|
||
public interface IBookmarkService | ||
{ | ||
public Task<bool> IsBookmarked(string postId); | ||
public Task<IReadOnlyList<string>> GetBookmarkedPostIds(); | ||
public Task SetBookmark(string postId, bool isBookmarked); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for consistency reasons: Can you wrap the if condition with brackets?