Skip to content

Commit

Permalink
Merge pull request #1959 from pantasystem/feature/suspend-streaming
Browse files Browse the repository at this point in the history
ストリーミングを受信しないときは購読を解除するようにした
  • Loading branch information
pantasystem authored Nov 12, 2023
2 parents 1b635f0 + 4e2d5f3 commit 4ac8931
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 71 deletions.
19 changes: 19 additions & 0 deletions app/src/main/java/jp/panta/misskeyandroidclient/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.bumptech.glide.Glide
Expand All @@ -33,6 +35,7 @@ import jp.panta.misskeyandroidclient.ui.main.SetupOnBackPressedDispatcherHandler
import jp.panta.misskeyandroidclient.ui.main.ToggleNavigationDrawerDelegate
import jp.panta.misskeyandroidclient.ui.main.viewmodel.MainViewModel
import jp.panta.misskeyandroidclient.ui.setLongPressListenerOnNavigationItem
import kotlinx.coroutines.launch
import net.pantasystem.milktea.app_store.setting.SettingStore
import net.pantasystem.milktea.common.ui.ApplyTheme
import net.pantasystem.milktea.common.ui.ToolbarSetter
Expand All @@ -42,6 +45,8 @@ import net.pantasystem.milktea.common_android_ui.report.ReportViewModel
import net.pantasystem.milktea.common_navigation.MainNavigation
import net.pantasystem.milktea.common_viewmodel.CurrentPageableTimelineViewModel
import net.pantasystem.milktea.common_viewmodel.ScrollToTopViewModel
import net.pantasystem.milktea.data.infrastructure.streaming.ChannelAPIMainEventDispatcherAdapter
import net.pantasystem.milktea.data.infrastructure.streaming.MediatorMainEventDispatcher
import net.pantasystem.milktea.note.renote.RenoteResultHandler
import net.pantasystem.milktea.note.renote.RenoteViewModel
import net.pantasystem.milktea.note.view.NoteActionHandler
Expand All @@ -67,6 +72,12 @@ class MainActivity : AppCompatActivity(), ToolbarSetter {
@Inject
internal lateinit var fabClickHandleFactory: FabClickHandler.Factory

@Inject
internal lateinit var mainEventDispatcherFactory: MediatorMainEventDispatcher.Factory

@Inject
internal lateinit var channelAPIMainEventDispatcherAdapter: ChannelAPIMainEventDispatcherAdapter

private val notesViewModel: NotesViewModel by viewModels()

private val accountViewModel: AccountViewModel by viewModels()
Expand Down Expand Up @@ -149,6 +160,14 @@ class MainActivity : AppCompatActivity(), ToolbarSetter {
handleIntent()
}


val mainEventDispatcher = mainEventDispatcherFactory.create()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
channelAPIMainEventDispatcherAdapter(mainEventDispatcher)
}
}

GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import net.pantasystem.milktea.app_store.account.AccountStore
import net.pantasystem.milktea.common.Logger
import net.pantasystem.milktea.common_android.platform.activeNetworkFlow
import net.pantasystem.milktea.data.infrastructure.MemoryCacheCleaner
import net.pantasystem.milktea.data.infrastructure.streaming.ChannelAPIMainEventDispatcherAdapter
import net.pantasystem.milktea.data.infrastructure.streaming.MediatorMainEventDispatcher
import net.pantasystem.milktea.data.streaming.SocketWithAccountProvider
import javax.inject.Inject

Expand All @@ -31,11 +29,8 @@ class MiApplication : Application(), Configuration.Provider {
internal lateinit var mSocketWithAccountProvider: SocketWithAccountProvider


@Inject
internal lateinit var mainEventDispatcherFactory: MediatorMainEventDispatcher.Factory

@Inject
internal lateinit var channelAPIMainEventDispatcherAdapter: ChannelAPIMainEventDispatcherAdapter


@Inject
internal lateinit var applicationScope: CoroutineScope
Expand Down Expand Up @@ -74,9 +69,6 @@ class MiApplication : Application(), Configuration.Provider {
}
}

val mainEventDispatcher = mainEventDispatcherFactory.create()
channelAPIMainEventDispatcherAdapter(mainEventDispatcher)

