Skip to content

Commit 90d599c

Browse files
authored
Merge pull request #2400 from booklore-app/develop
Merge develop into master for the release
2 parents 6b02fa4 + eb57af8 commit 90d599c

File tree

22 files changed

+114
-85
lines changed

22 files changed

+114
-85
lines changed

.github/workflows/draft-release.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

booklore-api/src/main/java/com/adityachandel/booklore/model/dto/KoreaderUser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ public class KoreaderUser {
1212
private String password;
1313
private String passwordMD5;
1414
private boolean syncEnabled;
15+
private boolean syncWithBookloreReader;
1516
}

booklore-api/src/main/java/com/adityachandel/booklore/repository/ReadingSessionRepository.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,23 @@ GROUP BY CAST(rs.startTime AS LocalDate)
2525
""")
2626
List<ReadingSessionCountDto> findSessionCountsByUserAndYear(@Param("userId") Long userId, @Param("year") int year);
2727

28-
@Query("""
29-
SELECT
30-
b.id as bookId,
31-
COALESCE(b.metadata.title,
32-
(SELECT bf.fileName FROM BookFileEntity bf WHERE bf.book.id = b.id ORDER BY bf.id ASC LIMIT 1),
33-
'Unknown Book') as bookTitle,
34-
rs.bookType as bookFileType,
35-
MIN(rs.startTime) as startDate,
36-
MAX(rs.endTime) as endDate,
37-
COUNT(rs) as totalSessions,
38-
SUM(rs.durationSeconds) as totalDurationSeconds
39-
FROM ReadingSessionEntity rs
40-
JOIN rs.book b
41-
WHERE rs.user.id = :userId
42-
AND rs.startTime >= :startOfWeek AND rs.startTime < :endOfWeek
43-
GROUP BY b.id, b.metadata.title, rs.bookType, CAST(rs.startTime AS LocalDate)
44-
ORDER BY MIN(rs.startTime)
45-
""")
28+
@Query("""
29+
SELECT
30+
b.id as bookId,
31+
COALESCE(b.metadata.title,
32+
(SELECT bf.fileName FROM BookFileEntity bf WHERE bf.book.id = b.id ORDER BY bf.id ASC LIMIT 1),
33+
'Unknown Book') as bookTitle,
34+
rs.bookType as bookFileType,
35+
rs.startTime as startDate,
36+
rs.endTime as endDate,
37+
1L as totalSessions,
38+
rs.durationSeconds as totalDurationSeconds
39+
FROM ReadingSessionEntity rs
40+
JOIN rs.book b
41+
WHERE rs.user.id = :userId
42+
AND rs.startTime >= :startOfWeek AND rs.startTime < :endOfWeek
43+
ORDER BY rs.startTime
44+
""")
4645
List<ReadingSessionTimelineDto> findSessionTimelineByUserAndWeek(
4746
@Param("userId") Long userId,
4847
@Param("startOfWeek") Instant startOfWeek,

booklore-api/src/test/java/com/adityachandel/booklore/controller/KoreaderUserControllerTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
import com.adityachandel.booklore.service.koreader.KoreaderUserService;
55
import org.junit.jupiter.api.BeforeEach;
66
import org.junit.jupiter.api.Test;
7-
import org.mockito.*;
7+
import org.mockito.InjectMocks;
8+
import org.mockito.Mock;
9+
import org.mockito.MockitoAnnotations;
810
import org.springframework.http.HttpStatus;
911
import org.springframework.http.ResponseEntity;
1012

1113
import java.util.Map;
1214

13-
import static org.junit.jupiter.api.Assertions.*;
14-
import static org.mockito.Mockito.*;
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertNull;
17+
import static org.mockito.Mockito.doNothing;
18+
import static org.mockito.Mockito.when;
1519

1620
class KoreaderUserControllerTest {
1721

@@ -26,7 +30,7 @@ class KoreaderUserControllerTest {
2630
@BeforeEach
2731
void setUp() {
2832
try (AutoCloseable mocks = MockitoAnnotations.openMocks(this)) {
29-
user = new KoreaderUser(1L, "testuser", "pass", "md5", true);
33+
user = new KoreaderUser(1L, "testuser", "pass", "md5", true, true);
3034
} catch (Exception e) {
3135
throw new RuntimeException(e);
3236
}

booklore-api/src/test/java/com/adityachandel/booklore/service/KoreaderUserServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void init() {
5353
entity.setBookLoreUser(ownerEntity);
5454
entity.setUsername("kvUser");
5555

56-
dto = new KoreaderUser(10L, "kvUser", null, null, false);
56+
dto = new KoreaderUser(10L, "kvUser", null, null, false, true);
5757
when(koreaderUserMapper.toDto(any(KoreaderUserEntity.class))).thenReturn(dto);
5858
}
5959

@@ -69,7 +69,7 @@ void upsertUser_createsNew_whenAbsent() {
6969

7070
when(koreaderUserMapper.toDto(any(KoreaderUserEntity.class))).thenAnswer(invocation -> {
7171
KoreaderUserEntity u = invocation.getArgument(0);
72-
return new KoreaderUser(u.getId(), u.getUsername(), u.getPassword(), u.getPasswordMD5(), u.isSyncEnabled());
72+
return new KoreaderUser(u.getId(), u.getUsername(), u.getPassword(), u.getPasswordMD5(), u.isSyncEnabled(), u.isSyncWithBookloreReader());
7373
});
7474

7575
KoreaderUser result = service.upsertUser("userA", "passA");

booklore-ui/src/app/features/metadata/component/book-metadata-center/book-reading-sessions/book-reading-sessions.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<tr>
3737
<td>{{ formatDate(session.startTime) }}</td>
3838
<td>{{ formatDate(session.endTime) }}</td>
39-
<td>{{ formatDuration(session.durationSeconds) }}</td>
39+
<td>{{ getActualDuration(session) }}</td>
4040
<td>
4141
@if (session.startProgress !== null && session.startProgress !== undefined && session.endProgress !== null && session.endProgress !== undefined) {
4242
<span>{{ session.startProgress }}% → {{ session.endProgress }}%</span>

booklore-ui/src/app/features/metadata/component/book-metadata-center/book-reading-sessions/book-reading-sessions.component.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,24 @@ export class BookReadingSessionsComponent implements OnInit, OnChanges {
6969
return `${secs}s`;
7070
}
7171

72+
calculateActualDuration(session: ReadingSessionResponse): number {
73+
const startTime = new Date(session.startTime).getTime();
74+
const endTime = new Date(session.endTime).getTime();
75+
return Math.floor((endTime - startTime) / 1000);
76+
}
77+
78+
getActualDuration(session: ReadingSessionResponse): string {
79+
const actualDuration = this.calculateActualDuration(session);
80+
const storedDuration = session.durationSeconds;
81+
82+
if (Math.abs(actualDuration - storedDuration) > 1) {
83+
// Discrepancy detected - show both values
84+
return `${this.formatDuration(actualDuration)}`;
85+
}
86+
87+
return this.formatDuration(actualDuration);
88+
}
89+
7290
formatDate(dateString: string): string {
7391
return new Date(dateString).toLocaleString();
7492
}

booklore-ui/src/app/features/readers/cbx-reader/layout/footer/cbx-footer.component.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use 'sass:color';
2+
13
// Variables
24
$footer-bg: #1a1a1a;
35
$text-primary: rgba(255, 255, 255, 0.95);
@@ -95,7 +97,7 @@ $transition-fast: 150ms ease;
9597
}
9698

9799
&:hover:not(:disabled) {
98-
background: darken($active-color, 10%);
100+
background: color.adjust($active-color, $lightness: -10%);
99101
}
100102

101103
&:disabled {
@@ -289,7 +291,7 @@ $transition-fast: 150ms ease;
289291
transition: all 0.2s ease;
290292

291293
&:hover:not(:disabled) {
292-
background: darken($active-color, 10%);
294+
background: color.adjust($active-color, $lightness: -10%);
293295
}
294296

295297
&:disabled {

booklore-ui/src/app/features/readers/cbx-reader/layout/quick-settings/cbx-quick-settings.component.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use 'sass:color';
2+
13
// Variables
24
$panel-bg: #1a1a1a;
35
$text-primary: rgba(255, 255, 255, 0.95);
@@ -134,7 +136,7 @@ $transition-normal: 200ms ease;
134136
background: rgba(255, 255, 255, 0.2);
135137

136138
&.active {
137-
background: lighten($active-color, 5%);
139+
background: color.adjust($active-color, $lightness: 5%);
138140
}
139141
}
140142
}

booklore-ui/src/app/features/settings/global-preferences/metadata-provider-settings/metadata-provider-settings.component.html

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,21 @@ <h4 class="provider-group-title">Providers with Configuration</h4>
7777
</p-toggleswitch>
7878
<label class="setting-label">Hardcover</label>
7979
</div>
80-
@if (hardcoverEnabled) {
81-
<div class="setting-options">
82-
<div class="config-field">
83-
<div class="config-label-row">
84-
<label class="config-label">API Token</label>
85-
<app-external-doc-link docType="hardcover"></app-external-doc-link>
86-
</div>
87-
<input
88-
type="text"
89-
pInputText
90-
placeholder="Enter Hardcover API token"
91-
[(ngModel)]="hardcoverToken"
92-
(ngModelChange)="onTokenChange($event)"
93-
class="config-input"/>
80+
<div class="setting-options">
81+
<div class="config-field">
82+
<div class="config-label-row">
83+
<label class="config-label">API Token</label>
84+
<app-external-doc-link docType="hardcover"></app-external-doc-link>
9485
</div>
86+
<input
87+
type="text"
88+
pInputText
89+
placeholder="Enter Hardcover API token"
90+
[(ngModel)]="hardcoverToken"
91+
(ngModelChange)="onTokenChange($event)"
92+
class="config-input"/>
9593
</div>
96-
}
94+
</div>
9795
</div>
9896

9997
<div class="setting-item">

0 commit comments

Comments
 (0)