diff --git a/app/src/fdroid/kotlin/app/pachli/di/UpdateCheckModule.kt b/app/src/fdroid/kotlin/app/pachli/di/UpdateCheckModule.kt index 774ea438a..6a48f09fa 100644 --- a/app/src/fdroid/kotlin/app/pachli/di/UpdateCheckModule.kt +++ b/app/src/fdroid/kotlin/app/pachli/di/UpdateCheckModule.kt @@ -24,11 +24,11 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.create -import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module @@ -37,7 +37,7 @@ object UpdateCheckModule { @Singleton fun providesFdroidService( httpClient: OkHttpClient, - gson: Gson + gson: Gson, ): FdroidService = Retrofit.Builder() .baseUrl("https://f-droid.org") .client(httpClient) diff --git a/app/src/fdroid/kotlin/app/pachli/updatecheck/FdroidService.kt b/app/src/fdroid/kotlin/app/pachli/updatecheck/FdroidService.kt index a243b2c76..da8b78876 100644 --- a/app/src/fdroid/kotlin/app/pachli/updatecheck/FdroidService.kt +++ b/app/src/fdroid/kotlin/app/pachli/updatecheck/FdroidService.kt @@ -25,19 +25,19 @@ import retrofit2.http.Path @Keep data class FdroidPackageVersion( val versionName: String, - val versionCode: Int + val versionCode: Int, ) @Keep data class FdroidPackage( val packageName: String, val suggestedVersionCode: Int, - val packages: List + val packages: List, ) interface FdroidService { @GET("/api/v1/packages/{package}") suspend fun getPackage( - @Path("package") pkg: String + @Path("package") pkg: String, ): NetworkResult } diff --git a/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt index 2d433380f..779fa759e 100644 --- a/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -27,7 +27,7 @@ import javax.inject.Singleton @Singleton class UpdateCheck @Inject constructor( sharedPreferencesRepository: SharedPreferencesRepository, - private val fdroidService: FdroidService + private val fdroidService: FdroidService, ) : UpdateCheckBase(sharedPreferencesRepository) { override val updateIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("market://details?id=${BuildConfig.APPLICATION_ID}") diff --git a/app/src/github/kotlin/app/pachli/di/UpdateCheckModule.kt b/app/src/github/kotlin/app/pachli/di/UpdateCheckModule.kt index 428a8371b..f95256f4c 100644 --- a/app/src/github/kotlin/app/pachli/di/UpdateCheckModule.kt +++ b/app/src/github/kotlin/app/pachli/di/UpdateCheckModule.kt @@ -24,11 +24,11 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.create -import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module @@ -37,7 +37,7 @@ object UpdateCheckModule { @Singleton fun providesGitHubService( httpClient: OkHttpClient, - gson: Gson + gson: Gson, ): GitHubService = Retrofit.Builder() .baseUrl("https://api.github.com") .client(httpClient) diff --git a/app/src/github/kotlin/app/pachli/updatecheck/GithubService.kt b/app/src/github/kotlin/app/pachli/updatecheck/GithubService.kt index 516a92882..9c94a1c3a 100644 --- a/app/src/github/kotlin/app/pachli/updatecheck/GithubService.kt +++ b/app/src/github/kotlin/app/pachli/updatecheck/GithubService.kt @@ -29,20 +29,20 @@ data class GitHubReleaseAsset( val name: String, /** MIME content type for the asset, e.g., "application/vnd.android.package-archive" */ - @SerializedName("content_type") val contentType: String + @SerializedName("content_type") val contentType: String, ) @Keep data class GitHubRelease( /** URL for the release's web page */ @SerializedName("html_url") val htmlUrl: String, - val assets: List + val assets: List, ) interface GitHubService { @GET("/repos/{owner}/{repo}/releases/latest") suspend fun getLatestRelease( @Path("owner") owner: String, - @Path("repo") repo: String + @Path("repo") repo: String, ): NetworkResult } diff --git a/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt index 86dda2292..7c5ba3ecd 100644 --- a/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -24,7 +24,7 @@ import javax.inject.Inject class UpdateCheck @Inject constructor( sharedPreferencesRepository: SharedPreferencesRepository, - private val gitHubService: GitHubService + private val gitHubService: GitHubService, ) : UpdateCheckBase(sharedPreferencesRepository) { private val versionCodeExtractor = """(\d+)\.apk""".toRegex() diff --git a/app/src/google/kotlin/app/pachli/di/UpdateCheckModule.kt b/app/src/google/kotlin/app/pachli/di/UpdateCheckModule.kt index 3b4f30658..e92394148 100644 --- a/app/src/google/kotlin/app/pachli/di/UpdateCheckModule.kt +++ b/app/src/google/kotlin/app/pachli/di/UpdateCheckModule.kt @@ -33,6 +33,6 @@ object UpdateCheckModule { @Provides @Singleton fun providesAppUpdateManager( - @ApplicationContext context: Context + @ApplicationContext context: Context, ): AppUpdateManager = AppUpdateManagerFactory.create(context) } diff --git a/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt index f0816e227..41ae9e3a4 100644 --- a/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -22,16 +22,17 @@ import android.net.Uri import app.pachli.BuildConfig import app.pachli.core.preferences.SharedPreferencesRepository import com.google.android.play.core.appupdate.AppUpdateManager -import kotlinx.coroutines.suspendCancellableCoroutine import javax.inject.Inject +import kotlinx.coroutines.suspendCancellableCoroutine class UpdateCheck @Inject constructor( sharedPreferencesRepository: SharedPreferencesRepository, - private val appUpdateManager: AppUpdateManager + private val appUpdateManager: AppUpdateManager, ) : UpdateCheckBase(sharedPreferencesRepository) { override val updateIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse( - "https://play.google.com/store/apps/details?id=${BuildConfig.APPLICATION_ID}") + "https://play.google.com/store/apps/details?id=${BuildConfig.APPLICATION_ID}", + ) setPackage("com.android.vending") } diff --git a/core/accounts/src/main/kotlin/app/pachli/core/accounts/AccountManager.kt b/core/accounts/src/main/kotlin/app/pachli/core/accounts/AccountManager.kt index c538b0f0f..3c5f14f7f 100644 --- a/core/accounts/src/main/kotlin/app/pachli/core/accounts/AccountManager.kt +++ b/core/accounts/src/main/kotlin/app/pachli/core/accounts/AccountManager.kt @@ -27,14 +27,14 @@ import app.pachli.core.network.model.Status import app.pachli.core.network.retrofit.InstanceSwitchAuthInterceptor import app.pachli.core.preferences.PrefKeys import app.pachli.core.preferences.SharedPreferencesRepository +import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import timber.log.Timber -import java.util.Locale -import javax.inject.Inject -import javax.inject.Singleton @Singleton class AccountManager @Inject constructor( @@ -54,7 +54,7 @@ class AccountManager @Inject constructor( instanceSwitchAuthInterceptor.credentials = value?.let { InstanceSwitchAuthInterceptor.Credentials( accessToken = it.accessToken, - domain = it.domain + domain = it.domain, ) } externalScope.launch { _activeAccountFlow.emit(value) } diff --git a/core/common/src/main/kotlin/app/pachli/core/common/di/CoroutineScopeModule.kt b/core/common/src/main/kotlin/app/pachli/core/common/di/CoroutineScopeModule.kt index 583b02a96..2eb884738 100644 --- a/core/common/src/main/kotlin/app/pachli/core/common/di/CoroutineScopeModule.kt +++ b/core/common/src/main/kotlin/app/pachli/core/common/di/CoroutineScopeModule.kt @@ -21,10 +21,10 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Qualifier import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import javax.inject.Qualifier /** * Scope for potentially long-running tasks that should outlive the viewmodel that diff --git a/core/common/src/test/kotlin/app/pachli/core/common/util/AbsoluteTimeFormatterTest.kt b/core/common/src/test/kotlin/app/pachli/core/common/util/AbsoluteTimeFormatterTest.kt index f0e64d875..a38c91443 100644 --- a/core/common/src/test/kotlin/app/pachli/core/common/util/AbsoluteTimeFormatterTest.kt +++ b/core/common/src/test/kotlin/app/pachli/core/common/util/AbsoluteTimeFormatterTest.kt @@ -17,14 +17,14 @@ package app.pachli.core.common.util -import org.junit.AfterClass -import org.junit.Assert.assertEquals -import org.junit.BeforeClass -import org.junit.Test import java.time.Instant import java.util.Date import java.util.Locale import java.util.TimeZone +import org.junit.AfterClass +import org.junit.Assert.assertEquals +import org.junit.BeforeClass +import org.junit.Test class AbsoluteTimeFormatterTest { companion object { diff --git a/core/common/src/test/kotlin/app/pachli/core/common/util/NumberUtilsTest.kt b/core/common/src/test/kotlin/app/pachli/core/common/util/NumberUtilsTest.kt index bb2e2119e..d23ba51a6 100644 --- a/core/common/src/test/kotlin/app/pachli/core/common/util/NumberUtilsTest.kt +++ b/core/common/src/test/kotlin/app/pachli/core/common/util/NumberUtilsTest.kt @@ -17,14 +17,14 @@ package app.pachli.core.common.util +import java.util.Locale +import kotlin.math.pow import org.junit.AfterClass import org.junit.Assert import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized -import java.util.Locale -import kotlin.math.pow @RunWith(Parameterized::class) class NumberUtilsTest(private val input: Long, private val want: String) { diff --git a/core/database/src/main/kotlin/app/pachli/core/database/Converters.kt b/core/database/src/main/kotlin/app/pachli/core/database/Converters.kt index 1a0f5bf4d..7cfdd0bd8 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/Converters.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/Converters.kt @@ -69,7 +69,8 @@ class Converters @Inject constructor( return str?.split(";") ?.map { val data = it.split(":") - TabData.from(data[0], data.drop(1).map { s -> URLDecoder.decode(s, "UTF-8") }) } + TabData.from(data[0], data.drop(1).map { s -> URLDecoder.decode(s, "UTF-8") }) + } } @TypeConverter diff --git a/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt b/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt index e6a7a5fe4..0fd239d31 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt @@ -269,8 +269,14 @@ WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = WHERE timelineUserId = :accountId AND serverId IN (:serverIds)""", ) - abstract suspend fun getStatusViewData(accountId: Long, serverIds: List): - Map<@MapColumn(columnName = "serverId") String, StatusViewDataEntity> + abstract suspend fun getStatusViewData( + accountId: Long, + serverIds: List, + ): Map< + @MapColumn(columnName = "serverId") + String, + StatusViewDataEntity, + > @Query( """UPDATE TimelineStatusEntity SET pinned = :pinned diff --git a/core/database/src/main/kotlin/app/pachli/core/database/dao/TranslatedStatusDao.kt b/core/database/src/main/kotlin/app/pachli/core/database/dao/TranslatedStatusDao.kt index 4f9daa956..22045a1f9 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/dao/TranslatedStatusDao.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/dao/TranslatedStatusDao.kt @@ -37,6 +37,12 @@ interface TranslatedStatusDao { WHERE timelineUserId = :accountId AND serverId IN (:serverIds)""", ) - suspend fun getTranslations(accountId: Long, serverIds: List): - Map<@MapColumn(columnName = "serverId") String, TranslatedStatusEntity> + suspend fun getTranslations( + accountId: Long, + serverIds: List, + ): Map< + @MapColumn(columnName = "serverId") + String, + TranslatedStatusEntity, + > } diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/AccountEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/AccountEntity.kt index a8a630f49..acb8f8d2b 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/AccountEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/AccountEntity.kt @@ -39,8 +39,10 @@ data class AccountEntity( @field:PrimaryKey(autoGenerate = true) var id: Long, val domain: String, var accessToken: String, - var clientId: String?, // nullable for backward compatibility - var clientSecret: String?, // nullable for backward compatibility + // nullable for backward compatibility + var clientId: String?, + // nullable for backward compatibility + var clientSecret: String?, var isActive: Boolean, var accountId: String = "", var username: String = "", diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/DraftEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/DraftEntity.kt index 1d75b2636..24cab9adf 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/DraftEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/DraftEntity.kt @@ -65,6 +65,8 @@ data class DraftAttachment( get() = uriString.toUri() enum class Type { - IMAGE, VIDEO, AUDIO; + IMAGE, + VIDEO, + AUDIO, } } diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/TabData.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/TabData.kt index 33dcac698..be5bebd78 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/TabData.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/TabData.kt @@ -33,7 +33,7 @@ enum class TabKind(val repr: String) { TRENDING_STATUSES("Trending_Statuses"), HASHTAG("Hashtag"), LIST("List"), - BOOKMARKS("Bookmarks") + BOOKMARKS("Bookmarks"), } /** this would be a good case for a sealed class, but that does not work nice with Room */ @@ -46,7 +46,7 @@ data class TabData(val kind: TabKind, val arguments: List = emptyList()) fun from(kind: String, arguments: List = emptyList()): TabData { // Work around for https://github.com/pachli/pachli-android/issues/329, // as the Trending... kinds may have been serialised without the `_` - return when(kind) { + return when (kind) { "TrendingTags" -> TabData(TabKind.TRENDING_TAGS, arguments) "TrendingLinks" -> TabData(TabKind.TRENDING_LINKS, arguments) "TrendingStatuses" -> TabData(TabKind.TRENDING_STATUSES, arguments) @@ -60,5 +60,5 @@ fun defaultTabs() = listOf( TabData.from(TabKind.HOME), TabData.from(TabKind.NOTIFICATIONS), TabData.from(TabKind.LOCAL), - TabData.from(TabKind.DIRECT) + TabData.from(TabKind.DIRECT), ) diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt index 789b526d9..5b51b53d3 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt @@ -64,7 +64,8 @@ import java.util.Date ) @TypeConverters(Converters::class) data class TimelineStatusEntity( - val serverId: String, // id never flips: we need it for sorting so it's a real id + // id never flips: we need it for sorting so it's a real id + val serverId: String, val url: String?, // our local id for the logged in user in case there are multiple accounts per instance val timelineUserId: Long, @@ -88,7 +89,8 @@ data class TimelineStatusEntity( val mentions: String?, val tags: String?, val application: String?, - val reblogServerId: String?, // if it has a reblogged status, it's id is stored here + // if it has a reblogged status, it's id is stored here + val reblogServerId: String?, val reblogAccountId: String?, val poll: String?, val muted: Boolean?, @@ -222,8 +224,9 @@ data class TimelineStatusWithAccount( val status: TimelineStatusEntity, @Embedded(prefix = "a_") val account: TimelineAccountEntity, + // null when no reblog @Embedded(prefix = "rb_") - val reblogAccount: TimelineAccountEntity? = null, // null when no reblog + val reblogAccount: TimelineAccountEntity? = null, @Embedded(prefix = "svd_") val viewData: StatusViewDataEntity? = null, @Embedded(prefix = "t_") @@ -286,13 +289,15 @@ data class TimelineStatusWithAccount( return if (reblog != null) { Status( id = status.serverId, - url = null, // no url for reblogs + // no url for reblogs + url = null, account = reblogAccount!!.toTimelineAccount(gson), inReplyToId = null, inReplyToAccountId = null, reblog = reblog, content = "", - createdAt = Date(status.createdAt), // lie but whatever? + // lie but whatever? + createdAt = Date(status.createdAt), editedAt = null, emojis = listOf(), reblogsCount = 0, diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt index 5de93971c..265301ba5 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt @@ -44,26 +44,26 @@ data class TranslatedStatusEntity( /** The translated text of the status (HTML), equivalent to [Status.content] */ val content: String, + // Not documented, see https://github.com/mastodon/documentation/issues/1248 /** * The translated spoiler text of the status (text), if it exists, equivalent to * [app.pachli.core.network.model.Status.spoilerText] */ - // Not documented, see https://github.com/mastodon/documentation/issues/1248 val spoilerText: String, + // Not documented, see https://github.com/mastodon/documentation/issues/1248 /** * The translated poll (if it exists). Does not contain all the poll data, only the * translated text. Vote counts and other metadata has to be determined from the original * poll object. */ - // Not documented, see https://github.com/mastodon/documentation/issues/1248 val poll: TranslatedPoll?, + // Not documented, see https://github.com/mastodon/documentation/issues/1248 /** * Translated descriptions for media attachments, if any were attached. Other metadata has * to be determined from the original attachment. */ - // Not documented, see https://github.com/mastodon/documentation/issues/1248 val attachments: List, /** The service that provided the machine translation */ diff --git a/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt b/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt index bf59cccbc..7cca8ad93 100644 --- a/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt +++ b/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt @@ -26,13 +26,13 @@ import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.network.model.Status import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest +import javax.inject.Inject import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import javax.inject.Inject @HiltAndroidTest @RunWith(AndroidJUnit4::class) diff --git a/core/navigation/src/main/kotlin/app/pachli/core/navigation/Navigation.kt b/core/navigation/src/main/kotlin/app/pachli/core/navigation/Navigation.kt index 48bfd3b32..05d2ac189 100644 --- a/core/navigation/src/main/kotlin/app/pachli/core/navigation/Navigation.kt +++ b/core/navigation/src/main/kotlin/app/pachli/core/navigation/Navigation.kt @@ -288,8 +288,10 @@ class ReportActivityIntent(context: Context, accountId: String, userName: String /** @return the `accountId` passed to this intent */ fun getAccountId(intent: Intent) = intent.getStringExtra(EXTRA_ACCOUNT_ID)!! + /** @return the `userName` passed to this intent */ fun getAccountUserName(intent: Intent) = intent.getStringExtra(EXTRA_ACCOUNT_USERNAME)!! + /** @return the `statusId` passed to this intent, or null */ fun getStatusId(intent: Intent) = intent.getStringExtra(EXTRA_STATUS_ID) } @@ -298,7 +300,7 @@ class ReportActivityIntent(context: Context, accountId: String, userName: String /** * Use one of [bookmarks], [favourites], [hashtag], or [list] to construct. */ -class StatusListActivityIntent private constructor (context: Context) : Intent() { +class StatusListActivityIntent private constructor(context: Context) : Intent() { init { setClassName(context, "app.pachli${QuadrantConstants.STATUS_LIST_ACTIVITY}") } @@ -412,71 +414,104 @@ class ViewThreadActivityIntent(context: Context, statusId: String, statusUrl: St /** @return the `statusId` passed to this intent */ fun getStatusId(intent: Intent) = intent.getStringExtra(EXTRA_STATUS_ID)!! + /** @return the `statusUrl` passed to this intent, or null */ fun getUrl(intent: Intent) = intent.getStringExtra(EXTRA_STATUS_URL) } } class AboutActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.ABOUT_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.ABOUT_ACTIVITY}") + } } class AnnouncementsActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.ANNOUNCEMENTS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.ANNOUNCEMENTS_ACTIVITY}") + } } class DraftsActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.DRAFTS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.DRAFTS_ACTIVITY}") + } } class EditProfileActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.EDIT_PROFILE_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.EDIT_PROFILE_ACTIVITY}") + } } class FiltersActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.FILTERS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.FILTERS_ACTIVITY}") + } } class FollowedTagsActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.FOLLOWED_TAGS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.FOLLOWED_TAGS_ACTIVITY}") + } } class InstanceListActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.INSTANCE_LIST_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.INSTANCE_LIST_ACTIVITY}") + } } class LicenseActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.LICENSE_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.LICENSE_ACTIVITY}") + } } class ListActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.LISTS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.LISTS_ACTIVITY}") + } } class LoginWebViewActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.LOGIN_WEB_VIEW_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.LOGIN_WEB_VIEW_ACTIVITY}") + } } class MainActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.MAIN_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.MAIN_ACTIVITY}") + } } class PrivacyPolicyActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.PRIVACY_POLICY_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.PRIVACY_POLICY_ACTIVITY}") + } } class ScheduledStatusActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.SCHEDULED_STATUS_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.SCHEDULED_STATUS_ACTIVITY}") + } } class SearchActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.SEARCH_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.SEARCH_ACTIVITY}") + } } class TabPreferenceActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.TAB_PREFERENCE_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.TAB_PREFERENCE_ACTIVITY}") + } } class TrendingActivityIntent(context: Context) : Intent() { - init { setClassName(context, "app.pachli${QuadrantConstants.TRENDING_ACTIVITY}") } + init { + setClassName(context, "app.pachli${QuadrantConstants.TRENDING_ACTIVITY}") + } } diff --git a/core/network/src/main/kotlin/app/pachli/core/network/di/MastodonApiModule.kt b/core/network/src/main/kotlin/app/pachli/core/network/di/MastodonApiModule.kt index 043f64825..fb84b5751 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/di/MastodonApiModule.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/di/MastodonApiModule.kt @@ -22,9 +22,9 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton import retrofit2.Retrofit import retrofit2.create -import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module diff --git a/core/network/src/main/kotlin/app/pachli/core/network/di/NetworkModule.kt b/core/network/src/main/kotlin/app/pachli/core/network/di/NetworkModule.kt index 2f47759ec..348f5c7e4 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/di/NetworkModule.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/di/NetworkModule.kt @@ -39,6 +39,12 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import java.net.IDN +import java.net.InetSocketAddress +import java.net.Proxy +import java.util.Date +import java.util.concurrent.TimeUnit +import javax.inject.Singleton import okhttp3.Cache import okhttp3.OkHttp import okhttp3.OkHttpClient @@ -47,12 +53,6 @@ import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.create import timber.log.Timber -import java.net.IDN -import java.net.InetSocketAddress -import java.net.Proxy -import java.util.Date -import java.util.concurrent.TimeUnit -import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module diff --git a/core/network/src/main/kotlin/app/pachli/core/network/json/Iso8601Utils.kt b/core/network/src/main/kotlin/app/pachli/core/network/json/Iso8601Utils.kt index 0176eae78..b8b8e1091 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/json/Iso8601Utils.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/json/Iso8601Utils.kt @@ -99,19 +99,40 @@ internal fun String.parseIsoDate(): Date { var offset = 0 // extract year - val year = parseInt(this, offset, 4.let { offset += it; offset }) + val year = parseInt( + this, + offset, + 4.let { + offset += it + offset + }, + ) if (checkOffset(this, offset, '-')) { offset += 1 } // extract month - val month = parseInt(this, offset, 2.let { offset += it; offset }) + val month = parseInt( + this, + offset, + 2.let { + offset += it + offset + }, + ) if (checkOffset(this, offset, '-')) { offset += 1 } // extract day - val day = parseInt(this, offset, 2.let { offset += it; offset }) + val day = parseInt( + this, + offset, + 2.let { + offset += it + offset + }, + ) // default time value var hour = 0 var minutes = 0 @@ -126,11 +147,27 @@ internal fun String.parseIsoDate(): Date { } if (hasT) { // extract hours, minutes, seconds and milliseconds - hour = parseInt(this, 1.let { offset += it; offset }, 2.let { offset += it; offset }) + hour = parseInt( + this, + 1.let { + offset += it + offset + }, + 2.let { + offset += it + offset + }, + ) if (checkOffset(this, offset, ':')) { offset += 1 } - minutes = parseInt(this, offset, 2.let { offset += it; offset }) + minutes = parseInt( + this, offset, + 2.let { + offset += it + offset + }, + ) if (checkOffset(this, offset, ':')) { offset += 1 } @@ -138,7 +175,13 @@ internal fun String.parseIsoDate(): Date { if (this.length > offset) { val c = this[offset] if (c != 'Z' && c != '+' && c != '-') { - seconds = parseInt(this, offset, 2.let { offset += it; offset }) + seconds = parseInt( + this, offset, + 2.let { + offset += it + offset + }, + ) if (seconds in 60..62) seconds = 59 // truncate up to 3 leap seconds // milliseconds can be optional in the format if (checkOffset(this, offset, '.')) { diff --git a/core/network/src/main/kotlin/app/pachli/core/network/json/Rfc3339DateJsonAdapter.kt b/core/network/src/main/kotlin/app/pachli/core/network/json/Rfc3339DateJsonAdapter.kt index c0ef5c044..1a26de3ee 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/json/Rfc3339DateJsonAdapter.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/json/Rfc3339DateJsonAdapter.kt @@ -21,9 +21,9 @@ import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter -import timber.log.Timber import java.io.IOException import java.util.Date +import timber.log.Timber class Rfc3339DateJsonAdapter : TypeAdapter() { diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Account.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Account.kt index 2cc6f7c46..d51cf9436 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Account.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Account.kt @@ -23,8 +23,10 @@ data class Account( val id: String, @SerializedName("username") val localUsername: String, @SerializedName("acct") val username: String, - @SerializedName("display_name") val displayName: String?, // should never be null per API definition, but some servers break the contract - @SerializedName("created_at") val createdAt: Date?, // should never be null per API definition, but some servers break the contract + // should never be null per API definition, but some servers break the contract + @SerializedName("display_name") val displayName: String?, + // should never be null per API definition, but some servers break the contract + @SerializedName("created_at") val createdAt: Date?, val note: String, val url: String, val avatar: String, @@ -35,10 +37,12 @@ data class Account( @SerializedName("statuses_count") val statusesCount: Int = 0, val source: AccountSource? = null, val bot: Boolean = false, - val emojis: List? = emptyList(), // nullable for backward compatibility - val fields: List? = emptyList(), // nullable for backward compatibility + // nullable for backward compatibility + val emojis: List? = emptyList(), + // nullable for backward compatibility + val fields: List? = emptyList(), val moved: Account? = null, - val roles: List? = emptyList() + val roles: List? = emptyList(), ) { val name: String diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Attachment.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Attachment.kt index 05044f312..2d4472019 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Attachment.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Attachment.kt @@ -30,7 +30,8 @@ import kotlinx.parcelize.Parcelize data class Attachment( val id: String, val url: String, - @SerializedName("preview_url") val previewUrl: String?, // can be null for e.g. audio attachments + // can be null for e.g. audio attachments + @SerializedName("preview_url") val previewUrl: String?, val meta: MetaData?, val type: Type, val description: String?, diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Conversation.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Conversation.kt index 86225a3b6..41320818a 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Conversation.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Conversation.kt @@ -21,6 +21,7 @@ import com.google.gson.annotations.SerializedName data class Conversation( val id: String, val accounts: List, - @SerializedName("last_status") val lastStatus: Status?, // should never be null, but apparently its possible https://github.com/tuskyapp/Tusky/issues/1038 + // should never be null, but apparently its possible https://github.com/tuskyapp/Tusky/issues/1038 + @SerializedName("last_status") val lastStatus: Status?, val unread: Boolean, ) diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Filter.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Filter.kt index 59b8b0fc6..5a510351a 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Filter.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Filter.kt @@ -2,8 +2,8 @@ package app.pachli.core.network.model import android.os.Parcelable import com.google.gson.annotations.SerializedName -import kotlinx.parcelize.Parcelize import java.util.Date +import kotlinx.parcelize.Parcelize @Parcelize data class Filter( diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/LinksHeader.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Links.kt similarity index 100% rename from core/network/src/main/kotlin/app/pachli/core/network/model/LinksHeader.kt rename to core/network/src/main/kotlin/app/pachli/core/network/model/Links.kt diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Notification.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Notification.kt index e555c2905..c7d1517ed 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Notification.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Notification.kt @@ -117,8 +117,8 @@ data class Notification( fun rewriteToStatusTypeIfNeeded(accountId: String): Notification { if (type == Type.MENTION && status != null) { return if (status.mentions.any { - it.id == accountId - } + it.id == accountId + } ) { this } else { diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Poll.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Poll.kt index f3d254948..bafe9241d 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Poll.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Poll.kt @@ -9,7 +9,8 @@ data class Poll( val expired: Boolean, val multiple: Boolean, @SerializedName("votes_count") val votesCount: Int, - @SerializedName("voters_count") val votersCount: Int?, // nullable for compatibility with Pleroma + // nullable for compatibility with Pleroma + @SerializedName("voters_count") val votersCount: Int?, val options: List, val voted: Boolean, @SerializedName("own_votes") val ownVotes: List?, diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Relationship.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Relationship.kt index 9ea3a0422..51dc52101 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Relationship.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Relationship.kt @@ -36,6 +36,8 @@ data class Relationship( */ @JsonAdapter(GuardedBooleanAdapter::class) val subscribing: Boolean? = null, @SerializedName("domain_blocking") val blockingDomain: Boolean, - val note: String?, // nullable for backward compatibility / feature detection - val notifying: Boolean?, // since 3.3.0rc + // nullable for backward compatibility / feature detection + val note: String?, + // since 3.3.0rc + val notifying: Boolean?, ) diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Status.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Status.kt index 8033f8784..7395bccb3 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Status.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Status.kt @@ -25,7 +25,8 @@ import java.util.Date data class Status( val id: String, - val url: String?, // not present if it's reblog + // not present if it's reblog + val url: String?, val account: TimelineAccount, @SerializedName("in_reply_to_id") val inReplyToId: String?, @SerializedName("in_reply_to_account_id") val inReplyToAccountId: String?, diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/TimelineAccount.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/TimelineAccount.kt index b4162abb8..9f73fd607 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/TimelineAccount.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/TimelineAccount.kt @@ -27,15 +27,15 @@ data class TimelineAccount( val id: String, @SerializedName("username") val localUsername: String, @SerializedName("acct") val username: String, - + // should never be null per Api definition, but some servers break the contract @Deprecated("prefer the `name` property, which is not-null and not-empty") - @SerializedName("display_name") - val displayName: String?, // should never be null per Api definition, but some servers break the contract + val displayName: String?, val url: String, val avatar: String, val note: String, val bot: Boolean = false, - val emojis: List? = emptyList(), // nullable for backward compatibility + // nullable for backward compatibility + val emojis: List? = emptyList(), ) { @Suppress("DEPRECATION") diff --git a/core/network/src/main/kotlin/app/pachli/core/network/model/Translation.kt b/core/network/src/main/kotlin/app/pachli/core/network/model/Translation.kt index fda8102b9..2ad855a06 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/model/Translation.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/model/Translation.kt @@ -30,22 +30,22 @@ data class Translation( */ @SerializedName("detected_source_language") val detectedSourceLanguage: String, + // Not documented, see https://github.com/mastodon/documentation/issues/1248 /** * The translated spoiler text of the status (text), if it exists, equivalent to * [Status.spoilerText] */ - // Not documented, see https://github.com/mastodon/documentation/issues/1248 @SerializedName("spoiler_text") val spoilerText: String, - /** The translated poll (if it exists) */ // Not documented, see https://github.com/mastodon/documentation/issues/1248 + /** The translated poll (if it exists) */ val poll: TranslatedPoll?, + // Not documented, see https://github.com/mastodon/documentation/issues/1248 /** * Translated descriptions for media attachments, if any were attached. Other metadata has * to be determined from the original attachment. */ - // Not documented, see https://github.com/mastodon/documentation/issues/1248 @SerializedName("media_attachments") val attachments: List, /** The service that provided the machine translation */ diff --git a/core/network/src/main/kotlin/app/pachli/core/network/retrofit/InstanceSwitchAuthInterceptor.kt b/core/network/src/main/kotlin/app/pachli/core/network/retrofit/InstanceSwitchAuthInterceptor.kt index 83c3a5d63..b4bfb3b81 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/retrofit/InstanceSwitchAuthInterceptor.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/retrofit/InstanceSwitchAuthInterceptor.kt @@ -17,6 +17,9 @@ package app.pachli.core.network.retrofit +import java.io.IOException +import javax.inject.Inject +import javax.inject.Singleton import okhttp3.HttpUrl import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType @@ -25,9 +28,6 @@ import okhttp3.Request import okhttp3.Response import okhttp3.ResponseBody.Companion.toResponseBody import timber.log.Timber -import java.io.IOException -import javax.inject.Inject -import javax.inject.Singleton // AccountManager can not be used here as that would create a circular dependency // between core.network and core.accounts. Instead, the singleton instance of this diff --git a/core/network/src/test/kotlin/app/pachli/core/network/retrofit/InstanceV1SwitchAuthInterceptorTest.kt b/core/network/src/test/kotlin/app/pachli/core/network/retrofit/InstanceV1SwitchAuthInterceptorTest.kt index 390b569d3..dadd95e3f 100644 --- a/core/network/src/test/kotlin/app/pachli/core/network/retrofit/InstanceV1SwitchAuthInterceptorTest.kt +++ b/core/network/src/test/kotlin/app/pachli/core/network/retrofit/InstanceV1SwitchAuthInterceptorTest.kt @@ -69,7 +69,7 @@ class InstanceV1SwitchAuthInterceptorTest { val interceptor = InstanceSwitchAuthInterceptor() interceptor.credentials = InstanceSwitchAuthInterceptor.Credentials( accessToken = "fakeToken", - domain = "test.domain" + domain = "test.domain", ) val okHttpClient = OkHttpClient.Builder() @@ -96,7 +96,7 @@ class InstanceV1SwitchAuthInterceptorTest { val interceptor = InstanceSwitchAuthInterceptor() interceptor.credentials = InstanceSwitchAuthInterceptor.Credentials( accessToken = "fakeToken", - domain = mockWebServer.hostName + domain = mockWebServer.hostName, ) val okHttpClient = OkHttpClient.Builder() diff --git a/core/preferences/src/main/kotlin/app/pachli/core/preferences/SharedPreferencesRepository.kt b/core/preferences/src/main/kotlin/app/pachli/core/preferences/SharedPreferencesRepository.kt index 528bf046a..162ce2a1e 100644 --- a/core/preferences/src/main/kotlin/app/pachli/core/preferences/SharedPreferencesRepository.kt +++ b/core/preferences/src/main/kotlin/app/pachli/core/preferences/SharedPreferencesRepository.kt @@ -20,12 +20,12 @@ package app.pachli.core.preferences import android.content.SharedPreferences import androidx.annotation.Keep import app.pachli.core.common.di.ApplicationScope +import javax.inject.Inject +import javax.inject.Singleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch import timber.log.Timber -import javax.inject.Inject -import javax.inject.Singleton /** * An implementation of [SharedPreferences] that exposes all changes to the diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db0c130e2..fd754dd97 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -77,7 +77,7 @@ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } -ktlint = "org.jlleitschuh.gradle.ktlint:12.0.3" +ktlint = "org.jlleitschuh.gradle.ktlint:12.1.0" room = { id = "androidx.room", version.ref = "androidx-room" } quadrant = { id = "com.gaelmarhic.quadrant", version.ref = "quadrant" }