mirror of https://github.com/Ashinch/ReadYou.git
feat(ui): add feed via system share sheet (#618)
This commit is contained in:
parent
8f4d24157e
commit
4c7bea918d
|
@ -27,17 +27,52 @@
|
|||
<activity
|
||||
android:name=".infrastructure.android.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/Theme.Reader">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
|
||||
<data android:host="*" />
|
||||
|
||||
<data android:mimeType="text/xml" />
|
||||
<data android:mimeType="application/rss+xml" />
|
||||
<data android:mimeType="application/atom+xml" />
|
||||
<data android:mimeType="application/xml" />
|
||||
<data android:mimeType="application/json" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".infrastructure.android.CrashReportActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.Reader">
|
||||
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package me.ash.reader.infrastructure.android
|
||||
|
||||
import android.content.Intent
|
||||
import android.database.CursorWindow
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -9,7 +10,10 @@ import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.core.util.Consumer
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.profileinstaller.ProfileInstallerInitializer
|
||||
import coil.ImageLoader
|
||||
import coil.compose.LocalImageLoader
|
||||
|
@ -20,8 +24,8 @@ import me.ash.reader.infrastructure.preference.LanguagesPreference
|
|||
import me.ash.reader.infrastructure.preference.SettingsProvider
|
||||
import me.ash.reader.ui.ext.languages
|
||||
import me.ash.reader.ui.page.common.HomeEntry
|
||||
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewModel
|
||||
import java.lang.reflect.Field
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
|
@ -30,7 +34,6 @@ import javax.inject.Inject
|
|||
*/
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var imageLoader: ImageLoader
|
||||
|
||||
|
@ -67,10 +70,39 @@ class MainActivity : AppCompatActivity() {
|
|||
) {
|
||||
AccountSettingsProvider(accountDao) {
|
||||
SettingsProvider {
|
||||
HomeEntry()
|
||||
val subscribeViewModel: SubscribeViewModel = hiltViewModel()
|
||||
DisposableEffect(this) {
|
||||
val listener = Consumer<Intent> { intent ->
|
||||
intent.getTextOrNull()?.let {
|
||||
subscribeViewModel.handleSharedUrlFromIntent(it)
|
||||
}
|
||||
}
|
||||
addOnNewIntentListener(listener)
|
||||
onDispose {
|
||||
removeOnNewIntentListener(listener)
|
||||
}
|
||||
}
|
||||
HomeEntry(subscribeViewModel = subscribeViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Intent.getTextOrNull(): String? {
|
||||
|
||||
return when (action) {
|
||||
Intent.ACTION_VIEW -> {
|
||||
dataString
|
||||
}
|
||||
|
||||
Intent.ACTION_SEND -> {
|
||||
getStringExtra(Intent.EXTRA_TEXT)
|
||||
?.also { removeExtra(Intent.EXTRA_TEXT) }
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import me.ash.reader.infrastructure.preference.LocalReadingDarkTheme
|
|||
import me.ash.reader.ui.ext.*
|
||||
import me.ash.reader.ui.page.home.HomeViewModel
|
||||
import me.ash.reader.ui.page.home.feeds.FeedsPage
|
||||
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewModel
|
||||
import me.ash.reader.ui.page.home.flow.FlowPage
|
||||
import me.ash.reader.ui.page.home.reading.ReadingPage
|
||||
import me.ash.reader.ui.page.settings.SettingsPage
|
||||
|
@ -42,10 +43,12 @@ import me.ash.reader.ui.theme.AppTheme
|
|||
@Composable
|
||||
fun HomeEntry(
|
||||
homeViewModel: HomeViewModel = hiltViewModel(),
|
||||
subscribeViewModel: SubscribeViewModel = hiltViewModel(),
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var isReadingPage by rememberSaveable { mutableStateOf(false) }
|
||||
val filterUiState = homeViewModel.filterUiState.collectAsStateValue()
|
||||
val subscribeUiState = subscribeViewModel.subscribeUiState.collectAsStateValue()
|
||||
val navController = rememberAnimatedNavController()
|
||||
|
||||
val intent by rememberSaveable { mutableStateOf(context.findActivity()?.intent) }
|
||||
|
@ -81,7 +84,23 @@ fun HomeEntry(
|
|||
Log.i("RLog", "currentBackStackEntry: ${navController.currentDestination?.route}")
|
||||
// Animation duration takes 310 ms
|
||||
delay(310L)
|
||||
isReadingPage = navController.currentDestination?.route == "${RouteName.READING}/{articleId}"
|
||||
isReadingPage =
|
||||
navController.currentDestination?.route == "${RouteName.READING}/{articleId}"
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(subscribeUiState.shouldNavigateToFeedPage) {
|
||||
if (subscribeUiState.shouldNavigateToFeedPage) {
|
||||
if (navController.currentDestination?.route != RouteName.FEEDS) {
|
||||
navController.popBackStack(
|
||||
route = RouteName.FEEDS,
|
||||
inclusive = false,
|
||||
saveState = true
|
||||
)
|
||||
}
|
||||
}
|
||||
onDispose {
|
||||
subscribeViewModel.onIntentConsumed()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +145,11 @@ fun HomeEntry(
|
|||
|
||||
// Home
|
||||
forwardAndBackwardComposable(route = RouteName.FEEDS) {
|
||||
FeedsPage(navController = navController, homeViewModel = homeViewModel)
|
||||
FeedsPage(
|
||||
navController = navController,
|
||||
homeViewModel = homeViewModel,
|
||||
subscribeViewModel = subscribeViewModel
|
||||
)
|
||||
}
|
||||
forwardAndBackwardComposable(route = RouteName.FLOW) {
|
||||
FlowPage(
|
||||
|
|
|
@ -322,7 +322,7 @@ fun FeedsPage(
|
|||
}
|
||||
)
|
||||
|
||||
SubscribeDialog()
|
||||
SubscribeDialog(subscribeViewModel = subscribeViewModel)
|
||||
GroupOptionDrawer()
|
||||
FeedOptionDrawer()
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.rometools.rome.feed.synd.SyndFeed
|
|||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
@ -52,7 +53,7 @@ class SubscribeViewModel @Inject constructor(
|
|||
searchJob?.cancel()
|
||||
searchJob = null
|
||||
_subscribeUiState.update {
|
||||
SubscribeUiState().copy(title = androidStringsHelper.getString(R.string.subscribe))
|
||||
SubscribeUiState(title = androidStringsHelper.getString(R.string.subscribe))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,9 @@ class SubscribeViewModel @Inject constructor(
|
|||
if (_subscribeUiState.value.newGroupContent.isNotBlank()) {
|
||||
applicationScope.launch {
|
||||
// TODO: How to add a single group without no feeds via Google Reader API?
|
||||
selectedGroup(rssService.get().addGroup(null, _subscribeUiState.value.newGroupContent))
|
||||
selectedGroup(
|
||||
rssService.get().addGroup(null, _subscribeUiState.value.newGroupContent)
|
||||
)
|
||||
hideNewGroupDialog()
|
||||
_subscribeUiState.update { it.copy(newGroupContent = "") }
|
||||
}
|
||||
|
@ -139,7 +142,8 @@ class SubscribeViewModel @Inject constructor(
|
|||
_subscribeUiState.update {
|
||||
it.copy(
|
||||
title = androidStringsHelper.getString(R.string.subscribe),
|
||||
errorMessage = e.message ?: androidStringsHelper.getString(R.string.unknown),
|
||||
errorMessage = e.message
|
||||
?: androidStringsHelper.getString(R.string.unknown),
|
||||
lockLinkInput = false,
|
||||
)
|
||||
}
|
||||
|
@ -175,6 +179,24 @@ class SubscribeViewModel @Inject constructor(
|
|||
_subscribeUiState.update { it.copy(newGroupContent = content) }
|
||||
}
|
||||
|
||||
fun handleSharedUrlFromIntent(url: String) {
|
||||
viewModelScope.launch {
|
||||
_subscribeUiState.update {
|
||||
it.copy(
|
||||
visible = true,
|
||||
shouldNavigateToFeedPage = true,
|
||||
linkContent = url,
|
||||
errorMessage = "",
|
||||
)
|
||||
}
|
||||
delay(50)
|
||||
}.invokeOnCompletion { search() }
|
||||
}
|
||||
|
||||
fun onIntentConsumed() {
|
||||
_subscribeUiState.update { it.copy(shouldNavigateToFeedPage = false) }
|
||||
}
|
||||
|
||||
fun showDrawer() {
|
||||
_subscribeUiState.update { it.copy(visible = true) }
|
||||
}
|
||||
|
@ -238,4 +260,5 @@ data class SubscribeUiState(
|
|||
val isSearchPage: Boolean = true,
|
||||
val newName: String = "",
|
||||
val renameDialogVisible: Boolean = false,
|
||||
val shouldNavigateToFeedPage: Boolean = false,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue