style: Require trailing comma, and break lines

Requiring trailing commas on multi-line lists of items (declarations
and call sites) reduces future repository churn when those lines are
changed, but introduces additional churn now.

Bite the bullet and make the change, as well as adjusting lines that
were too long / indented incorrectly.

The changes were performed automatically, using the `ktlintFormat` task.

Based on https://github.com/tuskyapp/Tusky/pull/3968 by
https://github.com/tinsukE
This commit is contained in:
Nik Clayton 2023-09-02 23:16:29 +02:00
parent cf26af25d8
commit a441576bf6
No known key found for this signature in database
GPG Key ID: F95268159C2EC897
308 changed files with 2485 additions and 2404 deletions

View File

@ -8,10 +8,13 @@ insert_final_newline = true
trim_trailing_whitespace = true
# Disable wildcard imports
[*.{java, kt}]
[*.{java,kt}]
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
ij_java_class_count_to_use_import_on_demand = 999
# Require trailing comma
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
[*.{yml,yaml}]
indent_size = 2

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ class MigrationsTest {
var helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
FrameworkSQLiteOpenHelperFactory(),
)
@Test
@ -37,7 +37,7 @@ class MigrationsTest {
id, domain, token, active, accountId, username, "Display Name",
"https://picture.url", true, true, true, true, true, true, true,
true, "1000", "[]", "[{\"shortcode\": \"emoji\", \"url\": \"yes\"}]", 0, false,
false, true
false, true,
)
db.execSQL(
@ -49,7 +49,7 @@ class MigrationsTest {
"`defaultPostPrivacy`,`defaultMediaSensitivity`,`alwaysShowSensitiveMedia`," +
"`mediaPreviewEnabled`) " +
"VALUES (nullif(?, 0),?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
values
values,
)
db.close()

View File

@ -49,7 +49,7 @@ class AboutActivity : BottomSheetActivity(), Injectable {
Build.MANUFACTURER,
Build.MODEL,
Build.VERSION.RELEASE,
Build.VERSION.SDK_INT
Build.VERSION.SDK_INT,
)
lifecycleScope.launch {
@ -59,7 +59,7 @@ class AboutActivity : BottomSheetActivity(), Injectable {
R.string.about_account_info,
account.username,
account.domain,
instanceInfo.version
instanceInfo.version,
)
binding.accountInfoTitle.show()
binding.accountInfo.show()

View File

@ -111,20 +111,22 @@ class AccountsInListFragment : DialogFragment(), Injectable {
}
binding.searchView.isSubmitButtonEnabled = true
binding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
viewModel.search(query.orEmpty())
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
// Close event is not sent so we use this instead
if (newText.isNullOrBlank()) {
viewModel.search("")
binding.searchView.setOnQueryTextListener(
object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
viewModel.search(query.orEmpty())
return true
}
return true
}
})
override fun onQueryTextChange(newText: String?): Boolean {
// Close event is not sent so we use this instead
if (newText.isNullOrBlank()) {
viewModel.search("")
}
return true
}
},
)
}
private fun setupSearchView(state: State) {

View File

@ -53,15 +53,17 @@ abstract class BottomSheetActivity : BaseActivity() {
val bottomSheetLayout: LinearLayout = findViewById(R.id.item_status_bottom_sheet)
bottomSheet = BottomSheetBehavior.from(bottomSheetLayout)
bottomSheet.state = BottomSheetBehavior.STATE_HIDDEN
bottomSheet.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
cancelActiveSearch()
bottomSheet.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
cancelActiveSearch()
}
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
},
)
}
open fun viewUrl(url: String, lookupFallbackBehavior: PostLookupFallbackBehavior = PostLookupFallbackBehavior.OPEN_IN_BROWSER) {
@ -72,7 +74,7 @@ abstract class BottomSheetActivity : BaseActivity() {
mastodonApi.searchObservable(
query = url,
resolve = true
resolve = true,
).observeOn(AndroidSchedulers.mainThread())
.autoDispose(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY))
.subscribe(
@ -101,7 +103,7 @@ abstract class BottomSheetActivity : BaseActivity() {
onEndSearch(url)
performUrlFallbackAction(url, lookupFallbackBehavior)
}
}
},
)
onBeginSearch(url)
@ -177,5 +179,5 @@ abstract class BottomSheetActivity : BaseActivity() {
enum class PostLookupFallbackBehavior {
OPEN_IN_BROWSER,
DISPLAY_ERROR
DISPLAY_ERROR,
}

View File

@ -81,7 +81,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
private enum class PickType {
AVATAR,
HEADER
HEADER,
}
private val cropImage = registerForActivityResult(CropImageContract()) { result ->
@ -105,7 +105,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
displayName = binding.displayNameEditText.text.toString(),
note = binding.noteEditText.text.toString(),
locked = binding.lockedCheckBox.isChecked,
fields = accountFieldEditAdapter.getFieldData()
fields = accountFieldEditAdapter.getFieldData(),
)
override fun onCreate(savedInstanceState: Bundle?) {
@ -162,7 +162,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
.placeholder(R.drawable.avatar_default)
.transform(
FitCenter(),
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp))
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)),
)
.into(binding.avatarPreview)
}
@ -198,7 +198,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
observeImage(viewModel.headerData, binding.headerPreview, false)
viewModel.saveData.observe(
this
this,
) {
when (it) {
is Success -> {
@ -238,10 +238,10 @@ class EditProfileActivity : BaseActivity(), Injectable {
private fun observeImage(
liveData: LiveData<Uri>,
imageView: ImageView,
roundedCorners: Boolean
roundedCorners: Boolean,
) {
liveData.observe(
this
this,
) { imageUri ->
// skipping all caches so we can always reuse the same uri
@ -253,7 +253,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
if (roundedCorners) {
glide.transform(
FitCenter(),
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp))
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)),
).into(imageView)
} else {
glide.into(imageView)
@ -276,7 +276,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
setImageSource(includeGallery = true, includeCamera = false)
setOutputUri(viewModel.getAvatarUri())
setOutputCompressFormat(Bitmap.CompressFormat.PNG)
}
},
)
}
PickType.HEADER -> {
@ -287,7 +287,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
setImageSource(includeGallery = true, includeCamera = false)
setOutputUri(viewModel.getHeaderUri())
setOutputCompressFormat(Bitmap.CompressFormat.PNG)
}
},
)
}
}

View File

@ -96,7 +96,7 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
binding.listsRecycler.adapter = adapter
binding.listsRecycler.layoutManager = LinearLayoutManager(this)
binding.listsRecycler.addItemDecoration(
DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
DividerItemDecoration(this, DividerItemDecoration.VERTICAL),
)
binding.swipeRefreshLayout.setOnRefreshListener { viewModel.retryLoading() }
@ -132,7 +132,7 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
R.string.action_create_list
} else {
R.string.action_rename_list
}
},
) { _, _ ->
onPickedDialogName(binding.nameText.text.toString(), list?.id, binding.exclusiveCheckbox.isChecked)
}
@ -190,7 +190,7 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
binding.messageView.setup(
R.drawable.elephant_friend_empty,
R.string.message_empty,
null
null,
)
} else {
binding.messageView.hide()
@ -202,13 +202,13 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
Snackbar.make(
binding.listsRecycler,
messageId,
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
).show()
}
private fun onListSelected(listId: String, listTitle: String) {
startActivityWithSlideInAnimation(
StatusListActivity.newListIntent(this, listId, listTitle)
StatusListActivity.newListIntent(this, listId, listTitle),
)
}

View File

