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
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />

<application
android:name=".MyApp"
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.github.wiiznokes.gitnote.helper

import android.Manifest
import android.content.Context
import android.os.Build
import androidx.core.content.PermissionChecker
import java.net.InetAddress
import java.net.URI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class NetworkPermissionHelper {
companion object {
fun isPermissionGranted(context: Context): Boolean {
if (Build.VERSION.SDK_INT < 37) return true
return PermissionChecker.checkSelfPermission(
context,
Manifest.permission.ACCESS_LOCAL_NETWORK
) == PermissionChecker.PERMISSION_GRANTED
}

suspend fun requiresLocalNetworkPermission(urlString: String): Boolean = withContext(Dispatchers.IO) {
try {
val host = if (urlString.contains("://")) {
URI(urlString).host
} else {
val afterAt = urlString.substringAfter('@', urlString)
afterAt.substringBefore(':')
}

if (host == null) return@withContext false

if (host.endsWith(".local", ignoreCase = true)) {
return@withContext true
}

val addresses = InetAddress.getAllByName(host)

addresses.any { address ->
address.isSiteLocalAddress ||
address.isLinkLocalAddress
}
} catch (_: Exception) {
false
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.wiiznokes.gitnote.ui.screen.setup.remote

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.text.KeyboardOptions
Expand All @@ -8,15 +10,21 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview
import io.github.wiiznokes.gitnote.MyApp
import io.github.wiiznokes.gitnote.R
import io.github.wiiznokes.gitnote.helper.NetworkPermissionHelper
import kotlinx.coroutines.launch
import io.github.wiiznokes.gitnote.manager.getUrlInfoLib
import io.github.wiiznokes.gitnote.provider.GithubProvider
import io.github.wiiznokes.gitnote.provider.Provider
Expand Down Expand Up @@ -87,6 +95,22 @@ fun EnterUrlScreen(
onBackClick: () -> Unit,
onUrl: (String) -> Unit
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val pendingUrl = remember { mutableStateOf<String?>(null) }
val nearbyPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (granted) {
pendingUrl.value?.let(onUrl)
} else {
MyApp.appModule.uiHelper.makeToast(
MyApp.appModule.context.getString(R.string.error_need_network_permission)
)
}
pendingUrl.value = null
}

AppPage(
title = "URL",
horizontalAlignment = Alignment.CenterHorizontally,
Expand All @@ -108,7 +132,15 @@ fun EnterUrlScreen(
SetupButton(
text = stringResource(R.string.next),
onClick = {
onUrl(url.value.text)
val urlText = url.value.text
scope.launch {
if (NetworkPermissionHelper.requiresLocalNetworkPermission(urlText) && !NetworkPermissionHelper.isPermissionGranted(context)) {
pendingUrl.value = urlText
nearbyPermissionLauncher.launch(android.Manifest.permission.ACCESS_LOCAL_NETWORK)
} else {
onUrl(urlText)
}
}
},
enabled = isUrlCorrect(url.value.text)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,4 @@ private fun GenerateNewSshKeysScreenPreview() {
onClone = {}
)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,4 @@ private fun LoadKeysFromDeviceScreenPreview() {
onClone = {},
url = "url",
)
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values-cs/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<string name="clone_remote_repo">Klonovat vzdálený repozitář</string>
<string name="use_app_storage">Použít úložiště aplikace</string>
<string name="error_need_storage_permission">Aplikace potřebuje toto oprávnění pro přístup k úložišti</string>
<string name="error_need_network_permission">Aplikace potřebuje toto oprávnění pro přístup k repozitářům v místní síti</string>
<string name="use_device_storage">Použít úložiště zařízení</string>
<string name="use_device_storage_info">Vyžaduje oprávnění pro přístup k úplnému úložišti zařízení. Poté budete mít přístup k úložišti ve svém zařízení.</string>
<string name="create_repo_explorer">Vytvořit repozitář v této složce</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
<string name="clone_remote_repo">Cloner un dépôt distant</string>
<string name="use_app_storage">Utiliser la mémoire de l\'app</string>
<string name="error_need_storage_permission">L\'application a besoin de cette permission pour accéder au stockage</string>
<string name="error_need_network_permission">L\'application a besoin de cette autorisation pour accéder aux dépôts sur votre réseau local</string>
<string name="use_device_storage">Utiliser la mémoire de l\'appareil</string>
<string name="use_device_storage_info">Requiert une autorisation d\'accès au stockage complet de l\'appareil. Vous aurez la possibilité d\'accéder au dépôt sur votre ordinateur par la suite.</string>
<string name="create_repo_explorer">Créer un dépôt dans ce dossier</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<string name="clone_remote_repo">Clonar repositório local</string>
<string name="use_app_storage">Usar armazenamento do aplicativo</string>
<string name="error_need_storage_permission">O aplicativo precisa desta permissão para acessar o armazenamento</string>
<string name="error_need_network_permission">O aplicativo precisa desta permissão para acessar repositórios em sua rede local</string>
<string name="use_device_storage">Usar armazenamento do dispositivo</string>
<string name="use_device_storage_info">Requer permissão para acessar todo o armazenamento do dispositivo. Você poderá acessar o repositório pelo computador após esse passo.</string>
<string name="create_repo_explorer">Criar repositório nessa pasta</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-ru-rRU/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<string name="clone_repo">Клонировать удалённый репозиторий</string>
<string name="use_app_storage">Использовать хранилище приложения</string>
<string name="error_need_storage_permission">Приложению необходимо это разрешение для доступа к хранилищу</string>
<string name="error_need_network_permission">Приложению необходимо это разрешение для доступа к репозиториям в вашей локальной сети</string>
<string name="use_device_storage">Использовать хранилище устройства</string>
<string name="use_device_storage_info">Требуется разрешение на доступ ко всему хранилищу устройства. После этого вы сможете получить доступ к репозиторию с компьютера.</string>
<string name="create_repo_explorer">Создать репозиторий в этой папке</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-uk/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<string name="clone_repo">Клонувати віддалений репозиторій</string>
<string name="use_app_storage">Використати сховище застосунку</string>
<string name="error_need_storage_permission">Застосунку потрібен цей дозвіл для доступу до сховища</string>
<string name="error_need_network_permission">Застосунку потрібен цей дозвіл для доступу до репозиторіїв у вашій локальній мережі</string>
<string name="use_device_storage">Використати сховище пристрою</string>
<string name="use_device_storage_info">Потрібен дозвіл на доступ до всього сховища пристрою. Після цього ви зможете отримати доступ до репозиторію з комп’ютера.</string>
<string name="create_repo_explorer">Створити репозиторій у цій папці</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<string name="clone_remote_repo">Clone remote repository</string>
<string name="use_app_storage">Use app storage</string>
<string name="error_need_storage_permission">The application needs this permission to access the storage</string>
<string name="error_need_network_permission">The application needs this permission to access repositories on your local network</string>
<string name="use_device_storage">Use device storage</string>
<string name="use_device_storage_info">Requires permission to access the full device storage. You will be able to access the repository on your computer afterwards.</string>
<string name="create_repo_explorer">Create repository in this folder</string>
Expand Down