From 8630b98fe89c8d8346aa3e3975822d5bc6169c42 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Thu, 19 Aug 2021 13:23:14 +0800 Subject: [PATCH 01/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03f8c0ded..5eec16699 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ For 1.6.0, we're planning to build an experimatal desktop version, this is a big - Experimatal desktop version. - Mute and block support. -- Optimizing video play for timelien. +- Optimizing video play for timeline. - Bug fixes. - UI/UX tweaking. - Stability. From 8fc0660e0d6b39fb04e2b63569bb4f9194b36e94 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Thu, 19 Aug 2021 16:58:31 +0800 Subject: [PATCH 02/14] upgrade jetpack library --- buildSrc/src/main/kotlin/Versions.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 848815883..7fc7ef9d3 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -13,15 +13,15 @@ object Versions { } const val ksp = "${Kotlin.lang}-1.0.0-beta06" - const val agp = "7.0.0" + const val agp = "7.0.1" const val spotless = "5.14.2" const val ktlint = "0.41.0" const val hilt = "2.38.1" const val okhttp = "4.9.1" const val retrofit2 = "2.9.0" const val hson = "0.1.4" - const val compose = "1.1.0-alpha01" - const val constraintLayout = "1.0.0-beta01" + const val compose = "1.1.0-alpha02" + const val constraintLayout = "1.0.0-beta02" const val paging = "3.1.0-alpha03" const val paging_compose = "1.0.0-alpha12" const val activity = "1.3.1" @@ -37,9 +37,9 @@ object Versions { const val nestedScrollView = "0.7.0" const val startup = "1.1.0" const val coil = "1.3.0" - const val accompanist = "0.15.0" + const val accompanist = "0.16.1" const val androidx_exifinterface = "1.3.2" - const val exoplayer = "2.14.2" + const val exoplayer = "2.15.0" const val browser = "1.3.0" const val protobuf = "3.17.3" const val androidx_test = "1.4.0" From d399b9e0b8fb92e038ae9429eec323ce035bad4a Mon Sep 17 00:00:00 2001 From: Tlaster Date: Fri, 20 Aug 2021 14:50:14 +0800 Subject: [PATCH 03/14] enable r8 support --- app/build.gradle.kts | 3 +- app/proguard-rules.pro | 81 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ca31a7f4a..d1f43f954 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -113,7 +113,8 @@ android { if (hasSigningProps) { signingConfig = signingConfigs.getByName("twidere") } - isMinifyEnabled = false + isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb4348..08f49e699 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,83 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +-keepattributes *Annotation*, InnerClasses +-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations + +# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer +-keepclassmembers class kotlinx.serialization.json.** { + *** Companion; +} +-keepclasseswithmembers class kotlinx.serialization.json.** { + kotlinx.serialization.KSerializer serializer(...); +} + +-keep,includedescriptorclasses class com.twidere.services.**$$serializer { *; } +-keepclassmembers class com.twidere.services.** { + *** Companion; +} +-keepclasseswithmembers class com.twidere.services.** { + kotlinx.serialization.KSerializer serializer(...); +} + +-keep,includedescriptorclasses class com.twidere.twiderex.**$$serializer { *; } +-keepclassmembers class com.twidere.twiderex.** { + *** Companion; +} +-keepclasseswithmembers class com.twidere.twiderex.** { + kotlinx.serialization.KSerializer serializer(...); +} + +-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite { + ; +} + + +# ServiceLoader support +-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {} +-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {} + +# Most of volatile fields are updated with AFU and should not be mangled +-keepclassmembers class kotlinx.coroutines.** { + volatile ; +} + +# Same story for the standard library's SafeContinuation that also uses AtomicReferenceFieldUpdater +-keepclassmembers class kotlin.coroutines.SafeContinuation { + volatile ; +} + +# These classes are only required by kotlinx.coroutines.debug.AgentPremain, which is only loaded when +# kotlinx-coroutines-core is used as a Java agent, so these are not needed in contexts where ProGuard is used. +-dontwarn java.lang.instrument.ClassFileTransformer +-dontwarn sun.misc.SignalHandler +-dontwarn java.lang.instrument.Instrumentation +-dontwarn sun.misc.Signal + +# JSR 305 annotations are for embedding nullability information. +-dontwarn javax.annotation.** + +# A resource is loaded with a relative path so the package of this class must be preserved. +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase + +# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. +-dontwarn org.codehaus.mojo.animal_sniffer.* + +# OkHttp platform used only on JVM and when Conscrypt dependency is available. +-dontwarn okhttp3.internal.platform.ConscryptPlatform +-dontwarn org.conscrypt.ConscryptHostnameVerifier + +# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java. +-dontwarn org.codehaus.mojo.animal_sniffer.* + +-keeppackagenames org.jsoup.nodes + +-keep class * extends com.google.protobuf.GeneratedMessageLite { *; } + +-keep class com.twidere.services.nitter.model.** + +-keepclassmembers class ** { + @moe.tlaster.hson.annotations.HtmlSerializable public *; +} From 8526ab073f125a5d000ded3fe16af0876dc0d059 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Fri, 20 Aug 2021 15:18:54 +0800 Subject: [PATCH 04/14] add build mapping ci --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5cda18337..5068c371a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,12 @@ jobs: with: name: build-reports path: ./app/build/reports + + - name: Upload build mapping + uses: actions/upload-artifact@v2 + with: + name: build-mapping + path: ./app/build/outputs/mapping unit-test: runs-on: ubuntu-latest From 997910de45e003ef7e28481b656baec9170511d6 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Fri, 20 Aug 2021 16:02:39 +0800 Subject: [PATCH 05/14] version 1.5.1-beta01 --- buildSrc/src/main/kotlin/Package.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/Package.kt b/buildSrc/src/main/kotlin/Package.kt index 45471ce4f..320295dcc 100644 --- a/buildSrc/src/main/kotlin/Package.kt +++ b/buildSrc/src/main/kotlin/Package.kt @@ -2,6 +2,6 @@ object Package { const val group = "com.twidere" const val name = "TwidereX" const val id = "$group.twiderex" - const val versionName = "1.5.0" - const val versionCode = 53 + const val versionName = "1.5.1-beta01" + const val versionCode = 54 } From 75e53ec9aad9580b7c377d1d40801f93d74a659f Mon Sep 17 00:00:00 2001 From: Tlaster Date: Mon, 23 Aug 2021 14:00:42 +0800 Subject: [PATCH 06/14] upgrade packages --- app/build.gradle.kts | 6 +++--- buildSrc/src/main/kotlin/Versions.kt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d1f43f954..796e727d8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ buildscript { if (enableGoogleVariant) { // START Non-FOSS component - classpath("com.google.gms:google-services:4.3.5") - classpath("com.google.firebase:firebase-crashlytics-gradle:2.5.2") + classpath("com.google.gms:google-services:4.3.10") + classpath("com.google.firebase:firebase-crashlytics-gradle:2.7.1") // END Non-FOSS component } } @@ -198,7 +198,7 @@ dependencies { if (enableGoogleVariant) { // START Non-FOSS component val googleImplementation by configurations - googleImplementation(platform("com.google.firebase:firebase-bom:26.1.0")) + googleImplementation(platform("com.google.firebase:firebase-bom:28.4.0")) googleImplementation("com.google.firebase:firebase-analytics-ktx") googleImplementation("com.google.firebase:firebase-crashlytics-ktx") googleImplementation("com.google.android.play:core-ktx:1.8.1") diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 7fc7ef9d3..be551e13f 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -12,7 +12,7 @@ object Versions { val java = JavaVersion.VERSION_11 } - const val ksp = "${Kotlin.lang}-1.0.0-beta06" + const val ksp = "${Kotlin.lang}-1.0.0-beta07" const val agp = "7.0.1" const val spotless = "5.14.2" const val ktlint = "0.41.0" @@ -36,9 +36,9 @@ object Versions { const val swiper = "0.6.0" const val nestedScrollView = "0.7.0" const val startup = "1.1.0" - const val coil = "1.3.0" - const val accompanist = "0.16.1" - const val androidx_exifinterface = "1.3.2" + const val coil = "1.3.2" + const val accompanist = "0.17.0" + const val androidx_exifinterface = "1.3.3" const val exoplayer = "2.15.0" const val browser = "1.3.0" const val protobuf = "3.17.3" From ea50441d42d793f2bde0d11d58e314a9c0ea2846 Mon Sep 17 00:00:00 2001 From: huixing Date: Wed, 25 Aug 2021 16:00:20 +0800 Subject: [PATCH 07/14] this is fixed on beta7 --- app/build.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 796e727d8..977f05f53 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -175,10 +175,6 @@ protobuf { } } -// TODO: workaround for https://github.com/google/ksp/issues/518 -evaluationDependsOn(":assistedProcessor") -evaluationDependsOn(":routeProcessor") - dependencies { android() kotlinSerialization() From 4fae932239b04cce0c6b895439c4460225849d62 Mon Sep 17 00:00:00 2001 From: itsMimao Date: Thu, 26 Aug 2021 15:39:28 +0800 Subject: [PATCH 08/14] migrate twitter like/retweet api to v2 --- .../twiderex/jobs/status/LikeStatusJob.kt | 16 +++------ .../twiderex/jobs/status/RetweetStatusJob.kt | 16 +++------ .../jobs/status/UnRetweetStatusJob.kt | 16 +++------ .../twiderex/jobs/status/UnlikeStatusJob.kt | 16 +++------ .../services/mastodon/MastodonService.kt | 20 +++++------ .../services/microblog/StatusService.kt | 8 ++--- .../services/twitter/TwitterService.kt | 36 ++++++++++++++++--- .../services/twitter/api/StatusResources.kt | 17 +++++++++ .../twitter/model/StatusReactionsV2.kt | 29 +++++++++++++++ .../request/TwitterReactionRequestBody.kt | 28 +++++++++++++++ 10 files changed, 138 insertions(+), 64 deletions(-) create mode 100644 services/src/main/java/com/twidere/services/twitter/model/StatusReactionsV2.kt create mode 100644 services/src/main/java/com/twidere/services/twitter/model/request/TwitterReactionRequestBody.kt diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt index 0adb1dfa4..8da1d51e0 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt @@ -21,10 +21,8 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService -import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult -import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -42,17 +40,13 @@ class LikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.like(status.statusId) - .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey = accountKey).let { - it.retweet ?: it - } + val liked = service.like(id = status.statusId, userId = accountKey.id) return StatusResult( - statusKey = newStatus.statusKey, + statusKey = status.statusKey, accountKey = accountKey, - liked = true, - retweetCount = newStatus.metrics.retweet, - likeCount = newStatus.metrics.like, + liked = liked, + retweetCount = status.metrics.retweet, + likeCount = if (liked) status.metrics.like + 1 else status.metrics.like, ) } diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt index fcc25f2dc..109d205e7 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt @@ -21,10 +21,8 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService -import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult -import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -42,17 +40,13 @@ class RetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.retweet(status.statusId) - .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey = accountKey).let { - it.retweet ?: it - } + val retweeted = service.retweet(id = status.statusId, userId = accountKey.id) return StatusResult( - statusKey = newStatus.statusKey, + statusKey = status.statusKey, accountKey = accountKey, - retweeted = true, - retweetCount = newStatus.metrics.retweet, - likeCount = newStatus.metrics.like, + retweeted = retweeted, + retweetCount = if (retweeted) status.metrics.retweet + 1 else status.metrics.retweet, + likeCount = status.metrics.like, ) } override fun fallback( diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt index d8f5e35e1..ce8edb24c 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt @@ -21,10 +21,8 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService -import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult -import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -42,17 +40,13 @@ class UnRetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.unRetweet(status.statusId) - .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey = accountKey).let { - it.retweet ?: it - } + val retweeted = service.unRetweet(id = status.statusId, userId = accountKey.id) return StatusResult( - statusKey = newStatus.statusKey, + statusKey = status.statusKey, accountKey = accountKey, - retweeted = false, - retweetCount = newStatus.metrics.retweet, - likeCount = newStatus.metrics.like, + retweeted = retweeted, + retweetCount = if (retweeted) status.metrics.retweet else status.metrics.retweet - 1, + likeCount = status.metrics.like, ) } override fun fallback( diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt index 18835bd3e..6a78a6c73 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt @@ -21,10 +21,8 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService -import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult -import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -42,17 +40,13 @@ class UnlikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.unlike(status.statusId) - .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey = accountKey).let { - it.retweet ?: it - } + val liked = service.unlike(id = status.statusId, userId = accountKey.id) return StatusResult( - statusKey = newStatus.statusKey, + statusKey = status.statusKey, accountKey = accountKey, - liked = false, - retweetCount = newStatus.metrics.retweet, - likeCount = newStatus.metrics.like, + liked = liked, + retweetCount = status.metrics.retweet, + likeCount = if (liked) status.metrics.like else status.metrics.like - 1, ) } override fun fallback( diff --git a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt index 46109d5fe..6f037b5ff 100644 --- a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt +++ b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt @@ -265,24 +265,20 @@ class MastodonService( max_id = max_id, ) - override suspend fun like(id: String): IStatus { - return resources.favourite(id) + override suspend fun like(id: String, userId: String): Boolean { + return resources.favourite(id).favourited ?: false } - override suspend fun unlike(id: String): IStatus { - return resources.unfavourite(id).let { - it.copy(favouritesCount = it.favouritesCount?.let { it - 1 }) - } + override suspend fun unlike(id: String, userId: String): Boolean { + return resources.unfavourite(id).favourited ?: false } - override suspend fun retweet(id: String): IStatus { - return resources.reblog(id) + override suspend fun retweet(id: String, userId: String): Boolean { + return resources.reblog(id).reblogged ?: false } - override suspend fun unRetweet(id: String): IStatus { - return resources.unreblog(id).let { - it.copy(favouritesCount = it.reblogsCount?.let { it - 1 }) - } + override suspend fun unRetweet(id: String, userId: String): Boolean { + return resources.unreblog(id).reblogged ?: false } override suspend fun delete(id: String): IStatus { diff --git a/services/src/main/java/com/twidere/services/microblog/StatusService.kt b/services/src/main/java/com/twidere/services/microblog/StatusService.kt index ee755fe33..3b0dd1370 100644 --- a/services/src/main/java/com/twidere/services/microblog/StatusService.kt +++ b/services/src/main/java/com/twidere/services/microblog/StatusService.kt @@ -23,9 +23,9 @@ package com.twidere.services.microblog import com.twidere.services.microblog.model.IStatus interface StatusService { - suspend fun like(id: String): IStatus - suspend fun unlike(id: String): IStatus - suspend fun retweet(id: String): IStatus - suspend fun unRetweet(id: String): IStatus + suspend fun like(id: String, userId: String): Boolean + suspend fun unlike(id: String, userId: String): Boolean + suspend fun retweet(id: String, userId: String): Boolean + suspend fun unRetweet(id: String, userId: String): Boolean suspend fun delete(id: String): IStatus } diff --git a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt index 744a541d4..67a992522 100644 --- a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt +++ b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt @@ -62,6 +62,7 @@ import com.twidere.services.twitter.model.fields.PlaceFields import com.twidere.services.twitter.model.fields.PollFields import com.twidere.services.twitter.model.fields.TweetFields import com.twidere.services.twitter.model.fields.UserFields +import com.twidere.services.twitter.model.request.TwitterReactionRequestBody import com.twidere.services.utils.Base64 import com.twidere.services.utils.await import com.twidere.services.utils.copyToInLength @@ -377,13 +378,40 @@ class TwitterService( resources.unfollow(user_id) } - override suspend fun like(id: String) = resources.like(id) + override suspend fun like(id: String, userId: String): Boolean { + return try { + resources.likeV2(userId = userId, body = TwitterReactionRequestBody(tweet_id = id)) + .data?.liked ?: false + } catch (e: TwitterApiExceptionV2) { + resources.like(id).favorited ?: false + } + } - override suspend fun unlike(id: String) = resources.unlike(id) + override suspend fun unlike(id: String, userId: String): Boolean { + return try { + resources.unlikeV2(userId = userId, tweetId = id).data?.liked ?: false + } catch (e: TwitterApiExceptionV2) { + resources.unlike(id).favorited ?: false + } + } - override suspend fun retweet(id: String) = resources.retweet(id) + override suspend fun retweet(id: String, userId: String): Boolean { + return try { + resources.retweetV2(userId = userId, body = TwitterReactionRequestBody(tweet_id = id)) + .data?.retweeted ?: false + } catch (e: TwitterApiExceptionV2) { + resources.retweet(id).retweeted ?: false + } + } - override suspend fun unRetweet(id: String) = resources.unretweet(id) + override suspend fun unRetweet(id: String, userId: String): Boolean { + return try { + resources.unRetweetV2(userId = userId, tweetId = id) + .data?.retweeted ?: false + } catch (e: TwitterApiExceptionV2) { + resources.unretweet(id).retweeted ?: false + } + } override suspend fun delete(id: String) = resources.destroy(id) diff --git a/services/src/main/java/com/twidere/services/twitter/api/StatusResources.kt b/services/src/main/java/com/twidere/services/twitter/api/StatusResources.kt index a861c5ba2..0a1629d02 100644 --- a/services/src/main/java/com/twidere/services/twitter/api/StatusResources.kt +++ b/services/src/main/java/com/twidere/services/twitter/api/StatusResources.kt @@ -21,6 +21,11 @@ package com.twidere.services.twitter.api import com.twidere.services.twitter.model.Status +import com.twidere.services.twitter.model.StatusReactionsV2 +import com.twidere.services.twitter.model.TwitterResponseV2 +import com.twidere.services.twitter.model.request.TwitterReactionRequestBody +import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query @@ -55,4 +60,16 @@ interface StatusResources { @POST("/1.1/statuses/destroy/{id}.json") suspend fun destroy(@Path(value = "id") id: String): Status + + @POST("/2/users/{userId}/retweets") + suspend fun retweetV2(@Path(value = "userId") userId: String, @Body body: TwitterReactionRequestBody): TwitterResponseV2 + + @DELETE("/2/users/{userId}/retweets/{tweetId}") + suspend fun unRetweetV2(@Path(value = "userId") userId: String, @Path(value = "tweetId") tweetId: String): TwitterResponseV2 + + @POST("/2/users/{userId}/likes") + suspend fun likeV2(@Path(value = "userId") userId: String, @Body body: TwitterReactionRequestBody): TwitterResponseV2 + + @DELETE("/2/users/{userId}/likes/{tweetId}") + suspend fun unlikeV2(@Path(value = "userId") userId: String, @Path(value = "tweetId") tweetId: String): TwitterResponseV2 } diff --git a/services/src/main/java/com/twidere/services/twitter/model/StatusReactionsV2.kt b/services/src/main/java/com/twidere/services/twitter/model/StatusReactionsV2.kt new file mode 100644 index 000000000..aa586a9f8 --- /dev/null +++ b/services/src/main/java/com/twidere/services/twitter/model/StatusReactionsV2.kt @@ -0,0 +1,29 @@ +/* + * Twidere X + * + * Copyright (C) 2020-2021 Tlaster + * + * This file is part of Twidere X. + * + * Twidere X is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Twidere X is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Twidere X. If not, see . + */ +package com.twidere.services.twitter.model + +import kotlinx.serialization.Serializable + +@Serializable +data class StatusReactionsV2( + val retweeted: Boolean? = null, + val liked: Boolean? = null +) diff --git a/services/src/main/java/com/twidere/services/twitter/model/request/TwitterReactionRequestBody.kt b/services/src/main/java/com/twidere/services/twitter/model/request/TwitterReactionRequestBody.kt new file mode 100644 index 000000000..cd078163e --- /dev/null +++ b/services/src/main/java/com/twidere/services/twitter/model/request/TwitterReactionRequestBody.kt @@ -0,0 +1,28 @@ +/* + * Twidere X + * + * Copyright (C) 2020-2021 Tlaster + * + * This file is part of Twidere X. + * + * Twidere X is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Twidere X is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Twidere X. If not, see . + */ +package com.twidere.services.twitter.model.request + +import kotlinx.serialization.Serializable + +@Serializable +data class TwitterReactionRequestBody( + val tweet_id: String +) From 039ea741b5ffee5e0953d26353cddfc7ea09a06d Mon Sep 17 00:00:00 2001 From: itsMimao Date: Thu, 26 Aug 2021 18:01:34 +0800 Subject: [PATCH 09/14] refactor TwitterService --- .../twiderex/http/TwidereServiceFactory.kt | 8 +++++--- .../twiderex/jobs/status/LikeStatusJob.kt | 2 +- .../twiderex/jobs/status/RetweetStatusJob.kt | 2 +- .../jobs/status/UnRetweetStatusJob.kt | 2 +- .../twiderex/jobs/status/UnlikeStatusJob.kt | 2 +- .../twidere/twiderex/model/AccountDetails.kt | 2 +- .../twitter/TwitterSignInViewModel.kt | 1 + .../services/mastodon/MastodonService.kt | 8 ++++---- .../services/microblog/StatusService.kt | 8 ++++---- .../services/twitter/TwitterService.kt | 19 ++++++++++--------- 10 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/src/main/kotlin/com/twidere/twiderex/http/TwidereServiceFactory.kt b/app/src/main/kotlin/com/twidere/twiderex/http/TwidereServiceFactory.kt index dcebf8e12..667624511 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/http/TwidereServiceFactory.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/http/TwidereServiceFactory.kt @@ -25,6 +25,7 @@ import com.twidere.services.http.config.HttpConfigClientFactory import com.twidere.services.mastodon.MastodonService import com.twidere.services.microblog.MicroBlogService import com.twidere.services.twitter.TwitterService +import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.cred.Credentials import com.twidere.twiderex.model.cred.OAuth2Credentials import com.twidere.twiderex.model.cred.OAuthCredentials @@ -39,7 +40,7 @@ class TwidereServiceFactory(private val configProvider: TwidereHttpConfigProvide instance = TwidereServiceFactory(configProvider) } - fun createApiService(type: PlatformType, credentials: Credentials, host: String = ""): MicroBlogService { + fun createApiService(type: PlatformType, credentials: Credentials, accountKey: MicroBlogKey): MicroBlogService { return instance?.let { when (type) { PlatformType.Twitter -> { @@ -51,7 +52,8 @@ class TwidereServiceFactory(private val configProvider: TwidereHttpConfigProvide consumer_secret = it.consumer_secret, access_token = it.access_token, access_token_secret = it.access_token_secret, - httpClientFactory = createHttpClientFactory() + httpClientFactory = createHttpClientFactory(), + accountId = accountKey.id ) } } @@ -62,7 +64,7 @@ class TwidereServiceFactory(private val configProvider: TwidereHttpConfigProvide it as OAuth2Credentials }.let { MastodonService( - host, + accountKey.host, it.access_token, httpClientFactory = createHttpClientFactory() ) diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt index 8da1d51e0..cca1710ab 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt @@ -40,7 +40,7 @@ class LikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val liked = service.like(id = status.statusId, userId = accountKey.id) + val liked = service.like(id = status.statusId) return StatusResult( statusKey = status.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt index 109d205e7..4032a1b75 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt @@ -40,7 +40,7 @@ class RetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val retweeted = service.retweet(id = status.statusId, userId = accountKey.id) + val retweeted = service.retweet(id = status.statusId) return StatusResult( statusKey = status.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt index ce8edb24c..582e43fe6 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt @@ -40,7 +40,7 @@ class UnRetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val retweeted = service.unRetweet(id = status.statusId, userId = accountKey.id) + val retweeted = service.unRetweet(id = status.statusId) return StatusResult( statusKey = status.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt index 6a78a6c73..c0c7ee2b2 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt @@ -40,7 +40,7 @@ class UnlikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val liked = service.unlike(id = status.statusId, userId = accountKey.id) + val liked = service.unlike(id = status.statusId) return StatusResult( statusKey = status.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/model/AccountDetails.kt b/app/src/main/kotlin/com/twidere/twiderex/model/AccountDetails.kt index e2f1c28b4..d1877aa89 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/model/AccountDetails.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/model/AccountDetails.kt @@ -58,7 +58,7 @@ data class AccountDetails( TwidereServiceFactory.createApiService( type = type, credentials = credentials, - host = accountKey.host + accountKey = accountKey ) } diff --git a/app/src/main/kotlin/com/twidere/twiderex/viewmodel/twitter/TwitterSignInViewModel.kt b/app/src/main/kotlin/com/twidere/twiderex/viewmodel/twitter/TwitterSignInViewModel.kt index 9b061b024..6455961b0 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/viewmodel/twitter/TwitterSignInViewModel.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/viewmodel/twitter/TwitterSignInViewModel.kt @@ -109,6 +109,7 @@ class TwitterSignInViewModel @AssistedInject constructor( access_token = accessToken.oauth_token, access_token_secret = accessToken.oauth_token_secret ), + accountKey = MicroBlogKey.Empty ) as TwitterService ).verifyCredentials() if (user != null) { diff --git a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt index 6f037b5ff..681c84afa 100644 --- a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt +++ b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt @@ -265,19 +265,19 @@ class MastodonService( max_id = max_id, ) - override suspend fun like(id: String, userId: String): Boolean { + override suspend fun like(id: String): Boolean { return resources.favourite(id).favourited ?: false } - override suspend fun unlike(id: String, userId: String): Boolean { + override suspend fun unlike(id: String): Boolean { return resources.unfavourite(id).favourited ?: false } - override suspend fun retweet(id: String, userId: String): Boolean { + override suspend fun retweet(id: String): Boolean { return resources.reblog(id).reblogged ?: false } - override suspend fun unRetweet(id: String, userId: String): Boolean { + override suspend fun unRetweet(id: String): Boolean { return resources.unreblog(id).reblogged ?: false } diff --git a/services/src/main/java/com/twidere/services/microblog/StatusService.kt b/services/src/main/java/com/twidere/services/microblog/StatusService.kt index 3b0dd1370..c5ed4e311 100644 --- a/services/src/main/java/com/twidere/services/microblog/StatusService.kt +++ b/services/src/main/java/com/twidere/services/microblog/StatusService.kt @@ -23,9 +23,9 @@ package com.twidere.services.microblog import com.twidere.services.microblog.model.IStatus interface StatusService { - suspend fun like(id: String, userId: String): Boolean - suspend fun unlike(id: String, userId: String): Boolean - suspend fun retweet(id: String, userId: String): Boolean - suspend fun unRetweet(id: String, userId: String): Boolean + suspend fun like(id: String): Boolean + suspend fun unlike(id: String): Boolean + suspend fun retweet(id: String): Boolean + suspend fun unRetweet(id: String): Boolean suspend fun delete(id: String): IStatus } diff --git a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt index 67a992522..183cf1cf1 100644 --- a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt +++ b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt @@ -78,7 +78,8 @@ class TwitterService( private val consumer_secret: String, private val access_token: String, private val access_token_secret: String, - private val httpClientFactory: HttpClientFactory + private val httpClientFactory: HttpClientFactory, + private val accountId: String = "" ) : MicroBlogService, TimelineService, LookupService, @@ -378,35 +379,35 @@ class TwitterService( resources.unfollow(user_id) } - override suspend fun like(id: String, userId: String): Boolean { + override suspend fun like(id: String): Boolean { return try { - resources.likeV2(userId = userId, body = TwitterReactionRequestBody(tweet_id = id)) + resources.likeV2(userId = accountId, body = TwitterReactionRequestBody(tweet_id = id)) .data?.liked ?: false } catch (e: TwitterApiExceptionV2) { resources.like(id).favorited ?: false } } - override suspend fun unlike(id: String, userId: String): Boolean { + override suspend fun unlike(id: String): Boolean { return try { - resources.unlikeV2(userId = userId, tweetId = id).data?.liked ?: false + resources.unlikeV2(userId = accountId, tweetId = id).data?.liked ?: false } catch (e: TwitterApiExceptionV2) { resources.unlike(id).favorited ?: false } } - override suspend fun retweet(id: String, userId: String): Boolean { + override suspend fun retweet(id: String): Boolean { return try { - resources.retweetV2(userId = userId, body = TwitterReactionRequestBody(tweet_id = id)) + resources.retweetV2(userId = accountId, body = TwitterReactionRequestBody(tweet_id = id)) .data?.retweeted ?: false } catch (e: TwitterApiExceptionV2) { resources.retweet(id).retweeted ?: false } } - override suspend fun unRetweet(id: String, userId: String): Boolean { + override suspend fun unRetweet(id: String): Boolean { return try { - resources.unRetweetV2(userId = userId, tweetId = id) + resources.unRetweetV2(userId = accountId, tweetId = id) .data?.retweeted ?: false } catch (e: TwitterApiExceptionV2) { resources.unretweet(id).retweeted ?: false From ec7914d9c78cac1be5fe8d01e2afe835ed32e334 Mon Sep 17 00:00:00 2001 From: itsMimao Date: Fri, 27 Aug 2021 13:53:37 +0800 Subject: [PATCH 10/14] StatusService return status --- .../twiderex/jobs/status/LikeStatusJob.kt | 14 +++++--- .../twiderex/jobs/status/RetweetStatusJob.kt | 14 +++++--- .../jobs/status/UnRetweetStatusJob.kt | 14 +++++--- .../twiderex/jobs/status/UnlikeStatusJob.kt | 14 +++++--- .../services/mastodon/MastodonService.kt | 20 ++++++----- .../services/microblog/StatusService.kt | 8 ++--- .../services/twitter/TwitterService.kt | 33 ++++++++++++------- 7 files changed, 73 insertions(+), 44 deletions(-) diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt index cca1710ab..bd5c8d9f9 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt @@ -21,8 +21,10 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService +import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult +import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -40,13 +42,15 @@ class LikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val liked = service.like(id = status.statusId) + val newStatus = service.like(id = status.statusId) + .toDbStatusWithReference(accountKey = accountKey) + .toUi(accountKey) return StatusResult( - statusKey = status.statusKey, + statusKey = newStatus.statusKey, accountKey = accountKey, - liked = liked, - retweetCount = status.metrics.retweet, - likeCount = if (liked) status.metrics.like + 1 else status.metrics.like, + liked = true, + retweetCount = newStatus.metrics.retweet, + likeCount = newStatus.metrics.like, ) } diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt index 4032a1b75..aa2f18fb2 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt @@ -21,8 +21,10 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService +import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult +import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -40,13 +42,15 @@ class RetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val retweeted = service.retweet(id = status.statusId) + val newStatus = service.retweet(id = status.statusId) + .toDbStatusWithReference(accountKey = accountKey) + .toUi(accountKey) return StatusResult( - statusKey = status.statusKey, + statusKey = newStatus.statusKey, accountKey = accountKey, - retweeted = retweeted, - retweetCount = if (retweeted) status.metrics.retweet + 1 else status.metrics.retweet, - likeCount = status.metrics.like, + retweeted = true, + retweetCount = newStatus.metrics.retweet, + likeCount = newStatus.metrics.like, ) } override fun fallback( diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt index 582e43fe6..80a2e4a2c 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt @@ -21,8 +21,10 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService +import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult +import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -40,13 +42,15 @@ class UnRetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val retweeted = service.unRetweet(id = status.statusId) + val newStatus = service.unRetweet(id = status.statusId) + .toDbStatusWithReference(accountKey = accountKey) + .toUi(accountKey) return StatusResult( - statusKey = status.statusKey, + statusKey = newStatus.statusKey, accountKey = accountKey, - retweeted = retweeted, - retweetCount = if (retweeted) status.metrics.retweet else status.metrics.retweet - 1, - likeCount = status.metrics.like, + retweeted = false, + retweetCount = newStatus.metrics.retweet, + likeCount = newStatus.metrics.like, ) } override fun fallback( diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt index c0c7ee2b2..738b0be6a 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt @@ -21,8 +21,10 @@ package com.twidere.twiderex.jobs.status import com.twidere.services.microblog.StatusService +import com.twidere.twiderex.db.mapper.toDbStatusWithReference import com.twidere.twiderex.model.MicroBlogKey import com.twidere.twiderex.model.job.StatusResult +import com.twidere.twiderex.model.transform.toUi import com.twidere.twiderex.model.ui.UiStatus import com.twidere.twiderex.notification.InAppNotification import com.twidere.twiderex.repository.AccountRepository @@ -40,13 +42,15 @@ class UnlikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val liked = service.unlike(id = status.statusId) + val newStatus = service.unlike(id = status.statusId) + .toDbStatusWithReference(accountKey = accountKey) + .toUi(accountKey) return StatusResult( - statusKey = status.statusKey, + statusKey = newStatus.statusKey, accountKey = accountKey, - liked = liked, - retweetCount = status.metrics.retweet, - likeCount = if (liked) status.metrics.like else status.metrics.like - 1, + liked = false, + retweetCount = newStatus.metrics.retweet, + likeCount = newStatus.metrics.like, ) } override fun fallback( diff --git a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt index 681c84afa..46109d5fe 100644 --- a/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt +++ b/services/src/main/java/com/twidere/services/mastodon/MastodonService.kt @@ -265,20 +265,24 @@ class MastodonService( max_id = max_id, ) - override suspend fun like(id: String): Boolean { - return resources.favourite(id).favourited ?: false + override suspend fun like(id: String): IStatus { + return resources.favourite(id) } - override suspend fun unlike(id: String): Boolean { - return resources.unfavourite(id).favourited ?: false + override suspend fun unlike(id: String): IStatus { + return resources.unfavourite(id).let { + it.copy(favouritesCount = it.favouritesCount?.let { it - 1 }) + } } - override suspend fun retweet(id: String): Boolean { - return resources.reblog(id).reblogged ?: false + override suspend fun retweet(id: String): IStatus { + return resources.reblog(id) } - override suspend fun unRetweet(id: String): Boolean { - return resources.unreblog(id).reblogged ?: false + override suspend fun unRetweet(id: String): IStatus { + return resources.unreblog(id).let { + it.copy(favouritesCount = it.reblogsCount?.let { it - 1 }) + } } override suspend fun delete(id: String): IStatus { diff --git a/services/src/main/java/com/twidere/services/microblog/StatusService.kt b/services/src/main/java/com/twidere/services/microblog/StatusService.kt index c5ed4e311..ee755fe33 100644 --- a/services/src/main/java/com/twidere/services/microblog/StatusService.kt +++ b/services/src/main/java/com/twidere/services/microblog/StatusService.kt @@ -23,9 +23,9 @@ package com.twidere.services.microblog import com.twidere.services.microblog.model.IStatus interface StatusService { - suspend fun like(id: String): Boolean - suspend fun unlike(id: String): Boolean - suspend fun retweet(id: String): Boolean - suspend fun unRetweet(id: String): Boolean + suspend fun like(id: String): IStatus + suspend fun unlike(id: String): IStatus + suspend fun retweet(id: String): IStatus + suspend fun unRetweet(id: String): IStatus suspend fun delete(id: String): IStatus } diff --git a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt index 183cf1cf1..31aaab8b3 100644 --- a/services/src/main/java/com/twidere/services/twitter/TwitterService.kt +++ b/services/src/main/java/com/twidere/services/twitter/TwitterService.kt @@ -379,38 +379,47 @@ class TwitterService( resources.unfollow(user_id) } - override suspend fun like(id: String): Boolean { + override suspend fun like(id: String): IStatus { return try { resources.likeV2(userId = accountId, body = TwitterReactionRequestBody(tweet_id = id)) - .data?.liked ?: false + .run { + lookupStatus(id) + } } catch (e: TwitterApiExceptionV2) { - resources.like(id).favorited ?: false + resources.like(id) } } - override suspend fun unlike(id: String): Boolean { + override suspend fun unlike(id: String): IStatus { return try { - resources.unlikeV2(userId = accountId, tweetId = id).data?.liked ?: false + resources.unlikeV2(userId = accountId, tweetId = id) + .run { + lookupStatus(id) + } } catch (e: TwitterApiExceptionV2) { - resources.unlike(id).favorited ?: false + resources.unlike(id) } } - override suspend fun retweet(id: String): Boolean { + override suspend fun retweet(id: String): IStatus { return try { resources.retweetV2(userId = accountId, body = TwitterReactionRequestBody(tweet_id = id)) - .data?.retweeted ?: false + .run { + lookupStatus(id) + } } catch (e: TwitterApiExceptionV2) { - resources.retweet(id).retweeted ?: false + resources.retweet(id) } } - override suspend fun unRetweet(id: String): Boolean { + override suspend fun unRetweet(id: String): IStatus { return try { resources.unRetweetV2(userId = accountId, tweetId = id) - .data?.retweeted ?: false + .run { + lookupStatus(id) + } } catch (e: TwitterApiExceptionV2) { - resources.unretweet(id).retweeted ?: false + resources.unretweet(id) } } From ecba838246615841c40e34e7009206f253e84522 Mon Sep 17 00:00:00 2001 From: itsMimao Date: Fri, 27 Aug 2021 13:57:34 +0800 Subject: [PATCH 11/14] reset code fro StatusJobs --- .../com/twidere/twiderex/jobs/status/LikeStatusJob.kt | 6 ++++-- .../com/twidere/twiderex/jobs/status/RetweetStatusJob.kt | 6 ++++-- .../com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt | 6 ++++-- .../com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt index bd5c8d9f9..0adb1dfa4 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/LikeStatusJob.kt @@ -42,9 +42,11 @@ class LikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.like(id = status.statusId) + val newStatus = service.like(status.statusId) .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey) + .toUi(accountKey = accountKey).let { + it.retweet ?: it + } return StatusResult( statusKey = newStatus.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt index aa2f18fb2..fcc25f2dc 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/RetweetStatusJob.kt @@ -42,9 +42,11 @@ class RetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.retweet(id = status.statusId) + val newStatus = service.retweet(status.statusId) .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey) + .toUi(accountKey = accountKey).let { + it.retweet ?: it + } return StatusResult( statusKey = newStatus.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt index 80a2e4a2c..d8f5e35e1 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnRetweetStatusJob.kt @@ -42,9 +42,11 @@ class UnRetweetStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.unRetweet(id = status.statusId) + val newStatus = service.unRetweet(status.statusId) .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey) + .toUi(accountKey = accountKey).let { + it.retweet ?: it + } return StatusResult( statusKey = newStatus.statusKey, accountKey = accountKey, diff --git a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt index 738b0be6a..18835bd3e 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/jobs/status/UnlikeStatusJob.kt @@ -42,9 +42,11 @@ class UnlikeStatusJob( service: StatusService, status: UiStatus ): StatusResult { - val newStatus = service.unlike(id = status.statusId) + val newStatus = service.unlike(status.statusId) .toDbStatusWithReference(accountKey = accountKey) - .toUi(accountKey) + .toUi(accountKey = accountKey).let { + it.retweet ?: it + } return StatusResult( statusKey = newStatus.statusKey, accountKey = accountKey, From 558ee6349671ab18712c85f2ab9412f219027247 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Mon, 30 Aug 2021 14:58:46 +0800 Subject: [PATCH 12/14] fix ConnectivityManager crash --- .../com/twidere/twiderex/TwidereXActivity.kt | 43 +++--------- .../utils/IsActiveNetworkMeteredLiveData.kt | 66 +++++++++++++++++++ 2 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 app/src/main/kotlin/com/twidere/twiderex/utils/IsActiveNetworkMeteredLiveData.kt diff --git a/app/src/main/kotlin/com/twidere/twiderex/TwidereXActivity.kt b/app/src/main/kotlin/com/twidere/twiderex/TwidereXActivity.kt index c2f51c77e..14f37ea7a 100644 --- a/app/src/main/kotlin/com/twidere/twiderex/TwidereXActivity.kt +++ b/app/src/main/kotlin/com/twidere/twiderex/TwidereXActivity.kt @@ -22,9 +22,6 @@ package com.twidere.twiderex import android.content.Intent import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.net.NetworkRequest import android.net.Uri import android.os.Bundle import android.view.WindowManager @@ -55,7 +52,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.core.net.ConnectivityManagerCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.lifecycle.lifecycleScope @@ -78,6 +74,7 @@ import com.twidere.twiderex.ui.LocalIsActiveNetworkMetered import com.twidere.twiderex.ui.LocalWindow import com.twidere.twiderex.ui.LocalWindowInsetsController import com.twidere.twiderex.utils.CustomTabSignInChannel +import com.twidere.twiderex.utils.IsActiveNetworkMeteredLiveData import com.twidere.twiderex.utils.LocalPlatformResolver import com.twidere.twiderex.utils.PlatformResolver import com.twidere.twiderex.viewmodel.ActiveAccountViewModel @@ -92,19 +89,6 @@ class TwidereXActivity : ComponentActivity() { private val navController by lazy { NavController() } - private val isActiveNetworkMetered = MutableStateFlow(false) - private val networkCallback by lazy { - object : ConnectivityManager.NetworkCallback() { - override fun onCapabilitiesChanged( - network: Network, - networkCapabilities: NetworkCapabilities - ) { - isActiveNetworkMetered.value = ConnectivityManagerCompat.isActiveNetworkMetered( - connectivityManager - ) - } - } - } @Inject lateinit var viewModelHolder: TwidereXActivityAssistedViewModelHolder @@ -124,15 +108,19 @@ class TwidereXActivity : ComponentActivity() { @Inject lateinit var platformResolver: PlatformResolver + private val isActiveNetworkMetered = MutableStateFlow(false) + private val isActiveNetworkMeteredLiveData by lazy { + IsActiveNetworkMeteredLiveData(connectivityManager = connectivityManager) + } + @OptIn(ExperimentalAnimationApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - isActiveNetworkMetered.value = ConnectivityManagerCompat.isActiveNetworkMetered( - connectivityManager - ) - WindowCompat.setDecorFitsSystemWindows(window, false) window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + isActiveNetworkMeteredLiveData.observe(this) { + isActiveNetworkMetered.value = it + } setContent { var showSplash by rememberSaveable { mutableStateOf(true) } LaunchedEffect(Unit) { @@ -230,19 +218,6 @@ class TwidereXActivity : ComponentActivity() { } } - override fun onStart() { - super.onStart() - connectivityManager.registerNetworkCallback( - NetworkRequest.Builder().build(), - networkCallback, - ) - } - - override fun onStop() { - super.onStop() - connectivityManager.unregisterNetworkCallback(networkCallback) - } - override fun onResume() { super.onResume() lifecycleScope.launchWhenResumed { diff --git a/app/src/main/kotlin/com/twidere/twiderex/utils/IsActiveNetworkMeteredLiveData.kt b/app/src/main/kotlin/com/twidere/twiderex/utils/IsActiveNetworkMeteredLiveData.kt new file mode 100644 index 000000000..88b0e7fec --- /dev/null +++ b/app/src/main/kotlin/com/twidere/twiderex/utils/IsActiveNetworkMeteredLiveData.kt @@ -0,0 +1,66 @@ +/* + * Twidere X + * + * Copyright (C) 2020-2021 Tlaster + * + * This file is part of Twidere X. + * + * Twidere X is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Twidere X is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Twidere X. If not, see . + */ +package com.twidere.twiderex.utils + +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import androidx.core.net.ConnectivityManagerCompat +import androidx.lifecycle.LiveData + +class IsActiveNetworkMeteredLiveData( + private val connectivityManager: ConnectivityManager, +) : LiveData() { + private val request = NetworkRequest.Builder().build() + private val networkCallback by lazy { + object : ConnectivityManager.NetworkCallback() { + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + updateValue() + } + } + } + + private fun updateValue() { + postValue( + ConnectivityManagerCompat.isActiveNetworkMetered( + connectivityManager + ) + ) + } + + override fun onActive() { + super.onActive() + updateValue() + connectivityManager.registerNetworkCallback( + request, + networkCallback, + ) + } + + override fun onInactive() { + super.onInactive() + connectivityManager.unregisterNetworkCallback(networkCallback) + } +} From 91867baa4a5a78b16884bff5f8889a51aac02d03 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Tue, 31 Aug 2021 16:43:08 +0800 Subject: [PATCH 13/14] crowdin sync --- .../res-localized/values-el-rGR/strings.xml | 54 ++++++++++++++ .../res-localized/values-fr-rFR/strings.xml | 74 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 +- localization | 2 +- 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res-localized/values-el-rGR/strings.xml diff --git a/app/src/main/res-localized/values-el-rGR/strings.xml b/app/src/main/res-localized/values-el-rGR/strings.xml new file mode 100644 index 000000000..468886d99 --- /dev/null +++ b/app/src/main/res-localized/values-el-rGR/strings.xml @@ -0,0 +1,54 @@ + + %s αναιρέθηκε η σίγαση + Κατάργηση ακολούθησης χρήστη %s; + Τα πολυμέσα θα κοινοποιηθούν μετά την ολοκλήρωση της λήψης + Αποτυχία κατάργησης Ακολούθησης + Παρακαλούμε προσπαθήστε ξανά + Tweet Στάλθηκε + Πάρα Πολλά Αιτήματα + Ακολούθηση Επιτυχής + Αποτυχία ακολούθησης + Παρακαλούμε προσπαθήστε ξανά + Κανόνες Twitter + Ο Λογαριασμός έχει Ανασταλεί + Το Twitter αναστέλλει λογαριασμούς που παραβιάζουν το %s + Αποτυχία αποθήκευσης των πολυμέσων + Παρακαλούμε προσπαθήστε ξανά + %s έχει αποκλειστεί + Ακύρωση αιτήματος ακολούθησης για %s; + Παρακαλούμε προσπαθήστε ξανά + Αποτυχία Αποθήκευσης Φωτογραφίας + Παρακαλούμε προσπαθήστε ξανά + Δεν Βρέθηκαν Tweets + Αποθήκευση πολυμέσων + %s έχει γίνει σίγαση + Η Άδεια Απορρίφθηκε + Λυπούμαστε, δεν είστε εξουσιοδοτημένοι + Αποτυχία αναίρεσης σίγασης %s + Παρακαλούμε προσπαθήστε ξανά + Υπέρβαση Όριου Αξιολόγησης + Φτάσατε στο όριο χρήσης του Twitter API + Αποτυχία φόρτωσης + Παρακαλούμε προσπαθήστε ξανά + Η Άδεια Απορρίφθηκε + Έχετε αποκλειστεί από την ακολούθηση αυτού του λογαριασμού κατόπιν αιτήματος του χρήστη + Τα πολυμέσα αποθηκεύτηκαν + Το Tweet Διαγράφηκε + Το Αίτημα Ακολούθησης Στάλθηκε + Αποτυχία σίγασης %s + Παρακαλούμε προσπαθήστε ξανά + Γίνεται αποστολή tweet + Η Διαγραφή του Tweet Απέτυχε + Παρακαλούμε προσπαθήστε ξανά + Η Φωτογραφία Αποθηκεύτηκε + Προσωρινά Κλειδωμένος Λογαριασμός + Άνοιγμα του Twitter για ξεκλείδωμα + Αποτυχία αποκλεισμού %s + Παρακαλούμε προσπαθήστε ξανά + Αποτυχία Tweet + Παρακαλούμε προσπαθήστε ξανά + Κατάργηση της Ακολούθησης Επιτυχής + Παρακαλούμε προσπαθήστε ξανά + Παρακαλούμε προσπαθήστε ξανά + Η Άδεια Απορρίφθηκε + \ No newline at end of file diff --git a/app/src/main/res-localized/values-fr-rFR/strings.xml b/app/src/main/res-localized/values-fr-rFR/strings.xml index 65a3923e2..253c0a4d2 100644 --- a/app/src/main/res-localized/values-fr-rFR/strings.xml +++ b/app/src/main/res-localized/values-fr-rFR/strings.xml @@ -1,33 +1,77 @@ + Ne plus suivre l\'utilisateur %s? + Le média sera partagé une fois le téléchargement terminé + Échec de l\'annulation de l\'abonnement Merci de réessayer Tweet envoyé + Échec de connexion + L’adresse du serveur est incorrecte. + Trop de Requêtes + Abonnement réussi + Échec de l\'abonnement Merci de réessayer + %s a été signalé pour spam Règles de Twitter + Compte suspendu + Twitter suspend les comptes qui violent les %s + Impossible d\'enregistrer le média Merci de réessayer %s a été bloqué·e + Annuler la demande de suivi pour %s? + Échec du signalement de %s Merci de réessayer + %s a été bloqué et signalé pour spam + Échec de l\'enregistrement de la photo Merci de réessayer Aucun tweet trouvé + Enregistrement du média + Échec de connexion + Délai de connexion expiré. %s a été débloqué·e + Permission refusée + Désolé, vous n\'êtes pas autorisé + Envoi du message + Échec de l\'envoi du message Merci de réessayer + Limite d\'utilisation de l\'API Twitter atteinte + Échec du chargement Merci de réessayer + Permission refusée + Vous avez été empêché de suivre ce compte à la demande de l\'utilisateur + Média enregistré + Tweet supprimé + Demande de suivi envoyée Merci de réessayer Envoi du tweet + La suppression du Tweet a échoué Merci de réessayer + Photo Enregistrée Compte verrouillé temporairement Ouvrez Twitter pour le déverrouiller Échec du blocage de %s Merci de réessayer + Echec de l\'envoi du tweet Merci de réessayer + Désabonnement réussi + Impossible de signaler et de bloquer %s Merci de réessayer Merci de réessayer Messages Messages directs Interactions + %s a boosté votre pouet + %s a demandé à vous suivre + Votre sondage est terminé + %s vous a mentionné + Nouveau message %s vous a envoyé un message + Un sondage auquel vous avez participé est maintenant terminé + %s a aimé votre pouet + %s vous suit + %s vient de poster Bloquer %s abonné·e - abonné·e·s + abonnés %s ne vous suit pas Vous suit Mettre en sourdine %s @@ -38,12 +82,15 @@ En attente Signaler Mettre en sourdine + Rétablir le son Bloquer S’abonner Se désabonner - Abonné·e·s + Abonnés + Listé Abonnements Charger plus + Galerie photo Ajouter Annuler Aperçu @@ -69,15 +116,22 @@ Partager le lien Supprimer le tweet Citation + Retweeter Copier le texte Voter Copier le lien + %s citation + %s citations + %s a retweeté + %s a aimé %s membre %s membres %s photo %s photos %s tweet %s tweets + %s réponse + %s réponses %s liste %s listes Plus @@ -92,6 +146,7 @@ Fait Emplacement Média + Retweeter Réponse Taille du texte Sauvegarder @@ -124,9 +179,10 @@ Supprimer le compte Comptes Masquer + Rechercher des tweets ou des utilisateurs Média Tweets - Utilisateur·rice·s + Utilisateurs Mot clé Recherche Afficher plus @@ -156,7 +212,9 @@ Bonjour !\nConnectez-vous pour commencer. Se connecter avec Twitter Se connecter avec une clé Twitter personnalisée + L\'accès à l’API v2 Twitter est requis. Authentification + J\'aimes Agencement Afficher la notification Comptes @@ -216,6 +274,8 @@ Exclure les réponses Masquer la réponse Moi + Permission refusée + Vous avez été empêché de consulter le profil de cet utilisateur. Gestion des comptes Se connecter Brouillons @@ -223,7 +283,8 @@ Modifier le brouillon Chercher des utilisateur·rice·s Signet - Abonné·e·s + Abonnés + Listé Enregistrer le brouillon Enregistrer le brouillon ? Répondre à … @@ -252,13 +313,18 @@ Mentions Abonnements Fil d’actualité + [Photo] Rechercher des personnes + Trouver des gens + L\'envoi de message a échoué + Copier le texte du message Messages 1 citation %d citations 1 retweet %d retweets 1 j’aime + %d J\'aimes Pouet Tweet 1 réponse diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bff316365..940f4ccde 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -362,10 +362,10 @@ Search people Find people Send message failed - The Current account does not support direct messages Copy message text Delete message for you Messages + The Current account does not support direct messages Search hashtag 1 Quote %d Quotes diff --git a/localization b/localization index 32a49017b..9490971a1 160000 --- a/localization +++ b/localization @@ -1 +1 @@ -Subproject commit 32a49017b010fe454b6829046c6394158750b84e +Subproject commit 9490971a1e0429701b15181dd3a1aa890a29a912 From 05cbb8a5b88d3075f68586a88716016920ac4c92 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Tue, 31 Aug 2021 17:34:07 +0800 Subject: [PATCH 14/14] version 1.5.1 --- buildSrc/src/main/kotlin/Package.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/Package.kt b/buildSrc/src/main/kotlin/Package.kt index 320295dcc..9558bebcb 100644 --- a/buildSrc/src/main/kotlin/Package.kt +++ b/buildSrc/src/main/kotlin/Package.kt @@ -2,6 +2,6 @@ object Package { const val group = "com.twidere" const val name = "TwidereX" const val id = "$group.twiderex" - const val versionName = "1.5.1-beta01" - const val versionCode = 54 + const val versionName = "1.5.1" + const val versionCode = 55 }