@ -242,7 +242,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
changeAccount(requestedId, intent)
}
}
}
},
)
}
} else if (openDrafts) {
@ -293,7 +293,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
setupDrawer(
savedInstanceState,
addSearchButton = hideTopToolbar
addSearchButton = hideTopToolbar,
)
/* Fetch user info while we're doing other things. This has to be done after setting up the
@ -317,7 +317,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
is ProfileEditedEvent -> onFetchUserInfoSuccess(event.newProfileData)
is MainTabsChangedEvent -> {
refreshMainDrawerItems(
addSearchButton = hideTopToolbar
addSearchButton = hideTopToolbar,
)
setupTabs(false)
@ -354,14 +354,14 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
}
}
}
}
},
)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
1
1,
)
}
@ -404,7 +404,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
Log.d(
TAG,
"onResume: EmojiPack has been changed from %s to %s"
.format(selectedEmojiPack, currentEmojiPack)
.format(selectedEmojiPack, currentEmojiPack),
)
selectedEmojiPack = currentEmojiPack
recreate()
@ -478,7 +478,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
private fun setupDrawer(
savedInstanceState: Bundle?,
addSearchButton: Boolean
addSearchButton: Boolean,
) {
val drawerOpenClickListener = View.OnClickListener { binding.mainDrawerLayout.open() }
@ -497,7 +497,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
descriptionRes = R.string.add_account_description
iconicsIcon = GoogleMaterial.Icon.gmd_add
},
0
0,
)
attachToSliderView(binding.mainDrawer)
dividerBelowHeader = false
@ -511,32 +511,34 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
header.accountHeaderBackground.setBackgroundColor(MaterialColors.getColor(header, R.attr.colorBackgroundAccent))
val animateAvatars = preferences.getBoolean("animateGifAvatars", false)
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
if (animateAvatars) {
glide.load(uri)
.placeholder(placeholder)
.into(imageView)
} else {
glide.asBitmap()
.load(uri)
.placeholder(placeholder)
.into(imageView)
}
}
override fun cancel(imageView: ImageView) {
glide.clear(imageView)
}
override fun placeholder(ctx: Context, tag: String?): Drawable {
if (tag == DrawerImageLoader.Tags.PROFILE.name || tag == DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name) {
return ctx.getDrawable(R.drawable.avatar_default)!!
DrawerImageLoader.init(
object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
if (animateAvatars) {
glide.load(uri)
.placeholder(placeholder)
.into(imageView)
} else {
glide.asBitmap()
.load(uri)
.placeholder(placeholder)
.into(imageView)
}
}
return super.placeholder(ctx, tag)
}
})
override fun cancel(imageView: ImageView) {
glide.clear(imageView)
}
override fun placeholder(ctx: Context, tag: String?): Drawable {
if (tag == DrawerImageLoader.Tags.PROFILE.name || tag == DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name) {
return ctx.getDrawable(R.drawable.avatar_default)!!
}
return super.placeholder(ctx, tag)
}
},
)
binding.mainDrawer.apply {
refreshMainDrawerItems(addSearchButton)
@ -645,7 +647,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
nameRes = R.string.action_logout
iconRes = R.drawable.ic_logout
onClick = ::logout
}
},
)
if (addSearchButton) {
@ -657,7 +659,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
onClick = {
startActivityWithSlideInAnimation(SearchActivity.getIntent(context))
}
}
},
)
}
@ -669,7 +671,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
onClick = {
startActivityWithSlideInAnimation(TrendingActivity.getIntent(context))
}
}
},
)
}
@ -686,7 +688,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
onClick = {
buildDeveloperToolsDialog().show()
}
}
},
)
}
@ -699,8 +701,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
.setItems(
arrayOf(
"Clear home timeline cache",
"Remove first 40 statuses"
)
"Remove first 40 statuses",
),
) { _, which ->
Log.d(TAG, "Developer tools: $which")
when (which) {
@ -912,7 +914,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
},
{ throwable ->
Log.e(TAG, "Failed to fetch user info. " + throwable.message)
}
},
)
}
@ -962,57 +964,61 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
.apply {
if (showPlaceholder) placeholder(R.drawable.avatar_default)
}
.into(object : CustomTarget<Drawable>(navIconSize, navIconSize) {
.into(
object : CustomTarget<Drawable>(navIconSize, navIconSize) {
override fun onLoadStarted(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
override fun onLoadStarted(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
}
}
}
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?
) {
if (resource is Animatable) resource.start()
activeToolbar.navigationIcon = FixedSizeDrawable(resource, navIconSize, navIconSize)
}
override fun onLoadCleared(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?,
) {
if (resource is Animatable) resource.start()
activeToolbar.navigationIcon = FixedSizeDrawable(resource, navIconSize, navIconSize)
}
}
})
override fun onLoadCleared(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
}
}
},
)
} else {
glide.asBitmap().load(avatarUrl).transform(RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp)))
.apply {
if (showPlaceholder) placeholder(R.drawable.avatar_default)
}
.into(object : CustomTarget<Bitmap>(navIconSize, navIconSize) {
override fun onLoadStarted(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
.into(
object : CustomTarget<Bitmap>(navIconSize, navIconSize) {
override fun onLoadStarted(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
}
}
}
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
activeToolbar.navigationIcon = FixedSizeDrawable(
BitmapDrawable(resources, resource),
navIconSize,
navIconSize
)
}
override fun onLoadCleared(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?,
) {
activeToolbar.navigationIcon = FixedSizeDrawable(
BitmapDrawable(resources, resource),
navIconSize,
navIconSize,
)
}
}
})
override fun onLoadCleared(placeholder: Drawable?) {
placeholder?.let {
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
}
}
},
)
}
}
@ -1026,7 +1032,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
},
{ throwable ->
Log.w(TAG, "Failed to fetch announcements.", throwable)
}
},
)
}
}
@ -1114,7 +1120,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
options: ComposeActivity.ComposeOptions,
tuskyAccountId: Long = -1,
notificationTag: String? = null,
notificationId: Int = -1
notificationId: Int = -1,
): Intent {
return accountSwitchIntent(context, tuskyAccountId).apply {
action = Intent.ACTION_SEND // so it can be opened via shortcuts

View File

@ -114,7 +114,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
},
{
Log.w(TAG, "Failed to query tag #$tag", it)
}
},
)
}
}
@ -134,7 +134,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
{
Snackbar.make(binding.root, getString(R.string.error_following_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
Log.e(TAG, "Failed to follow #$tag", it)
}
},
)
}
}
@ -154,7 +154,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
{
Snackbar.make(binding.root, getString(R.string.error_unfollowing_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
Log.e(TAG, "Failed to unfollow #$tag", it)
}
},
)
}
}
@ -193,12 +193,12 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
},
{ throwable ->
Log.e(TAG, "Error getting filters: $throwable")
}
},
)
} else {
Log.e(TAG, "Error getting filters: $throwable")
}
}
},
)
}
}
@ -223,7 +223,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
title = "#$tag",
context = listOf(FilterV1.HOME),
filterAction = Filter.Action.WARN.action,
expiresInSeconds = null
expiresInSeconds = null,
).fold(
{ filter ->
if (mastodonApi.addFilterKeyword(filterId = filter.id, keyword = tag, wholeWord = true).isSuccess) {
@ -242,7 +242,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
listOf(FilterV1.HOME),
irreversible = false,
wholeWord = true,
expiresInSeconds = null
expiresInSeconds = null,
).fold(
{ filter ->
mutedFilterV1 = filter
@ -252,13 +252,13 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
{ throwable ->
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
Log.e(TAG, "Failed to mute #$tag", throwable)
}
},
)
} else {
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
Log.e(TAG, "Failed to mute #$tag", throwable)
}
}
},
)
}
@ -274,7 +274,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
// This filter exists in multiple contexts, just remove the home context
mastodonApi.updateFilter(
id = filter.id,
context = filter.context.filter { it != Filter.Kind.HOME.kind }
context = filter.context.filter { it != Filter.Kind.HOME.kind },
)
} else {
mastodonApi.deleteFilter(filter.id)
@ -289,7 +289,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
context = filter.context.filter { it != FilterV1.HOME },
irreversible = null,
wholeWord = null,
expiresInSeconds = null
expiresInSeconds = null,
)
} else {
mastodonApi.deleteFilterV1(filter.id)
@ -309,7 +309,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
{ throwable ->
Snackbar.make(binding.root, getString(R.string.error_unmuting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
Log.e(TAG, "Failed to unmute #$tag", throwable)
}
},
)
}

View File

@ -47,7 +47,7 @@ data class TabData(
@DrawableRes val icon: Int,
val fragment: (List<String>) -> Fragment,
val arguments: List<String> = emptyList(),
val title: (Context) -> String = { context -> context.getString(text) }
val title: (Context) -> String = { context -> context.getString(text) },
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@ -70,49 +70,49 @@ fun createTabDataFromId(id: String, arguments: List<String> = emptyList()): TabD
id = HOME,
text = R.string.title_home,
icon = R.drawable.ic_home_24dp,
fragment = { TimelineFragment.newInstance(TimelineKind.Home) }
fragment = { TimelineFragment.newInstance(TimelineKind.Home) },
)
NOTIFICATIONS -> TabData(
id = NOTIFICATIONS,
text = R.string.title_notifications,
icon = R.drawable.ic_notifications_24dp,
fragment = { NotificationsFragment.newInstance() }
fragment = { NotificationsFragment.newInstance() },
)
LOCAL -> TabData(
id = LOCAL,
text = R.string.title_public_local,
icon = R.drawable.ic_local_24dp,
fragment = { TimelineFragment.newInstance(TimelineKind.PublicLocal) }
fragment = { TimelineFragment.newInstance(TimelineKind.PublicLocal) },
)
FEDERATED -> TabData(
id = FEDERATED,
text = R.string.title_public_federated,
icon = R.drawable.ic_public_24dp,
fragment = { TimelineFragment.newInstance(TimelineKind.PublicFederated) }
fragment = { TimelineFragment.newInstance(TimelineKind.PublicFederated) },
)
DIRECT -> TabData(
id = DIRECT,
text = R.string.title_direct_messages,
icon = R.drawable.ic_reblog_direct_24dp,
fragment = { ConversationsFragment.newInstance() }
fragment = { ConversationsFragment.newInstance() },
)
TRENDING_TAGS -> TabData(
id = TRENDING_TAGS,
text = R.string.title_public_trending_hashtags,
icon = R.drawable.ic_trending_up_24px,
fragment = { TrendingTagsFragment.newInstance() }
fragment = { TrendingTagsFragment.newInstance() },
)
TRENDING_LINKS -> TabData(
id = TRENDING_LINKS,
text = R.string.title_public_trending_links,
icon = R.drawable.ic_trending_up_24px,
fragment = { TrendingLinksFragment.newInstance() }
fragment = { TrendingLinksFragment.newInstance() },
)
TRENDING_STATUSES -> TabData(
id = TRENDING_STATUSES,
text = R.string.title_public_trending_statuses,
icon = R.drawable.ic_trending_up_24px,
fragment = { TimelineFragment.newInstance(TimelineKind.TrendingStatuses) }
fragment = { TimelineFragment.newInstance(TimelineKind.TrendingStatuses) },
)
HASHTAG -> TabData(
id = HASHTAG,
@ -120,7 +120,7 @@ fun createTabDataFromId(id: String, arguments: List<String> = emptyList()): TabD
icon = R.drawable.ic_hashtag,
fragment = { args -> TimelineFragment.newInstance(TimelineKind.Tag(args)) },
arguments = arguments,
title = { context -> arguments.joinToString(separator = " ") { context.getString(R.string.title_tag, it) } }
title = { context -> arguments.joinToString(separator = " ") { context.getString(R.string.title_tag, it) } },
)
LIST -> TabData(
id = LIST,
@ -128,13 +128,13 @@ fun createTabDataFromId(id: String, arguments: List<String> = emptyList()): TabD
icon = R.drawable.ic_list,
fragment = { args -> TimelineFragment.newInstance(TimelineKind.UserList(args.first(), args.last())) },
arguments = arguments,
title = { arguments.getOrNull(1).orEmpty() }
title = { arguments.getOrNull(1).orEmpty() },
)
BOOKMARKS -> TabData(
id = BOOKMARKS,
text = R.string.title_bookmarks,
icon = R.drawable.ic_bookmark_active_24dp,
fragment = { TimelineFragment.newInstance(TimelineKind.Bookmarks) }
fragment = { TimelineFragment.newInstance(TimelineKind.Bookmarks) },
)
else -> throw IllegalArgumentException("unknown tab type")
}
@ -145,6 +145,6 @@ fun defaultTabs(): List<TabData> {
createTabDataFromId(HOME),
createTabDataFromId(NOTIFICATIONS),
createTabDataFromId(LOCAL),
createTabDataFromId(DIRECT)
createTabDataFromId(DIRECT),
)
}

View File

@ -115,44 +115,46 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
binding.addTabRecyclerView.adapter = addTabAdapter
binding.addTabRecyclerView.layoutManager = LinearLayoutManager(this)
touchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
return makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.END)
}
override fun isLongPressDragEnabled(): Boolean {
return true
}
override fun isItemViewSwipeEnabled(): Boolean {
return MIN_TAB_COUNT < currentTabs.size
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val temp = currentTabs[viewHolder.bindingAdapterPosition]
currentTabs[viewHolder.bindingAdapterPosition] = currentTabs[target.bindingAdapterPosition]
currentTabs[target.bindingAdapterPosition] = temp
currentTabsAdapter.notifyItemMoved(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
saveTabs()
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
onTabRemoved(viewHolder.bindingAdapterPosition)
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
viewHolder?.itemView?.elevation = selectedItemElevation
touchHelper = ItemTouchHelper(
object : ItemTouchHelper.Callback() {
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
return makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.END)
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.elevation = 0f
}
})
override fun isLongPressDragEnabled(): Boolean {
return true
}
override fun isItemViewSwipeEnabled(): Boolean {
return MIN_TAB_COUNT < currentTabs.size
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val temp = currentTabs[viewHolder.bindingAdapterPosition]
currentTabs[viewHolder.bindingAdapterPosition] = currentTabs[target.bindingAdapterPosition]
currentTabs[target.bindingAdapterPosition] = temp
currentTabsAdapter.notifyItemMoved(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
saveTabs()
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
onTabRemoved(viewHolder.bindingAdapterPosition)
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
viewHolder?.itemView?.elevation = selectedItemElevation
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.elevation = 0f
}
},
)
touchHelper.attachToRecyclerView(binding.currentTabsRecyclerView)
@ -327,13 +329,13 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
dialog.hide()
Log.e("TabPreferenceActivity", "failed to load lists", throwable)
Snackbar.make(binding.root, R.string.error_list_load, Snackbar.LENGTH_LONG).show()
}
},
)
}
}
private fun getProgressBarJob(progressView: View, delayMs: Long) = this.lifecycleScope.launch(
start = CoroutineStart.LAZY
start = CoroutineStart.LAZY,
) {
try {
delay(delayMs)

View File

@ -105,7 +105,7 @@ class TuskyApplication : Application(), HasAndroidInjector {
this,
androidx.work.Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
.build(),
)
// Prune the database every ~ 12 hours when the device is idle.
@ -115,7 +115,7 @@ class TuskyApplication : Application(), HasAndroidInjector {
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
PruneCacheWorker.PERIODIC_WORK_TAG,
ExistingPeriodicWorkPolicy.KEEP,
pruneCacheWorker
pruneCacheWorker,
)
}

View File

@ -121,11 +121,13 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
binding.viewPager.adapter = adapter
binding.viewPager.setCurrentItem(initialPosition, false)
binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
binding.toolbar.title = getPageTitle(position)
}
})
binding.viewPager.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
binding.toolbar.title = getPageTitle(position)
}
},
)
// Setup the toolbar.
setSupportActionBar(binding.toolbar)
@ -149,12 +151,14 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE
window.statusBarColor = Color.BLACK
window.sharedElementEnterTransition.addListener(object : NoopTransitionListener {
override fun onTransitionEnd(transition: Transition) {
adapter.onTransitionEnd(binding.viewPager.currentItem)
window.sharedElementEnterTransition.removeListener(this)
}
})
window.sharedElementEnterTransition.addListener(
object : NoopTransitionListener {
override fun onTransitionEnd(transition: Transition) {
adapter.onTransitionEnd(binding.viewPager.currentItem)
window.sharedElementEnterTransition.removeListener(this)
}
},
)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@ -192,12 +196,14 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
}
binding.toolbar.animate().alpha(alpha)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
binding.toolbar.visibility = visibility
animation.removeListener(this)
}
})
.setListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
binding.toolbar.visibility = visibility
animation.removeListener(this)
}
},
)
.start()
}
@ -228,7 +234,7 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
showErrorDialog(
binding.toolbar,
R.string.error_media_download_permission,
R.string.action_retry
R.string.action_retry,
) { requestDownloadMedia() }
}
}
@ -263,7 +269,8 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
Attachment.Type.IMAGE -> shareImage(directory, attachment.url)
Attachment.Type.AUDIO,
Attachment.Type.VIDEO,
Attachment.Type.GIFV -> shareMediaFile(directory, attachment.url)
Attachment.Type.GIFV,
-> shareMediaFile(directory, attachment.url)
else -> Log.e(TAG, "Unknown media format for sharing.")
}
}
@ -321,7 +328,7 @@ class ViewMediaActivity : BaseActivity(), HasAndroidInjector, ViewImageFragment.
invalidateOptionsMenu()
binding.progressBarShare.visibility = View.GONE
Log.e(TAG, "Failed to download image", error)
}
},
)
}

View File

@ -28,7 +28,7 @@ import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.visible
class AccountViewHolder(
private val binding: ItemAccountBinding
private val binding: ItemAccountBinding,
) : RecyclerView.ViewHolder(binding.root) {
private lateinit var accountId: String
@ -36,19 +36,19 @@ class AccountViewHolder(
account: TimelineAccount,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) {
accountId = account.id
binding.accountUsername.text = binding.accountUsername.context.getString(
R.string.post_username_format,
account.username
account.username,
)
val emojifiedName = account.name.emojify(
account.emojis,
binding.accountDisplayName,
animateEmojis
animateEmojis,
)
binding.accountDisplayName.text = emojifiedName
@ -66,7 +66,7 @@ class AccountViewHolder(
fun setupLinkListener(listener: LinkListener) {
itemView.setOnClickListener {
listener.onViewAccount(
accountId
accountId,
)
}
}

View File

@ -28,7 +28,7 @@ import java.util.Locale
class EmojiAdapter(
emojiList: List<Emoji>,
private val onEmojiSelectedListener: OnEmojiSelectedListener,
private val animate: Boolean
private val animate: Boolean,
) : RecyclerView.Adapter<BindingHolder<ItemEmojiButtonBinding>>() {
private val emojiList: List<Emoji> = emojiList.filter { emoji -> emoji.visibleInPicker == null || emoji.visibleInPicker }

View File

@ -43,13 +43,13 @@ class FollowRequestViewHolder(
private val binding: ItemFollowRequestBinding,
private val accountActionListener: AccountActionListener,
private val linkListener: LinkListener,
private val showHeader: Boolean
private val showHeader: Boolean,
) : NotificationsPagingAdapter.ViewHolder, RecyclerView.ViewHolder(binding.root) {
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
// Skip updates with payloads. That indicates a timestamp update, and
// this view does not have timestamps.
@ -59,7 +59,7 @@ class FollowRequestViewHolder(
viewData.account,
statusDisplayOptions.animateAvatars,
statusDisplayOptions.animateEmojis,
statusDisplayOptions.showBotOverlay
statusDisplayOptions.showBotOverlay,
)
setupActionListener(accountActionListener, viewData.account.id)
@ -69,26 +69,26 @@ class FollowRequestViewHolder(
account: TimelineAccount,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) {
val wrappedName = account.name.unicodeWrap()
val emojifiedName: CharSequence = wrappedName.emojify(
account.emojis,
itemView,
animateEmojis
animateEmojis,
)
binding.displayNameTextView.text = emojifiedName
if (showHeader) {
val wholeMessage: String = itemView.context.getString(
R.string.notification_follow_request_format,
wrappedName
wrappedName,
)
binding.notificationTextView.text = SpannableStringBuilder(wholeMessage).apply {
setSpan(
StyleSpan(Typeface.BOLD),
0,
wrappedName.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
)
}.emojify(account.emojis, itemView, animateEmojis)
}

View File

@ -49,7 +49,7 @@ class PollAdapter : RecyclerView.Adapter<BindingHolder<ItemPollBinding>>() {
mode: Int,
resultClickListener: View.OnClickListener?,
animateEmojis: Boolean,
enabled: Boolean = true
enabled: Boolean = true,
) {
this.pollOptions = options
this.voteCount = voteCount

View File

@ -37,13 +37,13 @@ import java.util.Date
class ReportNotificationViewHolder(
private val binding: ItemReportNotificationBinding,
private val notificationActionListener: NotificationActionListener
private val notificationActionListener: NotificationActionListener,
) : NotificationsPagingAdapter.ViewHolder, RecyclerView.ViewHolder(binding.root) {
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
// Skip updates with payloads. That indicates a timestamp update, and
// this view does not have timestamps.
@ -53,13 +53,13 @@ class ReportNotificationViewHolder(
viewData.account,
viewData.report!!,
statusDisplayOptions.animateAvatars,
statusDisplayOptions.animateEmojis
statusDisplayOptions.animateEmojis,
)
setupActionListener(
notificationActionListener,
viewData.report.targetAccount.id,
viewData.account.id,
viewData.report.id
viewData.report.id,
)
}
@ -67,17 +67,17 @@ class ReportNotificationViewHolder(
reporter: TimelineAccount,
report: Report,
animateAvatar: Boolean,
animateEmojis: Boolean
animateEmojis: Boolean,
) {
val reporterName = reporter.name.unicodeWrap().emojify(
reporter.emojis,
binding.root,
animateEmojis
animateEmojis,
)
val reporteeName = report.targetAccount.name.unicodeWrap().emojify(
report.targetAccount.emojis,
itemView,
animateEmojis
animateEmojis,
)
val icon = ContextCompat.getDrawable(binding.root.context, R.drawable.ic_flag_24dp)
@ -85,12 +85,12 @@ class ReportNotificationViewHolder(
binding.notificationTopText.text = itemView.context.getString(
R.string.notification_header_report_format,
reporterName,
reporteeName
reporteeName,
)
binding.notificationSummary.text = itemView.context.getString(
R.string.notification_summary_report_format,
getRelativeTimeSpanString(itemView.context, report.createdAt.time, Date().time),
report.status_ids?.size ?: 0
report.status_ids?.size ?: 0,
)
binding.notificationCategory.text = getTranslatedCategory(itemView.context, report.category)
@ -102,13 +102,13 @@ class ReportNotificationViewHolder(
report.targetAccount.avatar,
binding.notificationReporteeAvatar,
itemView.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp),
animateAvatar
animateAvatar,
)
loadAvatar(
reporter.avatar,
binding.notificationReporterAvatar,
itemView.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_24dp),
animateAvatar
animateAvatar,
)
}
@ -116,7 +116,7 @@ class ReportNotificationViewHolder(
listener: NotificationActionListener,
reporteeId: String,
reporterId: String,
reportId: String
reportId: String,
) {
binding.notificationReporteeAvatar.setOnClickListener {
val position = bindingAdapterPosition

View File

@ -46,7 +46,7 @@ class TabAdapter(
private var data: List<TabData>,
private val small: Boolean,
private val listener: ItemInteractionListener,
private var removeButtonEnabled: Boolean = false
private var removeButtonEnabled: Boolean = false,
) : RecyclerView.Adapter<BindingHolder<ViewBinding>>() {
fun updateData(newData: List<TabData>) {
@ -103,7 +103,7 @@ class TabAdapter(
setDrawableTint(
holder.itemView.context,
binding.removeButton.drawable,
(if (removeButtonEnabled) android.R.attr.textColorTertiary else R.attr.textColorDisabled)
(if (removeButtonEnabled) android.R.attr.textColorTertiary else R.attr.textColorDisabled),
)
if (tab.id == HASHTAG) {

View File

@ -14,7 +14,7 @@ class CacheUpdater @Inject constructor(
eventHub: EventHub,
accountManager: AccountManager,
appDatabase: AppDatabase,
gson: Gson
gson: Gson,
) {
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

View File

@ -155,7 +155,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
private enum class FollowState {
NOT_FOLLOWING,
FOLLOWING,
REQUESTED
REQUESTED,
}
private lateinit var adapter: AccountPagerAdapter
@ -273,17 +273,19 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
val enableSwipeForTabs = preferences.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true)
binding.accountFragmentViewPager.isUserInputEnabled = enableSwipeForTabs
binding.accountTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) {
tab?.position?.let { position ->
(adapter.getFragment(position) as? ReselectableFragment)?.onReselect()
binding.accountTabLayout.addOnTabSelectedListener(
object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) {
tab?.position?.let { position ->
(adapter.getFragment(position) as? ReselectableFragment)?.onReselect()
}
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabSelected(tab: TabLayout.Tab?) {}
})
override fun onTabSelected(tab: TabLayout.Tab?) {}
},
)
}
private fun handleWindowInsets() {
@ -323,14 +325,14 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
binding.accountToolbar.navigationIcon = LayerDrawable(
arrayOf(
backgroundCircle,
binding.accountToolbar.navigationIcon
)
binding.accountToolbar.navigationIcon,
),
)
binding.accountToolbar.overflowIcon = LayerDrawable(
arrayOf(
backgroundCircle,
binding.accountToolbar.overflowIcon
)
binding.accountToolbar.overflowIcon,
),
)
binding.accountHeaderInfoContainer.background = MaterialShapeDrawable.createWithElevationOverlay(this, appBarElevation)
@ -345,47 +347,49 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
binding.accountAvatarImageView.background = avatarBackground
// Add a listener to change the toolbar icon color when it enters/exits its collapsed state.
binding.accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
binding.accountAppBarLayout.addOnOffsetChangedListener(
object : AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
if (verticalOffset == oldOffset) {
return
}
oldOffset = verticalOffset
if (titleVisibleHeight + verticalOffset < 0) {
supportActionBar?.setDisplayShowTitleEnabled(true)
} else {
supportActionBar?.setDisplayShowTitleEnabled(false)
}
if (hideFab && !blocking) {
if (verticalOffset > oldOffset) {
binding.accountFloatingActionButton.show()
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
if (verticalOffset == oldOffset) {
return
}
if (verticalOffset < oldOffset) {
binding.accountFloatingActionButton.hide()
oldOffset = verticalOffset
if (titleVisibleHeight + verticalOffset < 0) {
supportActionBar?.setDisplayShowTitleEnabled(true)
} else {
supportActionBar?.setDisplayShowTitleEnabled(false)
}
if (hideFab && !blocking) {
if (verticalOffset > oldOffset) {
binding.accountFloatingActionButton.show()
}
if (verticalOffset < oldOffset) {
binding.accountFloatingActionButton.hide()
}
}
val scaledAvatarSize = (avatarSize + verticalOffset) / avatarSize
binding.accountAvatarImageView.scaleX = scaledAvatarSize
binding.accountAvatarImageView.scaleY = scaledAvatarSize
binding.accountAvatarImageView.visible(scaledAvatarSize > 0)
val transparencyPercent = (abs(verticalOffset) / titleVisibleHeight.toFloat()).coerceAtMost(1f)
window.statusBarColor = argbEvaluator.evaluate(transparencyPercent, statusBarColorTransparent, statusBarColorOpaque) as Int
val evaluatedToolbarColor = argbEvaluator.evaluate(transparencyPercent, Color.TRANSPARENT, toolbarColor) as Int
toolbarBackground.fillColor = ColorStateList.valueOf(evaluatedToolbarColor)
binding.swipeToRefreshLayout.isEnabled = verticalOffset == 0
}
val scaledAvatarSize = (avatarSize + verticalOffset) / avatarSize
binding.accountAvatarImageView.scaleX = scaledAvatarSize
binding.accountAvatarImageView.scaleY = scaledAvatarSize
binding.accountAvatarImageView.visible(scaledAvatarSize > 0)
val transparencyPercent = (abs(verticalOffset) / titleVisibleHeight.toFloat()).coerceAtMost(1f)
window.statusBarColor = argbEvaluator.evaluate(transparencyPercent, statusBarColorTransparent, statusBarColorOpaque) as Int
val evaluatedToolbarColor = argbEvaluator.evaluate(transparencyPercent, Color.TRANSPARENT, toolbarColor) as Int
toolbarBackground.fillColor = ColorStateList.valueOf(evaluatedToolbarColor)
binding.swipeToRefreshLayout.isEnabled = verticalOffset == 0
}
})
},
)
}
private fun makeNotificationBarTransparent() {
@ -439,7 +443,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
private fun setupRefreshLayout() {
binding.swipeToRefreshLayout.setOnRefreshListener { onRefresh() }
viewModel.isRefreshing.observe(
this
this,
) { isRefreshing ->
binding.swipeToRefreshLayout.isRefreshing = isRefreshing == true
}
@ -496,7 +500,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
try {
binding.accountDateJoined.text = resources.getString(
R.string.account_date_joined,
SimpleDateFormat("MMMM, yyyy", Locale.getDefault()).format(account.createdAt)
SimpleDateFormat("MMMM, yyyy", Locale.getDefault()).format(account.createdAt),
)
binding.accountDateJoined.visibility = View.VISIBLE
} catch (e: ParseException) {
@ -515,7 +519,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
account.avatar,
binding.accountAvatarImageView,
resources.getDimensionPixelSize(R.dimen.avatar_radius_94dp),
animateAvatar
animateAvatar,
)
Glide.with(this)
@ -537,7 +541,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
view.transitionName = uri
startActivity(
ViewMediaActivity.newSingleImageIntent(view.context, uri),
ActivityOptionsCompat.makeSceneTransitionAnimation(this, view, uri).toBundle()
ActivityOptionsCompat.makeSceneTransitionAnimation(this, view, uri).toBundle(),
)
}
@ -863,7 +867,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
loadedAccount?.let {
showMuteAccountDialog(
this,
it.username
it.username,
) { notifications, duration ->
viewModel.muteAccount(notifications, duration)
}
@ -880,7 +884,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
} else {
ComposeActivity.ComposeOptions(
mentionedUsernames = setOf(it.username),
kind = ComposeActivity.ComposeKind.NEW
kind = ComposeActivity.ComposeKind.NEW,
)
}
val intent = ComposeActivity.startIntent(this, options)
@ -921,7 +925,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
override fun onAccountSelected(account: AccountEntity) {
openAsAccount(loadedAccount.url, account)
}
}
},
)
}
}

View File

@ -30,7 +30,7 @@ import com.keylesspalace.tusky.util.setClickableText
class AccountFieldAdapter(
private val linkListener: LinkListener,
private val animateEmojis: Boolean
private val animateEmojis: Boolean,
) : RecyclerView.Adapter<BindingHolder<ItemAccountFieldBinding>>() {
var emojis: List<Emoji> = emptyList()

View File

@ -25,7 +25,7 @@ import com.keylesspalace.tusky.util.CustomFragmentStateAdapter
class AccountPagerAdapter(
activity: FragmentActivity,
private val accountId: String
private val accountId: String,
) : CustomFragmentStateAdapter(activity) {
override fun getItemCount() = TAB_COUNT

View File

@ -28,7 +28,7 @@ import javax.inject.Inject
class AccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi,
private val eventHub: EventHub,
accountManager: AccountManager
accountManager: AccountManager,
) : ViewModel() {
val accountData = MutableLiveData<Resource<Account>>()
@ -79,7 +79,7 @@ class AccountViewModel @Inject constructor(
accountData.postValue(Error(cause = t))
isDataLoading = false
isRefreshing.postValue(false)
}
},
)
}
}
@ -98,7 +98,7 @@ class AccountViewModel @Inject constructor(
{ t ->
Log.w(TAG, "failed obtaining relationships", t)
relationshipData.postValue(Error(cause = t))
}
},
)
}
}
@ -150,7 +150,7 @@ class AccountViewModel @Inject constructor(
}
}, { e ->
Log.e(TAG, "Error muting $instance", e)
})
},)
}
}
@ -163,7 +163,7 @@ class AccountViewModel @Inject constructor(
}
}, { e ->
Log.e(TAG, "Error unmuting $instance", e)
})
},)
}
}
@ -181,7 +181,7 @@ class AccountViewModel @Inject constructor(
private fun changeRelationship(
relationshipAction: RelationShipAction,
parameter: Boolean? = null,
duration: Int? = null
duration: Int? = null,
) = viewModelScope.launch {
val relation = relationshipData.value?.data
val account = accountData.value?.data
@ -224,7 +224,7 @@ class AccountViewModel @Inject constructor(
val relationshipCall = when (relationshipAction) {
RelationShipAction.FOLLOW -> mastodonApi.followAccount(
accountId,
showReblogs = parameter ?: true
showReblogs = parameter ?: true,
)
RelationShipAction.UNFOLLOW -> mastodonApi.unfollowAccount(accountId)
RelationShipAction.BLOCK -> mastodonApi.blockAccount(accountId)
@ -232,7 +232,7 @@ class AccountViewModel @Inject constructor(
RelationShipAction.MUTE -> mastodonApi.muteAccount(
accountId,
parameter ?: true,
duration
duration,
)
RelationShipAction.UNMUTE -> mastodonApi.unmuteAccount(accountId)
RelationShipAction.SUBSCRIBE -> {
@ -265,7 +265,7 @@ class AccountViewModel @Inject constructor(
{ t ->
Log.w(TAG, "failed loading relationship", t)
relationshipData.postValue(Error(relation, cause = t))
}
},
)
}
@ -283,7 +283,7 @@ class AccountViewModel @Inject constructor(
},
{ t ->
Log.w(TAG, "Error updating note", t)
}
},
)
}
}

View File

@ -64,7 +64,7 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
dialog?.apply {
window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
LinearLayout.LayoutParams.MATCH_PARENT,
)
}
}
@ -72,7 +72,7 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View? {
return inflater.inflate(R.layout.fragment_lists_for_account, container, false)
}
@ -145,14 +145,14 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
private object Differ : DiffUtil.ItemCallback<AccountListState>() {
override fun areItemsTheSame(
oldItem: AccountListState,
newItem: AccountListState
newItem: AccountListState,
): Boolean {
return oldItem.list.id == newItem.list.id
}
override fun areContentsTheSame(
oldItem: AccountListState,
newItem: AccountListState
newItem: AccountListState,
): Boolean {
return oldItem == newItem
}
@ -162,7 +162,7 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
ListAdapter<AccountListState, BindingHolder<ItemAddOrRemoveFromListBinding>>(Differ) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
viewType: Int,
): BindingHolder<ItemAddOrRemoveFromListBinding> {
val binding =
ItemAddOrRemoveFromListBinding.inflate(LayoutInflater.from(parent.context), parent, false)

View File

@ -35,23 +35,23 @@ import javax.inject.Inject
data class AccountListState(
val list: MastoList,
val includesAccount: Boolean
val includesAccount: Boolean,
)
data class ActionError(
val error: Throwable,
val type: Type,
val listId: String
val listId: String,
) : Throwable(error) {
enum class Type {
ADD,
REMOVE
REMOVE,
}
}
@OptIn(ExperimentalCoroutinesApi::class)
class ListsForAccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi
private val mastodonApi: MastodonApi,
) : ViewModel() {
private lateinit var accountId: String
@ -75,16 +75,16 @@ class ListsForAccountViewModel @Inject constructor(
runCatching {
val (all, includes) = listOf(
async { mastodonApi.getLists() },
async { mastodonApi.getListsIncludesAccount(accountId) }
async { mastodonApi.getListsIncludesAccount(accountId) },
).awaitAll()
_states.emit(
all.getOrThrow().map { list ->
AccountListState(
list = list,
includesAccount = includes.getOrThrow().any { it.id == list.id }
includesAccount = includes.getOrThrow().any { it.id == list.id },
)
}
},
)
}
.onFailure {
@ -105,7 +105,7 @@ class ListsForAccountViewModel @Inject constructor(
} else {
state
}
}
},
)
}
.onFailure {
@ -126,7 +126,7 @@ class ListsForAccountViewModel @Inject constructor(
} else {
state
}
}
},
)
}
.onFailure {

View File

@ -88,7 +88,7 @@ class AccountMediaFragment :
adapter = AccountMediaGridAdapter(
useBlurhash = useBlurhash,
context = view.context,
onAttachmentClickListener = ::onAttachmentClick
onAttachmentClickListener = ::onAttachmentClick,
)
val columnCount = view.context.resources.getInteger(R.integer.profile_media_column_count)
@ -174,7 +174,8 @@ class AccountMediaFragment :
Attachment.Type.IMAGE,
Attachment.Type.GIFV,
Attachment.Type.VIDEO,
Attachment.Type.AUDIO -> {
Attachment.Type.AUDIO,
-> {
val intent = ViewMediaActivity.newIntent(context, attachmentsFromSameStatus, currentIndex)
if (activity != null) {
val url = selected.attachment.url

View File

@ -26,7 +26,7 @@ import java.util.Random
class AccountMediaGridAdapter(
private val useBlurhash: Boolean,
context: Context,
private val onAttachmentClickListener: (AttachmentViewData, View) -> Unit
private val onAttachmentClickListener: (AttachmentViewData, View) -> Unit,
) : PagingDataAdapter<AttachmentViewData, BindingHolder<ItemAccountMediaBinding>>(
object : DiffUtil.ItemCallback<AttachmentViewData>() {
override fun areItemsTheSame(oldItem: AttachmentViewData, newItem: AttachmentViewData): Boolean {
@ -36,7 +36,7 @@ class AccountMediaGridAdapter(
override fun areContentsTheSame(oldItem: AttachmentViewData, newItem: AttachmentViewData): Boolean {
return oldItem == newItem
}
}
},
) {
private val baseItemBackgroundColor = MaterialColors.getColor(context, com.google.android.material.R.attr.colorSurface, Color.BLACK)

View File

@ -20,7 +20,7 @@ import androidx.paging.PagingState
import com.keylesspalace.tusky.viewdata.AttachmentViewData
class AccountMediaPagingSource(
private val viewModel: AccountMediaViewModel
private val viewModel: AccountMediaViewModel,
) : PagingSource<String, AttachmentViewData>() {
override fun getRefreshKey(state: PagingState<String, AttachmentViewData>): String? = null

View File

@ -29,11 +29,11 @@ import retrofit2.HttpException
class AccountMediaRemoteMediator(
private val api: MastodonApi,
private val activeAccount: AccountEntity,
private val viewModel: AccountMediaViewModel
private val viewModel: AccountMediaViewModel,
) : RemoteMediator<String, AttachmentViewData>() {
override suspend fun load(
loadType: LoadType,
state: PagingState<String, AttachmentViewData>
state: PagingState<String, AttachmentViewData>,
): MediatorResult {
try {
val statusResponse = when (loadType) {

View File

@ -28,7 +28,7 @@ import javax.inject.Inject
class AccountMediaViewModel @Inject constructor(
private val accountManager: AccountManager,
api: MastodonApi
api: MastodonApi,
) : ViewModel() {
lateinit var accountId: String
@ -43,16 +43,16 @@ class AccountMediaViewModel @Inject constructor(
val media = Pager(
config = PagingConfig(
pageSize = LOAD_AT_ONCE,
prefetchDistance = LOAD_AT_ONCE * 2
prefetchDistance = LOAD_AT_ONCE * 2,
),
pagingSourceFactory = {
AccountMediaPagingSource(
viewModel = this
viewModel = this,
).also { source ->
currentSource = source
}
},
remoteMediator = AccountMediaRemoteMediator(api, activeAccount, this)
remoteMediator = AccountMediaRemoteMediator(api, activeAccount, this),
).flow
.cachedIn(viewModelScope)

View File

@ -23,14 +23,14 @@ import androidx.recyclerview.widget.RecyclerView.ItemDecoration
class GridSpacingItemDecoration(
private val spanCount: Int,
private val spacing: Int,
private val topOffset: Int
private val topOffset: Int,
) : ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
state: RecyclerView.State,
) {
val position = parent.getChildAdapterPosition(view) // item position
if (position < topOffset) return

View File

@ -38,7 +38,7 @@ class AccountListActivity : BottomSheetActivity(), HasAndroidInjector {
MUTES,
FOLLOW_REQUESTS,
REBLOGGED,
FAVOURITED
FAVOURITED,
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -115,7 +115,7 @@ class AccountListFragment :
Type.FOLLOW_REQUESTS -> {
val headerAdapter = FollowRequestsHeaderAdapter(
instanceName = activeAccount.domain,
accountLocked = activeAccount.locked
accountLocked = activeAccount.locked,
)
val followRequestsAdapter = FollowRequestsAdapter(this, this, animateAvatar, animateEmojis, showBotOverlay)
binding.recyclerView.adapter = ConcatAdapter(headerAdapter, followRequestsAdapter)
@ -247,7 +247,7 @@ class AccountListFragment :
override fun onRespondToFollowRequest(
accept: Boolean,
accountId: String,
position: Int
position: Int,
) {
if (accept) {
api.authorizeFollowRequest(accountId)
@ -266,7 +266,7 @@ class AccountListFragment :
"reject"
}
Log.e(TAG, "Failed to $verb account id $accountId.", throwable)
}
},
)
}
@ -365,7 +365,7 @@ class AccountListFragment :
binding.messageView.setup(
R.drawable.elephant_friend_empty,
R.string.message_empty,
null
null,
)
} else {
binding.messageView.hide()

View File

@ -28,7 +28,7 @@ abstract class AccountAdapter<AVH : RecyclerView.ViewHolder> internal constructo
protected val accountActionListener: AccountActionListener,
protected val animateAvatar: Boolean,
protected val animateEmojis: Boolean,
protected val showBotOverlay: Boolean
protected val showBotOverlay: Boolean,
) : RecyclerView.Adapter<RecyclerView.ViewHolder?>() {
protected var accountList: MutableList<TimelineAccount> = mutableListOf()
@ -51,7 +51,7 @@ abstract class AccountAdapter<AVH : RecyclerView.ViewHolder> internal constructo
final override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
viewType: Int,
): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_ACCOUNT -> this.createAccountViewHolder(parent)
@ -61,7 +61,7 @@ abstract class AccountAdapter<AVH : RecyclerView.ViewHolder> internal constructo
}
private fun createFooterViewHolder(
parent: ViewGroup
parent: ViewGroup,
): RecyclerView.ViewHolder {
val binding = ItemFooterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BindingHolder(binding)

View File

@ -30,12 +30,12 @@ class BlocksAdapter(
accountActionListener: AccountActionListener,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) : AccountAdapter<BindingHolder<ItemBlockedUserBinding>>(
accountActionListener = accountActionListener,
animateAvatar = animateAvatar,
animateEmojis = animateEmojis,
showBotOverlay = showBotOverlay
showBotOverlay = showBotOverlay,
) {
override fun createAccountViewHolder(parent: ViewGroup): BindingHolder<ItemBlockedUserBinding> {

View File

@ -26,12 +26,12 @@ class FollowAdapter(
accountActionListener: AccountActionListener,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) : AccountAdapter<AccountViewHolder>(
accountActionListener = accountActionListener,
animateAvatar = animateAvatar,
animateEmojis = animateEmojis,
showBotOverlay = showBotOverlay
showBotOverlay = showBotOverlay,
) {
override fun createAccountViewHolder(parent: ViewGroup): AccountViewHolder {
@ -44,7 +44,7 @@ class FollowAdapter(
accountList[position],
animateAvatar,
animateEmojis,
showBotOverlay
showBotOverlay,
)
viewHolder.setupActionListener(accountActionListener)
}

View File

@ -28,25 +28,25 @@ class FollowRequestsAdapter(
private val linkListener: LinkListener,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) : AccountAdapter<FollowRequestViewHolder>(
accountActionListener = accountActionListener,
animateAvatar = animateAvatar,
animateEmojis = animateEmojis,
showBotOverlay = showBotOverlay
showBotOverlay = showBotOverlay,
) {
override fun createAccountViewHolder(parent: ViewGroup): FollowRequestViewHolder {
val binding = ItemFollowRequestBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
false,
)
return FollowRequestViewHolder(
binding,
accountActionListener,
linkListener,
showHeader = false
showHeader = false,
)
}
@ -55,7 +55,7 @@ class FollowRequestsAdapter(
account = accountList[position],
animateAvatar = animateAvatar,
animateEmojis = animateEmojis,
showBotOverlay = showBotOverlay
showBotOverlay = showBotOverlay,
)
viewHolder.setupActionListener(accountActionListener, accountList[position].id)
}

View File

@ -24,7 +24,7 @@ import com.keylesspalace.tusky.util.BindingHolder
class FollowRequestsHeaderAdapter(
private val instanceName: String,
private val accountLocked: Boolean
private val accountLocked: Boolean,
) : RecyclerView.Adapter<BindingHolder<ItemFollowRequestsHeaderBinding>>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemFollowRequestsHeaderBinding> {

View File

@ -31,12 +31,12 @@ class MutesAdapter(
accountActionListener: AccountActionListener,
animateAvatar: Boolean,
animateEmojis: Boolean,
showBotOverlay: Boolean
showBotOverlay: Boolean,
) : AccountAdapter<BindingHolder<ItemMutedUserBinding>>(
accountActionListener = accountActionListener,
animateAvatar = animateAvatar,
animateEmojis = animateEmojis,
showBotOverlay = showBotOverlay
showBotOverlay = showBotOverlay,
) {
private val mutingNotificationsMap = HashMap<String, Boolean>()
@ -83,7 +83,7 @@ class MutesAdapter(
false,
account.id,
viewHolder.bindingAdapterPosition,
false
false,
)
}
binding.mutedUserMuteNotifications.setOnCheckedChangeListener { _, isChecked ->
@ -91,7 +91,7 @@ class MutesAdapter(
true,
account.id,
viewHolder.bindingAdapterPosition,
isChecked
isChecked,
)
}
binding.root.setOnClickListener { accountActionListener.onViewAccount(account.id) }

View File

@ -47,7 +47,7 @@ class AnnouncementAdapter(
private var items: List<Announcement> = emptyList(),
private val listener: AnnouncementActionListener,
private val wellbeingEnabled: Boolean = false,
private val animateEmojis: Boolean = false
private val animateEmojis: Boolean = false,
) : RecyclerView.Adapter<BindingHolder<ItemAnnouncementBinding>>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemAnnouncementBinding> {

View File

@ -37,7 +37,7 @@ import javax.inject.Inject
class AnnouncementsViewModel @Inject constructor(
private val instanceInfoRepo: InstanceInfoRepository,
private val mastodonApi: MastodonApi,
private val eventHub: EventHub
private val eventHub: EventHub,
) : ViewModel() {
private val announcementsMutable = MutableLiveData<Resource<List<Announcement>>>()
@ -70,15 +70,15 @@ class AnnouncementsViewModel @Inject constructor(
Log.d(
TAG,
"Failed to mark announcement as read.",
throwable
throwable,
)
}
},
)
}
},
{
announcementsMutable.postValue(Error(cause = it))
}
},
)
}
}
@ -98,7 +98,7 @@ class AnnouncementsViewModel @Inject constructor(
if (reaction.name == name) {
reaction.copy(
count = reaction.count + 1,
me = true
me = true,
)
} else {
reaction
@ -113,22 +113,22 @@ class AnnouncementsViewModel @Inject constructor(
1,
true,
url,
staticUrl
staticUrl,
)
}
},
)
}
},
)
} else {
announcement
}
}
)
},
),
)
},
{
Log.w(TAG, "Failed to add reaction to the announcement.", it)
}
},
)
}
}
@ -148,7 +148,7 @@ class AnnouncementsViewModel @Inject constructor(
if (reaction.count > 1) {
reaction.copy(
count = reaction.count - 1,
me = false
me = false,
)
} else {
null
@ -156,18 +156,18 @@ class AnnouncementsViewModel @Inject constructor(
} else {
reaction
}
}
},
)
} else {
announcement
}
}
)
},
),
)
},
{
Log.w(TAG, "Failed to remove reaction from the announcement.", it)
}
},
)
}
}

View File

@ -191,7 +191,7 @@ class ComposeActivity :
size,
itemOld.description,
null, // Intentionally reset focus when cropping
itemOld
itemOld,
)
}
}
@ -230,7 +230,7 @@ class ComposeActivity :
// TODO this is inconsistent to CaptionDialog (device rotation)?
},
onEditImage = this::editImageInQueue,
onRemove = this::removeMediaFromQueue
onRemove = this::removeMediaFromQueue,
)
binding.composeMediaPreviewBar.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
@ -248,7 +248,7 @@ class ComposeActivity :
if (accountManager.shouldDisplaySelfUsername(this)) {
binding.composeUsernameView.text = getString(
R.string.compose_active_account_description,
activeAccount.fullName
activeAccount.fullName,
)
binding.composeUsernameView.show()
} else {
@ -380,8 +380,8 @@ class ComposeActivity :
this,
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false),
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
preferences.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true)
)
preferences.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true),
),
)
binding.composeEditField.setTokenizer(ComposeTokenizer())
@ -473,8 +473,8 @@ class ComposeActivity :
displayTransientMessage(
getString(
R.string.error_media_upload_sending_fmt,
throwable.message
)
throwable.message,
),
)
}
}
@ -542,7 +542,7 @@ class ComposeActivity :
handleCloseButton()
}
}
},
)
}
@ -583,11 +583,11 @@ class ComposeActivity :
activeAccount.profilePictureUrl,
binding.composeAvatar,
avatarSize / 8,
animateAvatars
animateAvatars,
)
binding.composeAvatar.contentDescription = getString(
R.string.compose_active_account_description,
activeAccount.fullName
activeAccount.fullName,
)
}
@ -821,7 +821,7 @@ class ComposeActivity :
ActivityCompat.requestPermissions(
this@ComposeActivity,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE
PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE,
)
} else {
pickMediaFile.launch(true)
@ -830,7 +830,7 @@ class ComposeActivity :
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
}
},
)
addMediaBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
}
@ -845,7 +845,7 @@ class ComposeActivity :
maxOptionLength = instanceParams.pollMaxLength,
minDuration = instanceParams.pollMinDuration,
maxDuration = instanceParams.pollMaxDuration,
onUpdatePoll = viewModel::updatePoll
onUpdatePoll = viewModel::updatePoll,
)
}
@ -889,7 +889,7 @@ class ComposeActivity :
return statusLength(
binding.composeEditField.text,
binding.composeContentWarningField.text,
charactersReservedPerUrl
charactersReservedPerUrl,
)
}
@ -935,7 +935,7 @@ class ComposeActivity :
for (i in 0 until content.clip.itemCount) {
pickMedia(
content.clip.getItemAt(i).uri,
contentInfo.clip.description.label as String?
contentInfo.clip.description.label as String?,
)
}
}
@ -976,7 +976,7 @@ class ComposeActivity :
Snackbar.make(
binding.activityCompose,
R.string.error_media_upload_permission,
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
).apply {
setAction(R.string.action_retry) { onMediaPick() }
// necessary so snackbar is shown over everything
@ -1001,7 +1001,7 @@ class ComposeActivity :
photoUploadUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID + ".fileprovider",
photoFile
photoFile,
)
takePicture.launch(photoUploadUri)
}
@ -1015,7 +1015,7 @@ class ComposeActivity :
android.R.attr.textColorTertiary
} else {
R.attr.textColorDisabled
}
},
)
}
@ -1027,7 +1027,7 @@ class ComposeActivity :
android.R.attr.textColorTertiary
} else {
R.attr.textColorDisabled
}
},
)
binding.addPollTextActionTextView.setTextColor(textColor)
binding.addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN)
@ -1049,7 +1049,7 @@ class ComposeActivity :
options(uri = item.uri) {
setOutputUri(uriNew)
setOutputCompressFormat(if (isPng) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG)
}
},
)
}
@ -1227,7 +1227,7 @@ class ComposeActivity :
null,
getString(R.string.saving_draft),
true,
false
false,
)
} else {
null
@ -1263,7 +1263,7 @@ class ComposeActivity :
val id: String? = null,
val description: String? = null,
val focus: Attachment.Focus? = null,
val state: State
val state: State,
) {
enum class Type {
IMAGE, VIDEO, AUDIO;
@ -1306,7 +1306,7 @@ class ComposeActivity :
EDIT_DRAFT,
/** Editing an an existing scheduled status */
EDIT_SCHEDULED
EDIT_SCHEDULED,
}
@Parcelize
@ -1332,7 +1332,7 @@ class ComposeActivity :
var modifiedInitialState: Boolean? = null,
var language: String? = null,
var statusId: String? = null,
var kind: ComposeKind? = null
var kind: ComposeKind? = null,
) : Parcelable
companion object {
@ -1352,7 +1352,7 @@ class ComposeActivity :
@JvmStatic
fun startIntent(
context: Context,
options: ComposeOptions
options: ComposeOptions,
): Intent {
return Intent(context, ComposeActivity::class.java).apply {
putExtra(COMPOSE_OPTIONS_EXTRA, options)

View File

@ -37,7 +37,7 @@ class ComposeAutoCompleteAdapter(
private val autocompletionProvider: AutocompletionProvider,
private val animateAvatar: Boolean,
private val animateEmojis: Boolean,
private val showBotBadge: Boolean
private val showBotBadge: Boolean,
) : BaseAdapter(), Filterable {
private var resultList: List<AutocompleteResult> = emptyList()
@ -113,7 +113,7 @@ class ComposeAutoCompleteAdapter(
account.avatar,
binding.avatar,
avatarRadius,
animateAvatar
animateAvatar,
)
binding.avatarBadge.visible(showBotBadge && account.bot)
}

View File

@ -58,7 +58,7 @@ class ComposeViewModel @Inject constructor(
private val mediaUploader: MediaUploader,
private val serviceClient: ServiceClient,
private val draftHelper: DraftHelper,
instanceInfoRepo: InstanceInfoRepository
instanceInfoRepo: InstanceInfoRepository,
) : ViewModel() {
private var replyingStatusAuthor: String? = null
@ -124,7 +124,7 @@ class ComposeViewModel @Inject constructor(
mediaSize: Long,
description: String? = null,
focus: Attachment.Focus? = null,
replaceItem: QueuedMedia? = null
replaceItem: QueuedMedia? = null,
): QueuedMedia {
var stashMediaItem: QueuedMedia? = null
@ -136,7 +136,7 @@ class ComposeViewModel @Inject constructor(
mediaSize = mediaSize,
description = description,
focus = focus,
state = QueuedMedia.State.UPLOADING
state = QueuedMedia.State.UPLOADING,
)
stashMediaItem = mediaItem
@ -164,7 +164,7 @@ class ComposeViewModel @Inject constructor(
item.copy(
id = event.mediaId,
uploadPercent = -1,
state = if (event.processed) { QueuedMedia.State.PROCESSED } else { QueuedMedia.State.UNPROCESSED }
state = if (event.processed) { QueuedMedia.State.PROCESSED } else { QueuedMedia.State.UNPROCESSED },
)
is UploadEvent.ErrorEvent -> {
media.update { mediaList -> mediaList.filter { it.localId != mediaItem.localId } }
@ -197,7 +197,7 @@ class ComposeViewModel @Inject constructor(
id = id,
description = description,
focus = focus,
state = QueuedMedia.State.PUBLISHED
state = QueuedMedia.State.PUBLISHED,
)
mediaList + mediaItem
}
@ -297,7 +297,7 @@ class ComposeViewModel @Inject constructor(
failedToSendAlert = false,
scheduledAt = scheduledAt.value,
language = postLanguage,
statusId = originalStatusId
statusId = originalStatusId,
)
}
@ -308,7 +308,7 @@ class ComposeViewModel @Inject constructor(
suspend fun sendStatus(
content: String,
spoilerText: String,
accountId: Long
accountId: Long,
) {
if (!scheduledTootId.isNullOrEmpty()) {
api.deleteScheduledStatus(scheduledTootId!!)
@ -321,7 +321,7 @@ class ComposeViewModel @Inject constructor(
uri = item.uri.toString(),
description = item.description,
focus = item.focus,
processed = item.state == QueuedMedia.State.PROCESSED || item.state == QueuedMedia.State.PUBLISHED
processed = item.state == QueuedMedia.State.PROCESSED || item.state == QueuedMedia.State.PUBLISHED,
)
}
val tootToSend = StatusToSend(
@ -340,7 +340,7 @@ class ComposeViewModel @Inject constructor(
idempotencyKey = randomAlphanumericString(16),
retries = 0,
language = postLanguage,
statusId = originalStatusId
statusId = originalStatusId,
)
serviceClient.sendToot(tootToSend)
@ -379,7 +379,7 @@ class ComposeViewModel @Inject constructor(
}, { e ->
Log.e(TAG, "Autocomplete search for $token failed.", e)
emptyList()
})
},)
}
'#' -> {
return api.searchSync(query = token, type = SearchType.Hashtag.apiParameter, limit = 10)
@ -388,7 +388,7 @@ class ComposeViewModel @Inject constructor(
}, { e ->
Log.e(TAG, "Autocomplete search for $token failed.", e)
emptyList()
})
},)
}
':' -> {
val emojiList = emoji.replayCache.firstOrNull() ?: return emptyList()
@ -420,7 +420,7 @@ class ComposeViewModel @Inject constructor(
val replyVisibility = composeOptions?.replyVisibility ?: Status.Visibility.UNKNOWN
startingVisibility = Status.Visibility.byNum(
preferredVisibility.num.coerceAtLeast(replyVisibility.num)
preferredVisibility.num.coerceAtLeast(replyVisibility.num),
)
inReplyToId = composeOptions?.inReplyToId
@ -516,7 +516,7 @@ class ComposeViewModel @Inject constructor(
SAVE_OR_DISCARD,
UPDATE_OR_DISCARD,
CONTINUE_EDITING_OR_DISCARD_CHANGES, // editing post
CONTINUE_EDITING_OR_DISCARD_DRAFT // edit draft
CONTINUE_EDITING_OR_DISCARD_DRAFT, // edit draft
}
}

View File

@ -39,7 +39,7 @@ fun downsizeImage(
uri: Uri,
sizeLimit: Int,
contentResolver: ContentResolver,
tempFile: File
tempFile: File,
): Boolean {
val decodeBoundsInputStream = try {
contentResolver.openInputStream(uri)

View File

@ -34,7 +34,7 @@ class MediaPreviewAdapter(
private val onAddCaption: (ComposeActivity.QueuedMedia) -> Unit,
private val onAddFocus: (ComposeActivity.QueuedMedia) -> Unit,
private val onEditImage: (ComposeActivity.QueuedMedia) -> Unit,
private val onRemove: (ComposeActivity.QueuedMedia) -> Unit
private val onRemove: (ComposeActivity.QueuedMedia) -> Unit,
) : RecyclerView.Adapter<MediaPreviewAdapter.PreviewViewHolder>() {
fun submitList(list: List<ComposeActivity.QueuedMedia>) {
@ -120,7 +120,7 @@ class MediaPreviewAdapter(
override fun areContentsTheSame(oldItem: ComposeActivity.QueuedMedia, newItem: ComposeActivity.QueuedMedia): Boolean {
return oldItem == newItem
}
}
},
)
inner class PreviewViewHolder(val progressImageView: ProgressImageView) :

View File

@ -71,7 +71,7 @@ sealed class UploadEvent {
data class UploadData(
val flow: Flow<UploadEvent>,
val scope: CoroutineScope
val scope: CoroutineScope,
)
fun createNewImageFile(context: Context, suffix: String = ".jpg"): File {
@ -82,7 +82,7 @@ fun createNewImageFile(context: Context, suffix: String = ".jpg"): File {
return File.createTempFile(
imageFileName, /* prefix */
suffix, /* suffix */
storageDir /* directory */
storageDir, /* directory */
)
}
@ -96,7 +96,7 @@ class UploadServerError(val errorMessage: String) : Exception()
@Singleton
class MediaUploader @Inject constructor(
private val context: Context,
private val mediaUploadApi: MediaUploadApi
private val mediaUploadApi: MediaUploadApi,
) {
private val uploads = mutableMapOf<Int, UploadData>()
@ -175,7 +175,7 @@ class MediaUploader @Inject constructor(
uri = FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + ".fileprovider",
file
file,
)
mediaSize = getMediaSize(contentResolver, uri)
}
@ -198,7 +198,7 @@ class MediaUploader @Inject constructor(
uri = FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + ".fileprovider",
file
file,
)
mediaSize = getMediaSize(contentResolver, uri)
}
@ -268,7 +268,7 @@ class MediaUploader @Inject constructor(
context.getString(R.string.app_name),
Date().time.toString(),
randomAlphanumericString(10),
fileExtension
fileExtension,
)
val stream = contentResolver.openInputStream(media.uri)
@ -279,7 +279,7 @@ class MediaUploader @Inject constructor(
val fileBody = ProgressRequestBody(
stream!!,
media.mediaSize,
mimeType.toMediaTypeOrNull()!!
mimeType.toMediaTypeOrNull()!!,
) { percentage ->
if (percentage != lastProgress) {
trySend(UploadEvent.ProgressEvent(percentage))

View File

@ -33,7 +33,7 @@ fun showAddPollDialog(
maxOptionLength: Int,
minDuration: Int,
maxDuration: Int,
onUpdatePoll: (NewPoll) -> Unit
onUpdatePoll: (NewPoll) -> Unit,
) {
val binding = DialogAddPollBinding.inflate(LayoutInflater.from(context))
@ -54,7 +54,7 @@ fun showAddPollDialog(
},
onOptionChanged = { valid ->
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = valid
}
},
)
binding.pollChoices.adapter = adapter
@ -94,8 +94,8 @@ fun showAddPollDialog(
NewPoll(
options = adapter.pollOptions,
expiresIn = durations[selectedPollDurationId],
multiple = binding.multipleChoicesCheckBox.isChecked
)
multiple = binding.multipleChoicesCheckBox.isChecked,
),
)
dialog.dismiss()

View File

@ -30,7 +30,7 @@ class AddPollOptionsAdapter(
private var options: MutableList<String>,
private val maxOptionLength: Int,
private val onOptionRemoved: (Boolean) -> Unit,
private val onOptionChanged: (Boolean) -> Unit
private val onOptionChanged: (Boolean) -> Unit,
) : RecyclerView.Adapter<BindingHolder<ItemAddPollOptionBinding>>() {
val pollOptions: List<String>

View File

@ -56,7 +56,7 @@ class CaptionDialog : DialogFragment() {
input.hint = resources.getQuantityString(
R.plurals.hint_describe_for_visually_impaired,
MEDIA_DESCRIPTION_CHARACTER_LIMIT,
MEDIA_DESCRIPTION_CHARACTER_LIMIT
MEDIA_DESCRIPTION_CHARACTER_LIMIT,
)
input.filters = arrayOf(InputFilter.LengthFilter(MEDIA_DESCRIPTION_CHARACTER_LIMIT))
input.setText(arguments?.getString(EXISTING_DESCRIPTION_ARG))
@ -79,18 +79,20 @@ class CaptionDialog : DialogFragment() {
Glide.with(this)
.load(previewUri)
.downsample(DownsampleStrategy.CENTER_INSIDE)
.into(object : CustomTarget<Drawable>(4096, 4096) {
override fun onLoadCleared(placeholder: Drawable?) {
imageView.setImageDrawable(placeholder)
}
.into(
object : CustomTarget<Drawable>(4096, 4096) {
override fun onLoadCleared(placeholder: Drawable?) {
imageView.setImageDrawable(placeholder)
}
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?
) {
imageView.setImageDrawable(resource)
}
})
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?,
) {
imageView.setImageDrawable(resource)
}
},
)
return dialog
}
@ -103,7 +105,7 @@ class CaptionDialog : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View? {
savedInstanceState?.getString(DESCRIPTION_KEY)?.let {
input.setText(it)
@ -124,12 +126,12 @@ class CaptionDialog : DialogFragment() {
fun newInstance(
localId: Int,
existingDescription: String?,
previewUri: Uri
previewUri: Uri,
) = CaptionDialog().apply {
arguments = bundleOf(
LOCAL_ID_ARG to localId,
EXISTING_DESCRIPTION_ARG to existingDescription,
PREVIEW_URI_ARG to previewUri
PREVIEW_URI_ARG to previewUri,
)
}

View File

@ -37,7 +37,7 @@ import kotlinx.coroutines.launch
fun <T> T.makeFocusDialog(
existingFocus: Focus?,
previewUri: Uri,
onUpdateFocus: suspend (Focus) -> Unit
onUpdateFocus: suspend (Focus) -> Unit,
) where T : AppCompatActivity, T : LifecycleOwner {
val focus = existingFocus ?: Focus(0.0f, 0.0f) // Default to center
@ -48,31 +48,33 @@ fun <T> T.makeFocusDialog(
Glide.with(this)
.load(previewUri)
.downsample(DownsampleStrategy.CENTER_INSIDE)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(p0: GlideException?, p1: Any?, p2: Target<Drawable?>?, p3: Boolean): Boolean {
return false
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable?>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
val width = resource!!.intrinsicWidth
val height = resource.intrinsicHeight
dialogBinding.focusIndicator.setImageSize(width, height)
// We want the dialog to be a little taller than the image, so you can slide your thumb past the image border,
// but if it's *too* much taller that looks weird. See if a threshold has been crossed:
if (width > height) {
val maxHeight = dialogBinding.focusIndicator.maxAttractiveHeight()
if (dialogBinding.imageView.height > maxHeight) {
val verticalShrinkLayout = FrameLayout.LayoutParams(width, maxHeight)
dialogBinding.imageView.layoutParams = verticalShrinkLayout
dialogBinding.focusIndicator.layoutParams = verticalShrinkLayout
}
.listener(
object : RequestListener<Drawable> {
override fun onLoadFailed(p0: GlideException?, p1: Any?, p2: Target<Drawable?>?, p3: Boolean): Boolean {
return false
}
return false // Pass through
}
})
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable?>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
val width = resource!!.intrinsicWidth
val height = resource.intrinsicHeight
dialogBinding.focusIndicator.setImageSize(width, height)
// We want the dialog to be a little taller than the image, so you can slide your thumb past the image border,
// but if it's *too* much taller that looks weird. See if a threshold has been crossed:
if (width > height) {
val maxHeight = dialogBinding.focusIndicator.maxAttractiveHeight()
if (dialogBinding.imageView.height > maxHeight) {
val verticalShrinkLayout = FrameLayout.LayoutParams(width, maxHeight)
dialogBinding.imageView.layoutParams = verticalShrinkLayout
dialogBinding.focusIndicator.layoutParams = verticalShrinkLayout
}
}
return false // Pass through
}
},
)
.into(dialogBinding.imageView)
val okListener = { dialog: DialogInterface, _: Int ->
@ -90,7 +92,7 @@ fun <T> T.makeFocusDialog(
val window = dialog.window
window?.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE,
)
dialog.show()

View File

@ -40,7 +40,7 @@ class ComposeScheduleView
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) : ConstraintLayout(context, attrs, defStyleAttr) {
interface OnTimeSetListener {
fun onTimeSet(time: String?)
@ -48,14 +48,14 @@ class ComposeScheduleView
private var binding = ViewComposeScheduleBinding.inflate(
(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater),
this
this,
)
private var listener: OnTimeSetListener? = null
private var dateFormat = SimpleDateFormat.getDateInstance()
private var timeFormat = SimpleDateFormat.getTimeInstance()
private var iso8601 = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
Locale.getDefault()
Locale.getDefault(),
).apply {
timeZone = TimeZone.getTimeZone("UTC")
}
@ -85,7 +85,7 @@ class ComposeScheduleView
binding.scheduledDateTime.text = String.format(
"%s %s",
dateFormat.format(scheduled),
timeFormat.format(scheduled)
timeFormat.format(scheduled),
)
verifyScheduledTime(scheduled)
}
@ -184,7 +184,7 @@ class ComposeScheduleView
val minimumScheduledTime = calendar()
minimumScheduledTime.add(
Calendar.SECOND,
MINIMUM_SCHEDULED_SECONDS
MINIMUM_SCHEDULED_SECONDS,
)
scheduledTime.after(minimumScheduledTime.time)
} else {

View File

@ -30,7 +30,7 @@ import androidx.emoji2.viewsintegration.EmojiEditTextHelper
class EditTextTyped @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null
attributeSet: AttributeSet? = null,
) :
AppCompatMultiAutoCompleteTextView(context, attributeSet) {
@ -60,7 +60,7 @@ class EditTextTyped @JvmOverloads constructor(
EditorInfoCompat.setContentMimeTypes(editorInfo, arrayOf("image/*"))
return emojiEditTextHelper.onCreateInputConnection(
InputConnectionCompat.createWrapper(this, connection, editorInfo),
editorInfo
editorInfo,
)!!
}

View File

@ -19,7 +19,7 @@ class FocusIndicatorView
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) {
private var focus: Attachment.Focus? = null
private var imageSize: Point? = null

View File

@ -27,7 +27,7 @@ import com.keylesspalace.tusky.entity.NewPoll
class PollPreviewView @JvmOverloads constructor(
context: Context?,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) :
LinearLayout(context, attrs, defStyleAttr) {

View File

@ -33,7 +33,7 @@ class ProgressImageView
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) : MediaPreviewImageView(context, attrs, defStyleAttr) {
private var progress = -1
private val progressRect = RectF()
@ -52,7 +52,7 @@ class ProgressImageView
}
private val captionDrawable = AppCompatResources.getDrawable(
context,
R.drawable.spellcheck
R.drawable.spellcheck,
)!!.apply {
setTint(Color.WHITE)
}
@ -98,7 +98,7 @@ class ProgressImageView
width - circleMargin - circleRadius,
height - circleMargin - circleRadius,
width - circleMargin,
height - circleMargin
height - circleMargin,
)
captionDrawable.draw(canvas)
}

View File

@ -30,7 +30,7 @@ class TootButton
@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) : MaterialButton(context, attrs, defStyleAttr) {
private val smallStyle: Boolean = context.resources.getBoolean(R.bool.show_small_toot_button)
@ -58,7 +58,8 @@ class TootButton
null
}
Status.Visibility.PRIVATE,
Status.Visibility.DIRECT -> {
Status.Visibility.DIRECT,
-> {
setText(R.string.action_send)
IconicsDrawable(context, GoogleMaterial.Icon.gmd_lock).apply { sizeDp = 18; colorInt = Color.WHITE }
}

View File

@ -26,14 +26,14 @@ import com.keylesspalace.tusky.util.StatusDisplayOptions
class ConversationAdapter(
private var statusDisplayOptions: StatusDisplayOptions,
private val listener: StatusActionListener
private val listener: StatusActionListener,
) : PagingDataAdapter<ConversationViewData, ConversationViewHolder>(CONVERSATION_COMPARATOR) {
var mediaPreviewEnabled: Boolean
get() = statusDisplayOptions.mediaPreviewEnabled
set(mediaPreviewEnabled) {
statusDisplayOptions = statusDisplayOptions.copy(
mediaPreviewEnabled = mediaPreviewEnabled
mediaPreviewEnabled = mediaPreviewEnabled,
)
}
@ -49,7 +49,7 @@ class ConversationAdapter(
override fun onBindViewHolder(
holder: ConversationViewHolder,
position: Int,
payloads: List<Any>
payloads: List<Any>,
) {
getItem(position)?.let { conversationViewData ->
holder.setupWithConversation(conversationViewData, payloads.firstOrNull())

View File

@ -37,7 +37,7 @@ data class ConversationEntity(
val order: Int,
val accounts: List<ConversationAccountEntity>,
val unread: Boolean,
@Embedded(prefix = "s_") val lastStatus: ConversationStatusEntity
@Embedded(prefix = "s_") val lastStatus: ConversationStatusEntity,
) {
fun toViewData(): ConversationViewData {
return ConversationViewData(
@ -45,7 +45,7 @@ data class ConversationEntity(
order = order,
accounts = accounts,
unread = unread,
lastStatus = lastStatus.toViewData()
lastStatus = lastStatus.toViewData(),
)
}
}
@ -56,7 +56,7 @@ data class ConversationAccountEntity(
val username: String,
val displayName: String,
val avatar: String,
val emojis: List<Emoji>
val emojis: List<Emoji>,
) {
fun toAccount(): TimelineAccount {
return TimelineAccount(
@ -67,7 +67,7 @@ data class ConversationAccountEntity(
note = "",
url = "",
avatar = avatar,
emojis = emojis
emojis = emojis,
)
}
}
@ -97,7 +97,7 @@ data class ConversationStatusEntity(
val collapsed: Boolean,
val muted: Boolean,
val poll: Poll?,
val language: String?
val language: String?,
) {
fun toViewData(): StatusViewData {
@ -131,11 +131,11 @@ data class ConversationStatusEntity(
poll = poll,
card = null,
language = language,
filtered = null
filtered = null,
),
isExpanded = expanded,
isShowingContent = showingHiddenContent,
isCollapsed = collapsed
isCollapsed = collapsed,
)
}
}
@ -147,13 +147,13 @@ fun TimelineAccount.toEntity() =
username = username,
displayName = name,
avatar = avatar,
emojis = emojis.orEmpty()
emojis = emojis.orEmpty(),
)
fun Status.toEntity(
expanded: Boolean,
contentShowing: Boolean,
contentCollapsed: Boolean
contentCollapsed: Boolean,
) =
ConversationStatusEntity(
id = id,
@ -179,7 +179,7 @@ fun Status.toEntity(
collapsed = contentCollapsed,
muted = muted ?: false,
poll = poll,
language = language
language = language,
)
fun Conversation.toEntity(
@ -187,7 +187,7 @@ fun Conversation.toEntity(
order: Int,
expanded: Boolean,
contentShowing: Boolean,
contentCollapsed: Boolean
contentCollapsed: Boolean,
) =
ConversationEntity(
accountId = accountId,
@ -198,6 +198,6 @@ fun Conversation.toEntity(
lastStatus = lastStatus!!.toEntity(
expanded = expanded,
contentShowing = contentShowing,
contentCollapsed = contentCollapsed
)
contentCollapsed = contentCollapsed,
),
)

View File

@ -24,7 +24,7 @@ import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.visible
class ConversationLoadStateAdapter(
private val retryCallback: () -> Unit
private val retryCallback: () -> Unit,
) : LoadStateAdapter<BindingHolder<ItemNetworkStateBinding>>() {
override fun onBindViewHolder(holder: BindingHolder<ItemNetworkStateBinding>, loadState: LoadState) {
@ -45,7 +45,7 @@ class ConversationLoadStateAdapter(
override fun onCreateViewHolder(
parent: ViewGroup,
loadState: LoadState
loadState: LoadState,
): BindingHolder<ItemNetworkStateBinding> {
val binding = ItemNetworkStateBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BindingHolder(binding)

View File

@ -23,7 +23,7 @@ data class ConversationViewData(
val order: Int,
val accounts: List<ConversationAccountEntity>,
val unread: Boolean,
val lastStatus: StatusViewData
val lastStatus: StatusViewData,
) {
fun toEntity(
accountId: Long,
@ -33,7 +33,7 @@ data class ConversationViewData(
poll: Poll? = lastStatus.status.poll,
expanded: Boolean = lastStatus.isExpanded,
collapsed: Boolean = lastStatus.isCollapsed,
showingHiddenContent: Boolean = lastStatus.isShowingContent
showingHiddenContent: Boolean = lastStatus.isShowingContent,
): ConversationEntity {
return ConversationEntity(
accountId = accountId,
@ -48,8 +48,8 @@ data class ConversationViewData(
poll = poll,
expanded = expanded,
collapsed = collapsed,
showingHiddenContent = showingHiddenContent
)
showingHiddenContent = showingHiddenContent,
),
)
}
}
@ -61,7 +61,7 @@ fun StatusViewData.toConversationStatusEntity(
poll: Poll? = status.poll,
expanded: Boolean = isExpanded,
collapsed: Boolean = isCollapsed,
showingHiddenContent: Boolean = isShowingContent
showingHiddenContent: Boolean = isShowingContent,
): ConversationStatusEntity {
return ConversationStatusEntity(
id = id,
@ -87,6 +87,6 @@ fun StatusViewData.toConversationStatusEntity(
collapsed = collapsed,
muted = muted,
poll = poll,
language = status.language
language = status.language,
)
}

View File

@ -111,7 +111,7 @@ class ConversationsFragment :
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
)
adapter = ConversationAdapter(statusDisplayOptions, this)
@ -147,35 +147,39 @@ class ConversationsFragment :
}
}
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
if (positionStart == 0 && adapter.itemCount != itemCount) {
binding.recyclerView.post {
if (getView() != null) {
binding.recyclerView.scrollBy(0, Utils.dpToPx(requireContext(), -30))
adapter.registerAdapterDataObserver(
object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
if (positionStart == 0 && adapter.itemCount != itemCount) {
binding.recyclerView.post {
if (getView() != null) {
binding.recyclerView.scrollBy(0, Utils.dpToPx(requireContext(), -30))
}
}
}
}
}
})
},
)
hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false)
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
val composeButton = (activity as ActionButtonActivity).actionButton
if (composeButton != null) {
if (hideFab) {
if (dy > 0 && composeButton.isShown) {
composeButton.hide() // hides the button if we're scrolling down
} else if (dy < 0 && !composeButton.isShown) {
composeButton.show() // shows it if we are scrolling up
binding.recyclerView.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
val composeButton = (activity as ActionButtonActivity).actionButton
if (composeButton != null) {
if (hideFab) {
if (dy > 0 && composeButton.isShown) {
composeButton.hide() // hides the button if we're scrolling down
} else if (dy < 0 && !composeButton.isShown) {
composeButton.show() // shows it if we are scrolling up
}
} else if (!composeButton.isShown) {
composeButton.show()
}
} else if (!composeButton.isShown) {
composeButton.show()
}
}
}
})
},
)
viewLifecycleOwner.lifecycleScope.launch {
viewModel.conversationFlow.collectLatest { pagingData ->
@ -190,7 +194,7 @@ class ConversationsFragment :
adapter.notifyItemRangeChanged(
0,
adapter.itemCount,
listOf(StatusBaseViewHolder.Key.KEY_CREATED)
listOf(StatusBaseViewHolder.Key.KEY_CREATED),
)
delay(1.toDuration(DurationUnit.MINUTES))
}

View File

@ -15,7 +15,7 @@ import retrofit2.HttpException
class ConversationsRemoteMediator(
private val api: MastodonApi,
private val db: AppDatabase,
accountManager: AccountManager
accountManager: AccountManager,
) : RemoteMediator<Int, ConversationEntity>() {
private var nextKey: String? = null
@ -26,7 +26,7 @@ class ConversationsRemoteMediator(
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, ConversationEntity>
state: PagingState<Int, ConversationEntity>,
): MediatorResult {
if (loadType == LoadType.PREPEND) {
return MediatorResult.Success(endOfPaginationReached = true)
@ -68,9 +68,9 @@ class ConversationsRemoteMediator(
order = order++,
expanded = expanded,
contentShowing = contentShowing,
contentCollapsed = contentCollapsed
contentCollapsed = contentCollapsed,
)
}
},
)
}
return MediatorResult.Success(endOfPaginationReached = nextKey == null)

View File

@ -37,7 +37,7 @@ class ConversationsViewModel @Inject constructor(
private val timelineCases: TimelineCases,
private val database: AppDatabase,
private val accountManager: AccountManager,
private val api: MastodonApi
private val api: MastodonApi,
) : ViewModel() {
@OptIn(ExperimentalPagingApi::class)
@ -51,7 +51,7 @@ class ConversationsViewModel @Inject constructor(
} else {
database.conversationDao().conversationsForAccount(activeAccount.id)
}
}
},
)
.flow
.map { pagingData ->
@ -64,13 +64,13 @@ class ConversationsViewModel @Inject constructor(
timelineCases.favourite(conversation.lastStatus.id, favourite).fold({
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
favourited = favourite
favourited = favourite,
)
saveConversationToDb(newConversation)
}, { e ->
Log.w(TAG, "failed to favourite status", e)
})
},)
}
}
@ -79,13 +79,13 @@ class ConversationsViewModel @Inject constructor(
timelineCases.bookmark(conversation.lastStatus.id, bookmark).fold({
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
bookmarked = bookmark
bookmarked = bookmark,
)
saveConversationToDb(newConversation)
}, { e ->
Log.w(TAG, "failed to bookmark status", e)
})
},)
}
}
@ -95,13 +95,13 @@ class ConversationsViewModel @Inject constructor(
.fold({ poll ->
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
poll = poll
poll = poll,
)
saveConversationToDb(newConversation)
}, { e ->
Log.w(TAG, "failed to vote in poll", e)
})
},)
}
}
@ -109,7 +109,7 @@ class ConversationsViewModel @Inject constructor(
viewModelScope.launch {
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
expanded = expanded
expanded = expanded,
)
saveConversationToDb(newConversation)
}
@ -119,7 +119,7 @@ class ConversationsViewModel @Inject constructor(
viewModelScope.launch {
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
collapsed = collapsed
collapsed = collapsed,
)
saveConversationToDb(newConversation)
}
@ -129,7 +129,7 @@ class ConversationsViewModel @Inject constructor(
viewModelScope.launch {
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
showingHiddenContent = showing
showingHiddenContent = showing,
)
saveConversationToDb(newConversation)
}
@ -142,7 +142,7 @@ class ConversationsViewModel @Inject constructor(
database.conversationDao().delete(
id = conversation.id,
accountId = accountManager.activeAccount!!.id
accountId = accountManager.activeAccount!!.id,
)
} catch (e: Exception) {
Log.w(TAG, "failed to delete conversation", e)
@ -155,12 +155,12 @@ class ConversationsViewModel @Inject constructor(
try {
timelineCases.muteConversation(
conversation.lastStatus.id,
!(conversation.lastStatus.status.muted ?: false)
!(conversation.lastStatus.status.muted ?: false),
)
val newConversation = conversation.toEntity(
accountId = accountManager.activeAccount!!.id,
muted = !(conversation.lastStatus.status.muted ?: false)
muted = !(conversation.lastStatus.status.muted ?: false),
)
database.conversationDao().insert(newConversation)

View File

@ -45,7 +45,7 @@ import javax.inject.Inject
class DraftHelper @Inject constructor(
val context: Context,
private val okHttpClient: OkHttpClient,
db: AppDatabase
db: AppDatabase,
) {
private val draftDao = db.draftDao()
@ -66,7 +66,7 @@ class DraftHelper @Inject constructor(
failedToSendAlert: Boolean,
scheduledAt: String?,
language: String?,
statusId: String?
statusId: String?,
) = withContext(Dispatchers.IO) {
val externalFilesDir = context.getExternalFilesDir("Tusky")
@ -108,8 +108,8 @@ class DraftHelper @Inject constructor(
uriString = uris[i].toString(),
description = mediaDescriptions[i],
focus = mediaFocus[i],
type = types[i]
)
type = types[i],
),
)
}
@ -127,7 +127,7 @@ class DraftHelper @Inject constructor(
failedToSendNew = failedToSendAlert,
scheduledAt = scheduledAt,
language = language,
statusId = statusId
statusId = statusId,
)
draftDao.insertOrReplace(draft)

View File

@ -28,7 +28,7 @@ import com.keylesspalace.tusky.db.DraftAttachment
import com.keylesspalace.tusky.view.MediaPreviewImageView
class DraftMediaAdapter(
private val attachmentClick: () -> Unit
private val attachmentClick: () -> Unit,
) : ListAdapter<DraftAttachment, DraftMediaAdapter.DraftMediaViewHolder>(
object : DiffUtil.ItemCallback<DraftAttachment>() {
override fun areItemsTheSame(oldItem: DraftAttachment, newItem: DraftAttachment): Boolean {
@ -38,7 +38,7 @@ class DraftMediaAdapter(
override fun areContentsTheSame(oldItem: DraftAttachment, newItem: DraftAttachment): Boolean {
return oldItem == newItem
}
}
},
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DraftMediaViewHolder {

View File

@ -119,7 +119,7 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
scheduledAt = draft.scheduledAt,
language = draft.language,
statusId = draft.statusId,
kind = ComposeActivity.ComposeKind.EDIT_DRAFT
kind = ComposeActivity.ComposeKind.EDIT_DRAFT,
)
bottomSheet.state = BottomSheetBehavior.STATE_HIDDEN
@ -140,7 +140,7 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
Snackbar.make(binding.root, getString(R.string.drafts_failed_loading_reply), Snackbar.LENGTH_SHORT)
.show()
}
}
},
)
}
}
@ -157,7 +157,7 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
scheduledAt = draft.scheduledAt,
language = draft.language,
statusId = draft.statusId,
kind = ComposeActivity.ComposeKind.EDIT_DRAFT
kind = ComposeActivity.ComposeKind.EDIT_DRAFT,
)
startActivity(ComposeActivity.startIntent(this, composeOptions))