applicationScope.launch {
appStateController.initializeSettings()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@ import net.pantasystem.milktea.common_viewmodel.CurrentPageType
import net.pantasystem.milktea.common_viewmodel.CurrentPageableTimelineViewModel
import net.pantasystem.milktea.model.instance.FeatureEnables
import net.pantasystem.milktea.model.note.draft.DraftNoteService
import net.pantasystem.milktea.model.notification.Notification
import net.pantasystem.milktea.model.user.report.ReportState
import net.pantasystem.milktea.notification.notificationMessageScope
import net.pantasystem.milktea.user.ReportStateHandler
import net.pantasystem.milktea.worker.note.CreateNoteWorkerExecutor
import javax.inject.Inject

@Suppress("DEPRECATION")
internal class MainActivityEventHandler(
val activity: MainActivity,
val binding: ActivityMainBinding,
val lifecycleScope: CoroutineScope,
val lifecycleOwner: LifecycleOwner,
val mainViewModel: MainViewModel,
private val lifecycleScope: CoroutineScope,
private val lifecycleOwner: LifecycleOwner,
private val mainViewModel: MainViewModel,
val reportViewModel: ReportViewModel,
private val createNoteWorkerExecutor: CreateNoteWorkerExecutor,
val accountStore: AccountStore,
val requestPostNotificationsPermissionLauncher: ActivityResultLauncher<String>,
private val requestPostNotificationsPermissionLauncher: ActivityResultLauncher<String>,
val changeNavMenuVisibilityFromAPIVersion: ChangeNavMenuVisibilityFromAPIVersion,
private val configStore: SettingStore,
private val draftNoteService: DraftNoteService,
Expand Down Expand Up @@ -176,7 +176,7 @@ internal class MainActivityEventHandler(

// NOTE: 最新の通知をSnackBar等に表示する
lifecycleScope.launch {
lifecycleOwner.whenCreated {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mainViewModel.newNotifications.collect { notificationRelation ->
activity.apply {
notificationMessageScope {
Expand All @@ -188,16 +188,20 @@ internal class MainActivityEventHandler(
}
val audioManager = activity.getSystemService(Context.AUDIO_SERVICE) as AudioManager

var replayedNotifyId: Notification.Id?
lifecycleScope.launch {
lifecycleOwner.whenResumed {
// NOTE: 通知音を再生する
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mainViewModel.newNotifications.collect {
replayedNotifyId = it.notification.id
if (replayedNotifyId == it.notification.id) {
return@collect
}
if (ringtone?.isPlaying == true) {
ringtone.stop()
}
if (
configStore.configState.value.isEnableNotificationSound
&& audioManager.ringerMode == AudioManager.RINGER_MODE_NORMAL
&& audioManager.ringerMode == AudioManager.RINGER_MODE_NORMAL
) {
ringtone?.play()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ interface TimelineStore {
val isActiveStreaming: Boolean


suspend fun loadPrevious(): Result<Unit>
suspend fun loadFuture(): Result<Unit>
suspend fun loadPrevious(): Result<Int>
suspend fun loadFuture(): Result<Int>

/**
* @param initialLoadQuery コンテンツが空の状態の時にloadPreviousを呼び出した時に
Expand All @@ -39,6 +39,8 @@ interface TimelineStore {

suspend fun releaseUnusedPages(position: Int, offset: Int = 50)

fun setActiveStreamingChangedListener(listener: (Boolean) -> Unit)

}

sealed interface InitialLoadQuery {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class NoteStreamingImpl @Inject constructor(
true
}
}.map {
noteDataSourceAdder.addNoteDtoToDataSource(account, it.body)
noteDataSourceAdder.addNoteDtoToDataSource(account, it.body, skipExists = true)
}
}

Expand All @@ -146,7 +146,7 @@ class NoteStreamingImpl @Inject constructor(
true
}
}.map {
noteDataSourceAdder.addTootStatusDtoIntoDataSource(account, it)
noteDataSourceAdder.addTootStatusDtoIntoDataSource(account, it, skipExists = true)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class TimelineStoreImpl(
override val receiveNoteQueue: SharedFlow<Note.Id>
get() = willAddNoteQueue

private var activeStreamingChangedListener: ((Boolean) -> Unit)? = null


internal val pageableStore: TimelinePagingBase by lazy {
when (pageableTimeline) {
Expand Down Expand Up @@ -114,7 +116,10 @@ class TimelineStoreImpl(
private var initialLoadQuery: InitialLoadQuery? = null

override var isActiveStreaming: Boolean = true
private set
private set(value) {
field = value
activeStreamingChangedListener?.invoke(value)
}

init {
coroutineScope.launch(Dispatchers.IO) {
Expand All @@ -124,8 +129,8 @@ class TimelineStoreImpl(
}
}

override suspend fun loadFuture(): Result<Unit> {
return runCancellableCatching<Unit> {
override suspend fun loadFuture(): Result<Int> {
return runCancellableCatching<Int> {
val addedCount = when (val store = pageableStore) {
is TimelinePagingStoreImpl -> {
FuturePagingController.create(
Expand All @@ -148,12 +153,13 @@ class TimelineStoreImpl(
isActiveStreaming = true
}
latestReceiveId = null
addedCount.getOrThrow()
}
}

override suspend fun loadPrevious(): Result<Unit> {
return runCancellableCatching<Unit> {
when (val store = pageableStore) {
override suspend fun loadPrevious(): Result<Int> {
return runCancellableCatching<Int> {
val result = when (val store = pageableStore) {
is TimelinePagingStoreImpl -> {
PreviousPagingController.create(
store,
Expand All @@ -171,14 +177,15 @@ class TimelineStoreImpl(
}
}
latestReceiveId = null
result.getOrThrow()
}

}

override suspend fun clear(initialLoadQuery: InitialLoadQuery?) {
pageableStore.mutex.withLock {
this.initialLoadQuery = initialLoadQuery
isActiveStreaming = true
isActiveStreaming = initialLoadQuery == null
pageableStore.setState(PageableState.Loading.Init())
}
}
Expand All @@ -196,6 +203,10 @@ class TimelineStoreImpl(
isActiveStreaming = false
}

override fun setActiveStreamingChangedListener(listener: (Boolean) -> Unit) {
activeStreamingChangedListener = listener
}

private suspend fun appendStreamEventNote(noteId: Note.Id) {
val store = pageableStore
if (store is StreamingReceivableStore) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package net.pantasystem.milktea.data.infrastructure.streaming

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.plus
import net.pantasystem.milktea.api_streaming.ChannelBody
import net.pantasystem.milktea.api_streaming.channel.ChannelAPI
import net.pantasystem.milktea.app_store.account.AccountStore
Expand Down Expand Up @@ -77,17 +74,15 @@ class MediatorMainEventDispatcher(val logger: Logger) {

}

@Singleton
class ChannelAPIMainEventDispatcherAdapter @Inject constructor(
private val channelAPIProvider: ChannelAPIWithAccountProvider,
private val accountStore: AccountStore,
private val applicationScope: CoroutineScope,
loggerFactory: Logger.Factory
) {
val logger = loggerFactory.create("MainEventDispatcher")

@OptIn(ExperimentalCoroutinesApi::class)
operator fun invoke(mainDispatcher: MediatorMainEventDispatcher) {
suspend operator fun invoke(mainDispatcher: MediatorMainEventDispatcher) {
accountStore.state.map { it.currentAccount }.filterNotNull().filter {
it.instanceType == Account.InstanceType.MISSKEY || it.instanceType == Account.InstanceType.FIREFISH
}.flatMapLatest { ac ->
Expand All @@ -98,10 +93,10 @@ class ChannelAPIMainEventDispatcherAdapter @Inject constructor(
(it.second as? ChannelBody.Main)?.let { main ->
it.first to main
}
}.onEach {
mainDispatcher.dispatch(it.first, it.second)
}.catch { e ->
logger.error("Dispatch時にエラー発生", e = e)
}.launchIn(applicationScope + Dispatchers.IO)
}.collect {
mainDispatcher.dispatch(it.first, it.second)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ class TimelineFragment : Fragment(R.layout.fragment_swipe_refresh_recycler_view)
super.onItemRangeInserted(positionStart, itemCount)
if (mViewModel.timelineStore.latestReceiveNoteId() != null && positionStart == 0 && mFirstVisibleItemPosition == 0 && isShowing && itemCount == 1) {
lm.scrollToPosition(0)
} else {
mViewModel.onScrollPositionChanged(lm.findFirstVisibleItemPosition())
}
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ internal class NoteStreamingCollector(

private var job: Job? = null

fun onSuspend() {
fun suspendStreaming() {
synchronized(this) {
job?.cancel()
job = null
}
}

fun resumeStreaming() {
startObserveStreaming()
}

@OptIn(ExperimentalCoroutinesApi::class)
fun onResume() {
private fun startObserveStreaming() {
synchronized(this) {
if (job != null) {
return
Expand All @@ -52,6 +56,5 @@ internal class NoteStreamingCollector(
logger.error("receive not error", it)
}.launchIn(coroutineScope + Dispatchers.IO)
}

}
}
Loading

0 comments on commit 4ac8931

Please sign in to comment.