Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Deepr">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class DeeprApplication : Application() {
}

single {
NetworkRepository(get(), get())
NetworkRepository(get())
}

single<LocalServerRepository> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ package com.yogeshpaliyal.deepr.data

import com.yogeshpaliyal.deepr.util.normalizeLink
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText

class NetworkRepository(
val httpClient: HttpClient,
val httpParser: HtmlParser,
) {
val httpClient: HttpClient by lazy {
HttpClient(CIO)
}

suspend fun getLinkInfo(url: String): Result<LinkInfo> {
val normalizedUrl = normalizeLink(url)
try {
val response = httpClient.get(normalizedUrl)
val response =
httpClient.get(normalizedUrl) {
}
if (response.status.value != 200) {
return Result.failure(Exception("Failed to fetch data from $normalizedUrl, status code: ${response.status.value}"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,18 +256,34 @@ fun HomeBottomContent(
Spacer(modifier = Modifier.height(8.dp))

if (deeprInfo.thumbnail.isNotEmpty() && isThumbnailEnable) {
AsyncImage(
model = deeprInfo.thumbnail,
contentDescription = deeprInfo.name,
modifier =
Modifier
.fillMaxWidth()
.aspectRatio(1.91f)
.background(MaterialTheme.colorScheme.surfaceVariant),
placeholder = null,
error = null,
contentScale = ContentScale.Crop,
)
Column {
AsyncImage(
model = deeprInfo.thumbnail,
contentDescription = deeprInfo.name,
modifier =
Modifier
.fillMaxWidth()
.aspectRatio(1.91f)
.background(MaterialTheme.colorScheme.surfaceVariant),
placeholder = null,
error = null,
contentScale = ContentScale.Crop,
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedButton(
onClick = {
deeprInfo = deeprInfo.copy(thumbnail = "")
},
modifier = Modifier.fillMaxWidth(),
) {
Icon(
imageVector = TablerIcons.X,
contentDescription = stringResource(R.string.remove_thumbnail),
)
Spacer(modifier = Modifier.width(8.dp))
Text(stringResource(R.string.remove_thumbnail))
}
}
}

Spacer(modifier = Modifier.height(8.dp))
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<string name="add_to_favourites">Add to favourites</string>
<string name="remove_from_favourites">Remove from favourites</string>
<string name="add_link">Add Link</string>
<string name="fetch_name_from_link">Fetch name from link</string>
<string name="fetch_name_from_link">Fetch meta from link</string>
<string name="create_tag">Create Tag</string>
<string name="new_tag">New tag (Optional)</string>
<string name="no_links_saved_yet">No links saved yet</string>
Expand All @@ -33,6 +33,7 @@
<string name="no_links_with_tags_description">Try selecting different tags or clear filters.</string>
<string name="no_favourites_with_tags">No favourites in selected tags</string>
<string name="no_favourites_with_tags_description">Mark links with these tags as favourites or try different tags.</string>
<string name="remove_thumbnail">Remove thumbnail</string>

<!-- Menu and Dialog Items -->
<string name="more_options">More options</string>
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<network-security-config>
<debug-overrides>
<trust-anchors>
<!-- Trust user added CAs while debuggable only -->
<certificates src="user" />
<certificates src="system" />
</trust-anchors>
</debug-overrides>

<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.yogeshpaliyal.deepr.data
import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import io.ktor.client.engine.mock.respond
import io.ktor.client.plugins.UserAgent
import io.ktor.http.HttpStatusCode
import io.ktor.http.headersOf
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -152,4 +153,39 @@ class NetworkRepositoryTest {
assertEquals("Test Title", linkInfo?.title)
assertEquals("https://example.com/image.jpg", linkInfo?.image)
}

@Test
fun getLinkInfo_sendsUserAgentHeader() =
runTest {
// Create a mock HTTP client that captures the User-Agent header
var receivedUserAgent: String? = null
val mockEngine =
MockEngine { request ->
receivedUserAgent = request.headers["User-Agent"]
respond(
content = mockHtmlContent,
status = HttpStatusCode.OK,
headers = headersOf("Content-Type", "text/html"),
)
}

val httpClient =
HttpClient(mockEngine) {
install(UserAgent) {
agent =
"Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
}
}
val htmlParser = HtmlParser()
val repository = NetworkRepository(httpClient, htmlParser)

val result = repository.getLinkInfo("example.com")

// Verify the User-Agent header was sent
assertTrue(result.isSuccess)
assertEquals(
"Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
receivedUserAgent,
)
}
}