View File

@ -34,7 +34,7 @@ interface DraftActionListener {
}
class DraftsAdapter(
private val listener: DraftActionListener
private val listener: DraftActionListener,
) : PagingDataAdapter<DraftEntity, BindingHolder<ItemDraftBinding>>(
object : DiffUtil.ItemCallback<DraftEntity>() {
override fun areItemsTheSame(oldItem: DraftEntity, newItem: DraftEntity): Boolean {
@ -44,7 +44,7 @@ class DraftsAdapter(
override fun areContentsTheSame(oldItem: DraftEntity, newItem: DraftEntity): Boolean {
return oldItem == newItem
}
}
},
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemDraftBinding> {

View File

@ -33,12 +33,12 @@ class DraftsViewModel @Inject constructor(
val database: AppDatabase,
val accountManager: AccountManager,
val api: MastodonApi,
private val draftHelper: DraftHelper
private val draftHelper: DraftHelper,
) : ViewModel() {
val drafts = Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { database.draftDao().draftsPagingSource(accountManager.activeAccount?.id!!) }
pagingSourceFactory = { database.draftDao().draftsPagingSource(accountManager.activeAccount?.id!!) },
).flow
.cachedIn(viewModelScope)

View File

@ -60,7 +60,7 @@ class EditFilterActivity : BaseActivity() {
filterContextNotifications to Filter.Kind.NOTIFICATIONS,
filterContextPublic to Filter.Kind.PUBLIC,
filterContextThread to Filter.Kind.THREAD,
filterContextAccount to Filter.Kind.ACCOUNT
filterContextAccount to Filter.Kind.ACCOUNT,
)
}
@ -77,7 +77,7 @@ class EditFilterActivity : BaseActivity() {
R.string.filter_addition_title
} else {
R.string.filter_edit_title
}
},
)
binding.actionChip.setOnClickListener { showAddKeywordDialog() }
@ -110,7 +110,7 @@ class EditFilterActivity : BaseActivity() {
Filter.Action.WARN
} else {
Filter.Action.HIDE
}
},
)
}
binding.filterDurationSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
@ -120,7 +120,7 @@ class EditFilterActivity : BaseActivity() {
position
} else {
position - 1
}
},
)
}
@ -192,7 +192,7 @@ class EditFilterActivity : BaseActivity() {
chip.text = if (filterKeyword.wholeWord) {
binding.root.context.getString(
R.string.filter_keyword_display_format,
filterKeyword.keyword
filterKeyword.keyword,
)
} else {
filterKeyword.keyword
@ -225,8 +225,8 @@ class EditFilterActivity : BaseActivity() {
FilterKeyword(
"",
binding.phraseEditText.text.toString(),
binding.phraseWholeWord.isChecked
)
binding.phraseWholeWord.isChecked,
),
)
}
.setNegativeButton(android.R.string.cancel, null)
@ -246,8 +246,8 @@ class EditFilterActivity : BaseActivity() {
keyword,
keyword.copy(
keyword = binding.phraseEditText.text.toString(),
wholeWord = binding.phraseWholeWord.isChecked
)
wholeWord = binding.phraseWholeWord.isChecked,
),
)
}
.setNegativeButton(android.R.string.cancel, null)
@ -285,12 +285,12 @@ class EditFilterActivity : BaseActivity() {
},
{
Snackbar.make(binding.root, "Error deleting filter '${filter.title}'", Snackbar.LENGTH_SHORT).show()
}
},
)
} else {
Snackbar.make(binding.root, "Error deleting filter '${filter.title}'", Snackbar.LENGTH_SHORT).show()
}
}
},
)
}
}

