Skip to content

Commit 5f25b2a

Browse files
committed
Add support for read/wished/ongoing states in book editor app
1 parent 7416502 commit 5f25b2a

File tree

8 files changed

+357
-25
lines changed

8 files changed

+357
-25
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ firebase-debug.*.log*
2626
.firebase/
2727
tmp
2828
google_auth_token_cache.json
29+
scrapper/.idea/appInsightsSettings.xml
30+
scrapper/.idea/caches/deviceStreaming.xml
31+
scrapper/.idea/runConfigurations.xml

scrapper/.idea/codeStyles/Project.xml

Lines changed: 191 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scrapper/book-reading-editor-app/src/main/java/net/opatry/book/editor/BookReadingEditorApp.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2024 Olivier Patry
1+
// Copyright (c) 2025 Olivier Patry
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining
44
// a copy of this software and associated documentation files (the "Software"),
@@ -20,7 +20,6 @@
2020

2121
package net.opatry.book.editor
2222

23-
import androidx.compose.material.ExperimentalMaterialApi
2423
import androidx.compose.runtime.LaunchedEffect
2524
import androidx.compose.runtime.getValue
2625
import androidx.compose.runtime.mutableStateOf
@@ -49,13 +48,13 @@ import net.opatry.book.editor.screen.MainScreen
4948
import net.opatry.util.toColorInt
5049
import java.awt.Dimension
5150
import java.io.File
51+
import java.time.LocalDate
5252

5353
sealed class Instance(val site: String, val dir: File, val label: String) {
5454
data object Oliv : Instance("https://lecture.opatry.net", File("/Users/opatry/work/book-reading"), "Olivier")
5555
data object Fanny : Instance("https://fanny-lit.web.app", File("/Users/opatry/work/lecture-fanny"), "Fanny")
5656
}
5757

58-
@OptIn(ExperimentalMaterialApi::class)
5958
fun main() {
6059
application {
6160
val defaultSize = DpSize(900.dp, 900.dp)
@@ -82,7 +81,9 @@ fun main() {
8281
val httpClient = HttpClient(CIO) {
8382
CurlUserAgent()
8483
install(ContentNegotiation) {
85-
gson()
84+
gson {
85+
registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
86+
}
8687
}
8788
install(HttpTimeout) {
8889
requestTimeoutMillis = 3000

scrapper/book-reading-editor-app/src/main/java/net/opatry/book/editor/Bookshelf.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2024 Olivier Patry
1+
// Copyright (c) 2025 Olivier Patry
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining
44
// a copy of this software and associated documentation files (the "Software"),
@@ -21,6 +21,7 @@
2121
package net.opatry.book.editor
2222

2323
import com.google.gson.annotations.SerializedName
24+
import java.time.LocalDate
2425

2526
data class Bookshelf(
2627
@SerializedName("url")
@@ -47,12 +48,22 @@ data class Bookshelf(
4748
val author: String,
4849
@SerializedName("link")
4950
val url: String,
51+
@SerializedName("read_date")
52+
val readDate: LocalDate? = null,
5053
@SerializedName("rating")
51-
val rating: Int,
54+
val rating: Int = 0,
55+
@SerializedName("priority")
56+
val priority: Float? = 0f,
5257
@SerializedName("favorite")
5358
val isFavorite: Boolean,
59+
@SerializedName("ongoing")
60+
val isOngoing: Boolean = false,
5461
@SerializedName("cover")
5562
val coverUrl: String,
63+
@SerializedName("cover_mini")
64+
val miniCoverUrl: String? = null,
65+
@SerializedName("tags")
66+
val tags: List<String> = emptyList(),
5667
)
5768
}
5869

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2025 Olivier Patry
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining
4+
// a copy of this software and associated documentation files (the "Software"),
5+
// to deal in the Software without restriction, including without limitation
6+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
// and/or sell copies of the Software, and to permit persons to whom the Software
8+
// is furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19+
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
21+
package net.opatry.book.editor
22+
23+
import com.google.gson.JsonDeserializationContext
24+
import com.google.gson.JsonDeserializer
25+
import com.google.gson.JsonElement
26+
import com.google.gson.JsonPrimitive
27+
import com.google.gson.JsonSerializationContext
28+
import com.google.gson.JsonSerializer
29+
import java.lang.reflect.Type
30+
import java.time.LocalDate
31+
import java.time.format.DateTimeFormatter
32+
33+
class LocalDateAdapter : JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {
34+
private val formatter = DateTimeFormatter.ISO_DATE
35+
36+
override fun serialize(src: LocalDate, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
37+
return JsonPrimitive(src.format(formatter))
38+
}
39+
40+
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): LocalDate {
41+
return LocalDate.parse(json.asString, formatter)
42+
}
43+
}

0 commit comments

Comments
 (0)