show story progress and reset last read when resetting progress.

This commit is contained in:
Stefan Hardegger
2025-10-30 13:44:54 +01:00
parent a3bc83db8a
commit 0e1ed7c92e
8 changed files with 62 additions and 19 deletions

View File

@@ -591,10 +591,11 @@ public class StoryController {
dto.setVolume(story.getVolume());
dto.setCreatedAt(story.getCreatedAt());
dto.setUpdatedAt(story.getUpdatedAt());
// Reading progress fields
dto.setIsRead(story.getIsRead());
dto.setReadingPosition(story.getReadingPosition());
dto.setReadingProgressPercentage(calculateReadingProgressPercentage(story));
dto.setLastReadAt(story.getLastReadAt());
if (story.getAuthor() != null) {
@@ -613,7 +614,28 @@ public class StoryController {
return dto;
}
private Integer calculateReadingProgressPercentage(Story story) {
if (story.getReadingPosition() == null || story.getReadingPosition() == 0) {
return 0;
}
// Determine the total content length
int totalLength = 0;
if (story.getContentPlain() != null && !story.getContentPlain().isEmpty()) {
totalLength = story.getContentPlain().length();
} else if (story.getContentHtml() != null && !story.getContentHtml().isEmpty()) {
totalLength = story.getContentHtml().length();
}
if (totalLength == 0) {
return 0;
}
// Calculate percentage and round to nearest integer
return Math.round((float) story.getReadingPosition() * 100 / totalLength);
}
private StoryReadingDto convertToReadingDto(Story story) {
StoryReadingDto dto = new StoryReadingDto();
dto.setId(story.getId());
@@ -628,10 +650,11 @@ public class StoryController {
dto.setVolume(story.getVolume());
dto.setCreatedAt(story.getCreatedAt());
dto.setUpdatedAt(story.getUpdatedAt());
// Reading progress fields
dto.setIsRead(story.getIsRead());
dto.setReadingPosition(story.getReadingPosition());
dto.setReadingProgressPercentage(calculateReadingProgressPercentage(story));
dto.setLastReadAt(story.getLastReadAt());
if (story.getAuthor() != null) {

View File

@@ -31,6 +31,7 @@ public class StoryDto {
// Reading progress fields
private Boolean isRead;
private Integer readingPosition;
private Integer readingProgressPercentage; // Pre-calculated percentage (0-100)
private LocalDateTime lastReadAt;
// Related entities as simple references
@@ -146,7 +147,15 @@ public class StoryDto {
public void setReadingPosition(Integer readingPosition) {
this.readingPosition = readingPosition;
}
public Integer getReadingProgressPercentage() {
return readingProgressPercentage;
}
public void setReadingProgressPercentage(Integer readingProgressPercentage) {
this.readingProgressPercentage = readingProgressPercentage;
}
public LocalDateTime getLastReadAt() {
return lastReadAt;
}

View File

@@ -25,6 +25,7 @@ public class StoryReadingDto {
// Reading progress fields
private Boolean isRead;
private Integer readingPosition;
private Integer readingProgressPercentage; // Pre-calculated percentage (0-100)
private LocalDateTime lastReadAt;
// Related entities as simple references
@@ -135,7 +136,15 @@ public class StoryReadingDto {
public void setReadingPosition(Integer readingPosition) {
this.readingPosition = readingPosition;
}
public Integer getReadingProgressPercentage() {
return readingProgressPercentage;
}
public void setReadingProgressPercentage(Integer readingProgressPercentage) {
this.readingProgressPercentage = readingProgressPercentage;
}
public LocalDateTime getLastReadAt() {
return lastReadAt;
}

View File

@@ -287,10 +287,17 @@ public class Story {
/**
* Updates the reading progress and timestamp
* When position is 0 or null, resets lastReadAt to null so the story won't appear in "last read" sorting
*/
public void updateReadingProgress(Integer position) {
this.readingPosition = position;
this.lastReadAt = LocalDateTime.now();
// Only update lastReadAt if there's actual reading progress
// Reset to null when position is 0 or null to remove from "last read" sorting
if (position == null || position == 0) {
this.lastReadAt = null;
} else {
this.lastReadAt = LocalDateTime.now();
}
}
/**

View File

@@ -85,7 +85,8 @@ class StoryServiceTest {
Story result = storyService.updateReadingProgress(testId, position);
assertEquals(0, result.getReadingPosition());
assertNotNull(result.getLastReadAt());
// When position is 0, lastReadAt should be reset to null so the story doesn't appear in "last read" sorting
assertNull(result.getLastReadAt());
verify(storyRepository).save(testStory);
}
@@ -111,7 +112,8 @@ class StoryServiceTest {
Story result = storyService.updateReadingProgress(testId, position);
assertNull(result.getReadingPosition());
assertNotNull(result.getLastReadAt());
// When position is null, lastReadAt should be reset to null so the story doesn't appear in "last read" sorting
assertNull(result.getLastReadAt());
verify(storyRepository).save(testStory);
}