View File

@ -98,7 +98,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
title = title,
context = contexts,
filterAction = action,
expiresInSeconds = expiresInSeconds
expiresInSeconds = expiresInSeconds,
).fold(
{ newFilter ->
// This is _terrible_, but the all-in-one update filter api Just Doesn't Work
@ -112,7 +112,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
// Endpoint not found, fall back to v1 api
createFilterV1(contexts, expiresInSeconds)
)
}
},
)
}
@ -123,7 +123,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
title = title,
context = contexts,
filterAction = action,
expiresInSeconds = expiresInSeconds
expiresInSeconds = expiresInSeconds,
).fold(
{
// This is _terrible_, but the all-in-one update filter api Just Doesn't Work
@ -148,7 +148,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
}
}
return false
}
},
)
}
@ -166,7 +166,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
context = context,
irreversible = false,
wholeWord = keyword.wholeWord,
expiresInSeconds = expiresInSeconds
expiresInSeconds = expiresInSeconds,
)
} else {
api.updateFilterV1(
@ -175,7 +175,7 @@ class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub
context = context,
irreversible = false,
wholeWord = keyword.wholeWord,
expiresInSeconds = expiresInSeconds
expiresInSeconds = expiresInSeconds,
)
}
}

View File

@ -78,7 +78,7 @@ class FiltersActivity : BaseActivity(), FiltersListener {
binding.messageView.setup(
R.drawable.elephant_friend_empty,
R.string.message_empty,
null
null,
)
binding.messageView.show()
} else {

View File

@ -32,13 +32,13 @@ class FiltersAdapter(val listener: FiltersListener, val filters: List<Filter>) :
context.getString(
R.string.filter_expiration_format,
filter.title,
getRelativeTimeSpanString(binding.root.context, filter.expiresAt.time, System.currentTimeMillis())
getRelativeTimeSpanString(binding.root.context, filter.expiresAt.time, System.currentTimeMillis()),
)
}
binding.textSecondary.text = context.getString(
R.string.filter_description_format,
actions.getOrNull(filter.action.ordinal - 1),
filter.context.map { contexts.getOrNull(Filter.Kind.from(it).ordinal) }.joinToString("/")
filter.context.map { contexts.getOrNull(Filter.Kind.from(it).ordinal) }.joinToString("/"),
)
binding.delete.setOnClickListener {

View File

@ -18,7 +18,7 @@ import javax.inject.Inject
class FiltersViewModel @Inject constructor(
private val api: MastodonApi,
private val eventHub: EventHub
private val eventHub: EventHub,
) : ViewModel() {
enum class LoadingState {
@ -49,13 +49,13 @@ class FiltersViewModel @Inject constructor(
// TODO log errors (also below)
this@FiltersViewModel._state.value = _state.value.copy(loadingState = LoadingState.ERROR_OTHER)
}
},
)
this@FiltersViewModel._state.value = _state.value.copy(loadingState = LoadingState.ERROR_OTHER)
} else {
this@FiltersViewModel._state.value = _state.value.copy(loadingState = LoadingState.ERROR_NETWORK)
}
}
},
)
}
}
@ -77,12 +77,12 @@ class FiltersViewModel @Inject constructor(
},
{
Snackbar.make(parent, "Error deleting filter '${filter.title}'", Snackbar.LENGTH_SHORT).show()
}
},
)
} else {
Snackbar.make(parent, "Error deleting filter '${filter.title}'", Snackbar.LENGTH_SHORT).show()
}
}
},
)
}
}
@ -94,7 +94,7 @@ class FiltersViewModel @Inject constructor(
FilterV1.NOTIFICATIONS,
FilterV1.THREAD,
FilterV1.PUBLIC,
FilterV1.ACCOUNT
FilterV1.ACCOUNT,
)
}
}

