Skip to content

Commit ca33183

Browse files
author
FunkyMuse
committed
add the old way of the ui looking and bring a scraper that does the heavy lifting
1 parent 509617c commit ca33183

File tree

21 files changed

+285
-178
lines changed

21 files changed

+285
-178
lines changed

book/bookmodel/src/main/java/com/funkymuse/aurora/bookmodel/Book.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,9 @@ data class Book(
1010
override val image: String?,
1111
override val title: String?,
1212
override val author: String?,
13-
override val id: String
13+
override val id: String,
14+
override val extension: String?,
15+
override val pages: String?,
16+
override val size: String?,
17+
override val year: String?
1418
) : GeneralBook

book/bookui/src/main/java/com/funkymuse/aurora/bookui/BookUi.kt

+70-60
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,18 @@ import androidx.compose.runtime.Composable
1010
import androidx.compose.ui.Alignment
1111
import androidx.compose.ui.Modifier
1212
import androidx.compose.ui.geometry.Size
13+
import androidx.compose.ui.graphics.Color
1314
import androidx.compose.ui.res.stringResource
1415
import androidx.compose.ui.text.TextStyle
1516
import androidx.compose.ui.text.font.FontStyle
1617
import androidx.compose.ui.text.font.FontWeight
1718
import androidx.compose.ui.text.style.TextOverflow
18-
import androidx.compose.ui.tooling.preview.Preview
1919
import androidx.compose.ui.unit.dp
2020
import androidx.compose.ui.unit.sp
21-
import androidx.constraintlayout.compose.ConstrainedLayoutReference
22-
import androidx.constraintlayout.compose.ConstraintLayout
23-
import androidx.constraintlayout.compose.ConstraintLayoutScope
24-
import androidx.constraintlayout.compose.Dimension
2521
import coil.compose.ImagePainter
2622
import coil.compose.rememberImagePainter
2723
import com.funkymuse.aurora.generalbook.GeneralBook
2824
import com.funkymuse.aurora.loadingcomponent.BoxShimmer
29-
import com.funkymuse.aurora.loadingcomponent.CardShimmer
3025
import com.funkymuse.aurora.serverconstants.LIBGEN_BASE_URL
3126
import com.funkymuse.style.color.CardBackground
3227
import com.funkymuse.style.shape.Shapes
@@ -51,79 +46,104 @@ fun Book(
5146
.wrapContentHeight(),
5247
backgroundColor = CardBackground
5348
) {
54-
ConstraintLayout(
49+
Box(
5550
modifier = Modifier
5651
.combinedClickable(onLongClick = onLongClick, onClick = onClick)
5752
) {
58-
val image = image(book.image)
59-
val title = addTitle(image, book.title)
60-
addAuthor(title, image, book.author)
53+
Row {
54+
Box(
55+
modifier = Modifier
56+
.weight(0.3f)
57+
.padding(16.dp)
58+
) {
59+
AddStaticImage(remoteImage = book.image)
60+
}
61+
Box(
62+
modifier = Modifier
63+
.weight(0.7f)
64+
.padding(8.dp)
65+
) {
66+
Column {
67+
AddTitle(titleText = book.title)
68+
AddAuthor(authorText = book.author)
69+
AddYear(year = book.year)
70+
AddFormatPagesAndSize(book.extension, book.pages, book.size)
71+
}
72+
}
73+
}
6174
}
6275
}
6376
}
6477

6578
@Composable
66-
private fun ConstraintLayoutScope.addAuthor(
67-
title: ConstrainedLayoutReference,
68-
image: ConstrainedLayoutReference,
79+
fun AddFormatPagesAndSize(extension: String?, pages: String?, size: String?) {
80+
val pagesText =
81+
if (pages.isNullOrBlank()) "" else "($pages ${stringResource(id = R.string.pages)})"
82+
val extensionText = if (extension.isNullOrBlank()) "" else extension
83+
val sizeText = if (size.isNullOrBlank()) "" else size
84+
85+
val text = when {
86+
pages.isNullOrBlank() -> "$extensionText, $sizeText"
87+
extension.isNullOrBlank() -> "$pagesText, $sizeText"
88+
size.isNullOrBlank() -> "$extensionText $pagesText"
89+
else -> "$extensionText $pagesText, $sizeText"
90+
}
91+
92+
if (pages.isNullOrBlank() && extension.isNullOrBlank() && size.isNullOrBlank()) {
93+
return
94+
}
95+
96+
Text(
97+
text = text,
98+
color = Color.DarkGray,
99+
style = TextStyle(fontWeight = FontWeight.Light, fontSize = 17.sp),
100+
modifier = Modifier.padding(bottom = 8.dp),
101+
)
102+
}
103+
104+
@Composable
105+
private fun AddYear(year: String?) {
106+
year ?: return
107+
Text(
108+
text = year,
109+
color = Color.DarkGray,
110+
style = TextStyle(fontWeight = FontWeight.Light, fontSize = 17.sp)
111+
)
112+
}
113+
114+
@Composable
115+
private fun AddAuthor(
69116
authorText: String?
70-
): ConstrainedLayoutReference {
71-
val author = createRef()
117+
) {
72118
Text(
73119
text = authorText ?: stringResource(id = R.string.not_available),
74-
modifier = Modifier
75-
.constrainAs(author) {
76-
start.linkTo(image.end, 16.dp)
77-
top.linkTo(title.bottom, 8.dp)
78-
end.linkTo(parent.end, 16.dp)
79-
width = Dimension.fillToConstraints
80-
},
81-
style = TextStyle(fontStyle = FontStyle.Italic, fontSize = 16.sp),
82-
maxLines = 1,
83-
overflow = TextOverflow.Ellipsis,
84-
)
85-
return author
120+
modifier = Modifier.padding(end = 8.dp),
121+
fontStyle = FontStyle.Italic
122+
)
86123
}
87124

