Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package com.anytypeio.anytype.di.main
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import com.anytypeio.anytype.device.network_type.NetworkConnectionStatusImpl
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
import com.anytypeio.anytype.persistence.networkmode.DefaultNetworkModeProvider
import com.anytypeio.anytype.persistence.networkmode.DefaultNetworkModeProvider.NetworkModeConstants.NAMED_NETWORK_MODE_PREFS
import com.anytypeio.anytype.persistence.networkmode.NetworkModeProvider
import dagger.Module
import dagger.Provides
import javax.inject.Named
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope

@Module
object NetworkModeModule {
Expand All @@ -28,4 +33,19 @@ object NetworkModeModule {
fun provider(
@Named(NAMED_NETWORK_MODE_PREFS) sharedPreferences: SharedPreferences
): NetworkModeProvider = DefaultNetworkModeProvider(sharedPreferences)

@JvmStatic
@Provides
@Singleton
fun provideNetworkConnectionStatus(
context: Context,
dispatcher: AppCoroutineDispatchers,
blockRepository: BlockRepository,
@Named(ConfigModule.DEFAULT_APP_COROUTINE_SCOPE) scope: CoroutineScope
): NetworkConnectionStatus = NetworkConnectionStatusImpl(
context = context,
dispatchers = dispatcher,
coroutineScope = scope,
blockRepository = blockRepository
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.debugging.DebugAccountSelectTrace
import com.anytypeio.anytype.domain.debugging.Logger
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvider
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
Expand Down Expand Up @@ -221,13 +222,15 @@ object SubscriptionsModule {
relations: RelationsSubscriptionManager,
permissions: UserPermissionProvider,
isSpaceDeleted: SpaceDeletedStatusWatcher,
profileSubscriptionManager: ProfileSubscriptionManager
profileSubscriptionManager: ProfileSubscriptionManager,
networkConnectionStatus: NetworkConnectionStatus
): GlobalSubscriptionManager = GlobalSubscriptionManager.Default(
types = types,
relations = relations,
permissions = permissions,
isSpaceDeleted = isSpaceDeleted,
profile = profileSubscriptionManager
profile = profileSubscriptionManager,
networkConnectionStatus = networkConnectionStatus
)

@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.anytypeio.anytype.core_models

enum class DeviceNetworkType {
WIFI,
CELLULAR,
NOT_CONNECTED
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
Expand Down Expand Up @@ -1096,4 +1097,8 @@ class BlockDataRepository(
override suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct? {
return remote.objectDateByTimestamp(command)
}

override suspend fun setDeviceNetworkState(type: DeviceNetworkType) {
remote.setDeviceNetworkState(type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
Expand Down Expand Up @@ -465,4 +466,6 @@ interface BlockRemote {
suspend fun objectRelationListWithValue(command: Command.RelationListWithValue): List<RelationListWithValueItem>

suspend fun debugAccountSelectTrace(dir: String): String

suspend fun setDeviceNetworkState(type: DeviceNetworkType)
}
4 changes: 3 additions & 1 deletion device/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
<manifest />
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.anytypeio.anytype.device.network_type

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber

class NetworkConnectionStatusImpl(
context: Context,
private val coroutineScope: CoroutineScope,
private val blockRepository: BlockRepository,
private val dispatchers: AppCoroutineDispatchers
) : NetworkConnectionStatus {

private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
private var isMonitoring = false

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
// Called when the network is available
updateNetworkState(networkCapabilities = getNetworkCapabilities())
}

override fun onLost(network: Network) {
// Called when the network is disconnected
updateNetworkState(networkCapabilities = getNetworkCapabilities())
}

override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
// Called when the network capabilities (like Wi-Fi vs Cellular) change
updateNetworkState(networkCapabilities)
}
}

override fun start() {
if (!isMonitoring) {
try {
connectivityManager?.registerDefaultNetworkCallback(networkCallback)
isMonitoring = true
updateNetworkState(networkCapabilities = getNetworkCapabilities())
} catch (
e: RuntimeException
) {
Timber.w(e, "Failed to register network callback")
isMonitoring = false
}
}
}

override fun stop() {
if (isMonitoring) {
try {
connectivityManager?.unregisterNetworkCallback(networkCallback)
isMonitoring = false
} catch (e: Throwable) {
Timber.w(e, "Failed to unregister network callback")
isMonitoring = false
}
}
}

private fun updateNetworkState(networkCapabilities: NetworkCapabilities?) {
coroutineScope.launch {
val networkType = mapNetworkType(networkCapabilities)
withContext(dispatchers.io) {
try {
blockRepository.setDeviceNetworkState(networkType)
} catch (
e: Throwable
) {
Timber.w(e, "Failed to update network state")
}
}
}
}

private fun getNetworkCapabilities(): NetworkCapabilities? {
try {
return connectivityManager?.getNetworkCapabilities(connectivityManager.activeNetwork)
} catch (e: Throwable) {
Timber.w(e, "Failed to get network capabilities")
return null
}
}

private fun mapNetworkType(networkCapabilities: NetworkCapabilities?): DeviceNetworkType =
when {
networkCapabilities == null -> DeviceNetworkType.NOT_CONNECTED
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> DeviceNetworkType.WIFI
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> DeviceNetworkType.CELLULAR
else -> DeviceNetworkType.NOT_CONNECTED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
Expand Down Expand Up @@ -508,4 +509,6 @@ interface BlockRepository {
suspend fun debugAccountSelectTrace(dir: String): String

suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct?

suspend fun setDeviceNetworkState(type: DeviceNetworkType)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.anytypeio.anytype.domain.device

interface NetworkConnectionStatus {
fun start()
fun stop()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.anytypeio.anytype.domain.subscriptions

import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
import com.anytypeio.anytype.domain.search.ProfileSubscriptionManager
Expand All @@ -17,7 +18,8 @@ interface GlobalSubscriptionManager {
private val relations: RelationsSubscriptionManager,
private val permissions: UserPermissionProvider,
private val isSpaceDeleted: SpaceDeletedStatusWatcher,
private val profile: ProfileSubscriptionManager
private val profile: ProfileSubscriptionManager,
private val networkConnectionStatus: NetworkConnectionStatus
) : GlobalSubscriptionManager {

override fun onStart() {
Expand All @@ -26,6 +28,7 @@ interface GlobalSubscriptionManager {
permissions.start()
isSpaceDeleted.onStart()
profile.onStart()
networkConnectionStatus.start()
}

override fun onStop() {
Expand All @@ -34,6 +37,7 @@ interface GlobalSubscriptionManager {
permissions.stop()
isSpaceDeleted.onStop()
profile.onStop()
networkConnectionStatus.stop()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
Expand Down Expand Up @@ -1070,4 +1071,8 @@ class BlockMiddleware(
override suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct? {
return middleware.objectDateByTimestamp(command)
}

override suspend fun setDeviceNetworkState(type: DeviceNetworkType) {
middleware.setDeviceNetworkState(type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
Expand Down Expand Up @@ -2856,6 +2857,16 @@ class Middleware @Inject constructor(
return response.details
}

@Throws(Exception::class)
fun setDeviceNetworkState(type: DeviceNetworkType) {
val request = Rpc.Device.NetworkState.Set.Request(
deviceNetworkType = type.mw()
)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.deviceNetworkStateSet(request) }
logResponseIfDebug(response, time)
}

private fun logRequestIfDebug(request: Any) {
if (BuildConfig.DEBUG) {
logger.logRequest(request).also {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,6 @@ typealias MSpaceSyncError = anytype.Event.Space.SyncError

typealias MP2PStatus = anytype.Event.P2PStatus.Status
typealias MP2PStatusUpdate = P2PStatus.Update
typealias MSyncStatusUpdate = Space.SyncStatus.Update
typealias MSyncStatusUpdate = Space.SyncStatus.Update

typealias MDeviceNetworkType = anytype.model.DeviceNetworkType
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.BlockSplitMode
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.DVSortEmptyType
import com.anytypeio.anytype.core_models.DeviceNetworkType
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.NetworkMode
import com.anytypeio.anytype.core_models.ObjectType
Expand Down Expand Up @@ -630,3 +631,9 @@ fun Rpc.Object.SearchWithMeta.Response.toCoreModelSearchResults(): List<Command.
}
}

fun DeviceNetworkType.mw(): MDeviceNetworkType = when(this) {
DeviceNetworkType.WIFI -> MDeviceNetworkType.WIFI
DeviceNetworkType.CELLULAR -> MDeviceNetworkType.CELLULAR
DeviceNetworkType.NOT_CONNECTED -> MDeviceNetworkType.NOT_CONNECTED
}

Original file line number Diff line number Diff line change
Expand Up @@ -609,4 +609,7 @@ interface MiddlewareService {

@Throws(Exception::class)
fun debugAccountSelectTrace(request: Rpc.Debug.AccountSelectTrace.Request): Rpc.Debug.AccountSelectTrace.Response

@Throws(Exception::class)
fun deviceNetworkStateSet(request: Rpc.Device.NetworkState.Set.Request): Rpc.Device.NetworkState.Set.Response
}
Original file line number Diff line number Diff line change
Expand Up @@ -2450,4 +2450,17 @@ class MiddlewareServiceImplementation @Inject constructor(
return response
}
}

override fun deviceNetworkStateSet(request: Rpc.Device.NetworkState.Set.Request): Rpc.Device.NetworkState.Set.Response {
val encoded = Service.deviceNetworkStateSet(
Rpc.Device.NetworkState.Set.Request.ADAPTER.encode(request)
)
val response = Rpc.Device.NetworkState.Set.Response.ADAPTER.decode(encoded)
val error = response.error
if (error != null && error.code != Rpc.Device.NetworkState.Set.Response.Error.Code.NULL) {
throw Exception(error.description)
} else {
return response
}
}
}
Loading