View File

@ -86,15 +86,17 @@ class FollowedTagsActivity :
val hideFab = sharedPreferences.getBoolean(PrefKeys.FAB_HIDE, false)
if (hideFab) {
binding.followedTagsView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (dy > 0 && binding.fab.isShown) {
binding.fab.hide()
} else if (dy < 0 && !binding.fab.isShown) {
binding.fab.show()
binding.followedTagsView.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (dy > 0 && binding.fab.isShown) {
binding.fab.hide()
} else if (dy < 0 && !binding.fab.isShown) {
binding.fab.show()
}
}
}
})
},
)
}
}
@ -133,10 +135,10 @@ class FollowedTagsActivity :
this@FollowedTagsActivity,
binding.followedTagsView,
getString(R.string.error_following_hashtag_format, tagName),
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
)
.show()
}
},
)
}
}
@ -150,7 +152,7 @@ class FollowedTagsActivity :
this@FollowedTagsActivity,
binding.followedTagsView,
getString(R.string.confirmation_hashtag_unfollowed, tagName),
Snackbar.LENGTH_LONG
Snackbar.LENGTH_LONG,
)
.setAction(R.string.action_undo) {
follow(tagName, position)
@ -164,12 +166,12 @@ class FollowedTagsActivity :
binding.followedTagsView,
getString(
R.string.error_unfollowing_hashtag_format,
tagName
tagName,
),
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
)
.show()
}
},
)
}
}
@ -191,8 +193,8 @@ class FollowedTagsActivity :
requireActivity() as FollowedTagsActivity,
animateAvatar = false,
animateEmojis = false,
showBotBadge = false
)
showBotBadge = false,
),
)
return AlertDialog.Builder(requireActivity())
@ -200,7 +202,7 @@ class FollowedTagsActivity :
.setView(layout)
.setPositiveButton(android.R.string.ok) { _, _ ->
(requireActivity() as FollowedTagsActivity).follow(
autoCompleteTextView.text.toString().removePrefix("#")
autoCompleteTextView.text.toString().removePrefix("#"),
)
}
.setNegativeButton(android.R.string.cancel) { _: DialogInterface, _: Int -> }

