Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Update trusted device info based on listeners #1785

Merged
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 @@ -18,7 +18,16 @@ interface SyncRuntimeInfoDao {
block: SyncRuntimeInfo.() -> Unit,
): SyncRuntimeInfo?

fun insertOrUpdate(syncRuntimeInfo: SyncRuntimeInfo): Boolean
fun insertOrUpdate(syncRuntimeInfo: SyncRuntimeInfo): ChangeType

fun update(syncRuntimeInfos: List<SyncRuntimeInfo>): List<String>

fun deleteSyncRuntimeInfo(appInstanceId: String)
}

enum class ChangeType {
NEW_INSTANCE,
NO_CHANGE,
NET_CHANGE,
INFO_CHANGE,
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ interface SyncManager {

var waitToVerifySyncRuntimeInfo: SyncRuntimeInfo?

suspend fun resolveSyncs()
fun resolveSyncs()

suspend fun resolveSync(id: String)
fun resolveSync(id: String)

fun getSyncHandlers(): Map<String, SyncHandler>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ import com.crosspaste.ui.disconnectedColor
import com.crosspaste.ui.selectColor
import com.crosspaste.ui.unmatchedColor
import com.crosspaste.ui.unverifiedColor
import com.crosspaste.utils.cpuDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@OptIn(ExperimentalComposeUiApi::class)
@Composable
Expand Down Expand Up @@ -163,45 +161,45 @@ fun DeviceConnectView(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
) {
if (!refresh) {
PasteIconButton(
size = 20.dp,
onClick = {
scope.launch {
try {
refresh = true
withContext(cpuDispatcher) {
if (deviceInteractionEnabled) {
if (!refresh) {
PasteIconButton(
size = 20.dp,
onClick = {
scope.launch {
try {
refresh = true
syncManager.resolveSync(syncRuntimeInfo.appInstanceId)
delay(1000)
} catch (e: Exception) {
notificationManager.addNotification(
"${copywriter.getText("refresh_connection_failed")}:\n${e.message}",
MessageType.Error,
)
} finally {
refresh = false
}
delay(1000)
} catch (e: Exception) {
notificationManager.addNotification(
"${copywriter.getText("refresh_connection_failed")}:\n${e.message}",
MessageType.Error,
)
} finally {
refresh = false
}
}
},
modifier =
Modifier
.background(Color.Transparent, CircleShape)
.padding(end = 8.dp),
) {
Icon(
imageVector = Icons.Outlined.Refresh,
contentDescription = "refresh",
},
modifier =
Modifier
.background(Color.Transparent, CircleShape)
.padding(end = 8.dp),
) {
Icon(
imageVector = Icons.Outlined.Refresh,
contentDescription = "refresh",
modifier = Modifier.size(18.dp),
tint = connectColor,
)
}
} else {
CircularProgressIndicator(
modifier = Modifier.size(18.dp),
tint = connectColor,
color = connectColor,
)
Spacer(modifier = Modifier.width(8.dp))
}
} else {
CircularProgressIndicator(
modifier = Modifier.size(18.dp),
color = connectColor,
)
Spacer(modifier = Modifier.width(8.dp))
}
Icon(
painter = connectIcon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class CrossPaste {
}
single<SyncRefresher> { get<DesktopSyncManager>() }
single<SyncManager> { get<DesktopSyncManager>() }
single<DeviceManager> { DesktopDeviceManager(get(), get(), get()) }
single<DeviceManager> { DesktopDeviceManager(get(), get(), get(), get()) }
single<FaviconLoader> { DesktopFaviconLoader(get()) }

// signal component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.realm.kotlin.Realm
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort
import io.realm.kotlin.types.RealmInstant
import kotlin.reflect.KMutableProperty1

class SyncRuntimeInfoRealm(private val realm: Realm) : SyncRuntimeInfoDao {

Expand Down Expand Up @@ -48,80 +49,92 @@ class SyncRuntimeInfoRealm(private val realm: Realm) : SyncRuntimeInfoDao {
private fun updateSyncRuntimeInfo(
syncRuntimeInfo: SyncRuntimeInfo,
newSyncRuntimeInfo: SyncRuntimeInfo,
): Boolean {
var hasModify = false
if (syncRuntimeInfo.appVersion != newSyncRuntimeInfo.appVersion) {
syncRuntimeInfo.appVersion = newSyncRuntimeInfo.appVersion
hasModify = true
}

if (syncRuntimeInfo.userName != newSyncRuntimeInfo.userName) {
syncRuntimeInfo.userName = newSyncRuntimeInfo.userName
hasModify = true
}

if (syncRuntimeInfo.deviceId != newSyncRuntimeInfo.deviceId) {
syncRuntimeInfo.deviceId = newSyncRuntimeInfo.deviceId
hasModify = true
}

if (syncRuntimeInfo.deviceName != newSyncRuntimeInfo.deviceName) {
syncRuntimeInfo.deviceName = newSyncRuntimeInfo.deviceName
hasModify = true
}

if (syncRuntimeInfo.platformName != newSyncRuntimeInfo.platformName) {
syncRuntimeInfo.platformName = newSyncRuntimeInfo.platformName
hasModify = true
}

if (syncRuntimeInfo.platformVersion != newSyncRuntimeInfo.platformVersion) {
syncRuntimeInfo.platformVersion = newSyncRuntimeInfo.platformVersion
hasModify = true
}

if (syncRuntimeInfo.platformArch != newSyncRuntimeInfo.platformArch) {
syncRuntimeInfo.platformArch = newSyncRuntimeInfo.platformArch
hasModify = true
}

if (syncRuntimeInfo.platformBitMode != newSyncRuntimeInfo.platformBitMode) {
syncRuntimeInfo.platformBitMode = newSyncRuntimeInfo.platformBitMode
hasModify = true
}

if (!hostInfoListEqual(syncRuntimeInfo.hostInfoList, newSyncRuntimeInfo.hostInfoList)) {
syncRuntimeInfo.hostInfoList = newSyncRuntimeInfo.hostInfoList
hasModify = true
): ChangeType {
var netChange = false
var infoChange = false

fun <T> updateField(
field: KMutableProperty1<SyncRuntimeInfo, T>,
isNetField: Boolean = false,
customEquals: ((T, T) -> Boolean)? = null,
): Boolean {
val oldValue = field.get(syncRuntimeInfo)
val newValue = field.get(newSyncRuntimeInfo)
val areEqual = customEquals?.invoke(oldValue, newValue) ?: (oldValue == newValue)
return if (!areEqual) {
field.set(syncRuntimeInfo, newValue)
if (isNetField) {
netChange = true
} else {
infoChange = true
}
true
} else {
false
}
}

if (syncRuntimeInfo.port != newSyncRuntimeInfo.port) {
syncRuntimeInfo.port = newSyncRuntimeInfo.port
hasModify = true
// Update network-related fields
updateField(SyncRuntimeInfo::hostInfoList, true, ::hostInfoListEqual)
updateField(SyncRuntimeInfo::port, true)

// Update info-related fields
updateField(SyncRuntimeInfo::appVersion)
updateField(SyncRuntimeInfo::userName)
updateField(SyncRuntimeInfo::deviceId)
updateField(SyncRuntimeInfo::deviceName)
updateField(SyncRuntimeInfo::platformName)
updateField(SyncRuntimeInfo::platformVersion)
updateField(SyncRuntimeInfo::platformArch)
updateField(SyncRuntimeInfo::platformBitMode)

// Update modifyTime if necessary
if (netChange || infoChange || syncRuntimeInfo.connectState != SyncState.CONNECTED) {
syncRuntimeInfo.modifyTime = RealmInstant.now()
}

// When the state is not connected,
// we will update the modifyTime at least to drive the refresh
if (hasModify || syncRuntimeInfo.connectState != SyncState.CONNECTED) {
syncRuntimeInfo.modifyTime = RealmInstant.now()
return when {
netChange -> ChangeType.NET_CHANGE
infoChange -> ChangeType.INFO_CHANGE
else -> ChangeType.NO_CHANGE
}
return hasModify
}

override fun insertOrUpdate(syncRuntimeInfo: SyncRuntimeInfo): Boolean {
try {
return realm.writeBlocking {
override fun insertOrUpdate(syncRuntimeInfo: SyncRuntimeInfo): ChangeType {
return try {
realm.writeBlocking {
query(SyncRuntimeInfo::class, "appInstanceId == $0", syncRuntimeInfo.appInstanceId)
.first()
.find()?.let {
return@let updateSyncRuntimeInfo(it, syncRuntimeInfo)
} ?: run {
copyToRealm(syncRuntimeInfo)
return@run true
return@run ChangeType.NEW_INSTANCE
}
}
} catch (e: Exception) {
return false
ChangeType.NO_CHANGE
}
}

override fun update(syncRuntimeInfos: List<SyncRuntimeInfo>): List<String> {
return try {
realm.writeBlocking {
val ids = mutableListOf<String>()
for (syncRuntimeInfo in syncRuntimeInfos) {
query(SyncRuntimeInfo::class, "appInstanceId == $0", syncRuntimeInfo.appInstanceId)
.first()
.find()?.let {
val changeType = updateSyncRuntimeInfo(it, syncRuntimeInfo)
if (changeType == ChangeType.NET_CHANGE) {
ids.add(it.appInstanceId)
}
}
}
ids
}
} catch (ignore: Exception) {
emptyList()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.crosspaste.app.AppInfo
import com.crosspaste.config.ConfigManager
import com.crosspaste.dao.sync.SyncRuntimeInfoDao
import com.crosspaste.dao.sync.createSyncRuntimeInfo
import com.crosspaste.dto.sync.SyncInfo
import com.crosspaste.utils.DesktopJsonUtils
import com.crosspaste.utils.TxtRecordUtils
Expand All @@ -19,6 +21,7 @@ class DesktopDeviceManager(
private val appInfo: AppInfo,
private val configManager: ConfigManager,
private val syncManager: SyncManager,
private val syncRuntimeInfoDao: SyncRuntimeInfoDao,
) : DeviceManager, ServiceListener {

private val logger = KotlinLogging.logger {}
Expand Down Expand Up @@ -53,6 +56,15 @@ class DesktopDeviceManager(
searching = true
try {
syncInfos.clear()
val existSyncRuntimeInfos =
allSyncInfos.filter { !isNew(it.key) }
.map { createSyncRuntimeInfo(it.value) }
if (existSyncRuntimeInfos.isNotEmpty()) {
syncRuntimeInfoDao.update(existSyncRuntimeInfos)
.forEach {
syncManager.resolveSync(it)
}
}
syncInfos.addAll(allSyncInfos.filter { isNew(it.key) && !isBlackListed(it.key) }.values)
} finally {
searching = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ class DesktopSyncHandler(
}

override suspend fun markExit() {
logger.info { "markExit ${syncRuntimeInfo.appInstanceId}" }
update {
this.connectState = SyncState.DISCONNECTED
this.modifyTime = RealmInstant.now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.runtime.setValue
import com.crosspaste.app.AppInfo
import com.crosspaste.app.VersionCompatibilityChecker
import com.crosspaste.dao.signal.SignalDao
import com.crosspaste.dao.sync.ChangeType
import com.crosspaste.dao.sync.SyncRuntimeInfo
import com.crosspaste.dao.sync.SyncRuntimeInfoDao
import com.crosspaste.dao.sync.SyncState
Expand Down Expand Up @@ -163,15 +164,15 @@ class DesktopSyncManager(
refreshWaitToVerifySyncRuntimeInfo()
}

override suspend fun resolveSyncs() {
override fun resolveSyncs() {
internalSyncHandlers.values.forEach { syncHandler ->
realTimeSyncScope.launch {
doResolveSync(syncHandler)
}
}
}

override suspend fun resolveSync(id: String) {
override fun resolveSync(id: String) {
internalSyncHandlers[id]?.let { syncHandler ->
realTimeSyncScope.launch {
doResolveSync(syncHandler)
Expand Down Expand Up @@ -228,7 +229,7 @@ class DesktopSyncManager(
override fun updateSyncInfo(syncInfo: SyncInfo) {
realTimeSyncScope.launch(CoroutineName("UpdateSyncInfo")) {
val newSyncRuntimeInfo = createSyncRuntimeInfo(syncInfo)
if (!syncRuntimeInfoDao.insertOrUpdate(newSyncRuntimeInfo)) {
if (syncRuntimeInfoDao.insertOrUpdate(newSyncRuntimeInfo) == ChangeType.NO_CHANGE) {
internalSyncHandlers[syncInfo.appInfo.appInstanceId]?.tryDirectUpdateConnected()
}
}
Expand Down
Loading