88125
@Composable
89-
private fun ConstraintLayoutScope.addTitle(
90-
image: ConstrainedLayoutReference,
126+
private fun AddTitle(
91127
titleText: String?
92-
): ConstrainedLayoutReference {
93-
val title = createRef()
128+
) {
94129
Text(
130+
modifier = Modifier.padding(end = 8.dp),
95131
text = titleText ?: stringResource(id = R.string.not_available),
96-
modifier = Modifier
97-
.constrainAs(title) {
98-
start.linkTo(image.end, 16.dp)
99-
top.linkTo(parent.top, 10.dp)
100-
end.linkTo(parent.end, 16.dp)
101-
width = Dimension.fillToConstraints
102-
},
103132
overflow = TextOverflow.Ellipsis,
104-
maxLines = 2,
133+
maxLines = 3,
105134
style = TextStyle(fontWeight = FontWeight.SemiBold, fontSize = 17.sp)
106135
)
107-
return title
108136
}
109137

110138
@Composable
111-
private fun ConstraintLayoutScope.image(remoteImage: String?): ConstrainedLayoutReference {
112-
139+
private fun AddStaticImage(remoteImage: String?) {
113140
val imageUrl = LIBGEN_BASE_URL + remoteImage
114141
val painter = rememberImagePainter(data = imageUrl)
115142

116-
val image = createRef()
117-
118143
val size = Size(85.dp.value, 130.dp.value)
119144

120145
val imageModifier = Modifier
121146
.size(size.width.dp, size.height.dp)
122-
.constrainAs(image) {
123-
top.linkTo(parent.top)
124-
start.linkTo(parent.start)
125-
bottom.linkTo(parent.bottom)
126-
}
127147

128148
when (painter.state) {
129149
is ImagePainter.State.Loading -> {
@@ -132,22 +152,12 @@ private fun ConstraintLayoutScope.image(remoteImage: String?): ConstrainedLayout
132152
}
133153
}
134154
is ImagePainter.State.Success, is ImagePainter.State.Error, ImagePainter.State.Empty -> {
135-
Box(modifier = imageModifier, contentAlignment = Alignment.CenterStart) {
155+
Box(modifier = imageModifier, contentAlignment = Alignment.Center) {
136156
Image(
137157
painter = painter,
138158
contentDescription = stringResource(id = R.string.book_details)
139159
)
140160
}
141161
}
142162
}
143-
144-
return image
145-
}
146-
147-
@Preview
148-
@Composable
149-
fun BookPreview(){
150-
Book(book = com.funkymuse.aurora.bookmodel.Book("/covers/23000/897294668dce7c4cc065e7d7d96a4923-d.jpg",
151-
title = "Communicating Design: Developing Web Site Documentation for Design and Planning",
152-
author = "Dan M. Brown", "897294668DCE7C4CC065E7D7D96A4923"))
153163
}

book/generalbook/src/main/java/com/funkymuse/aurora/generalbook/GeneralBook.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ interface GeneralBook {
77
val image: String?
88
val title: String?
99
val author: String?
10-
val id:String
10+
val id: String
11+
val extension: String?
12+
val pages: String?
13+
val size: String?
14+
val year: String?
1115
}

book/skraper/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

book/skraper/build.gradle

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
plugins {
2+
id 'kotlin-kapt'
3+
}
4+
5+
applyHiltDeps(this)
6+
7+
dependencies {
8+
implementation project(path: ':book:bookmodel')
9+
implementation project(path: ':extensions')
10+
implementation project(path: ':serverconstants')
11+
12+
13+
//jsoup
14+
implementation "it.skrape:skrapeit:$skrapeit"
15+
16+
implementation "com.github.FunkyMuse.KAHelpers:common:$KAHelpers"
17+
implementation project(path: ':coroutines:dispatchers')
18+
19+
}

book/skraper/consumer-rules.pro

Whitespace-only changes.

book/skraper/proguard-rules.pro

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.funkymuse.aurora.skraper
2+
3+
import androidx.test.platform.app.InstrumentationRegistry
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
6+
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
9+
import org.junit.Assert.*
10+
11+
/**
12+
* Instrumented test, which will execute on an Android device.
13+
*
14+
* See [testing documentation](http://d.android.com/tools/testing).
15+
*/
16+
@RunWith(AndroidJUnit4::class)
17+
class ExampleInstrumentedTest {
18+
@Test
19+
fun useAppContext() {
20+
// Context of the app under test.
21+
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22+
assertEquals("com.funkymuse.aurora.skraper.test", appContext.packageName)
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.funkymuse.aurora.skraper">
4+
5+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.funkymuse.aurora.skraper
2+
3+
import android.util.Log
4+
import com.crazylegend.common.tryOrNull
5+
import com.funkymuse.aurora.bookmodel.Book
6+
import com.funkymuse.aurora.extensions.removeBrackets
7+
import com.funkymuse.aurora.serverconstants.*
8+
import it.skrape.core.htmlDocument
9+
import it.skrape.fetcher.HttpFetcher
10+
import it.skrape.fetcher.response
11+
import it.skrape.fetcher.skrape
12+
import it.skrape.selects.DocElement
13+
import javax.inject.Inject
14+
import javax.inject.Singleton
15+
16+
/**
17+
* Created by funkymuse on 8/2/21 to long live and prosper !
18+
*/
19+
@Singleton
20+
class BookScraper @Inject constructor() {
21+
22+
private fun List<DocElement>.toBook(): Book? {
23+
val id = tryOrNull {
24+
this[2].eachLink.values.firstOrNull()?.substringAfter("md5=")
25+
} ?: return null
26+
val extension = tryOrNull { this[33].text }?.uppercase()
27+
val size = tryOrNull { this[31].text }?.substringBefore("(")?.trim()
28+
val pages = tryOrNull { this[21].text }?.removeBrackets()?.substringBefore(" ")
29+
val image = tryOrNull { this[0].eachImage.values.firstOrNull() }
30+
val title = tryOrNull { this[2].text }
31+
val author = tryOrNull { this[5].text }
32+
val year = tryOrNull { this[15].text }
33+
return Book(image, title, author, id, extension, pages, size, year)
34+
}
35+
36+
fun generateSearchDataUrl(
37+
page: Int, searchQuery: String, sortQuery: String, sortType: String,
38+
searchInFieldsPosition: Int, maskWord: Boolean
39+
): String = "$SEARCH_BASE_URL?$REQ_CONST=${
40+
searchQuery.replace(
41+
" ",
42+
"+"
43+
)
44+
}&$SORT_QUERY=$sortQuery&$VIEW_QUERY=$VIEW_QUERY_PARAM&$RES_CONST=$PAGE_SIZE&" +
45+
"&$COLUM_QUERY=${getFieldParamByPosition(searchInFieldsPosition)}&$SORT_TYPE=$sortType&" +
46+
"$SEARCH_WITH_MASK=${if (maskWord) SEARCH_WITH_MASK_YES else SEARCH_WITH_MASK_NO}&" +
47+
"$PAGE_CONST=$page"
48+
49+
50+
fun generateLatestBooksUrl(page: Int, sortQuery: String, sortType: String): String =
51+
"$SEARCH_BASE_URL?$SORT_QUERY=$sortQuery&$VIEW_QUERY=$VIEW_QUERY_PARAM&$RES_CONST=$PAGE_SIZE&" +
52+
"$LAST_MODE=$LAST_QUERY&$COLUM_QUERY=$FIELD_DEFAULT_PARAM&$SORT_TYPE=$sortType&" +
53+
"$PAGE_CONST=$page"
54+
55+
56+
suspend fun fetch(requestUrl: String): List<Book> =
57+
skrape(HttpFetcher) {
58+
request {
59+
timeout = DEFAULT_API_TIMEOUT
60+
url = requestUrl
61+
Log.d("URL REQUESt", url)
62+
}
63+
response {
64+
htmlDocument {
65+
findAll("table").asSequence().drop(2).map {
66+
67+
val elementList =
68+
tryOrNull {
69+
it.findAll("tr").filter { it.children.size >= 2 }
70+
}?.map { it.findAll("td") }?.flatten()
71+
72+
val res = if (!elementList.isNullOrEmpty()) {
73+
elementList.mapNotNull {
74+
elementList.toBook()
75+
}
76+
} else {
77+
emptyList()
78+
}
79+
80+
res
81+
}.flatten().toSet().toList()
82+
}
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)