From be51a17315404ad161e6302065e7f42e3cc51f3e Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Mon, 29 Aug 2022 09:33:48 -0700 Subject: [PATCH 01/12] extracy logout button to it's own comosable function --- .../app/omnivore/omnivore/ui/home/HomeView.kt | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index da1c0e4d9..0fcb81a21 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -20,8 +20,6 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable fun HomeView(viewModel: LoginViewModel) { - val context = LocalContext.current - Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, @@ -31,18 +29,24 @@ fun HomeView(viewModel: LoginViewModel) { .padding(horizontal = 6.dp) ) { Text("You have a valid auth token. Nice. Go save something in Chrome!") - - Button(onClick = { - // Sign out google users - val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .build() - - val googleSignIn = GoogleSignIn.getClient(context, signInOptions) - googleSignIn.signOut() - - viewModel.logout() - }) { - Text(text = "Logout") - } + LogoutButton { viewModel.logout() } + } +} + +@Composable +fun LogoutButton(actionHandler: () -> Unit) { + val context = LocalContext.current + + Button(onClick = { + // Sign out google users + val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .build() + + val googleSignIn = GoogleSignIn.getClient(context, signInOptions) + googleSignIn.signOut() + + actionHandler() + }) { + Text(text = "Logout") } } From 2eabc318fe489aef26a6ce1fea5bd4f6d9a4fc71 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Mon, 29 Aug 2022 13:38:56 -0700 Subject: [PATCH 02/12] add a home view model --- .../app/src/main/graphql/SaveUrl.graphql | 6 +-- .../app/src/main/graphql/Search.graphql | 51 +++++++++++++++++++ .../app/omnivore/omnivore/MainActivity.kt | 6 ++- .../app/omnivore/omnivore/ui/home/HomeView.kt | 8 +-- .../omnivore/ui/home/HomeViewModel.kt | 22 ++++++++ .../app/omnivore/omnivore/ui/root/RootView.kt | 18 ++++--- 6 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 android/Omnivore/app/src/main/graphql/Search.graphql create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt diff --git a/android/Omnivore/app/src/main/graphql/SaveUrl.graphql b/android/Omnivore/app/src/main/graphql/SaveUrl.graphql index c2a2d2428..964e2b332 100644 --- a/android/Omnivore/app/src/main/graphql/SaveUrl.graphql +++ b/android/Omnivore/app/src/main/graphql/SaveUrl.graphql @@ -1,5 +1,5 @@ -mutation SaveUrl ($input: SaveUrlInput!) { - saveUrl(input:$input){ +mutation SaveUrl($input: SaveUrlInput!) { + saveUrl(input: $input) { ... on SaveSuccess { url } @@ -7,4 +7,4 @@ mutation SaveUrl ($input: SaveUrlInput!) { errorCodes } } -} \ No newline at end of file +} diff --git a/android/Omnivore/app/src/main/graphql/Search.graphql b/android/Omnivore/app/src/main/graphql/Search.graphql new file mode 100644 index 000000000..2532cfc1e --- /dev/null +++ b/android/Omnivore/app/src/main/graphql/Search.graphql @@ -0,0 +1,51 @@ +query Search($after: String, $first: Int, $query: String) { + search(first: $first, after: $after, query: $query) { + ... on SearchSuccess { + edges { + cursor + node { + id + title + slug + url + pageType + contentReader + createdAt + isArchived + readingProgressPercent + readingProgressAnchorIndex + author + image + description + publishedAt + ownedByViewer + originalArticleUrl + uploadFileId + labels { + id + name + color + } + pageId + shortId + quote + annotation + state + siteName + subscription + readAt + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + totalCount + } + } + ... on SearchError { + errorCodes + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt index eed5b92be..274cef68e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import app.omnivore.omnivore.ui.auth.LoginViewModel +import app.omnivore.omnivore.ui.home.HomeViewModel import app.omnivore.omnivore.ui.root.RootView import dagger.hilt.android.AndroidEntryPoint @@ -18,11 +19,12 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val viewModel: LoginViewModel by viewModels() + val loginViewModel: LoginViewModel by viewModels() + val homeViewModel: HomeViewModel by viewModels() setContent { OmnivoreTheme { - RootView(viewModel = viewModel) + RootView(loginViewModel, homeViewModel) } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 0fcb81a21..031b50931 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -13,13 +13,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import androidx.navigation.NavHostController import app.omnivore.omnivore.ui.auth.LoginViewModel import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable -fun HomeView(viewModel: LoginViewModel) { +fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, @@ -29,7 +28,10 @@ fun HomeView(viewModel: LoginViewModel) { .padding(horizontal = 6.dp) ) { Text("You have a valid auth token. Nice. Go save something in Chrome!") - LogoutButton { viewModel.logout() } + LogoutButton { loginViewModel.logout() } + Button(onClick = { homeViewModel.loggo() } ) { + Text("Loggo") + } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt new file mode 100644 index 000000000..1b9e431c7 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt @@ -0,0 +1,22 @@ +package app.omnivore.omnivore.ui.home + +import android.util.Log +import androidx.lifecycle.ViewModel +import app.omnivore.omnivore.DatastoreKeys +import app.omnivore.omnivore.DatastoreRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.runBlocking +import javax.inject.Inject + +@HiltViewModel +class HomeViewModel @Inject constructor( + private val datastoreRepo: DatastoreRepository +): ViewModel() { + private fun getAuthToken(): String? = runBlocking { + datastoreRepo.getString(DatastoreKeys.omnivoreAuthToken) + } + + fun loggo() { + Log.d("TAG", "logging it!") + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index 9bdd36a04..81940a231 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -6,14 +6,18 @@ import androidx.compose.runtime.livedata.observeAsState import app.omnivore.omnivore.ui.auth.LoginViewModel import app.omnivore.omnivore.ui.auth.WelcomeScreen import app.omnivore.omnivore.ui.home.HomeView +import app.omnivore.omnivore.ui.home.HomeViewModel @Composable -fun RootView(viewModel: LoginViewModel) { - val hasAuthToken: Boolean by viewModel.hasAuthTokenLiveData.observeAsState(false) +fun RootView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { + val hasAuthToken: Boolean by loginViewModel.hasAuthTokenLiveData.observeAsState(false) - if (hasAuthToken) { - HomeView(viewModel = viewModel) - } else { - WelcomeScreen(viewModel = viewModel) - } + if (hasAuthToken) { + HomeView( + loginViewModel = loginViewModel, + homeViewModel = homeViewModel + ) + } else { + WelcomeScreen(viewModel = loginViewModel) + } } From 67d8d95825c8d36021bb606c3b5b4b477dd9cabc Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Tue, 30 Aug 2022 08:06:12 -0700 Subject: [PATCH 03/12] WIP: Render list of linked items --- .../app/omnivore/omnivore/ui/home/HomeView.kt | 108 ++++++++++++++++-- .../omnivore/ui/home/HomeViewModel.kt | 84 +++++++++++++- .../omnivore/ui/save/SaveViewModel.kt | 2 - 3 files changed, 179 insertions(+), 15 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 031b50931..886af579e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -1,25 +1,46 @@ package app.omnivore.omnivore.ui.home +import android.annotation.SuppressLint +import android.net.Uri +import android.util.Log +import android.view.ViewGroup +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.ui.window.Dialog +import app.omnivore.omnivore.AppleConstants +import app.omnivore.omnivore.ui.auth.AppleAuthDialog import app.omnivore.omnivore.ui.auth.LoginViewModel import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { - Column( + val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) + + // Fetch items + homeViewModel.load() + + LazyColumn( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier @@ -27,10 +48,19 @@ fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { .fillMaxSize() .padding(horizontal = 6.dp) ) { - Text("You have a valid auth token. Nice. Go save something in Chrome!") - LogoutButton { loginViewModel.logout() } - Button(onClick = { homeViewModel.loggo() } ) { - Text("Loggo") + item { + Text("You have a valid auth token. Nice. Go save something in Chrome!") + } + + item { + LogoutButton { loginViewModel.logout() } + } + + items(linkedItems) { item -> + Text(item.title, modifier = Modifier.clickable { + Log.d("log", "clicked title: ${item.title}") + }) + Spacer(modifier = Modifier.height(16.dp)) } } } @@ -52,3 +82,63 @@ fun LogoutButton(actionHandler: () -> Unit) { Text(text = "Logout") } } + + +if (showDialog.value) { + AppleAuthDialog(onDismiss = { token -> + if (token != null ) { + viewModel.handleAppleToken(token) + } + showDialog.value = false + }) +} + +@Composable +fun ArticleWebViewDialog(onDismiss: (String?) -> Unit) { + Dialog(onDismissRequest = { onDismiss(null) }) { + Surface( + shape = RoundedCornerShape(16.dp), + color = Color.White + ) { + AppleAuthWebView(onDismiss) + } + } +} + +@SuppressLint("SetJavaScriptEnabled") +@Composable +fun ArticleWebView(onDismiss: (String?) -> Unit) { + val url = AppleConstants.authUrl + + "?client_id=" + AppleConstants.clientId + + "&redirect_uri=" + AppleConstants.redirectURI + + "&response_type=code%20id_token" + + "&scope=" + AppleConstants.scope + + "&response_mode=form_post" + + "&state=android:login" + + // Adding a WebView inside AndroidView + // with layout as full screen + AndroidView(factory = { + WebView(it).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { + if (request?.url.toString().contains("android-apple-token")) { + val uri = Uri.parse(request!!.url.toString()) + val token = uri.getQueryParameter("token") + + onDismiss(token) + } + return true + } + } + settings.javaScriptEnabled = true + loadUrl(url) + } + }, update = { + it.loadUrl(url) + }) +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt index 1b9e431c7..a7b9d4921 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt @@ -1,10 +1,29 @@ package app.omnivore.omnivore.ui.home -import android.util.Log -import androidx.lifecycle.ViewModel +import android.annotation.SuppressLint +import android.net.Uri +import android.view.ViewGroup +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.ui.window.Dialog +import androidx.lifecycle.* +import app.omnivore.omnivore.AppleConstants +import app.omnivore.omnivore.Constants import app.omnivore.omnivore.DatastoreKeys import app.omnivore.omnivore.DatastoreRepository +import app.omnivore.omnivore.graphql.generated.SearchQuery +import app.omnivore.omnivore.ui.auth.AppleAuthDialog +import com.apollographql.apollo3.ApolloClient +import com.apollographql.apollo3.api.Optional import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import javax.inject.Inject @@ -12,11 +31,68 @@ import javax.inject.Inject class HomeViewModel @Inject constructor( private val datastoreRepo: DatastoreRepository ): ViewModel() { + val itemsLiveData = MutableLiveData>(listOf()) + private fun getAuthToken(): String? = runBlocking { datastoreRepo.getString(DatastoreKeys.omnivoreAuthToken) } - fun loggo() { - Log.d("TAG", "logging it!") + fun load() { + viewModelScope.launch { + val authToken = getAuthToken() + + val apolloClient = ApolloClient.Builder() + .serverUrl("${Constants.apiURL}/api/graphql") + .addHttpHeader("Authorization", value = authToken ?: "") + .build() + + val response = apolloClient.query( + SearchQuery( + first = Optional.presentIfNotNull(20), + ) + ).execute() + + val itemList = response.data?.search?.onSearchSuccess?.edges ?: listOf() + + val newItems = itemList.map { + LinkedItem( + id = it.node.id, + title = it.node.title, + createdAt = it.node.createdAt, + readAt = it.node.readAt, + readingProgress = it.node.readingProgressPercent, + readingProgressAnchor = it.node.readingProgressAnchorIndex, + imageURLString = it.node.image, + descriptionText = it.node.description, + slug = it.node.slug + ) + } + + itemsLiveData.value = newItems + } } } + +public data class LinkedItem( + public val id: String, + public val title: String, + public val createdAt: Any, +// public val savedAt: Any, + public val readAt: Any?, +// public val updatedAt: Any, + public val readingProgress: Double, + public val readingProgressAnchor: Int, + public val imageURLString: String?, +// public val onDeviceImageURLString: String?, +// public val documentDirectoryPath: String?, +// public val pageURLString: String, + public val descriptionText: String?, +// public val publisherURLString: String?, +// public val siteName: String?, +// public val author: String?, +// public val publishDate: Any?, + public val slug: String, +// public val isArchived: Boolean, +// public val contentReader: String?, +// public val originalHtml: String?, +) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt index 62a11b9ac..ba706a0cd 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt @@ -40,8 +40,6 @@ class SaveViewModel @Inject constructor( val authToken = getAuthToken() - Log.d(ContentValues.TAG, "AuthToken: $authToken") - if (authToken == null) { message = "You are not logged in. Please login before saving." isLoading = false From efe0475be7248afcc9df53047856e10f6d52dafa Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Tue, 30 Aug 2022 14:45:46 -0700 Subject: [PATCH 04/12] load /app/me/slug pages in android webview --- .../omnivore/omnivore/ui/auth/AppleAuth.kt | 2 +- .../omnivore/ui/auth/LoginViewModel.kt | 2 + .../app/omnivore/omnivore/ui/home/HomeView.kt | 69 ++++++++++--------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/AppleAuth.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/AppleAuth.kt index ff9ef3b8b..13f9c9626 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/AppleAuth.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/AppleAuth.kt @@ -25,7 +25,7 @@ import java.util.* @Composable fun AppleAuthButton(viewModel: LoginViewModel) { - val showDialog = remember { mutableStateOf(false) } + val showDialog = remember { mutableStateOf(false) } LoadingButtonWithIcon( text = "Continue with Apple", diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt index 36e5c315f..f2a9eb57a 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt @@ -121,6 +121,8 @@ class LoginViewModel @Inject constructor( } if (result.body()?.authCookieString != null) { + Log.d("loggo", result.body()?.authCookieString!!) + datastoreRepo.putString( DatastoreKeys.omnivoreAuthCookieString, result.body()?.authCookieString!! ) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 886af579e..092df5772 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -1,12 +1,11 @@ package app.omnivore.omnivore.ui.home import android.annotation.SuppressLint +import android.graphics.Bitmap import android.net.Uri import android.util.Log import android.view.ViewGroup -import android.webkit.WebResourceRequest -import android.webkit.WebView -import android.webkit.WebViewClient +import android.webkit.* import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -20,6 +19,8 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -35,6 +36,7 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { + val selectedItemSlug = remember { mutableStateOf(null) } val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) // Fetch items @@ -58,11 +60,17 @@ fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { items(linkedItems) { item -> Text(item.title, modifier = Modifier.clickable { - Log.d("log", "clicked title: ${item.title}") + selectedItemSlug.value = item.slug }) Spacer(modifier = Modifier.height(16.dp)) } } + + if (selectedItemSlug.value != null) { + ArticleWebViewDialog(selectedItemSlug.value!!) { + selectedItemSlug.value = null + } + } } @Composable @@ -84,37 +92,27 @@ fun LogoutButton(actionHandler: () -> Unit) { } -if (showDialog.value) { - AppleAuthDialog(onDismiss = { token -> - if (token != null ) { - viewModel.handleAppleToken(token) - } - showDialog.value = false - }) -} - @Composable -fun ArticleWebViewDialog(onDismiss: (String?) -> Unit) { - Dialog(onDismissRequest = { onDismiss(null) }) { +fun ArticleWebViewDialog(slug: String, onDismiss: () -> Unit) { + Dialog(onDismissRequest = { onDismiss() }) { Surface( shape = RoundedCornerShape(16.dp), color = Color.White ) { - AppleAuthWebView(onDismiss) + ArticleWebView(slug) } } } @SuppressLint("SetJavaScriptEnabled") @Composable -fun ArticleWebView(onDismiss: (String?) -> Unit) { - val url = AppleConstants.authUrl + - "?client_id=" + AppleConstants.clientId + - "&redirect_uri=" + AppleConstants.redirectURI + - "&response_type=code%20id_token" + - "&scope=" + AppleConstants.scope + - "&response_mode=form_post" + - "&state=android:login" +fun ArticleWebView(slug: String) { + WebView.setWebContentsDebuggingEnabled(true) + + val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly" + // add to local storage + val url = "https://demo.omnivore.app/app/me/$slug" +// val url = "https://demo.omnivore.app/app/me/algae-bloom-in-san-francisco-bay-lake-merritt-is-killing-fish-th-182e81e01dc" // Adding a WebView inside AndroidView // with layout as full screen @@ -124,19 +122,22 @@ fun ArticleWebView(onDismiss: (String?) -> Unit) { ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) - webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { - if (request?.url.toString().contains("android-apple-token")) { - val uri = Uri.parse(request!!.url.toString()) - val token = uri.getQueryParameter("token") - onDismiss(token) - } - return true - } + webViewClient = object : WebViewClient() { } + settings.javaScriptEnabled = true - loadUrl(url) + settings.allowContentAccess = true + settings.allowFileAccess = true + settings.domStorageEnabled = true + + // need to add an authVerified: true value to local storage + + CookieManager.getInstance().setAcceptThirdPartyCookies(this, true) + CookieManager.getInstance().setAcceptCookie(true) + CookieManager.getInstance().setCookie("demo.omnivore.app", authCookieString) { + loadUrl(url) + } } }, update = { it.loadUrl(url) From a280e29ee63bcaed79f324a4c655f523e47c46e6 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 06:18:34 -0700 Subject: [PATCH 05/12] fix cookie settings in android webview --- .../java/app/omnivore/omnivore/ui/home/HomeView.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 092df5772..ed67e8dbf 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -109,7 +109,7 @@ fun ArticleWebViewDialog(slug: String, onDismiss: () -> Unit) { fun ArticleWebView(slug: String) { WebView.setWebContentsDebuggingEnabled(true) - val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly" + val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly; secure;" // add to local storage val url = "https://demo.omnivore.app/app/me/$slug" // val url = "https://demo.omnivore.app/app/me/algae-bloom-in-san-francisco-bay-lake-merritt-is-killing-fish-th-182e81e01dc" @@ -123,21 +123,19 @@ fun ArticleWebView(slug: String) { ViewGroup.LayoutParams.MATCH_PARENT ) - webViewClient = object : WebViewClient() { - } - settings.javaScriptEnabled = true settings.allowContentAccess = true settings.allowFileAccess = true settings.domStorageEnabled = true - // need to add an authVerified: true value to local storage + webViewClient = object : WebViewClient() { + } CookieManager.getInstance().setAcceptThirdPartyCookies(this, true) CookieManager.getInstance().setAcceptCookie(true) - CookieManager.getInstance().setCookie("demo.omnivore.app", authCookieString) { - loadUrl(url) + CookieManager.getInstance().setCookie("https://api-demo.omnivore.app", authCookieString) { } + loadUrl(url) } }, update = { it.loadUrl(url) From bc9ee845dce286a28e2d4b0b1e41f966dd189598 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 10:30:51 -0700 Subject: [PATCH 06/12] use card component to render item list --- android/Omnivore/app/build.gradle | 2 + .../app/omnivore/omnivore/ui/home/HomeView.kt | 21 ++++---- .../omnivore/ui/home/LinkedItemCard.kt | 53 +++++++++++++++++++ 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/LinkedItemCard.kt diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index 185ef7e89..c86595512 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -156,6 +156,8 @@ dependencies { implementation 'com.google.android.gms:play-services-auth:20.2.0' implementation "com.google.accompanist:accompanist-systemuicontroller:0.25.1" + + implementation("io.coil-kt:coil-compose:2.2.0") } apollo { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index ed67e8dbf..99769a54a 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -6,6 +6,7 @@ import android.net.Uri import android.util.Log import android.view.ViewGroup import android.webkit.* +import android.widget.Space import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -50,19 +51,21 @@ fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { .fillMaxSize() .padding(horizontal = 6.dp) ) { - item { - Text("You have a valid auth token. Nice. Go save something in Chrome!") - } item { - LogoutButton { loginViewModel.logout() } + Row( + horizontalArrangement = Arrangement.End + ) { + Spacer(modifier = Modifier.weight(1.0F)) + LogoutButton { loginViewModel.logout() } + } } items(linkedItems) { item -> - Text(item.title, modifier = Modifier.clickable { - selectedItemSlug.value = item.slug - }) - Spacer(modifier = Modifier.height(16.dp)) + LinkedItemCard( + item = item, + onClickHandler = { selectedItemSlug.value = item.slug } + ) } } @@ -134,8 +137,8 @@ fun ArticleWebView(slug: String) { CookieManager.getInstance().setAcceptThirdPartyCookies(this, true) CookieManager.getInstance().setAcceptCookie(true) CookieManager.getInstance().setCookie("https://api-demo.omnivore.app", authCookieString) { + loadUrl(url) } - loadUrl(url) } }, update = { it.loadUrl(url) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/LinkedItemCard.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/LinkedItemCard.kt new file mode 100644 index 000000000..c4ab6d4ed --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/LinkedItemCard.kt @@ -0,0 +1,53 @@ +package app.omnivore.omnivore.ui.home + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.material3.Card +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import coil.compose.rememberAsyncImagePainter + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LinkedItemCard( + item: LinkedItem, + onClickHandler: () -> Unit, + modifier: Modifier = Modifier +) { + Card( + onClick = { onClickHandler() }, + shape = MaterialTheme.shapes.medium, + modifier = modifier + .fillMaxWidth() + .padding(15.dp) + ) { + Row { + Image( + painter = rememberAsyncImagePainter(item.imageURLString), + contentDescription = "Image associated with linked item", + modifier = Modifier.size(100.dp) + ) + + Column(modifier = Modifier.padding(8.dp)) { + Text( + text = item.title, + style = MaterialTheme.typography.titleMedium, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + + Text( + text = item.descriptionText ?: "", + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodyMedium + ) + } + } + } +} From 3e41d3d59bea8401dc47806e0ec60f602cafdf53 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 11:27:02 -0700 Subject: [PATCH 07/12] add navController to root of home --- .../main/java/app/omnivore/omnivore/Routes.kt | 3 +- .../app/omnivore/omnivore/ui/home/HomeView.kt | 53 ++++++++++++++----- .../app/omnivore/omnivore/ui/root/RootView.kt | 27 ++++++++-- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt index 47f70b2b3..4355c954e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt @@ -1,7 +1,6 @@ package app.omnivore.omnivore sealed class Routes(val route: String) { - object Root : Routes("Root") object Home : Routes("Home") - object Welcome : Routes("Welcome") + object WebReader : Routes("WebReader") } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 99769a54a..68514c71a 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -1,22 +1,17 @@ package app.omnivore.omnivore.ui.home import android.annotation.SuppressLint -import android.graphics.Bitmap -import android.net.Uri -import android.util.Log import android.view.ViewGroup import android.webkit.* -import android.widget.Space import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text +import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState @@ -29,14 +24,46 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog -import app.omnivore.omnivore.AppleConstants -import app.omnivore.omnivore.ui.auth.AppleAuthDialog +import androidx.navigation.NavHostController import app.omnivore.omnivore.ui.auth.LoginViewModel import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInOptions + +@OptIn(ExperimentalMaterial3Api::class) +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun HomeView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { +fun HomeView( + loginViewModel: LoginViewModel, + homeViewModel: HomeViewModel, + navController: NavHostController +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text("Home") }, + backgroundColor = MaterialTheme.colorScheme.surfaceVariant, + actions = { + IconButton(onClick = { }) { + Icon( + imageVector = Icons.Default.Menu, + contentDescription = null + ) + } + } + ) + } + ) { + HomeViewContent(loginViewModel, homeViewModel, navController) + } +} + +@Composable +fun HomeViewContent( + loginViewModel: LoginViewModel, + homeViewModel: HomeViewModel, + navController: NavHostController +) { val selectedItemSlug = remember { mutableStateOf(null) } val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) @@ -113,9 +140,7 @@ fun ArticleWebView(slug: String) { WebView.setWebContentsDebuggingEnabled(true) val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly; secure;" - // add to local storage val url = "https://demo.omnivore.app/app/me/$slug" -// val url = "https://demo.omnivore.app/app/me/algae-bloom-in-san-francisco-bay-lake-merritt-is-killing-fish-th-182e81e01dc" // Adding a WebView inside AndroidView // with layout as full screen diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index 81940a231..cc4d5c2f5 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -3,6 +3,10 @@ package app.omnivore.omnivore.ui.root import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import app.omnivore.omnivore.Routes import app.omnivore.omnivore.ui.auth.LoginViewModel import app.omnivore.omnivore.ui.auth.WelcomeScreen import app.omnivore.omnivore.ui.home.HomeView @@ -13,11 +17,26 @@ fun RootView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) { val hasAuthToken: Boolean by loginViewModel.hasAuthTokenLiveData.observeAsState(false) if (hasAuthToken) { - HomeView( - loginViewModel = loginViewModel, - homeViewModel = homeViewModel - ) + PrimaryNavigator(loginViewModel = loginViewModel, homeViewModel = homeViewModel) } else { WelcomeScreen(viewModel = loginViewModel) } } + +@Composable +fun PrimaryNavigator(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel){ + val navController = rememberNavController() + + NavHost(navController = navController, startDestination = Routes.Home.route) { + composable(Routes.Home.route) { + HomeView( + loginViewModel = loginViewModel, // TODO: remove loginViewModel from here + homeViewModel = homeViewModel, + navController = navController + ) + } +// composable(Routes.EmailLogin.route) { +// EmailLoginPage(viewModel = viewModel, navController = navController) +// } + } +} From ca54edad2637ce50bc88972cf065fd1b8fe766bf Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 11:41:30 -0700 Subject: [PATCH 08/12] navigate to webreader by using the navhost --- .../omnivore/ui/auth/WelcomeScreen.kt | 2 -- .../app/omnivore/omnivore/ui/home/HomeView.kt | 25 +++---------------- .../app/omnivore/omnivore/ui/root/RootView.kt | 8 +++--- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt index 455037475..f839361cf 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.Intent import android.net.Uri import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.ClickableText @@ -19,7 +18,6 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 68514c71a..a3e70e67c 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog import androidx.navigation.NavHostController +import app.omnivore.omnivore.Routes import app.omnivore.omnivore.ui.auth.LoginViewModel import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInOptions @@ -64,7 +65,6 @@ fun HomeViewContent( homeViewModel: HomeViewModel, navController: NavHostController ) { - val selectedItemSlug = remember { mutableStateOf(null) } val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) // Fetch items @@ -91,16 +91,12 @@ fun HomeViewContent( items(linkedItems) { item -> LinkedItemCard( item = item, - onClickHandler = { selectedItemSlug.value = item.slug } + onClickHandler = { + navController.navigate("WebReader/${item.slug}") + } ) } } - - if (selectedItemSlug.value != null) { - ArticleWebViewDialog(selectedItemSlug.value!!) { - selectedItemSlug.value = null - } - } } @Composable @@ -121,19 +117,6 @@ fun LogoutButton(actionHandler: () -> Unit) { } } - -@Composable -fun ArticleWebViewDialog(slug: String, onDismiss: () -> Unit) { - Dialog(onDismissRequest = { onDismiss() }) { - Surface( - shape = RoundedCornerShape(16.dp), - color = Color.White - ) { - ArticleWebView(slug) - } - } -} - @SuppressLint("SetJavaScriptEnabled") @Composable fun ArticleWebView(slug: String) { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index cc4d5c2f5..4dc195028 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -9,6 +9,7 @@ import androidx.navigation.compose.rememberNavController import app.omnivore.omnivore.Routes import app.omnivore.omnivore.ui.auth.LoginViewModel import app.omnivore.omnivore.ui.auth.WelcomeScreen +import app.omnivore.omnivore.ui.home.ArticleWebView import app.omnivore.omnivore.ui.home.HomeView import app.omnivore.omnivore.ui.home.HomeViewModel @@ -35,8 +36,9 @@ fun PrimaryNavigator(loginViewModel: LoginViewModel, homeViewModel: HomeViewMode navController = navController ) } -// composable(Routes.EmailLogin.route) { -// EmailLoginPage(viewModel = viewModel, navController = navController) -// } + + composable("WebReader/{slug}") { + ArticleWebView(it.arguments?.getString("slug") ?: "") + } } } From fb5b77a522362e42c3424fdb713c9b81020a1c6c Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 11:48:38 -0700 Subject: [PATCH 09/12] navigate to web reader via navhost when item card is tapped --- .../java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt | 7 +++++-- .../main/java/app/omnivore/omnivore/ui/home/HomeView.kt | 6 ++---- .../main/java/app/omnivore/omnivore/ui/root/RootView.kt | 6 +++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt index f2a9eb57a..2b2f682eb 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/LoginViewModel.kt @@ -13,6 +13,7 @@ import com.google.android.gms.tasks.Task import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import javax.inject.Inject @@ -36,6 +37,10 @@ class LoginViewModel @Inject constructor( .distinctUntilChanged() .asLiveData() + fun getAuthCookieString(): String? = runBlocking { + datastoreRepo.getString(DatastoreKeys.omnivoreAuthCookieString) + } + fun login(email: String, password: String) { val emailLogin = RetrofitHelper.getInstance().create(EmailLoginSubmit::class.java) @@ -121,8 +126,6 @@ class LoginViewModel @Inject constructor( } if (result.body()?.authCookieString != null) { - Log.d("loggo", result.body()?.authCookieString!!) - datastoreRepo.putString( DatastoreKeys.omnivoreAuthCookieString, result.body()?.authCookieString!! ) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index a3e70e67c..5e5d78f0b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -119,14 +119,12 @@ fun LogoutButton(actionHandler: () -> Unit) { @SuppressLint("SetJavaScriptEnabled") @Composable -fun ArticleWebView(slug: String) { +fun ArticleWebView(slug: String, authCookieString: String) { WebView.setWebContentsDebuggingEnabled(true) - val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly; secure;" +// val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly; secure;" val url = "https://demo.omnivore.app/app/me/$slug" - // Adding a WebView inside AndroidView - // with layout as full screen AndroidView(factory = { WebView(it).apply { layoutParams = ViewGroup.LayoutParams( diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index 4dc195028..c7618b2c6 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -3,6 +3,7 @@ package app.omnivore.omnivore.ui.root import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @@ -38,7 +39,10 @@ fun PrimaryNavigator(loginViewModel: LoginViewModel, homeViewModel: HomeViewMode } composable("WebReader/{slug}") { - ArticleWebView(it.arguments?.getString("slug") ?: "") + ArticleWebView( + it.arguments?.getString("slug") ?: "", + authCookieString = loginViewModel.getAuthCookieString() ?: "" + ) } } } From 06390bd4799d7347a7691f9f847ea9cf0e13abc7 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 13:36:17 -0700 Subject: [PATCH 10/12] add a settings view --- android/Omnivore/app/build.gradle | 6 -- .../main/java/app/omnivore/omnivore/Routes.kt | 1 + .../app/omnivore/omnivore/ui/home/HomeView.kt | 59 ++++----------- .../app/omnivore/omnivore/ui/root/RootView.kt | 6 +- .../omnivore/ui/settings/SettingsContent.kt | 73 +++++++++++++++++++ 5 files changed, 93 insertions(+), 52 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/settings/SettingsContent.kt diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index c86595512..b5757af1b 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -139,12 +139,6 @@ dependencies { implementation "androidx.security:security-crypto:1.0.0" implementation "androidx.datastore:datastore-preferences:1.0.0" - - -// Activity KTX for viewModels() - // TODO: remove this since compose-activity imports ktx? -// implementation "androidx.activity:activity-ktx:1.3.1" - //Dagger - Hilt implementation 'com.google.dagger:hilt-android:2.42' kapt 'com.google.dagger:hilt-compiler:2.42' diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt index 4355c954e..36140cb11 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt @@ -3,4 +3,5 @@ package app.omnivore.omnivore sealed class Routes(val route: String) { object Home : Routes("Home") object WebReader : Routes("WebReader") + object Settings: Routes("Settings") } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 5e5d78f0b..ed09e0f3e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu @@ -15,27 +14,18 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView -import androidx.compose.ui.window.Dialog import androidx.navigation.NavHostController import app.omnivore.omnivore.Routes -import app.omnivore.omnivore.ui.auth.LoginViewModel -import com.google.android.gms.auth.api.signin.GoogleSignIn -import com.google.android.gms.auth.api.signin.GoogleSignInOptions @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun HomeView( - loginViewModel: LoginViewModel, homeViewModel: HomeViewModel, navController: NavHostController ) { @@ -45,7 +35,7 @@ fun HomeView( title = { Text("Home") }, backgroundColor = MaterialTheme.colorScheme.surfaceVariant, actions = { - IconButton(onClick = { }) { + IconButton(onClick = { navController.navigate(Routes.Settings.route) }) { Icon( imageVector = Icons.Default.Menu, contentDescription = null @@ -54,16 +44,24 @@ fun HomeView( } ) } - ) { - HomeViewContent(loginViewModel, homeViewModel, navController) + ) { paddingValues -> + HomeViewContent( + homeViewModel, + navController, + modifier = Modifier + .padding( + top = paddingValues.calculateTopPadding(), + bottom = paddingValues.calculateBottomPadding() + ) + ) } } @Composable fun HomeViewContent( - loginViewModel: LoginViewModel, homeViewModel: HomeViewModel, - navController: NavHostController + navController: NavHostController, + modifier: Modifier ) { val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) @@ -73,21 +71,11 @@ fun HomeViewContent( LazyColumn( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier + modifier = modifier .background(MaterialTheme.colorScheme.background) .fillMaxSize() .padding(horizontal = 6.dp) ) { - - item { - Row( - horizontalArrangement = Arrangement.End - ) { - Spacer(modifier = Modifier.weight(1.0F)) - LogoutButton { loginViewModel.logout() } - } - } - items(linkedItems) { item -> LinkedItemCard( item = item, @@ -99,30 +87,11 @@ fun HomeViewContent( } } -@Composable -fun LogoutButton(actionHandler: () -> Unit) { - val context = LocalContext.current - - Button(onClick = { - // Sign out google users - val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .build() - - val googleSignIn = GoogleSignIn.getClient(context, signInOptions) - googleSignIn.signOut() - - actionHandler() - }) { - Text(text = "Logout") - } -} - @SuppressLint("SetJavaScriptEnabled") @Composable fun ArticleWebView(slug: String, authCookieString: String) { WebView.setWebContentsDebuggingEnabled(true) -// val authCookieString = "auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIwODFkZThlOC01ODU0LTExZWMtODY4ZS03ZjU0ZjhiMzY0NGEiLCJpYXQiOjE2NjE4OTA1NjB9.zDE6SOGgRKKV7QuZUIsxEzb_M7o2pyTwshI_Lc_C8Co; Expires=Wed, 30 Aug 2023 20:16:00 GMT; HttpOnly; secure;" val url = "https://demo.omnivore.app/app/me/$slug" AndroidView(factory = { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index c7618b2c6..956485e54 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -1,5 +1,6 @@ package app.omnivore.omnivore.ui.root +import SettingsView import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState @@ -32,7 +33,6 @@ fun PrimaryNavigator(loginViewModel: LoginViewModel, homeViewModel: HomeViewMode NavHost(navController = navController, startDestination = Routes.Home.route) { composable(Routes.Home.route) { HomeView( - loginViewModel = loginViewModel, // TODO: remove loginViewModel from here homeViewModel = homeViewModel, navController = navController ) @@ -44,5 +44,9 @@ fun PrimaryNavigator(loginViewModel: LoginViewModel, homeViewModel: HomeViewMode authCookieString = loginViewModel.getAuthCookieString() ?: "" ) } + + composable(Routes.Settings.route) { + SettingsView(loginViewModel = loginViewModel, navController = navController) + } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/settings/SettingsContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/settings/SettingsContent.kt new file mode 100644 index 000000000..64d0b4bf8 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/settings/SettingsContent.kt @@ -0,0 +1,73 @@ +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.* +import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController +import app.omnivore.omnivore.Routes +import app.omnivore.omnivore.ui.auth.LoginViewModel +import app.omnivore.omnivore.ui.home.HomeViewContent +import app.omnivore.omnivore.ui.home.HomeViewModel +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInOptions + +@OptIn(ExperimentalMaterial3Api::class) +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun SettingsView( + loginViewModel: LoginViewModel, + navController: NavHostController +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text("Settings") }, + backgroundColor = MaterialTheme.colorScheme.surfaceVariant, + actions = { + IconButton(onClick = { navController.navigate(Routes.Home.route) }) { + Icon( + imageVector = Icons.Default.Home, + contentDescription = null + ) + } + } + ) + } + ) { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(horizontal = 16.dp) + ) { + LogoutButton { loginViewModel.logout() } + } + } +} + +@Composable +fun LogoutButton(actionHandler: () -> Unit) { + val context = LocalContext.current + + Button(onClick = { + // Sign out google users + val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .build() + + val googleSignIn = GoogleSignIn.getClient(context, signInOptions) + googleSignIn.signOut() + + actionHandler() + }) { + Text(text = "Logout") + } +} From 4fafca7f467c92e9e04cbf08e56ab6a66221689b Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 13:38:01 -0700 Subject: [PATCH 11/12] Move web reader into own file --- .../app/omnivore/omnivore/ui/home/HomeView.kt | 36 ---------------- .../omnivore/ui/reader/WebAppReader.kt | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebAppReader.kt diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index ed09e0f3e..238e47c94 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -1,8 +1,6 @@ package app.omnivore.omnivore.ui.home import android.annotation.SuppressLint -import android.view.ViewGroup -import android.webkit.* import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -17,7 +15,6 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavHostController import app.omnivore.omnivore.Routes @@ -86,36 +83,3 @@ fun HomeViewContent( } } } - -@SuppressLint("SetJavaScriptEnabled") -@Composable -fun ArticleWebView(slug: String, authCookieString: String) { - WebView.setWebContentsDebuggingEnabled(true) - - val url = "https://demo.omnivore.app/app/me/$slug" - - AndroidView(factory = { - WebView(it).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - - settings.javaScriptEnabled = true - settings.allowContentAccess = true - settings.allowFileAccess = true - settings.domStorageEnabled = true - - webViewClient = object : WebViewClient() { - } - - CookieManager.getInstance().setAcceptThirdPartyCookies(this, true) - CookieManager.getInstance().setAcceptCookie(true) - CookieManager.getInstance().setCookie("https://api-demo.omnivore.app", authCookieString) { - loadUrl(url) - } - } - }, update = { - it.loadUrl(url) - }) -} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebAppReader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebAppReader.kt new file mode 100644 index 000000000..1b1091bbe --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebAppReader.kt @@ -0,0 +1,42 @@ +package app.omnivore.omnivore.ui.reader + +import android.annotation.SuppressLint +import android.view.ViewGroup +import android.webkit.CookieManager +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.runtime.Composable +import androidx.compose.ui.viewinterop.AndroidView + +@SuppressLint("SetJavaScriptEnabled") +@Composable +fun ArticleWebView(slug: String, authCookieString: String) { + WebView.setWebContentsDebuggingEnabled(true) + + val url = "https://demo.omnivore.app/app/me/$slug" + + AndroidView(factory = { + WebView(it).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + settings.javaScriptEnabled = true + settings.allowContentAccess = true + settings.allowFileAccess = true + settings.domStorageEnabled = true + + webViewClient = object : WebViewClient() { + } + + CookieManager.getInstance().setAcceptThirdPartyCookies(this, true) + CookieManager.getInstance().setAcceptCookie(true) + CookieManager.getInstance().setCookie("https://api-demo.omnivore.app", authCookieString) { + loadUrl(url) + } + } + }, update = { + it.loadUrl(url) + }) +} From 538f85e3d23fac987b453a5fcccb1a03cbf4218f Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 31 Aug 2022 14:53:27 -0700 Subject: [PATCH 12/12] add infinite loader to home feed --- .../app/omnivore/omnivore/ui/home/HomeView.kt | 41 ++++++++++++++++--- .../omnivore/ui/home/HomeViewModel.kt | 7 +++- .../app/omnivore/omnivore/ui/root/RootView.kt | 3 +- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 238e47c94..accd3acec 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -4,23 +4,24 @@ import android.annotation.SuppressLint import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import app.omnivore.omnivore.Routes +import kotlinx.coroutines.flow.distinctUntilChanged @OptIn(ExperimentalMaterial3Api::class) -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun HomeView( homeViewModel: HomeViewModel, @@ -60,12 +61,11 @@ fun HomeViewContent( navController: NavHostController, modifier: Modifier ) { + val listState = rememberLazyListState() val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf()) - // Fetch items - homeViewModel.load() - LazyColumn( + state = listState, verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier @@ -82,4 +82,33 @@ fun HomeViewContent( ) } } + + InfiniteListHandler(listState = listState) { + homeViewModel.load() + } +} + +@Composable +fun InfiniteListHandler( + listState: LazyListState, + buffer: Int = 2, + onLoadMore: () -> Unit +) { + val loadMore = remember { + derivedStateOf { + val layoutInfo = listState.layoutInfo + val totalItemsNumber = layoutInfo.totalItemsCount + val lastVisibleItemIndex = (layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1 + + lastVisibleItemIndex > (totalItemsNumber - buffer) + } + } + + LaunchedEffect(loadMore) { + snapshotFlow { loadMore.value } + .distinctUntilChanged() + .collect { + onLoadMore() + } + } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt index a7b9d4921..be3f1227a 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt @@ -31,6 +31,7 @@ import javax.inject.Inject class HomeViewModel @Inject constructor( private val datastoreRepo: DatastoreRepository ): ViewModel() { + var cursor: String? = null val itemsLiveData = MutableLiveData>(listOf()) private fun getAuthToken(): String? = runBlocking { @@ -48,10 +49,12 @@ class HomeViewModel @Inject constructor( val response = apolloClient.query( SearchQuery( - first = Optional.presentIfNotNull(20), + after = Optional.presentIfNotNull(cursor), + first = Optional.presentIfNotNull(15), ) ).execute() + cursor = response.data?.search?.onSearchSuccess?.pageInfo?.endCursor val itemList = response.data?.search?.onSearchSuccess?.edges ?: listOf() val newItems = itemList.map { @@ -68,7 +71,7 @@ class HomeViewModel @Inject constructor( ) } - itemsLiveData.value = newItems + itemsLiveData.value = (itemsLiveData.value ?: listOf()).plus(newItems) } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt index 956485e54..ac8e5e907 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt @@ -4,16 +4,15 @@ import SettingsView import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import app.omnivore.omnivore.Routes import app.omnivore.omnivore.ui.auth.LoginViewModel import app.omnivore.omnivore.ui.auth.WelcomeScreen -import app.omnivore.omnivore.ui.home.ArticleWebView import app.omnivore.omnivore.ui.home.HomeView import app.omnivore.omnivore.ui.home.HomeViewModel +import app.omnivore.omnivore.ui.reader.ArticleWebView @Composable fun RootView(loginViewModel: LoginViewModel, homeViewModel: HomeViewModel) {