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