View File

@ -13,7 +13,7 @@ import com.keylesspalace.tusky.util.BindingHolder
class FollowedTagsAdapter(
private val actionListener: HashtagActionListener,
private val viewModel: FollowedTagsViewModel
private val viewModel: FollowedTagsViewModel,
) : PagingDataAdapter<String, BindingHolder<ItemFollowedHashtagBinding>>(STRING_COMPARATOR) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemFollowedHashtagBinding> =
BindingHolder(ItemFollowedHashtagBinding.inflate(LayoutInflater.from(parent.context), parent, false))

View File

@ -13,11 +13,11 @@ import retrofit2.Response
@OptIn(ExperimentalPagingApi::class)
class FollowedTagsRemoteMediator(
private val api: MastodonApi,
private val viewModel: FollowedTagsViewModel
private val viewModel: FollowedTagsViewModel,
) : RemoteMediator<String, String>() {
override suspend fun load(
loadType: LoadType,
state: PagingState<String, String>
state: PagingState<String, String>,
): MediatorResult {
return try {
val response = request(loadType)

View File

@ -16,7 +16,7 @@ import com.keylesspalace.tusky.network.MastodonApi
import javax.inject.Inject
class FollowedTagsViewModel @Inject constructor(
private val api: MastodonApi
private val api: MastodonApi,
) : ViewModel(), Injectable {
val tags: MutableList<HashTag> = mutableListOf()
var nextKey: String? = null
@ -28,11 +28,11 @@ class FollowedTagsViewModel @Inject constructor(
remoteMediator = FollowedTagsRemoteMediator(api, this),
pagingSourceFactory = {
FollowedTagsPagingSource(
viewModel = this
viewModel = this,
).also { source ->
currentSource = source
}
}
},
).flow.cachedIn(viewModelScope)
fun searchAutocompleteSuggestions(token: String): List<ComposeAutoCompleteAdapter.AutocompleteResult> {
@ -42,7 +42,7 @@ class FollowedTagsViewModel @Inject constructor(
}, { e ->
Log.e(TAG, "Autocomplete search for $token failed.", e)
emptyList()
})
},)
}
companion object {

View File

@ -29,5 +29,5 @@ data class InstanceInfo(
val maxFields: Int,
val maxFieldNameLength: Int?,
val maxFieldValueLength: Int?,
val version: String?
val version: String?,
)

View File

@ -32,7 +32,7 @@ import javax.inject.Inject
class InstanceInfoRepository @Inject constructor(
private val api: MastodonApi,
db: AppDatabase,
accountManager: AccountManager
accountManager: AccountManager,
) {
private val dao = db.instanceDao()
@ -76,7 +76,7 @@ class InstanceInfoRepository @Inject constructor(
maxMediaAttachments = instance.configuration?.statuses?.maxMediaAttachments ?: instance.maxMediaAttachments,
maxFields = instance.pleroma?.metadata?.fieldLimits?.maxFields,
maxFieldNameLength = instance.pleroma?.metadata?.fieldLimits?.nameLength,
maxFieldValueLength = instance.pleroma?.metadata?.fieldLimits?.valueLength
maxFieldValueLength = instance.pleroma?.metadata?.fieldLimits?.valueLength,
)
dao.upsert(instanceEntity)
instanceEntity
@ -84,7 +84,7 @@ class InstanceInfoRepository @Inject constructor(
{ throwable ->
Log.w(TAG, "failed to instance, falling back to cache and default values", throwable)
dao.getInstanceInfo(instanceName)
}
},
).let { instanceInfo: InstanceInfoEntity? ->
InstanceInfo(
maxChars = instanceInfo?.maximumTootCharacters ?: DEFAULT_CHARACTER_LIMIT,
@ -100,7 +100,7 @@ class InstanceInfoRepository @Inject constructor(
maxFields = instanceInfo?.maxFields ?: DEFAULT_MAX_ACCOUNT_FIELDS,
maxFieldNameLength = instanceInfo?.maxFieldNameLength,
maxFieldValueLength = instanceInfo?.maxFieldValueLength,
version = instanceInfo?.version
version = instanceInfo?.version,
)
}
}

View File

@ -8,7 +8,7 @@ import com.keylesspalace.tusky.databinding.ItemMutedDomainBinding
import com.keylesspalace.tusky.util.BindingHolder
class DomainMutesAdapter(
private val actionListener: InstanceActionListener
private val actionListener: InstanceActionListener,
) : RecyclerView.Adapter<BindingHolder<ItemMutedDomainBinding>>() {
var instances: MutableList<String> = mutableListOf()

View File

@ -69,7 +69,7 @@ class InstanceListFragment : Fragment(R.layout.fragment_instance_list), Injectab
adapter.addItem(instance)
}, { e ->
Log.e(TAG, "Error muting domain $instance", e)
})
},)
} else {
api.unblockDomain(instance).fold({
adapter.removeItem(position)
@ -80,7 +80,7 @@ class InstanceListFragment : Fragment(R.layout.fragment_instance_list), Injectab
.show()
}, { e ->
Log.e(TAG, "Error unmuting domain $instance", e)
})
},)
}
}
}
@ -111,7 +111,7 @@ class InstanceListFragment : Fragment(R.layout.fragment_instance_list), Injectab
},
{ throwable ->
onFetchInstancesFailure(throwable)
}
},
)
}
@ -131,7 +131,7 @@ class InstanceListFragment : Fragment(R.layout.fragment_instance_list), Injectab
binding.messageView.setup(
R.drawable.elephant_friend_empty,
R.string.message_empty,
null
null,
)
} else {
binding.messageView.hide()

View File

@ -100,7 +100,7 @@ class LoginActivity : BaseActivity(), Injectable {
preferences = getSharedPreferences(
getString(R.string.preferences_file_key),
Context.MODE_PRIVATE
Context.MODE_PRIVATE,
)
binding.loginButton.setOnClickListener { onLoginClick(true) }
@ -173,7 +173,7 @@ class LoginActivity : BaseActivity(), Injectable {
getString(R.string.app_name),
oauthRedirectUri,
OAUTH_SCOPES,
getString(R.string.tusky_website)
getString(R.string.tusky_website),
).fold(
{ credentials ->
// Before we open browser page we save the data.
@ -196,7 +196,7 @@ class LoginActivity : BaseActivity(), Injectable {
setLoading(false)
Log.e(TAG, Log.getStackTraceString(e))
return@launch
}
},
)
}
}
@ -282,7 +282,7 @@ class LoginActivity : BaseActivity(), Injectable {
clientSecret,
oauthRedirectUri,
code,
"authorization_code"
"authorization_code",
).fold(
{ accessToken ->
fetchAccountDetails(accessToken, domain, clientId, clientSecret)
@ -292,7 +292,7 @@ class LoginActivity : BaseActivity(), Injectable {
binding.domainTextInputLayout.error =
getString(R.string.error_retrieving_oauth_token)
Log.e(TAG, getString(R.string.error_retrieving_oauth_token), e)
}
},
)
}
@ -300,11 +300,11 @@ class LoginActivity : BaseActivity(), Injectable {
accessToken: AccessToken,
domain: String,
clientId: String,
clientSecret: String
clientSecret: String,
) {
mastodonApi.accountVerifyCredentials(
domain = domain,
auth = "Bearer ${accessToken.accessToken}"
auth = "Bearer ${accessToken.accessToken}",
).fold({ newAccount ->
accountManager.addAccount(
accessToken = accessToken.accessToken,
@ -312,7 +312,7 @@ class LoginActivity : BaseActivity(), Injectable {
clientId = clientId,
clientSecret = clientSecret,
oauthScopes = OAUTH_SCOPES,
newAccount = newAccount
newAccount = newAccount,
)
val intent = Intent(this, MainActivity::class.java)
@ -325,7 +325,7 @@ class LoginActivity : BaseActivity(), Injectable {
binding.domainTextInputLayout.error =
getString(R.string.error_loading_account_details)
Log.e(TAG, getString(R.string.error_loading_account_details), e)
})
},)
}
private fun setLoading(loadingState: Boolean) {

View File

@ -88,7 +88,7 @@ class OauthLogin : ActivityResultContract<LoginData, LoginResult>() {
data class LoginData(
val domain: String,
val url: Uri,
val oauthRedirectUrl: Uri
val oauthRedirectUrl: Uri,
) : Parcelable
sealed class LoginResult : Parcelable {
@ -149,7 +149,7 @@ class LoginWebViewActivity : BaseActivity(), Injectable {
override fun onReceivedError(
view: WebView,
request: WebResourceRequest,
error: WebResourceError
error: WebResourceError,
) {
Log.d("LoginWeb", "Failed to load ${data.url}: $error")
sendResult(LoginResult.Err(getString(R.string.error_could_not_load_login_page)))
@ -157,7 +157,7 @@ class LoginWebViewActivity : BaseActivity(), Injectable {
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
request: WebResourceRequest,
): Boolean {
return shouldOverrideUrlLoading(request.url)
}
@ -204,7 +204,7 @@ class LoginWebViewActivity : BaseActivity(), Injectable {
AlertDialog.Builder(this@LoginWebViewActivity)
.setTitle(getString(R.string.instance_rule_title, data.domain))
.setMessage(
instanceRules.joinToString(separator = "\n\n") { "$it" }
instanceRules.joinToString(separator = "\n\n") { "$it" },
)
.setPositiveButton(android.R.string.ok, null)
.show()

View File

@ -25,7 +25,7 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
class LoginWebViewViewModel @Inject constructor(
private val api: MastodonApi
private val api: MastodonApi,
) : ViewModel() {
val instanceRules: MutableStateFlow<List<String>> = MutableStateFlow(emptyList())
@ -40,7 +40,7 @@ class LoginWebViewViewModel @Inject constructor(
instanceRules.value = instance.rules?.map { rule -> rule.text }.orEmpty()
}, { throwable ->
Log.w("LoginWebViewViewModel", "failed to load instance info", throwable)
})
},)
}
}
}

View File

@ -34,16 +34,16 @@ import com.keylesspalace.tusky.viewdata.NotificationViewData
class FollowViewHolder(
private val binding: ItemFollowBinding,
private val notificationActionListener: NotificationActionListener,
private val linkListener: LinkListener
private val linkListener: LinkListener,
) : NotificationsPagingAdapter.ViewHolder, RecyclerView.ViewHolder(binding.root) {
private val avatarRadius42dp = itemView.context.resources.getDimensionPixelSize(
R.dimen.avatar_radius_42dp
R.dimen.avatar_radius_42dp,
)
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
// Skip updates with payloads. That indicates a timestamp update, and
// this view does not have timestamps.
@ -53,7 +53,7 @@ class FollowViewHolder(
viewData.account,
viewData.type === Notification.Type.SIGN_UP,
statusDisplayOptions.animateAvatars,
statusDisplayOptions.animateEmojis
statusDisplayOptions.animateEmojis,
)
setupButtons(notificationActionListener, viewData.account.id)
}
@ -62,7 +62,7 @@ class FollowViewHolder(
account: TimelineAccount,
isSignUp: Boolean,
animateAvatars: Boolean,
animateEmojis: Boolean
animateEmojis: Boolean,
) {
val context = binding.notificationText.context
val format =
@ -71,7 +71,7 @@ class FollowViewHolder(
R.string.notification_sign_up_format
} else {
R.string.notification_follow_format
}
},
)
val wrappedDisplayName = account.name.unicodeWrap()
val wholeMessage = String.format(format, wrappedDisplayName)
@ -79,7 +79,7 @@ class FollowViewHolder(
wholeMessage.emojify(
account.emojis,
binding.notificationText,
animateEmojis
animateEmojis,
)
binding.notificationText.text = emojifiedMessage
val username = context.getString(R.string.post_username_format, account.username)
@ -87,20 +87,20 @@ class FollowViewHolder(
val emojifiedDisplayName = wrappedDisplayName.emojify(
account.emojis,
binding.notificationUsername,
animateEmojis
animateEmojis,
)
binding.notificationDisplayName.text = emojifiedDisplayName
loadAvatar(
account.avatar,
binding.notificationAvatar,
avatarRadius42dp,
animateAvatars
animateAvatars,
)
val emojifiedNote = account.note.parseAsMastodonHtml().emojify(
account.emojis,
binding.notificationAccountNote,
animateEmojis
animateEmojis,
)
setClickableText(binding.notificationAccountNote, emojifiedNote, emptyList(), null, linkListener)
}

View File

@ -46,7 +46,7 @@ import kotlin.time.Duration.Companion.milliseconds
class NotificationFetcher @Inject constructor(
private val mastodonApi: MastodonApi,
private val accountManager: AccountManager,
private val context: Context
private val context: Context,
) {
suspend fun fetchAndShow() {
for (account in accountManager.getAllAccountsOrderedByActive()) {
@ -93,7 +93,7 @@ class NotificationFetcher @Inject constructor(
notificationManager,
notification,
account,
index == 0
index == 0,
)
notificationManager.notify(notification.id, account.id.toInt(), androidNotification)
// Android will rate limit / drop notifications if they're posted too
@ -105,7 +105,7 @@ class NotificationFetcher @Inject constructor(
NotificationHelper.updateSummaryNotifications(
context,
notificationManager,
account
account,
)
accountManager.saveAccount(account)
@ -161,7 +161,7 @@ class NotificationFetcher @Inject constructor(
val response = mastodonApi.notificationsWithAuth(
authHeader,
account.domain,
minId = minId
minId = minId,
)
if (!response.isSuccessful) break
@ -185,7 +185,7 @@ class NotificationFetcher @Inject constructor(
mastodonApi.updateMarkersWithAuth(
auth = authHeader,
domain = account.domain,
notificationsLastReadId = newMarkerId
notificationsLastReadId = newMarkerId,
)
account.notificationMarkerId = newMarkerId
accountManager.saveAccount(account)
@ -199,7 +199,7 @@ class NotificationFetcher @Inject constructor(
val allMarkers = mastodonApi.markersWithAuth(
authHeader,
account.domain,
listOf("notifications")
listOf("notifications"),
)
val notificationMarker = allMarkers["notifications"]
Log.d(TAG, "Fetched marker for ${account.fullName}: $notificationMarker")

View File

@ -114,14 +114,14 @@ class NotificationsFragment :
statusActionListener = this,
notificationActionListener = this,
accountActionListener = this,
statusDisplayOptions = viewModel.statusDisplayOptions.value
statusDisplayOptions = viewModel.statusDisplayOptions.value,
)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
return inflater.inflate(R.layout.fragment_timeline_notifications, container, false)
}
@ -149,7 +149,7 @@ class NotificationsFragment :
binding.recyclerView.setAccessibilityDelegateCompat(
ListStatusAccessibilityDelegate(
binding.recyclerView,
this
this,
) { pos: Int ->
val notification = adapter.snapshot().getOrNull(pos)
// We support replies only for now
@ -158,49 +158,51 @@ class NotificationsFragment :
} else {
null
}
}
},
)
binding.recyclerView.addItemDecoration(
DividerItemDecoration(
context,
DividerItemDecoration.VERTICAL
)
DividerItemDecoration.VERTICAL,
),
)
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
val actionButton = (activity as ActionButtonActivity).actionButton
binding.recyclerView.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
val actionButton = (activity as ActionButtonActivity).actionButton
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
actionButton?.let { fab ->
if (!viewModel.uiState.value.showFabWhileScrolling) {
if (dy > 0 && fab.isShown) {
fab.hide() // Hide when scrolling down
} else if (dy < 0 && !fab.isShown) {
fab.show() // Show when scrolling up
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
actionButton?.let { fab ->
if (!viewModel.uiState.value.showFabWhileScrolling) {
if (dy > 0 && fab.isShown) {
fab.hide() // Hide when scrolling down
} else if (dy < 0 && !fab.isShown) {
fab.show() // Show when scrolling up
}
} else if (!fab.isShown) {
fab.show()
}
} else if (!fab.isShown) {
fab.show()
}
}
}
@Suppress("SyntheticAccessor")
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
newState != SCROLL_STATE_IDLE && return
@Suppress("SyntheticAccessor")
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
newState != SCROLL_STATE_IDLE && return
// Save the ID of the first notification visible in the list, so the user's
// reading position is always restorable.
layoutManager.findFirstVisibleItemPosition().takeIf { it != NO_POSITION }?.let { position ->
adapter.snapshot().getOrNull(position)?.id?.let { id ->
viewModel.accept(InfallibleUiAction.SaveVisibleId(visibleId = id))
// Save the ID of the first notification visible in the list, so the user's
// reading position is always restorable.
layoutManager.findFirstVisibleItemPosition().takeIf { it != NO_POSITION }?.let { position ->
adapter.snapshot().getOrNull(position)?.id?.let { id ->
viewModel.accept(InfallibleUiAction.SaveVisibleId(visibleId = id))
}
}
}
}
})
},
)
binding.recyclerView.adapter = adapter.withLoadStateHeaderAndFooter(
header = TimelineLoadStateAdapter { adapter.retry() },
footer = TimelineLoadStateAdapter { adapter.retry() }
footer = TimelineLoadStateAdapter { adapter.retry() },
)
(binding.recyclerView.itemAnimator as SimpleItemAnimator?)!!.supportsChangeAnimations =
@ -241,13 +243,13 @@ class NotificationsFragment :
val message = getString(
error.message,
error.throwable.localizedMessage
?: getString(R.string.ui_error_unknown)
?: getString(R.string.ui_error_unknown),
)
val snackbar = Snackbar.make(
// Without this the FAB will not move out of the way
(activity as ActionButtonActivity).actionButton ?: binding.root,
message,
Snackbar.LENGTH_INDEFINITE
Snackbar.LENGTH_INDEFINITE,
).setTextMaxLines(5)
error.action?.let { action ->
snackbar.setAction(R.string.action_retry) {
@ -281,14 +283,15 @@ class NotificationsFragment :
Snackbar.make(
(activity as ActionButtonActivity).actionButton ?: binding.root,
getString(it.msg),
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
).show()
when (it) {
// The follow request is no longer valid, refresh the adapter to
// remove it.
is NotificationActionSuccess.AcceptFollowRequest,
is NotificationActionSuccess.RejectFollowRequest -> adapter.refresh()
is NotificationActionSuccess.RejectFollowRequest,
-> adapter.refresh()
}
}
}
@ -318,11 +321,11 @@ class NotificationsFragment :
statusViewData.status.copy(reblogged = it.action.state)
is StatusActionSuccess.VoteInPoll ->
statusViewData.status.copy(
poll = it.action.poll.votedCopy(it.action.choices)
poll = it.action.poll.votedCopy(it.action.choices),
)
}
indexedViewData.value?.statusViewData = statusViewData.copy(
status = status
status = status,
)
adapter.notifyItemChanged(indexedViewData.index)
@ -402,7 +405,7 @@ class NotificationsFragment :
getView() ?: return@post
binding.recyclerView.smoothScrollBy(
0,
Utils.dpToPx(requireContext(), -30)
Utils.dpToPx(requireContext(), -30),
)
}
peeked = true
@ -441,7 +444,7 @@ class NotificationsFragment :
if (adapter.itemCount == 0) {
binding.statusView.setup(
R.drawable.elephant_friend_empty,
R.string.message_empty
R.string.message_empty,
)
binding.recyclerView.hide()
binding.statusView.show()
@ -559,7 +562,7 @@ class NotificationsFragment :
super.viewMedia(
attachmentIndex,
list(status, viewModel.statusDisplayOptions.value.showSensitiveMedia),
view
view,
)
}
@ -576,7 +579,7 @@ class NotificationsFragment :
override fun onExpandedChange(expanded: Boolean, position: Int) {
val notificationViewData = adapter.snapshot()[position] ?: return
notificationViewData.statusViewData = notificationViewData.statusViewData?.copy(
isExpanded = expanded
isExpanded = expanded,
)
adapter.notifyItemChanged(position)
}
@ -584,7 +587,7 @@ class NotificationsFragment :
override fun onContentHiddenChange(isShowing: Boolean, position: Int) {
val notificationViewData = adapter.snapshot()[position] ?: return
notificationViewData.statusViewData = notificationViewData.statusViewData?.copy(
isShowingContent = isShowing
isShowingContent = isShowing,
)
adapter.notifyItemChanged(position)
}
@ -592,7 +595,7 @@ class NotificationsFragment :
override fun onContentCollapsedChange(isCollapsed: Boolean, position: Int) {
val notificationViewData = adapter.snapshot()[position] ?: return
notificationViewData.statusViewData = notificationViewData.statusViewData?.copy(
isCollapsed = isCollapsed
isCollapsed = isCollapsed,
)
adapter.notifyItemChanged(position)
}
@ -604,7 +607,7 @@ class NotificationsFragment :
override fun clearWarningAction(position: Int) {
val notificationViewData = adapter.snapshot()[position] ?: return
notificationViewData.statusViewData = notificationViewData.statusViewData?.copy(
filterAction = Filter.Action.NONE
filterAction = Filter.Action.NONE,
)
adapter.notifyItemChanged(position)
}
@ -654,7 +657,7 @@ class NotificationsFragment :
override fun onViewReport(reportId: String) {
requireContext().openLink(
"https://${viewModel.account.domain}/admin/reports/$reportId"
"https://${viewModel.account.domain}/admin/reports/$reportId",
)
}
@ -676,21 +679,21 @@ class NotificationsFragment :
object : DiffUtil.ItemCallback<NotificationViewData>() {
override fun areItemsTheSame(
oldItem: NotificationViewData,
newItem: NotificationViewData
newItem: NotificationViewData,
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: NotificationViewData,
newItem: NotificationViewData
newItem: NotificationViewData,
): Boolean {
return false
}
override fun getChangePayload(
oldItem: NotificationViewData,
newItem: NotificationViewData
newItem: NotificationViewData,
): Any? {
return if (oldItem == newItem) {
// If items are equal - update timestamp only
@ -706,7 +709,7 @@ class NotificationsFragment :
class FilterDialogFragment(
private val activeFilter: Set<Notification.Type>,
private val listener: ((filter: Set<Notification.Type>) -> Unit)
private val listener: ((filter: Set<Notification.Type>) -> Unit),
) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val context = requireContext()

View File

@ -52,20 +52,24 @@ enum class NotificationViewKind {
FOLLOW,
FOLLOW_REQUEST,
REPORT,
UNKNOWN;
UNKNOWN,
;
companion object {
fun from(kind: Notification.Type?): NotificationViewKind {
return when (kind) {
Notification.Type.MENTION,
Notification.Type.POLL,
Notification.Type.UNKNOWN -> STATUS
Notification.Type.UNKNOWN,
-> STATUS
Notification.Type.FAVOURITE,
Notification.Type.REBLOG,
Notification.Type.STATUS,
Notification.Type.UPDATE -> NOTIFICATION
Notification.Type.UPDATE,
-> NOTIFICATION
Notification.Type.FOLLOW,
Notification.Type.SIGN_UP -> FOLLOW
Notification.Type.SIGN_UP,
-> FOLLOW
Notification.Type.FOLLOW_REQUEST -> FOLLOW_REQUEST
Notification.Type.REPORT -> REPORT
null -> UNKNOWN
@ -106,7 +110,7 @@ class NotificationsPagingAdapter(
private val statusActionListener: StatusActionListener,
private val notificationActionListener: NotificationActionListener,
private val accountActionListener: AccountActionListener,
var statusDisplayOptions: StatusDisplayOptions
var statusDisplayOptions: StatusDisplayOptions,
) : PagingDataAdapter<NotificationViewData, RecyclerView.ViewHolder>(diffCallback) {
private val absoluteTimeFormatter = AbsoluteTimeFormatter()
@ -117,7 +121,7 @@ class NotificationsPagingAdapter(
fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
)
}
@ -138,14 +142,14 @@ class NotificationsPagingAdapter(
StatusViewHolder(
ItemStatusBinding.inflate(inflater, parent, false),
statusActionListener,
accountId
accountId,
)
}
NotificationViewKind.STATUS_FILTERED -> {
StatusViewHolder(
ItemStatusWrapperBinding.inflate(inflater, parent, false),
statusActionListener,
accountId
accountId,
)
}
NotificationViewKind.NOTIFICATION -> {
@ -153,14 +157,14 @@ class NotificationsPagingAdapter(
ItemStatusNotificationBinding.inflate(inflater, parent, false),
statusActionListener,
notificationActionListener,
absoluteTimeFormatter
absoluteTimeFormatter,
)
}
NotificationViewKind.FOLLOW -> {
FollowViewHolder(
ItemFollowBinding.inflate(inflater, parent, false),
notificationActionListener,
statusActionListener
statusActionListener,
)
}
NotificationViewKind.FOLLOW_REQUEST -> {
@ -168,18 +172,18 @@ class NotificationsPagingAdapter(
ItemFollowRequestBinding.inflate(inflater, parent, false),
accountActionListener,
statusActionListener,
showHeader = true
showHeader = true,
)
}
NotificationViewKind.REPORT -> {
ReportNotificationViewHolder(
ItemReportNotificationBinding.inflate(inflater, parent, false),
notificationActionListener
notificationActionListener,
)
}
else -> {
FallbackNotificationViewHolder(
SimpleListItem1Binding.inflate(inflater, parent, false)
SimpleListItem1Binding.inflate(inflater, parent, false),
)
}
}
@ -192,7 +196,7 @@ class NotificationsPagingAdapter(
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
payloads: MutableList<Any>,
) {
bindViewHolder(holder, position, payloads)
}
@ -200,7 +204,7 @@ class NotificationsPagingAdapter(
private fun bindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: List<*>?
payloads: List<*>?,
) {
getItem(position)?.let { (holder as ViewHolder).bind(it, payloads, statusDisplayOptions) }
}
@ -210,12 +214,12 @@ class NotificationsPagingAdapter(
* be used, but is useful when migrating code.
*/
private class FallbackNotificationViewHolder(
val binding: SimpleListItem1Binding
val binding: SimpleListItem1Binding,
) : ViewHolder, RecyclerView.ViewHolder(binding.root) {
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
binding.text1.text = viewData.statusViewData?.content
}

View File

@ -37,7 +37,7 @@ private val INVALID = LoadResult.Invalid<String, Notification>()
class NotificationsPagingSource @Inject constructor(
private val mastodonApi: MastodonApi,
private val gson: Gson,
private val notificationFilter: Set<Notification.Type>
private val notificationFilter: Set<Notification.Type>,
) : PagingSource<String, Notification>() {
override suspend fun load(params: LoadParams<String>): LoadResult<String, Notification> {
Log.d(TAG, "load() with ${params.javaClass.simpleName} for key: ${params.key}")
@ -50,12 +50,12 @@ class NotificationsPagingSource @Inject constructor(
is LoadParams.Append -> mastodonApi.notifications(
maxId = params.key,
limit = params.loadSize,
excludes = notificationFilter
excludes = notificationFilter,
)
is LoadParams.Prepend -> mastodonApi.notifications(
minId = params.key,
limit = params.loadSize,
excludes = notificationFilter
excludes = notificationFilter,
)
}
@ -92,7 +92,7 @@ class NotificationsPagingSource @Inject constructor(
return LoadResult.Page(
data = response.body()!!,
nextKey = links.next,
prevKey = links.prev
prevKey = links.prev,
)
} catch (e: Exception) {
return LoadResult.Error(e)
@ -116,7 +116,7 @@ class NotificationsPagingSource @Inject constructor(
val key = params.key
?: return@coroutineScope mastodonApi.notifications(
limit = params.loadSize,
excludes = notificationFilter
excludes = notificationFilter,
)
// It's important to return *something* from this state. If an empty page is returned
@ -193,7 +193,7 @@ class NotificationsPagingSource @Inject constructor(
// Everything failed -- fallback to fetching the most recent notifications
return@coroutineScope mastodonApi.notifications(
limit = params.loadSize,
excludes = notificationFilter
excludes = notificationFilter,
)
}

View File

@ -37,7 +37,7 @@ import javax.inject.Inject
class NotificationsRepository @Inject constructor(
private val mastodonApi: MastodonApi,
private val gson: Gson,
@ApplicationScope private val externalScope: CoroutineScope
@ApplicationScope private val externalScope: CoroutineScope,
) {
private var factory: InvalidatingPagingSourceFactory<String, Notification>? = null
@ -48,7 +48,7 @@ class NotificationsRepository @Inject constructor(
fun getNotificationsStream(
filter: Set<Notification.Type>,
pageSize: Int = PAGE_SIZE,
initialKey: String? = null
initialKey: String? = null,
): Flow<PagingData<Notification>> {
Log.d(TAG, "getNotificationsStream(), filtering: $filter")
@ -59,7 +59,7 @@ class NotificationsRepository @Inject constructor(
return Pager(
config = PagingConfig(pageSize = pageSize, initialLoadSize = pageSize),
initialKey = initialKey,
pagingSourceFactory = factory!!
pagingSourceFactory = factory!!,
).flow
}

View File

@ -82,17 +82,17 @@ data class UiState(
val activeFilter: Set<Notification.Type> = emptySet(),
/** True if the FAB should be shown while scrolling */
val showFabWhileScrolling: Boolean = true
val showFabWhileScrolling: Boolean = true,
)
/** Preferences the UI reacts to */
data class UiPrefs(
val showFabWhileScrolling: Boolean
val showFabWhileScrolling: Boolean,
) {
companion object {
/** Relevant preference keys. Changes to any of these trigger a display update */
val prefKeys = setOf(
PrefKeys.FAB_HIDE
PrefKeys.FAB_HIDE,
)
}
}
@ -164,7 +164,7 @@ sealed class NotificationActionSuccess(
* The original action, in case additional information is required from it to display the
* message.
*/
open val action: NotificationAction
open val action: NotificationAction,
) : UiSuccess() {
data class AcceptFollowRequest(override val action: NotificationAction) :
NotificationActionSuccess(R.string.ui_success_accepted_follow_request, action)
@ -181,7 +181,7 @@ sealed class NotificationActionSuccess(
/** Actions the user can trigger on an individual status */
sealed class StatusAction(
open val statusViewData: StatusViewData
open val statusViewData: StatusViewData,
) : FallibleUiAction() {
/** Set the bookmark state for a status */
data class Bookmark(val state: Boolean, override val statusViewData: StatusViewData) :
@ -199,7 +199,7 @@ sealed class StatusAction(
data class VoteInPoll(
val poll: Poll,
val choices: List<Int>,
override val statusViewData: StatusViewData
override val statusViewData: StatusViewData,
) : StatusAction(statusViewData)
}
@ -236,45 +236,45 @@ sealed class UiError(
@StringRes val message: Int,
/** The action that failed. Can be resent to retry the action */
open val action: UiAction? = null
open val action: UiAction? = null,
) {
data class ClearNotifications(override val throwable: Throwable) : UiError(
throwable,
R.string.ui_error_clear_notifications
R.string.ui_error_clear_notifications,
)
data class Bookmark(
override val throwable: Throwable,
override val action: StatusAction.Bookmark
override val action: StatusAction.Bookmark,
) : UiError(throwable, R.string.ui_error_bookmark, action)
data class Favourite(
override val throwable: Throwable,
override val action: StatusAction.Favourite
override val action: StatusAction.Favourite,
) : UiError(throwable, R.string.ui_error_favourite, action)
data class Reblog(
override val throwable: Throwable,
override val action: StatusAction.Reblog
override val action: StatusAction.Reblog,
) : UiError(throwable, R.string.ui_error_reblog, action)
data class VoteInPoll(
override val throwable: Throwable,
override val action: StatusAction.VoteInPoll
override val action: StatusAction.VoteInPoll,
) : UiError(throwable, R.string.ui_error_vote, action)
data class AcceptFollowRequest(
override val throwable: Throwable,
override val action: NotificationAction.AcceptFollowRequest
override val action: NotificationAction.AcceptFollowRequest,
) : UiError(throwable, R.string.ui_error_accept_follow_request, action)
data class RejectFollowRequest(
override val throwable: Throwable,
override val action: NotificationAction.RejectFollowRequest
override val action: NotificationAction.RejectFollowRequest,
) : UiError(throwable, R.string.ui_error_reject_follow_request, action)
data class GetFilters(
override val throwable: Throwable
override val throwable: Throwable,
) : UiError(throwable, R.string.ui_error_filter_v1_load, null)
companion object {
@ -298,7 +298,7 @@ class NotificationsViewModel @Inject constructor(
private val timelineCases: TimelineCases,
private val eventHub: EventHub,
private val filtersRepository: FiltersRepository,
private val filterModel: FilterModel
private val filterModel: FilterModel,
) : ViewModel() {
/** The account to display notifications for */
val account = accountManager.activeAccount!!
@ -355,8 +355,8 @@ class NotificationsViewModel @Inject constructor(
.onStart {
emit(
InfallibleUiAction.ApplyFilter(
filter = deserialize(account.notificationsFilter)
)
filter = deserialize(account.notificationsFilter),
),
)
}
@ -391,8 +391,8 @@ class NotificationsViewModel @Inject constructor(
statusDisplayOptions = MutableStateFlow(
StatusDisplayOptions.from(
preferences,
account
)
account,
),
)
viewModelScope.launch {
@ -403,7 +403,7 @@ class NotificationsViewModel @Inject constructor(
statusDisplayOptions.value.make(
preferences,
it.preferenceKey,
account
account,
)
}
.collect {
@ -458,23 +458,23 @@ class NotificationsViewModel @Inject constructor(
is StatusAction.Bookmark ->
timelineCases.bookmark(
action.statusViewData.actionableId,
action.state
action.state,
)
is StatusAction.Favourite ->
timelineCases.favourite(
action.statusViewData.actionableId,
action.state
action.state,
)
is StatusAction.Reblog ->
timelineCases.reblog(
action.statusViewData.actionableId,
action.state
action.state,
)
is StatusAction.VoteInPoll ->
timelineCases.voteInPoll(
action.statusViewData.actionableId,
action.poll.id,
action.choices
action.choices,
)
}.getOrThrow()
uiSuccess.emit(StatusActionSuccess.from(action))
@ -516,18 +516,18 @@ class NotificationsViewModel @Inject constructor(
uiState = combine(notificationFilter, getUiPrefs()) { filter, prefs ->
UiState(
activeFilter = filter.filter,
showFabWhileScrolling = prefs.showFabWhileScrolling
showFabWhileScrolling = prefs.showFabWhileScrolling,
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000),
initialValue = UiState()
initialValue = UiState(),
)
}
private fun getNotifications(
filters: Set<Notification.Type>,
initialKey: String? = null
initialKey: String? = null,
): Flow<PagingData<NotificationViewData>> {
Log.d(TAG, "getNotifications: $initialKey")
return repository.getNotificationsStream(filter = filters, initialKey = initialKey)
@ -539,7 +539,7 @@ class NotificationsViewModel @Inject constructor(
!(notification.status?.actionableStatus?.sensitive ?: false),
isExpanded = statusDisplayOptions.value.openSpoiler,
isCollapsed = true,
filterAction = filterAction
filterAction = filterAction,
)
}.filter {
it.statusViewData?.filterAction != Filter.Action.HIDE
@ -561,7 +561,7 @@ class NotificationsViewModel @Inject constructor(
filterModel.initWithFilters(
filters.filters.filter {
it.context.contains("notifications")
}
},
)
repository.invalidate()
}
@ -594,7 +594,7 @@ class NotificationsViewModel @Inject constructor(
.onStart { emit(toPrefs()) }
private fun toPrefs() = UiPrefs(
showFabWhileScrolling = !preferences.getBoolean(PrefKeys.FAB_HIDE, false)
showFabWhileScrolling = !preferences.getBoolean(PrefKeys.FAB_HIDE, false),
)
companion object {

View File

@ -55,7 +55,7 @@ fun showMigrationNoticeIfNecessary(
context: Context,
parent: View,
anchorView: View?,
accountManager: AccountManager
accountManager: AccountManager,
) {
// No point showing anything if we cannot enable it
if (!isUnifiedPushAvailable(context)) return
@ -163,7 +163,7 @@ suspend fun registerUnifiedPushEndpoint(
api: MastodonApi,
accountManager: AccountManager,
account: AccountEntity,
endpoint: String
endpoint: String,
) = withContext(Dispatchers.IO) {
// Generate a prime256v1 key pair for WebPush
// Decryption is unimplemented for now, since Mastodon uses an old WebPush
@ -179,7 +179,7 @@ suspend fun registerUnifiedPushEndpoint(
endpoint,
keyPair.pubkey,
auth,
buildSubscriptionData(context, account)
buildSubscriptionData(context, account),
).onFailure { throwable ->
Log.w(TAG, "Error setting push endpoint for account ${account.id}", throwable)
disableUnifiedPushNotificationsForAccount(context, account)
@ -201,7 +201,7 @@ suspend fun updateUnifiedPushSubscription(context: Context, api: MastodonApi, ac
api.updatePushNotificationSubscription(
"Bearer ${account.accessToken}",
account.domain,
buildSubscriptionData(context, account)
buildSubscriptionData(context, account),
).onSuccess {
Log.d(TAG, "UnifiedPush subscription updated for account ${account.id}")

View File

@ -67,22 +67,22 @@ internal class StatusNotificationViewHolder(
private val binding: ItemStatusNotificationBinding,
private val statusActionListener: StatusActionListener,
private val notificationActionListener: NotificationActionListener,
private val absoluteTimeFormatter: AbsoluteTimeFormatter
private val absoluteTimeFormatter: AbsoluteTimeFormatter,
) : NotificationsPagingAdapter.ViewHolder, RecyclerView.ViewHolder(binding.root) {
private val avatarRadius48dp = itemView.context.resources.getDimensionPixelSize(
R.dimen.avatar_radius_48dp
R.dimen.avatar_radius_48dp,
)
private val avatarRadius36dp = itemView.context.resources.getDimensionPixelSize(
R.dimen.avatar_radius_36dp
R.dimen.avatar_radius_36dp,
)
private val avatarRadius24dp = itemView.context.resources.getDimensionPixelSize(
R.dimen.avatar_radius_24dp
R.dimen.avatar_radius_24dp,
)
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
val statusViewData = viewData.statusViewData
if (payloads.isNullOrEmpty()) {
@ -103,13 +103,13 @@ internal class StatusNotificationViewHolder(
account.avatar,
account.bot,
statusDisplayOptions.animateAvatars,
statusDisplayOptions.showBotOverlay
statusDisplayOptions.showBotOverlay,
)
} else {
setAvatars(
account.avatar,
viewData.account.avatar,
statusDisplayOptions.animateAvatars
statusDisplayOptions.animateAvatars,
)
}
@ -129,7 +129,7 @@ internal class StatusNotificationViewHolder(
if (StatusBaseViewHolder.Key.KEY_CREATED == item && statusViewData != null) {
setCreatedAt(
statusViewData.status.actionableStatus.createdAt,
statusDisplayOptions.useAbsoluteTime
statusDisplayOptions.useAbsoluteTime,
)
}
}
@ -178,7 +178,7 @@ internal class StatusNotificationViewHolder(
then,
now,
DateUtils.SECOND_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE
DateUtils.FORMAT_ABBREV_RELATIVE,
)
} else {
// unknown minutes~
@ -193,7 +193,7 @@ internal class StatusNotificationViewHolder(
private fun getIconWithColor(
context: Context,
@DrawableRes drawable: Int,
@ColorRes color: Int
@ColorRes color: Int,
): Drawable? {
val icon = ContextCompat.getDrawable(context, drawable)
icon?.setColorFilter(context.getColor(color), PorterDuff.Mode.SRC_ATOP)
@ -206,7 +206,7 @@ internal class StatusNotificationViewHolder(
statusAvatarUrl,
binding.notificationStatusAvatar,
avatarRadius48dp,
animateAvatars
animateAvatars,
)
if (showBotOverlay && isBot) {
binding.notificationNotificationAvatar.visibility = View.VISIBLE
@ -225,21 +225,21 @@ internal class StatusNotificationViewHolder(
statusAvatarUrl,
binding.notificationStatusAvatar,
avatarRadius36dp,
animateAvatars
animateAvatars,
)
binding.notificationNotificationAvatar.visibility = View.VISIBLE
loadAvatar(
notificationAvatarUrl,
binding.notificationNotificationAvatar,
avatarRadius24dp,
animateAvatars
animateAvatars,
)
}
fun setMessage(
notificationViewData: NotificationViewData,
listener: LinkListener,
animateEmojis: Boolean
animateEmojis: Boolean,
) {
val statusViewData = notificationViewData.statusViewData
val displayName = notificationViewData.account.name.unicodeWrap()
@ -273,7 +273,7 @@ internal class StatusNotificationViewHolder(
icon,
null,
null,
null
null,
)
val wholeMessage = String.format(format, displayName)
val str = SpannableStringBuilder(wholeMessage)
@ -282,12 +282,12 @@ internal class StatusNotificationViewHolder(
StyleSpan(Typeface.BOLD),
displayNameIndex,
displayNameIndex + displayName.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
)
val emojifiedText = str.emojify(
notificationViewData.account.emojis,
binding.notificationTopText,
animateEmojis
animateEmojis,
)
binding.notificationTopText.text = emojifiedText
if (statusViewData != null) {
@ -298,18 +298,18 @@ internal class StatusNotificationViewHolder(
if (hasSpoiler) View.VISIBLE else View.GONE
if (statusViewData.isExpanded) {
binding.notificationContentWarningButton.setText(
R.string.post_content_warning_show_less
R.string.post_content_warning_show_less,
)
} else {
binding.notificationContentWarningButton.setText(
R.string.post_content_warning_show_more
R.string.post_content_warning_show_more,
)
}
binding.notificationContentWarningButton.setOnClickListener {
if (bindingAdapterPosition != RecyclerView.NO_POSITION) {
notificationActionListener.onExpandedChange(
!statusViewData.isExpanded,
bindingAdapterPosition
bindingAdapterPosition,
)
}
binding.notificationContent.visibility =
@ -322,7 +322,7 @@ internal class StatusNotificationViewHolder(
private fun setupContentAndSpoiler(
listener: LinkListener,
statusViewData: StatusViewData,
animateEmojis: Boolean
animateEmojis: Boolean,
) {
val shouldShowContentIfSpoiler = statusViewData.isExpanded
val hasSpoiler = !TextUtils.isEmpty(statusViewData.status.spoilerText)
@ -339,19 +339,19 @@ internal class StatusNotificationViewHolder(
if (position != RecyclerView.NO_POSITION) {
notificationActionListener.onNotificationContentCollapsedChange(
!statusViewData.isCollapsed,
position
position,
)
}
}
binding.buttonToggleNotificationContent.visibility = View.VISIBLE
if (statusViewData.isCollapsed) {
binding.buttonToggleNotificationContent.setText(
R.string.post_content_warning_show_more
R.string.post_content_warning_show_more,
)
binding.notificationContent.filters = COLLAPSE_INPUT_FILTER
} else {
binding.buttonToggleNotificationContent.setText(
R.string.post_content_warning_show_less
R.string.post_content_warning_show_less,
)
binding.notificationContent.filters = NO_INPUT_FILTER
}
@ -363,19 +363,19 @@ internal class StatusNotificationViewHolder(
content.emojify(
emojis,
binding.notificationContent,
animateEmojis
animateEmojis,
)
setClickableText(
binding.notificationContent,
emojifiedText,
statusViewData.actionable.mentions,
statusViewData.actionable.tags,
listener
listener,
)
val emojifiedContentWarning: CharSequence = statusViewData.spoilerText.emojify(
statusViewData.actionable.emojis,
binding.notificationContentWarningDescription,
animateEmojis
animateEmojis,
)
binding.notificationContentWarningDescription.text = emojifiedContentWarning
}

View File

@ -27,13 +27,13 @@ import com.keylesspalace.tusky.viewdata.NotificationViewData
internal class StatusViewHolder(
binding: ViewBinding,
private val statusActionListener: StatusActionListener,
private val accountId: String
private val accountId: String,
) : NotificationsPagingAdapter.ViewHolder, StatusViewHolder(binding.root) {
override fun bind(
viewData: NotificationViewData,
payloads: List<*>?,
statusDisplayOptions: StatusDisplayOptions
statusDisplayOptions: StatusDisplayOptions,
) {
val statusViewData = viewData.statusViewData
if (statusViewData == null) {
@ -48,7 +48,7 @@ internal class StatusViewHolder(
statusViewData,
statusActionListener,
statusDisplayOptions,
payloads?.firstOrNull()
payloads?.firstOrNull(),
)
}
if (viewData.type == Notification.Type.POLL) {

View File

@ -99,7 +99,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
activity?.startActivity(intent)
activity?.overridePendingTransition(
R.anim.slide_from_right,
R.anim.slide_to_left
R.anim.slide_to_left,
)
true
}
@ -113,7 +113,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
activity?.startActivity(intent)
activity?.overridePendingTransition(
R.anim.slide_from_right,
R.anim.slide_to_left
R.anim.slide_to_left,
)
true
}
@ -128,7 +128,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
activity?.startActivity(intent)
activity?.overridePendingTransition(
R.anim.slide_from_right,
R.anim.slide_to_left
R.anim.slide_to_left,
)
true
}
@ -146,7 +146,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
activity?.startActivity(intent)
activity?.overridePendingTransition(
R.anim.slide_from_right,
R.anim.slide_to_left
R.anim.slide_to_left,
)
true
}
@ -160,7 +160,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
activity?.startActivity(intent)
activity?.overridePendingTransition(
R.anim.slide_from_right,
R.anim.slide_to_left
R.anim.slide_to_left,
)
true
}
@ -294,28 +294,30 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
// TODO these could also be "datastore backed" preferences (a ServerPreferenceDataStore); follow-up of issue #3204
mastodonApi.accountUpdateSource(visibility, sensitive, language)
.enqueue(object : Callback<Account> {
override fun onResponse(call: Call<Account>, response: Response<Account>) {
val account = response.body()
if (response.isSuccessful && account != null) {
accountManager.activeAccount?.let {
it.defaultPostPrivacy = account.source?.privacy
?: Status.Visibility.PUBLIC
it.defaultMediaSensitivity = account.source?.sensitive ?: false
it.defaultPostLanguage = language.orEmpty()
accountManager.saveAccount(it)
.enqueue(
object : Callback<Account> {
override fun onResponse(call: Call<Account>, response: Response<Account>) {
val account = response.body()
if (response.isSuccessful && account != null) {
accountManager.activeAccount?.let {
it.defaultPostPrivacy = account.source?.privacy
?: Status.Visibility.PUBLIC
it.defaultMediaSensitivity = account.source?.sensitive ?: false
it.defaultPostLanguage = language.orEmpty()
accountManager.saveAccount(it)
}
} else {
Log.e("AccountPreferences", "failed updating settings on server")
showErrorSnackbar(visibility, sensitive)
}
} else {
Log.e("AccountPreferences", "failed updating settings on server")
}
override fun onFailure(call: Call<Account>, t: Throwable) {
Log.e("AccountPreferences", "failed updating settings on server", t)
showErrorSnackbar(visibility, sensitive)
}
}
override fun onFailure(call: Call<Account>, t: Throwable) {
Log.e("AccountPreferences", "failed updating settings on server", t)
showErrorSnackbar(visibility, sensitive)
}
})
},
)
}
private fun showErrorSnackbar(visibility: String?, sensitive: Boolean?) {

View File

@ -97,18 +97,18 @@ class PreferencesActivity :
onBackPressedDispatcher.addCallback(this, restartActivitiesOnBackPressedCallback)
restartActivitiesOnBackPressedCallback.isEnabled = intent.extras?.getBoolean(
EXTRA_RESTART_ON_BACK
EXTRA_RESTART_ON_BACK,
) ?: savedInstanceState?.getBoolean(EXTRA_RESTART_ON_BACK, false) ?: false
}
override fun onPreferenceStartFragment(
caller: PreferenceFragmentCompat,
pref: Preference
pref: Preference,
): Boolean {
val args = pref.extras
val fragment = supportFragmentManager.fragmentFactory.instantiate(
classLoader,
pref.fragment!!
pref.fragment!!,
)
fragment.arguments = args
fragment.setTargetFragment(caller, 0)
@ -117,7 +117,7 @@ class PreferencesActivity :
R.anim.slide_from_right,
R.anim.slide_to_left,
R.anim.slide_from_left,
R.anim.slide_to_right
R.anim.slide_to_right,
)
replace(R.id.fragment_container, fragment)
addToBackStack(null)
@ -160,7 +160,8 @@ class PreferencesActivity :
}
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars", "useBlurhash",
"showSelfUsername", "showCardsInTimelines", "confirmReblogs", "confirmFavourites",
"enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR, PrefKeys.SHOW_STATS_INLINE -> {
"enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR, PrefKeys.SHOW_STATS_INLINE,
-> {
restartActivitiesOnBackPressedCallback.isEnabled = true
}
}

View File

@ -56,7 +56,7 @@ class ProxyPreferencesFragment : PreferenceFragmentCompat() {
val portErrorMessage = getString(
R.string.pref_title_http_proxy_port_message,
MIN_PROXY_PORT,
MAX_PROXY_PORT
MAX_PROXY_PORT,
)
validatedEditTextPreference(portErrorMessage, ProxyConfiguration::isValidProxyPort) {

Some files were not shown because too many files have changed in this diff Show More