chore(deps): update plugin ktlint to v12.1.0 (#358)
This commit is contained in:
parent
d8be70a465
commit
993b74691a
|
@ -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)
|
||||
|
|
|
@ -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<FdroidPackageVersion>
|
||||
val packages: List<FdroidPackageVersion>,
|
||||
)
|
||||
|
||||
interface FdroidService {
|
||||
@GET("/api/v1/packages/{package}")
|
||||
suspend fun getPackage(
|
||||
@Path("package") pkg: String
|
||||
@Path("package") pkg: String,
|
||||
): NetworkResult<FdroidPackage>
|
||||
}
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<GitHubReleaseAsset>
|
||||
val assets: List<GitHubReleaseAsset>,
|
||||
)
|
||||
|
||||
interface GitHubService {
|
||||
@GET("/repos/{owner}/{repo}/releases/latest")
|
||||
suspend fun getLatestRelease(
|
||||
@Path("owner") owner: String,
|
||||
@Path("repo") repo: String
|
||||
@Path("repo") repo: String,
|
||||
): NetworkResult<GitHubRelease>
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -33,6 +33,6 @@ object UpdateCheckModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun providesAppUpdateManager(
|
||||
@ApplicationContext context: Context
|
||||
@ApplicationContext context: Context,
|
||||
): AppUpdateManager = AppUpdateManagerFactory.create(context)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<String>):
|
||||
Map<@MapColumn(columnName = "serverId") String, StatusViewDataEntity>
|
||||
abstract suspend fun getStatusViewData(
|
||||
accountId: Long,
|
||||
serverIds: List<String>,
|
||||
): Map<
|
||||
@MapColumn(columnName = "serverId")
|
||||
String,
|
||||
StatusViewDataEntity,
|
||||
>
|
||||
|
||||
@Query(
|
||||
"""UPDATE TimelineStatusEntity SET pinned = :pinned
|
||||
|
|
|
@ -37,6 +37,12 @@ interface TranslatedStatusDao {
|
|||
WHERE timelineUserId = :accountId
|
||||
AND serverId IN (:serverIds)""",
|
||||
)
|
||||
suspend fun getTranslations(accountId: Long, serverIds: List<String>):
|
||||
Map<@MapColumn(columnName = "serverId") String, TranslatedStatusEntity>
|
||||
suspend fun getTranslations(
|
||||
accountId: Long,
|
||||
serverIds: List<String>,
|
||||
): Map<
|
||||
@MapColumn(columnName = "serverId")
|
||||
String,
|
||||
TranslatedStatusEntity,
|
||||
>
|
||||
}
|
||||
|
|
|
@ -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 = "",
|
||||
|
|
|
@ -65,6 +65,8 @@ data class DraftAttachment(
|
|||
get() = uriString.toUri()
|
||||
|
||||
enum class Type {
|
||||
IMAGE, VIDEO, AUDIO;
|
||||
IMAGE,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> = emptyList())
|
|||
fun from(kind: String, arguments: List<String> = 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),
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<TranslatedAttachment>,
|
||||
|
||||
/** The service that provided the machine translation */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, '.')) {
|
||||
|
|
|
@ -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<Date?>() {
|
||||
|
||||
|
|
|
@ -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<Emoji>? = emptyList(), // nullable for backward compatibility
|
||||
val fields: List<Field>? = emptyList(), // nullable for backward compatibility
|
||||
// nullable for backward compatibility
|
||||
val emojis: List<Emoji>? = emptyList(),
|
||||
// nullable for backward compatibility
|
||||
val fields: List<Field>? = emptyList(),
|
||||
val moved: Account? = null,
|
||||
val roles: List<Role>? = emptyList()
|
||||
val roles: List<Role>? = emptyList(),
|
||||
) {
|
||||
|
||||
val name: String
|
||||
|
|
|
@ -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?,
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.google.gson.annotations.SerializedName
|
|||
data class Conversation(
|
||||
val id: String,
|
||||
val accounts: List<TimelineAccount>,
|
||||
@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,
|
||||
)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<PollOption>,
|
||||
val voted: Boolean,
|
||||
@SerializedName("own_votes") val ownVotes: List<Int>?,
|
||||
|
|
|
@ -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?,
|
||||
)
|
||||
|
|
|
@ -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?,
|
||||
|
|
|
@ -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<Emoji>? = emptyList(), // nullable for backward compatibility
|
||||
// nullable for backward compatibility
|
||||
val emojis: List<Emoji>? = emptyList(),
|
||||
) {
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
|
|
|
@ -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<TranslatedAttachment>,
|
||||
|
||||
/** The service that provided the machine translation */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
|
||||
|
|
Loading…
Reference in New Issue