diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 58ad66a..c323f02 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,7 +17,7 @@ android { val versionMajor = 2 val versionMinor = 3 - val versionPatch = 0 + val versionPatch = 1 val versionBuild = 0 defaultConfig { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt index 4cce6a2..c25dc78 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt @@ -6,6 +6,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings +import android.view.KeyEvent import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts @@ -22,6 +23,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.input.key.onKeyEvent import com.google.accompanist.navigation.animation.AnimatedNavHost import com.google.accompanist.navigation.animation.composable import com.google.accompanist.navigation.animation.rememberAnimatedNavController @@ -40,6 +44,8 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen import com.zaneschepke.wireguardautotunnel.ui.theme.TransparentSystemBars import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme import dagger.hilt.android.AndroidEntryPoint +import timber.log.Timber +import java.lang.IllegalStateException @AndroidEntryPoint class MainActivity : AppCompatActivity() { @@ -51,6 +57,8 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContent { val navController = rememberAnimatedNavController() + val focusRequester = remember { FocusRequester() } + WireguardAutoTunnelTheme { TransparentSystemBars() @@ -80,7 +88,25 @@ class MainActivity : AppCompatActivity() { } else requestNotificationPermission() } - Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) }, + Scaffold(snackbarHost = { SnackbarHost(snackbarHostState)}, + modifier = Modifier.onKeyEvent { + if (it.nativeKeyEvent.action == KeyEvent.ACTION_UP) { + when (it.nativeKeyEvent.keyCode) { + KeyEvent.KEYCODE_DPAD_UP -> { + try { + focusRequester.requestFocus() + } catch(e : IllegalStateException) { + Timber.e("No D-Pad focus request modifier added to element on screen") + } + false + } else -> { + false; + } + } + } else { + false + } + }, bottomBar = if (vpnIntent == null && notificationPermissionState.status.isGranted) { { BottomNavBar(navController, Routes.navItems) } } else { @@ -126,7 +152,7 @@ class MainActivity : AppCompatActivity() { } } }) { - MainScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController) + MainScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) } composable(Routes.Settings.name, enterTransition = { when (initialState.destination.route) { @@ -147,7 +173,7 @@ class MainActivity : AppCompatActivity() { fadeIn(animationSpec = tween(1000)) } } - }) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController) } + }) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) } composable(Routes.Support.name, enterTransition = { when (initialState.destination.route) { Routes.Settings.name, Routes.Main.name -> @@ -160,10 +186,10 @@ class MainActivity : AppCompatActivity() { fadeIn(animationSpec = tween(1000)) } } - }) { SupportScreen(padding = padding) } + }) { SupportScreen(padding = padding, focusRequester) } composable("${Routes.Config.name}/{id}", enterTransition = { fadeIn(animationSpec = tween(1000)) - }) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"))} + }) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"), focusRequester = focusRequester)} composable("${Routes.Detail.name}/{id}", enterTransition = { fadeIn(animationSpec = tween(1000)) }) { DetailScreen(padding = padding, id = it.arguments?.getString("id")) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt index 7c5c2ad..985386e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt @@ -52,13 +52,13 @@ import kotlinx.coroutines.launch fun ConfigScreen( viewModel: ConfigViewModel = hiltViewModel(), padding: PaddingValues, + focusRequester: FocusRequester, navController: NavController, id : String? ) { val context = LocalContext.current val focusManager = LocalFocusManager.current - val focusRequester = remember { FocusRequester() } val keyboardController = LocalSoftwareKeyboardController.current val scope = rememberCoroutineScope() @@ -228,10 +228,5 @@ fun ConfigScreen( } } } - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } } } \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt index a1747bb..9842faf 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -82,17 +82,17 @@ import com.zaneschepke.wireguardautotunnel.ui.theme.mint import kotlinx.coroutines.launch @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") -@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun MainScreen( viewModel: MainViewModel = hiltViewModel(), padding: PaddingValues, + focusRequester: FocusRequester, snackbarHostState: SnackbarHostState, navController: NavController ) { val haptic = LocalHapticFeedback.current val context = LocalContext.current val isVisible = rememberSaveable { mutableStateOf(true) } - val focusRequester = remember { FocusRequester() } val scope = rememberCoroutineScope() val sheetState = rememberModalBottomSheetState() diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt index 87cfdd4..77659ce 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt @@ -80,12 +80,12 @@ fun SettingsScreen( viewModel: SettingsViewModel = hiltViewModel(), padding: PaddingValues, navController: NavController, + focusRequester: FocusRequester, snackbarHostState: SnackbarHostState = remember { SnackbarHostState() } ) { val scope = rememberCoroutineScope() val context = LocalContext.current - val focusRequester = remember { FocusRequester() } val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } @@ -163,11 +163,6 @@ fun SettingsScreen( }) { Text(stringResource(id = R.string.turn_on)) } - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } } } return @@ -192,11 +187,6 @@ fun SettingsScreen( }) { Text(stringResource(id = R.string.request)) } - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } } return @@ -244,11 +234,6 @@ fun SettingsScreen( }) { Text(stringResource(id = R.string.check_again)) } - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } } return } @@ -282,11 +267,6 @@ fun SettingsScreen( } } ) - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } } Text( stringResource(id = R.string.select_tunnel), diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt index 3c264a9..5ab5b13 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt @@ -37,10 +37,9 @@ import androidx.compose.ui.unit.sp import com.zaneschepke.wireguardautotunnel.R @Composable -fun SupportScreen(padding : PaddingValues) { +fun SupportScreen(padding : PaddingValues, focusRequester: FocusRequester) { val context = LocalContext.current - val focusRequester = remember { FocusRequester() } fun openWebPage(url: String) { val webpage: Uri = Uri.parse(url) @@ -73,11 +72,11 @@ fun SupportScreen(padding : PaddingValues) { }) { Icon(imageVector = ImageVector.vectorResource(R.drawable.github), "Github") } - LaunchedEffect(Unit) { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - focusRequester.requestFocus() - } - } +// LaunchedEffect(Unit) { +// if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { +// focusRequester.requestFocus() +// } +// } } Spacer(modifier = Modifier.weight(1f)) Text(stringResource(id = R.string.privacy_policy), style = TextStyle(textDecoration = TextDecoration.Underline), diff --git a/app/src/main/res/mipmap-xhdpi/ic_banner.png b/app/src/main/res/mipmap-xhdpi/ic_banner.png index b85f129..fbd39f5 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_banner.png and b/app/src/main/res/mipmap-xhdpi/ic_banner.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_banner_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_banner_foreground.png index 7df06a4..634417a 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_banner_foreground.png and b/app/src/main/res/mipmap-xhdpi/ic_banner_foreground.png differ diff --git a/asset/main_screen_tv.png b/asset/main_screen_tv.png new file mode 100644 index 0000000..6f18bde Binary files /dev/null and b/asset/main_screen_tv.png differ