Merge remote-tracking branch 'tuskyapp/develop'

This commit is contained in:
kyori19 2020-12-16 23:47:26 +09:00
commit ea822004dd
71 changed files with 665 additions and 370 deletions

View File

@ -58,6 +58,7 @@ android {
productFlavors { productFlavors {
blue {} blue {}
green { green {
resValue "string", "app_name", APP_NAME + " Test"
applicationIdSuffix ".test" applicationIdSuffix ".test"
versionNameSuffix "-" + getGitSha() versionNameSuffix "-" + getGitSha()
} }
@ -105,10 +106,10 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
ext.lifecycleVersion = "2.2.0" ext.lifecycleVersion = "2.2.0"
ext.roomVersion = '2.2.5' ext.roomVersion = '2.2.5'
ext.retrofitVersion = '2.9.0' ext.retrofitVersion = '2.9.0'
ext.okhttpVersion = '4.8.1' ext.okhttpVersion = '4.9.0'
ext.glideVersion = '4.11.0' ext.glideVersion = '4.11.0'
ext.daggerVersion = '2.28.3' ext.daggerVersion = '2.30.1'
ext.materialdrawerVersion = '8.1.8' ext.materialdrawerVersion = '8.2.0'
repositories { repositories {
maven { maven {
@ -120,22 +121,22 @@ repositories {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "androidx.core:core-ktx:1.3.1" implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.fragment:fragment-ktx:1.2.5" implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.browser:browser:1.2.0" implementation "androidx.browser:browser:1.3.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.1.0" implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.exifinterface:exifinterface:1.2.0" implementation "androidx.exifinterface:exifinterface:1.3.2"
implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.preference:preference:1.1.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.sharetarget:sharetarget:1.0.0" implementation "androidx.sharetarget:sharetarget:1.0.0"
implementation "androidx.emoji:emoji:1.1.0" implementation "androidx.emoji:emoji:1.1.0"
implementation "androidx.emoji:emoji-appcompat:1.1.0" implementation "androidx.emoji:emoji-appcompat:1.1.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycleVersion" implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycleVersion"
implementation "androidx.constraintlayout:constraintlayout:1.1.3" implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.paging:paging-runtime-ktx:2.1.2" implementation "androidx.paging:paging-runtime-ktx:2.1.2"
implementation "androidx.viewpager2:viewpager2:1.0.0" implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "androidx.work:work-runtime:2.4.0" implementation "androidx.work:work-runtime:2.4.0"
@ -151,13 +152,14 @@ dependencies {
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion" implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion" implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
implementation "com.squareup.okhttp3:okhttp-tls:$okhttpVersion"
implementation "org.conscrypt:conscrypt-android:2.4.0" implementation "org.conscrypt:conscrypt-android:2.5.1"
implementation "com.github.bumptech.glide:glide:$glideVersion" implementation "com.github.bumptech.glide:glide:$glideVersion"
implementation "com.github.bumptech.glide:okhttp3-integration:$glideVersion" implementation "com.github.bumptech.glide:okhttp3-integration:$glideVersion"
implementation "io.reactivex.rxjava2:rxjava:2.2.19" implementation "io.reactivex.rxjava2:rxjava:2.2.20"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1" implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0" implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
@ -170,7 +172,7 @@ dependencies {
implementation "com.google.dagger:dagger-android-support:$daggerVersion" implementation "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion" kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
implementation "com.github.connyduck:sparkbutton:4.0.0" implementation "com.github.connyduck:sparkbutton:4.1.0"
implementation "com.github.chrisbanes:PhotoView:2.3.0" implementation "com.github.chrisbanes:PhotoView:2.3.0"
@ -182,14 +184,14 @@ dependencies {
implementation "de.c1710:filemojicompat:1.0.17" implementation "de.c1710:filemojicompat:1.0.17"
testImplementation "androidx.test.ext:junit:1.1.1" testImplementation "androidx.test.ext:junit:1.1.2"
testImplementation "org.robolectric:robolectric:4.3.1" testImplementation "org.robolectric:robolectric:4.4"
testImplementation "org.mockito:mockito-inline:3.3.3" testImplementation "org.mockito:mockito-inline:3.6.28"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0" androidTestImplementation "androidx.test.espresso:espresso-core:3.3.0"
androidTestImplementation "androidx.room:room-testing:$roomVersion" androidTestImplementation "androidx.room:room-testing:$roomVersion"
androidTestImplementation "androidx.test.ext:junit:1.1.1" androidTestImplementation "androidx.test.ext:junit:1.1.2"
implementation 'net.accelf:easter:1.0.2' implementation 'net.accelf:easter:1.0.2'
} }

View File

@ -47,6 +47,7 @@ import androidx.lifecycle.Lifecycle
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.viewpager2.widget.MarginPageTransformer import androidx.viewpager2.widget.MarginPageTransformer
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.target.FixedSizeDrawable import com.bumptech.glide.request.target.FixedSizeDrawable
@ -129,6 +130,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
private lateinit var glide: RequestManager
private val emojiInitCallback = object : InitCallback() { private val emojiInitCallback = object : InitCallback() {
override fun onInitialized() { override fun onInitialized() {
if (!isDestroyed) { if (!isDestroyed) {
@ -139,7 +142,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (accountManager.activeAccount == null) {
val activeAccount = accountManager.activeAccount
if (activeAccount == null) {
// will be redirected to LoginActivity by BaseActivity // will be redirected to LoginActivity by BaseActivity
return return
} }
@ -157,11 +162,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
} }
val accountRequested = accountId != -1L val accountRequested = accountId != -1L
if (accountRequested) { if (accountRequested && accountId != activeAccount.id) {
val account = accountManager.activeAccount accountManager.setActiveAccount(accountId)
if (account == null || accountId != account.id) {
accountManager.setActiveAccount(accountId)
}
} }
if (canHandleMimeType(intent.type)) { if (canHandleMimeType(intent.type)) {
// Sharing to Tusky from an external app // Sharing to Tusky from an external app
@ -173,8 +175,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
showAccountChooserDialog(getString(R.string.action_share_as), true, object : AccountSelectionListener { showAccountChooserDialog(getString(R.string.action_share_as), true, object : AccountSelectionListener {
override fun onAccountSelected(account: AccountEntity) { override fun onAccountSelected(account: AccountEntity) {
val requestedId = account.id val requestedId = account.id
val activeAccount = accountManager.activeAccount if (requestedId == activeAccount.id) {
if (activeAccount != null && requestedId == activeAccount.id) {
// The correct account is already active // The correct account is already active
forwardShare(intent) forwardShare(intent)
} else { } else {
@ -193,14 +194,15 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
glide = Glide.with(this)
viewQuickToot.attachViewModel(quickTootViewModel, this) viewQuickToot.attachViewModel(quickTootViewModel, this)
composeButton.setOnClickListener(viewQuickToot::onFABClicked) composeButton.setOnClickListener(viewQuickToot::onFABClicked)
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false) val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
mainToolbar.visible(!hideTopToolbar) mainToolbar.visible(!hideTopToolbar)
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size) loadDrawerAvatar(activeAccount.profilePictureUrl, true)
mainToolbar.navigationIcon = FixedSizeDrawable(getDrawable(R.drawable.avatar_default), navIconSize, navIconSize)
mainToolbar.menu.add(R.string.action_search).apply { mainToolbar.menu.add(R.string.action_search).apply {
setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM) setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
@ -256,8 +258,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
viewQuickToot.handleEvent(event) viewQuickToot.handleEvent(event)
} }
// Flush old media that was cached for sharing Schedulers.io().scheduleDirect {
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky")) // Flush old media that was cached for sharing
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky"))
}
} }
override fun onResume() { override fun onResume() {
@ -381,13 +385,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
DrawerImageLoader.init(object : AbstractDrawerImageLoader() { DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) { override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
if (animateAvatars) { if (animateAvatars) {
Glide.with(imageView.context) glide.load(uri)
.load(uri)
.placeholder(placeholder) .placeholder(placeholder)
.into(imageView) .into(imageView)
} else { } else {
Glide.with(imageView.context) glide.asBitmap()
.asBitmap()
.load(uri) .load(uri)
.placeholder(placeholder) .placeholder(placeholder)
.into(imageView) .into(imageView)
@ -395,7 +397,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
override fun cancel(imageView: ImageView) { override fun cancel(imageView: ImageView) {
Glide.with(imageView.context).clear(imageView) glide.clear(imageView)
} }
override fun placeholder(ctx: Context, tag: String?): Drawable { override fun placeholder(ctx: Context, tag: String?): Drawable {
@ -814,29 +816,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
private fun onFetchUserInfoSuccess(me: Account) { private fun onFetchUserInfoSuccess(me: Account) {
Glide.with(this) glide.asBitmap()
.asBitmap()
.load(me.header) .load(me.header)
.into(header.accountHeaderBackground) .into(header.accountHeaderBackground)
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size) loadDrawerAvatar(me.avatar, false)
Glide.with(this)
.asDrawable()
.override(navIconSize)
.load(me.avatar)
.transform(
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp))
)
.into(object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
mainToolbar.navigationIcon = resource
}
override fun onLoadCleared(placeholder: Drawable?) {
mainToolbar.navigationIcon = placeholder
}
})
accountManager.updateActiveAccount(me) accountManager.updateActiveAccount(me)
NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this) NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this)
@ -861,6 +845,36 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
updateShortcut(this, accountManager.activeAccount!!) updateShortcut(this, accountManager.activeAccount!!)
} }
private fun loadDrawerAvatar(avatarUrl: String, showPlaceholder: Boolean) {
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size)
glide.asDrawable()
.load(avatarUrl)
.transform(
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp))
)
.apply {
if (showPlaceholder) {
placeholder(R.drawable.avatar_default)
}
}
.into(object : CustomTarget<Drawable>(navIconSize, navIconSize) {
override fun onLoadStarted(placeholder: Drawable?) {
if(placeholder != null) {
mainToolbar.navigationIcon = FixedSizeDrawable(placeholder, navIconSize, navIconSize)
}
}
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
mainToolbar.navigationIcon = resource
}
override fun onLoadCleared(placeholder: Drawable?) {
mainToolbar.navigationIcon = placeholder
}
})
}
private fun fetchAnnouncements() { private fun fetchAnnouncements() {
mastodonApi.listAnnouncements(false) mastodonApi.listAnnouncements(false)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -877,7 +891,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
private fun updateAnnouncementsBadge() { private fun updateAnnouncementsBadge() {
mainDrawer.updateBadge(DRAWER_ITEM_ANNOUNCEMENTS, StringHolder(if (unreadAnnouncementsCount == 0) null else unreadAnnouncementsCount.toString())) mainDrawer.updateBadge(DRAWER_ITEM_ANNOUNCEMENTS, StringHolder(if (unreadAnnouncementsCount <= 0) null else unreadAnnouncementsCount.toString()))
} }
private fun updateProfiles() { private fun updateProfiles() {

View File

@ -25,7 +25,9 @@ import androidx.work.WorkManager
import com.keylesspalace.tusky.components.notifications.NotificationWorkerFactory import com.keylesspalace.tusky.components.notifications.NotificationWorkerFactory
import com.keylesspalace.tusky.di.AppInjector import com.keylesspalace.tusky.di.AppInjector
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.util.EmojiCompatFont
import com.keylesspalace.tusky.util.LocaleManager
import com.keylesspalace.tusky.util.ThemeUtils
import com.uber.autodispose.AutoDisposePlugins import com.uber.autodispose.AutoDisposePlugins
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
@ -38,11 +40,21 @@ class TuskyApplication : Application(), HasAndroidInjector {
@Inject @Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any> lateinit var androidInjector: DispatchingAndroidInjector<Any>
@Inject @Inject
lateinit var notificationWorkerFactory: NotificationWorkerFactory lateinit var notificationWorkerFactory: NotificationWorkerFactory
override fun onCreate() { override fun onCreate() {
// Uncomment me to get StrictMode violation logs
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
// .detectDiskReads()
// .detectDiskWrites()
// .detectNetwork()
// .detectUnbufferedIo()
// .penaltyLog()
// .build())
// }
super.onCreate() super.onCreate()
Security.insertProviderAt(Conscrypt.newProvider(), 1) Security.insertProviderAt(Conscrypt.newProvider(), 1)
@ -64,16 +76,16 @@ class TuskyApplication : Application(), HasAndroidInjector {
val theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT) val theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT)
ThemeUtils.setAppNightMode(theme) ThemeUtils.setAppNightMode(theme)
RxJavaPlugins.setErrorHandler {
Log.w("RxJava", "undeliverable exception", it)
}
WorkManager.initialize( WorkManager.initialize(
this, this,
androidx.work.Configuration.Builder() androidx.work.Configuration.Builder()
.setWorkerFactory(notificationWorkerFactory) .setWorkerFactory(notificationWorkerFactory)
.build() .build()
) )
RxJavaPlugins.setErrorHandler {
Log.w("RxJava", "undeliverable exception", it)
}
} }
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {

View File

@ -22,7 +22,6 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.ThemeUtils
import kotlinx.android.synthetic.main.item_picker_list.view.* import kotlinx.android.synthetic.main.item_picker_list.view.*
class ListSelectionAdapter(context: Context) : ArrayAdapter<MastoList>(context, R.layout.item_autocomplete_hashtag) { class ListSelectionAdapter(context: Context) : ArrayAdapter<MastoList>(context, R.layout.item_autocomplete_hashtag) {
@ -34,10 +33,7 @@ class ListSelectionAdapter(context: Context) : ArrayAdapter<MastoList>(context,
?: layoutInflater.inflate(R.layout.item_picker_list, parent, false) ?: layoutInflater.inflate(R.layout.item_picker_list, parent, false)
getItem(position)?.let { list -> getItem(position)?.let { list ->
val title = view.title view.title.text = list.title
title.text = list.title
val icon = ThemeUtils.getTintedDrawable(context, R.drawable.ic_list, R.attr.iconColor)
title.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
} }
return view return view

View File

@ -22,7 +22,6 @@ import android.widget.TextView
import androidx.core.widget.TextViewCompat import androidx.core.widget.TextViewCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.util.ThemeUtils
class PreviewPollOptionsAdapter: RecyclerView.Adapter<PreviewViewHolder>() { class PreviewPollOptionsAdapter: RecyclerView.Adapter<PreviewViewHolder>() {
@ -55,9 +54,7 @@ class PreviewPollOptionsAdapter: RecyclerView.Adapter<PreviewViewHolder>() {
R.drawable.ic_radio_button_unchecked_18dp R.drawable.ic_radio_button_unchecked_18dp
} }
val iconDrawable = ThemeUtils.getTintedDrawable(textView.context, iconId, android.R.attr.textColorTertiary) TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, iconId, 0, 0, 0)
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, iconDrawable, null, null, null)
textView.text = options[position] textView.text = options[position]

View File

@ -60,7 +60,6 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import at.connyduck.sparkbutton.SparkButton; import at.connyduck.sparkbutton.SparkButton;
import at.connyduck.sparkbutton.helpers.Utils; import at.connyduck.sparkbutton.helpers.Utils;
@ -648,9 +647,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
// Set the icon next to the label. // Set the icon next to the label.
int drawableId = getLabelIcon(attachments.get(0).getType()); int drawableId = getLabelIcon(attachments.get(0).getType());
Drawable drawable = Objects.requireNonNull(context.getDrawable(drawableId)); mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0);
ThemeUtils.setDrawableTint(context, drawable, android.R.attr.textColorTertiary);
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
setAttachmentClickListener(mediaLabel, listener, i, attachment, false); setAttachmentClickListener(mediaLabel, listener, i, attachment, false);
} else { } else {

View File

@ -15,6 +15,7 @@
package com.keylesspalace.tusky.adapter package com.keylesspalace.tusky.adapter
import android.content.res.ColorStateList
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@ -68,8 +69,7 @@ class TabAdapter(private var data: List<TabData>,
} else { } else {
holder.itemView.textView.setText(tab.text) holder.itemView.textView.setText(tab.text)
} }
val iconDrawable = ThemeUtils.getTintedDrawable(context, tab.icon, android.R.attr.textColorSecondary) holder.itemView.textView.setCompoundDrawablesRelativeWithIntrinsicBounds(tab.icon, 0, 0, 0)
holder.itemView.textView.setCompoundDrawablesRelativeWithIntrinsicBounds(iconDrawable, null, null, null)
if (small) { if (small) {
holder.itemView.textView.setOnClickListener { holder.itemView.textView.setOnClickListener {
listener.onTabAdded(tab) listener.onTabAdded(tab)
@ -110,6 +110,7 @@ class TabAdapter(private var data: List<TabData>,
val chip = holder.itemView.chipGroup.getChildAt(i).takeUnless { it.id == R.id.actionChip } as Chip? val chip = holder.itemView.chipGroup.getChildAt(i).takeUnless { it.id == R.id.actionChip } as Chip?
?: Chip(context).apply { ?: Chip(context).apply {
holder.itemView.chipGroup.addView(this, holder.itemView.chipGroup.size - 1) holder.itemView.chipGroup.addView(this, holder.itemView.chipGroup.size - 1)
chipIconTint = ColorStateList.valueOf(ThemeUtils.getColor(context, android.R.attr.textColorPrimary))
} }
chip.text = arg chip.text = arg
@ -118,8 +119,7 @@ class TabAdapter(private var data: List<TabData>,
chip.chipIcon = null chip.chipIcon = null
chip.setOnClickListener(null) chip.setOnClickListener(null)
} else { } else {
val cancelIcon = ThemeUtils.getTintedDrawable(context, R.drawable.ic_cancel_24dp, android.R.attr.textColorPrimary) chip.setChipIconResource(R.drawable.ic_cancel_24dp)
chip.chipIcon = cancelIcon
chip.setOnClickListener { chip.setOnClickListener {
listener.onChipClicked(tab, holder.adapterPosition, i) listener.onChipClicked(tab, holder.adapterPosition, i)
} }

View File

@ -27,10 +27,12 @@ import com.google.android.material.chip.ChipGroup
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.entity.Announcement import com.keylesspalace.tusky.entity.Announcement
import com.keylesspalace.tusky.entity.Emoji import com.keylesspalace.tusky.entity.Emoji
import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.util.LinkHelper
import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.emojify
import kotlinx.android.synthetic.main.item_announcement.view.* import kotlinx.android.synthetic.main.item_announcement.view.*
interface AnnouncementActionListener { interface AnnouncementActionListener: LinkListener {
fun openReactionPicker(announcementId: String, target: View) fun openReactionPicker(announcementId: String, target: View)
fun addReaction(announcementId: String, name: String) fun addReaction(announcementId: String, name: String)
fun removeReaction(announcementId: String, name: String) fun removeReaction(announcementId: String, name: String)
@ -59,13 +61,12 @@ class AnnouncementAdapter(
} }
inner class AnnouncementViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { inner class AnnouncementViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
private val text: TextView = view.text private val text: TextView = view.text
private val chips: ChipGroup = view.chipGroup private val chips: ChipGroup = view.chipGroup
private val addReactionChip: Chip = view.addReactionChip private val addReactionChip: Chip = view.addReactionChip
fun bind(item: Announcement) { fun bind(item: Announcement) {
text.text = item.content LinkHelper.setClickableText(text, item.content, null, listener, false)
item.reactions.forEachIndexed { i, reaction -> item.reactions.forEachIndexed { i, reaction ->
(chips.getChildAt(i)?.takeUnless { it.id == R.id.addReactionChip } as Chip? (chips.getChildAt(i)?.takeUnless { it.id == R.id.addReactionChip } as Chip?

View File

@ -22,11 +22,9 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.PopupWindow import android.widget.PopupWindow
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.*
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.adapter.EmojiAdapter import com.keylesspalace.tusky.adapter.EmojiAdapter
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
@ -37,7 +35,7 @@ import kotlinx.android.synthetic.main.activity_announcements.*
import kotlinx.android.synthetic.main.toolbar_basic.* import kotlinx.android.synthetic.main.toolbar_basic.*
import javax.inject.Inject import javax.inject.Inject
class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable { class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable {
@Inject @Inject
lateinit var viewModelFactory: ViewModelFactory lateinit var viewModelFactory: ViewModelFactory
@ -79,7 +77,7 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
announcementsList.addItemDecoration(divider) announcementsList.addItemDecoration(divider)
announcementsList.adapter = adapter announcementsList.adapter = adapter
viewModel.announcements.observe(this, Observer { viewModel.announcements.observe(this) {
when (it) { when (it) {
is Success -> { is Success -> {
progressBar.hide() progressBar.hide()
@ -104,11 +102,11 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
errorMessageView.show() errorMessageView.show()
} }
} }
}) }
viewModel.emojis.observe(this, Observer { viewModel.emojis.observe(this) {
picker.adapter = EmojiAdapter(it, this) picker.adapter = EmojiAdapter(it, this)
}) }
viewModel.load() viewModel.load()
progressBar.show() progressBar.show()
@ -147,6 +145,24 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
viewModel.removeReaction(announcementId, name) viewModel.removeReaction(announcementId, name)
} }
override fun onViewTag(tag: String?) {
val intent = Intent(this, ViewTagActivity::class.java)
intent.putExtra("hashtag", tag)
startActivityWithSlideInAnimation(intent)
}
override fun onViewAccount(id: String?) {
if (id != null) {
viewAccount(id)
}
}
override fun onViewUrl(url: String?, text: String?) {
if (url != null) {
viewUrl(url)
}
}
companion object { companion object {
fun newIntent(context: Context) = Intent(context, AnnouncementsActivity::class.java) fun newIntent(context: Context) = Intent(context, AnnouncementsActivity::class.java)
} }

View File

@ -51,7 +51,7 @@ class AnnouncementsViewModel @Inject constructor(
.map<Either<InstanceEntity, Instance>> { Either.Left(it) } .map<Either<InstanceEntity, Instance>> { Either.Left(it) }
.onErrorResumeNext( .onErrorResumeNext(
mastodonApi.getInstance() mastodonApi.getInstance()
.map { Either.Right<InstanceEntity, Instance>(it) } .map { Either.Right(it) }
) )
) { emojis, either -> ) { emojis, either ->
either.asLeftOrNull()?.copy(emojiList = emojis) either.asLeftOrNull()?.copy(emojiList = emojis)

View File

@ -626,8 +626,7 @@ class ComposeActivity : BaseActivity(),
Status.Visibility.UNLEAKABLE -> R.drawable.ic_low_vision_24dp Status.Visibility.UNLEAKABLE -> R.drawable.ic_low_vision_24dp
else -> R.drawable.ic_lock_open_24dp else -> R.drawable.ic_lock_open_24dp
} }
val drawable = ThemeUtils.getTintedDrawable(this, iconRes, android.R.attr.textColorTertiary) composeToggleVisibilityButton.setImageResource(iconRes)
composeToggleVisibilityButton.setImageDrawable(drawable)
} }
private fun showComposeOptions() { private fun showComposeOptions() {

View File

@ -19,10 +19,8 @@ import android.net.Uri
import android.util.Log import android.util.Log
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.work.impl.utils.LiveDataUtils
import com.keylesspalace.tusky.adapter.ComposeAutoCompleteAdapter import com.keylesspalace.tusky.adapter.ComposeAutoCompleteAdapter
import com.keylesspalace.tusky.components.compose.ComposeActivity.QueuedMedia import com.keylesspalace.tusky.components.compose.ComposeActivity.QueuedMedia
import com.keylesspalace.tusky.components.search.SearchType import com.keylesspalace.tusky.components.search.SearchType
@ -35,7 +33,6 @@ import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.service.ServiceClient import com.keylesspalace.tusky.service.ServiceClient
import com.keylesspalace.tusky.service.TootToSend import com.keylesspalace.tusky.service.TootToSend
import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.util.*
import io.reactivex.Observable.empty
import io.reactivex.Observable.just import io.reactivex.Observable.just
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.Singles import io.reactivex.rxkotlin.Singles

View File

@ -26,13 +26,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import com.google.android.material.datepicker.CalendarConstraints; import com.google.android.material.datepicker.CalendarConstraints;
import com.google.android.material.datepicker.DateValidatorPointForward; import com.google.android.material.datepicker.DateValidatorPointForward;
import com.google.android.material.datepicker.MaterialDatePicker; import com.google.android.material.datepicker.MaterialDatePicker;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.fragment.TimePickerFragment; import com.keylesspalace.tusky.fragment.TimePickerFragment;
import com.keylesspalace.tusky.util.ThemeUtils;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
@ -106,7 +106,7 @@ public class ComposeScheduleView extends ConstraintLayout {
} }
private void setEditIcons() { private void setEditIcons() {
Drawable icon = ThemeUtils.getTintedDrawable(getContext(), R.drawable.ic_create_24dp, android.R.attr.textColorTertiary); Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_create_24dp);
if (icon == null) { if (icon == null) {
return; return;
} }

View File

@ -295,7 +295,7 @@ public class NotificationHelper {
.setSmallIcon(R.drawable.ic_notify) .setSmallIcon(R.drawable.ic_notify)
.setContentIntent(summary ? summaryResultPendingIntent : eventResultPendingIntent) .setContentIntent(summary ? summaryResultPendingIntent : eventResultPendingIntent)
.setDeleteIntent(deletePendingIntent) .setDeleteIntent(deletePendingIntent)
.setColor(BuildConfig.DEBUG ? Color.parseColor("#19A341") : ContextCompat.getColor(context, R.color.tusky_blue)) .setColor(BuildConfig.FLAVOR == "green" ? Color.parseColor("#19A341") : ContextCompat.getColor(context, R.color.tusky_blue))
.setGroup(account.getAccountId()) .setGroup(account.getAccountId())
.setAutoCancel(true) .setAutoCancel(true)
.setShortcutId(Long.toString(account.getId())) .setShortcutId(Long.toString(account.getId()))

View File

@ -16,10 +16,10 @@
package com.keylesspalace.tusky.components.preference package com.keylesspalace.tusky.components.preference
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.annotation.DrawableRes
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.* import com.keylesspalace.tusky.*
@ -71,7 +71,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
preference { preference {
setTitle(R.string.title_tab_preferences) setTitle(R.string.title_tab_preferences)
icon = getTintedIcon(R.drawable.ic_tabs) setIcon(R.drawable.ic_tabs)
setOnPreferenceClickListener { setOnPreferenceClickListener {
val intent = Intent(context, TabPreferenceActivity::class.java) val intent = Intent(context, TabPreferenceActivity::class.java)
activity?.startActivity(intent) activity?.startActivity(intent)
@ -83,7 +83,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
preference { preference {
setTitle(R.string.action_view_mutes) setTitle(R.string.action_view_mutes)
icon = getTintedIcon(R.drawable.ic_mute_24dp) setIcon(R.drawable.ic_mute_24dp)
setOnPreferenceClickListener { setOnPreferenceClickListener {
val intent = Intent(context, AccountListActivity::class.java) val intent = Intent(context, AccountListActivity::class.java)
intent.putExtra("type", AccountListActivity.Type.MUTES) intent.putExtra("type", AccountListActivity.Type.MUTES)
@ -112,7 +112,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
preference { preference {
setTitle(R.string.title_domain_mutes) setTitle(R.string.title_domain_mutes)
icon = getTintedIcon(R.drawable.ic_mute_24dp) setIcon(R.drawable.ic_mute_24dp)
setOnPreferenceClickListener { setOnPreferenceClickListener {
val intent = Intent(context, InstanceListActivity::class.java) val intent = Intent(context, InstanceListActivity::class.java)
activity?.startActivity(intent) activity?.startActivity(intent)
@ -132,11 +132,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
val visibility = accountManager.activeAccount?.defaultPostPrivacy val visibility = accountManager.activeAccount?.defaultPostPrivacy
?: Status.Visibility.PUBLIC ?: Status.Visibility.PUBLIC
value = visibility.serverString() value = visibility.serverString()
icon = getIconForVisibility(visibility) setIcon(getIconForVisibility(visibility))
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
icon = getIconForVisibility( setIcon(getIconForVisibility(Status.Visibility.byString(newValue as String)))
Status.Visibility.byString(newValue as String)
)
syncWithServer(visibility = newValue) syncWithServer(visibility = newValue)
eventHub.dispatch(PreferenceChangedEvent(key)) eventHub.dispatch(PreferenceChangedEvent(key))
true true
@ -151,9 +149,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
val sensitivity = accountManager.activeAccount?.defaultMediaSensitivity val sensitivity = accountManager.activeAccount?.defaultMediaSensitivity
?: false ?: false
setDefaultValue(sensitivity) setDefaultValue(sensitivity)
icon = getIconForSensitivity(sensitivity) setIcon(getIconForSensitivity(sensitivity))
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
icon = getIconForSensitivity(newValue as Boolean) setIcon(getIconForSensitivity(newValue as Boolean))
syncWithServer(sensitive = newValue) syncWithServer(sensitive = newValue)
eventHub.dispatch(PreferenceChangedEvent(key)) eventHub.dispatch(PreferenceChangedEvent(key))
true true
@ -303,30 +301,24 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
} }
} }
private fun getIconForVisibility(visibility: Status.Visibility): Drawable? { @DrawableRes
val drawableId = when (visibility) { private fun getIconForVisibility(visibility: Status.Visibility): Int {
return when (visibility) {
Status.Visibility.PRIVATE -> R.drawable.ic_lock_outline_24dp Status.Visibility.PRIVATE -> R.drawable.ic_lock_outline_24dp
Status.Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp Status.Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp
else -> R.drawable.ic_public_24dp else -> R.drawable.ic_public_24dp
} }
return getTintedIcon(drawableId)
} }
private fun getIconForSensitivity(sensitive: Boolean): Drawable? { @DrawableRes
val drawableId = if (sensitive) { private fun getIconForSensitivity(sensitive: Boolean): Int {
return if (sensitive) {
R.drawable.ic_hide_media_24dp R.drawable.ic_hide_media_24dp
} else { } else {
R.drawable.ic_eye_24dp R.drawable.ic_eye_24dp
} }
return getTintedIcon(drawableId)
}
private fun getTintedIcon(iconId: Int): Drawable? {
return ThemeUtils.getTintedDrawable(requireContext(), iconId, R.attr.iconColor)
} }
private fun launchFilterActivity(filterContext: String, titleResource: Int) { private fun launchFilterActivity(filterContext: String, titleResource: Int) {

View File

@ -42,7 +42,6 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
private var httpProxyPref: Preference? = null private var httpProxyPref: Preference? = null
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val context = requireContext()
makePreferenceScreen { makePreferenceScreen {
lateinit var limitedBandwidthMobilePref: SwitchPreference lateinit var limitedBandwidthMobilePref: SwitchPreference
lateinit var limitedBandwidthTimelinePref: SwitchPreference lateinit var limitedBandwidthTimelinePref: SwitchPreference
@ -121,11 +120,8 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
key = PrefKeys.SHOW_BOT_OVERLAY key = PrefKeys.SHOW_BOT_OVERLAY
setTitle(R.string.pref_title_bot_overlay) setTitle(R.string.pref_title_bot_overlay)
isSingleLineTitle = false isSingleLineTitle = false
icon = ThemeUtils.getTintedDrawable( setIcon(R.drawable.ic_bot_24dp)
context,
R.drawable.ic_bot_24dp,
R.attr.iconColor
)
} }
switchPreference { switchPreference {

View File

@ -62,7 +62,7 @@ class AccountManager @Inject constructor(db: AppDatabase) {
accountDao.insertOrReplace(it) accountDao.insertOrReplace(it)
} }
val maxAccountId = accounts.maxBy { it.id }?.id ?: 0 val maxAccountId = accounts.maxByOrNull { it.id }?.id ?: 0
val newAccountId = maxAccountId + 1 val newAccountId = maxAccountId + 1
activeAccount = AccountEntity(id = newAccountId, domain = domain.toLowerCase(Locale.ROOT), accessToken = accessToken, isActive = true) activeAccount = AccountEntity(id = newAccountId, domain = domain.toLowerCase(Locale.ROOT), accessToken = accessToken, isActive = true)

View File

@ -25,7 +25,7 @@ import com.keylesspalace.tusky.json.SpannedTypeAdapter
import com.keylesspalace.tusky.network.InstanceSwitchAuthInterceptor import com.keylesspalace.tusky.network.InstanceSwitchAuthInterceptor
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.network.NotestockApi import com.keylesspalace.tusky.network.NotestockApi
import com.keylesspalace.tusky.util.OkHttpUtils import com.keylesspalace.tusky.util.okhttpClient
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import net.accelf.yuito.HttpToastInterceptor import net.accelf.yuito.HttpToastInterceptor
@ -34,6 +34,7 @@ import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.create
import javax.inject.Singleton import javax.inject.Singleton
/** /**
@ -57,7 +58,7 @@ class NetworkModule {
accountManager: AccountManager, accountManager: AccountManager,
context: Context context: Context
): OkHttpClient { ): OkHttpClient {
return OkHttpUtils.getCompatibleClientBuilder(context) return okhttpClient(context)
.apply { .apply {
addInterceptor(InstanceSwitchAuthInterceptor(accountManager)) addInterceptor(InstanceSwitchAuthInterceptor(accountManager))
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
@ -84,13 +85,13 @@ class NetworkModule {
@Provides @Provides
@Singleton @Singleton
fun providesApi(retrofit: Retrofit): MastodonApi = retrofit.create(MastodonApi::class.java) fun providesApi(retrofit: Retrofit): MastodonApi = retrofit.create()
@Provides @Provides
@Singleton @Singleton
fun providesNotestockApi(context: Context, fun providesNotestockApi(context: Context,
gson: Gson): NotestockApi { gson: Gson): NotestockApi {
val httpClient = OkHttpUtils.getCompatibleClientBuilder(context) val httpClient = okhttpClient(context)
.apply { .apply {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }) addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC })
@ -105,4 +106,4 @@ class NetworkModule {
.build() .build()
return retrofit.create(NotestockApi::class.java) return retrofit.create(NotestockApi::class.java)
} }
} }

View File

@ -28,7 +28,7 @@ import kotlinx.android.parcel.Parcelize
data class Attachment( data class Attachment(
val id: String, val id: String,
val url: String, val url: String,
@SerializedName("preview_url") val previewUrl: String, @SerializedName("preview_url") val previewUrl: String?, // can be null for e.g. audio attachments
val meta: MetaData?, val meta: MetaData?,
val type: Type, val type: Type,
val description: String?, val description: String?,

View File

@ -330,6 +330,7 @@ class AccountListFragment : BaseFragment(), AccountActionListener, Injectable {
private fun fetchRelationships(ids: List<String>) { private fun fetchRelationships(ids: List<String>) {
api.relationships(ids) api.relationships(ids)
.observeOn(AndroidSchedulers.mainThread())
.autoDispose(from(this)) .autoDispose(from(this))
.subscribe(::onFetchRelationshipsSuccess) { .subscribe(::onFetchRelationshipsSuccess) {
onFetchRelationshipsFailure(ids) onFetchRelationshipsFailure(ids)

View File

@ -502,6 +502,7 @@ public class TimelineFragment extends SFragment implements
// home, notifications, public, thread // home, notifications, public, thread
switch (kind) { switch (kind) {
case HOME: case HOME:
case LIST:
return filterContext.contains(Filter.HOME); return filterContext.contains(Filter.HOME);
case PUBLIC_FEDERATED: case PUBLIC_FEDERATED:
case PUBLIC_LOCAL: case PUBLIC_LOCAL:

View File

@ -54,7 +54,7 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View) : CharSequence {
while(matcher.find()) { while(matcher.find()) {
val span = EmojiSpan(WeakReference(view)) val span = EmojiSpan(WeakReference(view))
builder.setSpan(span, matcher.start(), matcher.end(), 0); builder.setSpan(span, matcher.start(), matcher.end(), 0)
Glide.with(view) Glide.with(view)
.asBitmap() .asBitmap()
.load(url) .load(url)
@ -89,7 +89,7 @@ class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan()
drawable.setBounds(0, 0, emojiSize, emojiSize) drawable.setBounds(0, 0, emojiSize, emojiSize)
var transY = bottom - drawable.bounds.bottom var transY = bottom - drawable.bounds.bottom
transY -= paint.fontMetricsInt.descent / 2; transY -= paint.fontMetricsInt.descent / 2
canvas.translate(x, transY.toFloat()) canvas.translate(x, transY.toFloat())
drawable.draw(canvas) drawable.draw(canvas)

View File

@ -1,87 +0,0 @@
/* Copyright 2017 Andrew Dawson
*
* This file is part of Tusky.
*
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with Tusky. If
* not, see <http://www.gnu.org/licenses/>. */
package com.keylesspalace.tusky.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import com.keylesspalace.tusky.BuildConfig;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class OkHttpUtils {
@NonNull
public static OkHttpClient.Builder getCompatibleClientBuilder(@NonNull Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
boolean httpProxyEnabled = preferences.getBoolean("httpProxyEnabled", false);
String httpServer = preferences.getString("httpProxyServer", "");
int httpPort;
try {
httpPort = Integer.parseInt(preferences.getString("httpProxyPort", "-1"));
} catch (NumberFormatException e) {
// user has entered wrong port, fall back to no proxy
httpPort = -1;
}
int cacheSize = 25*1024*1024; // 25 MiB
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(getUserAgentInterceptor())
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.cache(new Cache(context.getCacheDir(), cacheSize));
if (httpProxyEnabled && !httpServer.isEmpty() && (httpPort > 0) && (httpPort < 65535)) {
InetSocketAddress address = InetSocketAddress.createUnresolved(httpServer, httpPort);
builder.proxy(new Proxy(Proxy.Type.HTTP, address));
}
return builder;
}
/**
* Add a custom User-Agent that contains Tusky & Android Version to all requests
* Example:
* User-Agent: Tusky/1.1.2 Android/5.0.2
*/
@NonNull
private static Interceptor getUserAgentInterceptor() {
return chain -> {
Request originalRequest = chain.request();
Request requestWithUserAgent = originalRequest.newBuilder()
.header("User-Agent", "Tusky/"+ BuildConfig.VERSION_NAME+" Android/"+Build.VERSION.RELEASE)
.build();
return chain.proceed(requestWithUserAgent);
};
}
}

View File

@ -0,0 +1,115 @@
/* Copyright 2020 Tusky Contributors
*
* This file is part of Tusky.
*
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with Tusky. If
* not, see <http://www.gnu.org/licenses/>. */
package com.keylesspalace.tusky.util
import android.content.Context
import android.os.Build
import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.BuildConfig
import okhttp3.Cache
import okhttp3.OkHttp
import okhttp3.OkHttpClient
import okhttp3.tls.HandshakeCertificates
import java.io.ByteArrayInputStream
import java.net.InetSocketAddress
import java.net.Proxy
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
fun okhttpClient(context: Context): OkHttpClient.Builder {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val httpProxyEnabled = preferences.getBoolean("httpProxyEnabled", false)
val httpServer = preferences.getNonNullString("httpProxyServer", "")
val httpPort = preferences.getNonNullString("httpProxyPort", "-1").toIntOrNull() ?: -1
val cacheSize = 25 * 1024 * 1024 // 25 MiB
val builder = OkHttpClient.Builder()
.addInterceptor { chain ->
/**
* Add a custom User-Agent that contains Tusky, Android and Okhttp Version to all requests
* Example:
* User-Agent: Tusky/1.1.2 Android/5.0.2
* */
val requestWithUserAgent = chain.request().newBuilder()
.header(
"User-Agent",
"Tusky/${BuildConfig.VERSION_NAME} Android/${Build.VERSION.RELEASE} OkHttp/${OkHttp.VERSION}"
)
.build()
chain.proceed(requestWithUserAgent)
}
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.cache(Cache(context.cacheDir, cacheSize.toLong()))
if (httpProxyEnabled && httpServer.isNotEmpty() && httpPort > 0 && httpPort < 65535) {
val address = InetSocketAddress.createUnresolved(httpServer, httpPort)
builder.proxy(Proxy(Proxy.Type.HTTP, address))
}
// trust the new Let's Encrypt root certificate that is not available on Android < 7.1.1
// new cert https://letsencrypt.org/certs/isrgrootx1.pem
// see https://letsencrypt.org/2020/11/06/own-two-feet.html
// see https://stackoverflow.com/questions/64844311/certpathvalidatorexception-connecting-to-a-lets-encrypt-host-on-android-m-or-ea
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
val isgCert = """
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
""".trimIndent()
val cf = CertificateFactory.getInstance("X.509")
val isgCertificate = cf.generateCertificate(ByteArrayInputStream(isgCert.toByteArray(charset("UTF-8"))))
val certificates = HandshakeCertificates.Builder()
.addTrustedCertificate(isgCertificate as X509Certificate)
.addPlatformTrustedCertificates()
.build()
builder.sslSocketFactory(
certificates.sslSocketFactory(),
certificates.trustManager
)
}
return builder
}

View File

@ -23,7 +23,6 @@ import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
@ -220,9 +219,7 @@ class StatusViewHelper(private val itemView: View) {
// Set the icon next to the label. // Set the icon next to the label.
val drawableId = getLabelIcon(attachments[0].type) val drawableId = getLabelIcon(attachments[0].type)
val drawable = AppCompatResources.getDrawable(context, drawableId) mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0)
ThemeUtils.setDrawableTint(context, drawable!!, android.R.attr.textColorTertiary)
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
mediaLabel.setOnClickListener { listener.onViewMedia(null, 0) } mediaLabel.setOnClickListener { listener.onViewMedia(null, 0) }
} }

View File

@ -24,9 +24,7 @@ import android.util.TypedValue;
import androidx.annotation.AttrRes; import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
/** /**
@ -60,17 +58,6 @@ public class ThemeUtils {
return dimen; return dimen;
} }
/** this can be replaced with drawableTint in xml once minSdkVersion >= 23 */
@Nullable
public static Drawable getTintedDrawable(@NonNull Context context, @DrawableRes int drawableId, @AttrRes int colorAttr) {
Drawable drawable = context.getDrawable(drawableId);
if(drawable == null) {
return null;
}
setDrawableTint(context, drawable, colorAttr);
return drawable;
}
public static void setDrawableTint(Context context, Drawable drawable, @AttrRes int attribute) { public static void setDrawableTint(Context context, Drawable drawable, @AttrRes int attribute) {
drawable.setColorFilter(getColor(context, attribute), PorterDuff.Mode.SRC_IN); drawable.setColorFilter(getColor(context, attribute), PorterDuff.Mode.SRC_IN);
} }

View File

@ -36,4 +36,6 @@
tools:src="@drawable/elephant_error" tools:src="@drawable/elephant_error"
tools:visibility="visible" /> tools:visibility="visible" />
<include layout="@layout/item_status_bottom_sheet" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -166,10 +166,10 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/composeMediaPreviewBar" android:id="@+id/composeMediaPreviewBar"
android:visibility="gone"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="none" /> android:scrollbars="none"
android:visibility="gone" />
<com.keylesspalace.tusky.components.compose.view.PollPreviewView <com.keylesspalace.tusky.components.compose.view.PollPreviewView
android:id="@+id/pollPreview" android:id="@+id/pollPreview"
@ -297,9 +297,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:animateLayoutChanges="true"
android:background="?attr/colorSurface" android:background="?attr/colorSurface"
android:elevation="12dp" android:elevation="12dp"
android:animateLayoutChanges="true"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="8dp" android:paddingStart="8dp"
android:paddingTop="4dp" android:paddingTop="4dp"
@ -314,8 +314,8 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_add_media" android:contentDescription="@string/action_add_media"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_add_media" app:srcCompat="@drawable/ic_attach_file_24dp"
app:srcCompat="@drawable/ic_attach_file_24dp" /> app:tooltipText="@string/action_add_media" />
<ImageButton <ImageButton
android:id="@+id/composeToggleVisibilityButton" android:id="@+id/composeToggleVisibilityButton"
@ -325,7 +325,8 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_toggle_visibility" android:contentDescription="@string/action_toggle_visibility"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_toggle_visibility" android:tint="?android:attr/textColorTertiary"
app:tooltipText="@string/action_toggle_visibility"
tools:src="@drawable/ic_public_24dp" /> tools:src="@drawable/ic_public_24dp" />
<ImageButton <ImageButton
@ -336,7 +337,7 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_hide_media" android:contentDescription="@string/action_hide_media"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_hide_media" app:tooltipText="@string/action_hide_media"
tools:src="@drawable/ic_eye_24dp" /> tools:src="@drawable/ic_eye_24dp" />
<ImageButton <ImageButton
@ -347,8 +348,8 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_content_warning" android:contentDescription="@string/action_content_warning"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_content_warning" app:srcCompat="@drawable/ic_cw_24dp"
app:srcCompat="@drawable/ic_cw_24dp" /> app:tooltipText="@string/action_content_warning" />
<ImageButton <ImageButton
android:id="@+id/composeEmojiButton" android:id="@+id/composeEmojiButton"
@ -358,8 +359,8 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_emoji_keyboard" android:contentDescription="@string/action_emoji_keyboard"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_emoji_keyboard" app:srcCompat="@drawable/ic_emoji_24dp"
app:srcCompat="@drawable/ic_emoji_24dp" /> app:tooltipText="@string/action_emoji_keyboard" />
<ImageButton <ImageButton
android:id="@+id/composeScheduleButton" android:id="@+id/composeScheduleButton"
@ -369,8 +370,8 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:contentDescription="@string/action_schedule_toot" android:contentDescription="@string/action_schedule_toot"
android:padding="4dp" android:padding="4dp"
android:tooltipText="@string/action_schedule_toot" app:srcCompat="@drawable/ic_access_time"
app:srcCompat="@drawable/ic_access_time" /> app:tooltipText="@string/action_schedule_toot" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"

View File

@ -29,7 +29,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp" app:contentInsetStartWithNavigation="0dp"
app:layout_scrollFlags="scroll|enterAlways" /> app:layout_scrollFlags="scroll|enterAlways"
app:navigationContentDescription="@string/action_open_drawer" />
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout" android:id="@+id/tabLayout"

View File

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/hashtag" android:id="@+id/hashtag"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="16dp" android:padding="16dp"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:textStyle="normal|bold" /> android:textStyle="normal|bold"
app:drawableStartCompat="@drawable/ic_list"
app:drawableTint="?attr/iconColor" />

View File

@ -340,6 +340,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -353,6 +354,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
@ -366,6 +368,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
@ -379,6 +382,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />

View File

@ -6,8 +6,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
android:paddingBottom="8dp" android:paddingTop="8dp"
android:paddingTop="8dp"> android:paddingBottom="8dp">
<!--This is a thumbnail picture--> <!--This is a thumbnail picture-->
<ImageView <ImageView
@ -15,23 +15,25 @@
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="42dp" android:layout_height="42dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:importantForAccessibility="no"
android:padding="4dp" android:padding="4dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_emoji_24dp" /> app:srcCompat="@drawable/ic_emoji_24dp"
app:tint="#0000" /> <!-- unset the preference theme tint -->
<!--This is the font's name--> <!--This is the font's name-->
<TextView <TextView
android:id="@+id/emojicompat_name" android:id="@+id/emojicompat_name"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="72dp"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginEnd="72dp"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
app:layout_constraintBottom_toTopOf="@+id/emojicompat_caption" app:layout_constraintBottom_toTopOf="@+id/emojicompat_caption"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/emojicompat_thumb" app:layout_constraintStart_toEndOf="@+id/emojicompat_thumb"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="@string/system_default" /> tools:text="@string/system_default" />
@ -58,8 +60,8 @@
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="72dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="72dp"
android:indeterminate="false" android:indeterminate="false"
android:visibility="gone" android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawablePadding="4dp" android:drawablePadding="4dp"
@ -7,4 +8,5 @@
android:focusableInTouchMode="false" android:focusableInTouchMode="false"
android:gravity="center_vertical" android:gravity="center_vertical"
android:lines="1" android:lines="1"
android:maxEms="20" /> android:maxEms="20"
app:drawableTint="?android:attr/textColorTertiary" />

View File

@ -198,8 +198,8 @@
app:layout_constraintLeft_toLeftOf="@+id/status_media_preview_container" app:layout_constraintLeft_toLeftOf="@+id/status_media_preview_container"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_container" app:layout_constraintTop_toTopOf="@+id/status_media_preview_container"
app:srcCompat="@drawable/ic_eye_24dp" app:srcCompat="@drawable/ic_eye_24dp"
tools:visibility="visible" app:tint="@color/white"
app:tint="@color/white" /> tools:visibility="visible" />
<TextView <TextView
android:id="@+id/status_sensitive_media_warning" android:id="@+id/status_sensitive_media_warning"
@ -231,6 +231,7 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@ -168,9 +168,9 @@
android:foreground="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground"
android:minHeight="80dp" android:minHeight="80dp"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/status_display_name" app:layout_constraintStart_toStartOf="@id/status_display_name"
app:layout_constraintTop_toBottomOf="@+id/button_toggle_content" app:layout_constraintTop_toBottomOf="@+id/button_toggle_content"
app:layout_constraintEnd_toEndOf="parent"
tools:visibility="gone"> tools:visibility="gone">
<ImageView <ImageView
@ -411,6 +411,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -424,6 +425,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
@ -437,6 +439,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
@ -450,6 +453,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />

View File

@ -356,6 +356,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -369,6 +370,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
@ -382,6 +384,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
@ -395,6 +398,7 @@
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone" android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" /> app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />

View File

@ -32,6 +32,7 @@
android:paddingBottom="8dp" android:paddingBottom="8dp"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_large" android:textSize="?attr/status_text_large"
app:drawableTint="?android:attr/textColorSecondary"
app:layout_constraintBottom_toTopOf="@id/chipGroup" app:layout_constraintBottom_toTopOf="@id/chipGroup"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView" app:layout_constraintStart_toEndOf="@id/imageView"

View File

@ -1,17 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/textView" android:id="@+id/textView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:drawableStart="@drawable/ic_home_24dp"
android:layout_height="48dp" android:layout_height="48dp"
android:gravity="center_vertical" android:background="?attr/selectableItemBackground"
android:drawablePadding="12dp" android:drawablePadding="12dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:paddingStart="8dp" android:paddingStart="8dp"
android:paddingEnd="8dp" android:paddingEnd="8dp"
android:lines="1"
android:ellipsize="end"
android:background="?attr/selectableItemBackground"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_large" /> android:textSize="?attr/status_text_large"
app:drawableStartCompat="@drawable/ic_home_24dp"
app:drawableTint="?android:attr/textColorSecondary" />

View File

@ -23,6 +23,7 @@
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:textColor="?android:textColorTertiary" android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintBottom_toTopOf="@id/invalidScheduleWarning" app:layout_constraintBottom_toTopOf="@id/invalidScheduleWarning"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
@ -39,11 +40,11 @@
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:textColor="?android:textColorTertiary" android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium" android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
tools:text="@string/warning_scheduling_interval" tools:text="@string/warning_scheduling_interval" />
android:visibility="gone" />
</merge> </merge>

View File

@ -381,7 +381,7 @@
<string name="poll_vote">ভোট</string> <string name="poll_vote">ভোট</string>
<string name="poll_info_closed">বন্ধ</string> <string name="poll_info_closed">বন্ধ</string>
<string name="poll_info_time_absolute">\'%s এ শেষ হবে\'</string> <string name="poll_info_time_absolute">\'%s এ শেষ হবে\'</string>
<string name="poll_info_format">" &lt;!-- ১৫ ভোট • ১ ঘন্টা বাকি --&gt; %1$s • %2$s"<!-- 15 votes • 1 hour left --> <string name="poll_info_format"><!-- 15 votes • 1 hour left -->
%1$s • %2$s</string> %1$s • %2$s</string>
<string name="compose_preview_image_description">ছবি %s এর জন্য ক্রিয়া</string> <string name="compose_preview_image_description">ছবি %s এর জন্য ক্রিয়া</string>
<string name="notification_clear_text">আপনি কি আপনার সমস্ত বিজ্ঞপ্তি স্থায়ীভাবে মুছে ফেলতে চান\?</string> <string name="notification_clear_text">আপনি কি আপনার সমস্ত বিজ্ঞপ্তি স্থায়ীভাবে মুছে ফেলতে চান\?</string>

View File

@ -475,11 +475,7 @@
<string name="action_unmute_notifications_desc">Odkrýt oznámení od %s</string> <string name="action_unmute_notifications_desc">Odkrýt oznámení od %s</string>
<string name="action_unmute_desc">Odkrýt %s</string> <string name="action_unmute_desc">Odkrýt %s</string>
<string name="dialog_mute_warning">Ztišit @%s\?</string> <string name="dialog_mute_warning">Ztišit @%s\?</string>
<plurals name="poll_info_people">
<item quantity="one"/>
<item quantity="few"/>
<item quantity="other"/>
</plurals>
<string name="notification_follow_request_format">%s požádal/a aby vás mohl/a sledovat</string> <string name="notification_follow_request_format">%s požádal/a aby vás mohl/a sledovat</string>
<string name="pref_title_confirm_reblogs">Zobrazit dialogové okno s potvrzením při boostování</string> <string name="pref_title_confirm_reblogs">Zobrazit dialogové okno s potvrzením při boostování</string>
</resources> </resources>

View File

@ -101,7 +101,7 @@
<string name="action_accept">Akzeptieren</string> <string name="action_accept">Akzeptieren</string>
<string name="action_reject">Ablehnen</string> <string name="action_reject">Ablehnen</string>
<string name="action_search">Suche</string> <string name="action_search">Suche</string>
<string name="action_access_saved_toot">Gespeicherte Beiträge</string> <string name="action_access_saved_toot">Entwürfe</string>
<string name="action_toggle_visibility">Beitragssichtbarkeit</string> <string name="action_toggle_visibility">Beitragssichtbarkeit</string>
<string name="action_content_warning">Inhaltswarnung</string> <string name="action_content_warning">Inhaltswarnung</string>
<string name="action_emoji_keyboard">Emoji</string> <string name="action_emoji_keyboard">Emoji</string>
@ -465,4 +465,9 @@
<string name="abbreviated_hours_ago">%dSt.</string> <string name="abbreviated_hours_ago">%dSt.</string>
<string name="abbreviated_in_days">in %d T.</string> <string name="abbreviated_in_days">in %d T.</string>
<string name="abbreviated_years_ago">%dJ.</string> <string name="abbreviated_years_ago">%dJ.</string>
<string name="account_note_saved">Gespeichert!</string>
<string name="account_note_hint">Private Notiz über diesen Account</string>
<string name="pref_title_hide_top_toolbar">Titel der Hauptnavigation verstecken</string>
<string name="no_announcements">Im Moment gibt es keine Ankündigungen.</string>
<string name="title_announcements">Ankündigungen</string>
</resources> </resources>

View File

@ -164,9 +164,9 @@
<string name="pref_title_notification_alert_vibrate">Sciigi per vibro</string> <string name="pref_title_notification_alert_vibrate">Sciigi per vibro</string>
<string name="pref_title_notification_alert_light">Sciigi per lumo</string> <string name="pref_title_notification_alert_light">Sciigi per lumo</string>
<string name="pref_title_notification_filters">Sciigi al mi kiam</string> <string name="pref_title_notification_filters">Sciigi al mi kiam</string>
<string name="pref_title_notification_filter_mentions">menciita</string> <string name="pref_title_notification_filter_mentions">iu mencias min</string>
<string name="pref_title_notification_filter_follows">sekvita</string> <string name="pref_title_notification_filter_follows">iu sekvas min</string>
<string name="pref_title_notification_filter_reblogs">viaj mesaĝoj estas diskonigitaj</string> <string name="pref_title_notification_filter_reblogs">miaj mesaĝoj estas diskonigitaj</string>
<string name="pref_title_notification_filter_favourites">miaj mesaĝoj estas stelumitaj</string> <string name="pref_title_notification_filter_favourites">miaj mesaĝoj estas stelumitaj</string>
<string name="pref_title_appearance_settings">Aspekto</string> <string name="pref_title_appearance_settings">Aspekto</string>
<string name="pref_title_app_theme">Temo de la apo</string> <string name="pref_title_app_theme">Temo de la apo</string>
@ -363,7 +363,7 @@
<string name="pref_title_animate_gif_avatars">Moviĝi GIF profilbildojn</string> <string name="pref_title_animate_gif_avatars">Moviĝi GIF profilbildojn</string>
<string name="notification_poll_name">Enketoj</string> <string name="notification_poll_name">Enketoj</string>
<string name="notification_poll_description">Sciigoj pri enketoj kiuj finiĝis</string> <string name="notification_poll_description">Sciigoj pri enketoj kiuj finiĝis</string>
<string name="edit_hashtag_hint">Kradvortoj sen #</string> <string name="edit_hashtag_hint">Kradvorto sen #</string>
<string name="notifications_clear">Viŝi</string> <string name="notifications_clear">Viŝi</string>
<string name="notifications_apply_filter">Filtri</string> <string name="notifications_apply_filter">Filtri</string>
<string name="filter_apply">Apliki</string> <string name="filter_apply">Apliki</string>
@ -373,15 +373,14 @@
<string name="compose_preview_image_description">Agoj por bildo %s</string> <string name="compose_preview_image_description">Agoj por bildo %s</string>
<string name="poll_info_format"> <!-- 15 votes • 1 hour left --> %1$s • %2$s</string> <string name="poll_info_format"> <!-- 15 votes • 1 hour left --> %1$s • %2$s</string>
<plurals name="poll_info_votes"> <plurals name="poll_info_votes">
<item quantity="one"/> <item quantity="one">%s voĉdono</item>
<item quantity="other"/> <item quantity="other">%s voĉdonoj</item>
</plurals> </plurals>
<string name="poll_info_time_absolute">finiĝos je %s</string> <string name="poll_info_time_absolute">finiĝos je %s</string>
<string name="poll_info_closed">finiĝita</string> <string name="poll_info_closed">finiĝita</string>
<string name="poll_vote">Voĉdoni</string> <string name="poll_vote">Voĉdoni</string>
<string name="poll_ended_voted">Enketo al kiu vi voĉdonis finiĝis</string> <string name="poll_ended_voted">Enketo al kiu vi voĉdonis finiĝis</string>
<string name="poll_ended_created">Enketo kiu vi kreis finiĝis</string> <string name="poll_ended_created">Enketo kiu vi kreis finiĝis</string>
<string name="title_domain_mutes">Kaŝitaj domajnoj</string> <string name="title_domain_mutes">Kaŝitaj domajnoj</string>
<string name="action_view_domain_mutes">Kaŝitaj domajnoj</string> <string name="action_view_domain_mutes">Kaŝitaj domajnoj</string>
<string name="action_mute_domain">Silentigi %s</string> <string name="action_mute_domain">Silentigi %s</string>
@ -437,4 +436,50 @@
<string name="no_scheduled_status">Vi ne havas iun ajn planitan mesaĝon.</string> <string name="no_scheduled_status">Vi ne havas iun ajn planitan mesaĝon.</string>
<string name="notification_follow_request_name">Petoj de sekvado</string> <string name="notification_follow_request_name">Petoj de sekvado</string>
<string name="hashtags">Kradvortoj</string> <string name="hashtags">Kradvortoj</string>
<plurals name="poll_info_people">
<item quantity="one">%s homo</item>
<item quantity="other">%s homoj</item>
</plurals>
<string name="add_hashtag_title">Aldoni kradvorton</string>
<string name="notification_follow_request_description">Sciigoj pri petoj de sekvado</string>
<string name="pref_title_gradient_for_media">Montri buntajn transirojn por kaŝitaj aŭdovidaĵoj</string>
<string name="dialog_mute_hide_notifications">Kaŝi la sciigojn</string>
<string name="dialog_mute_warning">Silentigi @%s\?</string>
<string name="dialog_block_warning">Bloki @%s\?</string>
<string name="action_unmute_conversation">Malsilentigi la konversacion</string>
<string name="action_mute_conversation">Silentigi la konversacion</string>
<string name="action_unmute_domain">Malsilentigi %s</string>
<string name="action_mute_notifications_desc">Silentigi sciigojn de %s</string>
<string name="action_unmute_notifications_desc">Malsilentigi sciigojn de %s</string>
<string name="action_unmute_desc">Malsilentigi %s</string>
<string name="notification_follow_request_format">%s petis sekvi vin</string>
<string name="title_announcements">Anoncoj</string>
<plurals name="poll_timespan_minutes">
<item quantity="one">%d minuto restas</item>
<item quantity="other">%d minutoj restas</item>
</plurals>
<plurals name="poll_timespan_seconds">
<item quantity="one">%d sekundo restas</item>
<item quantity="other">%d sekundoj restas</item>
</plurals>
<plurals name="poll_timespan_hours">
<item quantity="one">%d horo restas</item>
<item quantity="other">%d horoj restas</item>
</plurals>
<plurals name="poll_timespan_days">
<item quantity="one">%d tago restas</item>
<item quantity="other">%d tagoj restas</item>
</plurals>
<string name="pref_main_nav_position">Pozicio de la ĉefa naviga breto</string>
<string name="pref_title_notification_filter_follow_requests">iu petas sekvi min</string>
<string name="pref_main_nav_position_option_bottom">Malsupro</string>
<string name="pref_main_nav_position_option_top">Supro</string>
<string name="account_note_saved">Konservita!</string>
<string name="account_note_hint">Via privata noto pri ĉi tiu konto</string>
<string name="pref_title_hide_top_toolbar">Kaŝi la titolon de la supra ilobreto</string>
<string name="pref_title_show_cards_in_timelines">Montri antaŭvidojn de ligiloj en tempolinioj</string>
<string name="pref_title_confirm_reblogs">Montri konfirman fenestron antaŭ ol diskonigi</string>
<string name="no_announcements">Estas neniu anonco.</string>
<string name="pref_title_enable_swipe_for_tabs">Ebligi ŝovumadon por ŝanĝi inter la langetoj</string>
<string name="warning_scheduling_interval">Mastodon havas minimuman intervalon de planado de 5 minutoj.</string>
</resources> </resources>

View File

@ -475,4 +475,8 @@
<string name="action_mute_notifications_desc">Silenciar notificaciones desde %s</string> <string name="action_mute_notifications_desc">Silenciar notificaciones desde %s</string>
<string name="action_unmute_notifications_desc">Dejar de silenciar notificaciones desde %s</string> <string name="action_unmute_notifications_desc">Dejar de silenciar notificaciones desde %s</string>
<string name="pref_title_hide_top_toolbar">Ocultar el título de la barra de herramientas superior</string> <string name="pref_title_hide_top_toolbar">Ocultar el título de la barra de herramientas superior</string>
<string name="account_note_saved">¡Guardado!</string>
<string name="account_note_hint">Tu nota privada acerca de esta cuenta</string>
<string name="no_announcements">No hay anuncios.</string>
<string name="title_announcements">Anuncios</string>
</resources> </resources>

View File

@ -450,10 +450,7 @@
<string name="hashtags">Traolak</string> <string name="hashtags">Traolak</string>
<string name="dialog_mute_hide_notifications">Ez erakutsi jakinarazpenak</string> <string name="dialog_mute_hide_notifications">Ez erakutsi jakinarazpenak</string>
<string name="action_unmute_desc">Desmututu %s</string> <string name="action_unmute_desc">Desmututu %s</string>
<plurals name="poll_info_people">
<item quantity="one">Pertsona %1</item>
<item quantity="other">%2 pertsona</item>
</plurals>
<string name="pref_title_hide_top_toolbar">Ezkutatu goiko tresna-barraren izenburua</string> <string name="pref_title_hide_top_toolbar">Ezkutatu goiko tresna-barraren izenburua</string>
<string name="pref_title_confirm_reblogs">Erakutsi berrespen-abisua tuta bultzatu aurretik</string> <string name="pref_title_confirm_reblogs">Erakutsi berrespen-abisua tuta bultzatu aurretik</string>
<string name="pref_title_show_cards_in_timelines">Erakutsi esteken aurrebista denbora-lerroetan</string> <string name="pref_title_show_cards_in_timelines">Erakutsi esteken aurrebista denbora-lerroetan</string>

View File

@ -93,7 +93,7 @@
<string name="action_accept">پذیرش</string> <string name="action_accept">پذیرش</string>
<string name="action_reject">رد</string> <string name="action_reject">رد</string>
<string name="action_search">جست‌وجو</string> <string name="action_search">جست‌وجو</string>
<string name="action_access_saved_toot">پیش‌نویس</string> <string name="action_access_saved_toot">پیش‌نویسها</string>
<string name="action_toggle_visibility">نمایانی بوق</string> <string name="action_toggle_visibility">نمایانی بوق</string>
<string name="action_content_warning">هشدار محتوا</string> <string name="action_content_warning">هشدار محتوا</string>
<string name="action_emoji_keyboard">صفحه‌کلید اموجی</string> <string name="action_emoji_keyboard">صفحه‌کلید اموجی</string>
@ -148,27 +148,27 @@
<string name="pref_title_notification_filter_reblogs">فرسته‌هایم تقویت شدند</string> <string name="pref_title_notification_filter_reblogs">فرسته‌هایم تقویت شدند</string>
<string name="pref_title_notification_filter_favourites">فرسته‌هایم برگزیده شدند</string> <string name="pref_title_notification_filter_favourites">فرسته‌هایم برگزیده شدند</string>
<string name="pref_title_appearance_settings">ظاهر</string> <string name="pref_title_appearance_settings">ظاهر</string>
<string name="pref_title_app_theme">تم برنامه</string> <string name="pref_title_app_theme">زمینهٔ کاره</string>
<string name="pref_title_timelines">خط‌ زمانی‌ها</string> <string name="pref_title_timelines">خط‌ زمانی‌ها</string>
<string name="app_them_dark">روشن</string> <string name="app_them_dark">تاریک</string>
<string name="app_theme_light">سیاه</string> <string name="app_theme_light">روشن</string>
<string name="app_theme_black">سیاه</string> <string name="app_theme_black">سیاه</string>
<string name="app_theme_auto">خودکار در غروب</string> <string name="app_theme_auto">خودکار در غروب</string>
<string name="pref_title_browser_settings">مرورگر</string> <string name="pref_title_browser_settings">مرورگر</string>
<string name="pref_title_custom_tabs">استفاده از زبانه‌های سفارشی کروم</string> <string name="pref_title_custom_tabs">استفاده از زبانه‌های سفارشی کروم</string>
<string name="pref_title_hide_follow_button">پنهان کردن دکمه ایجاد هنگام پیمایش</string> <string name="pref_title_hide_follow_button">نهفتن دکمهٔ ایجاد، هنگام پیمایش</string>
<string name="pref_title_status_filter">فیلتر کردن خط زمانی</string> <string name="pref_title_status_filter">فیلتر کردن خط زمانی</string>
<string name="pref_title_status_tabs">زبانه‌ها</string> <string name="pref_title_status_tabs">زبانه‌ها</string>
<string name="pref_title_show_boosts">نمایش تقویت‌ها</string> <string name="pref_title_show_boosts">نمایش تقویت‌ها</string>
<string name="pref_title_show_replies">نمایش پاسخ‌ها</string> <string name="pref_title_show_replies">نمایش پاسخ‌ها</string>
<string name="pref_title_show_media_preview">بارگیری پیش‌نمایش رسانه</string> <string name="pref_title_show_media_preview">بارگیری پیش‌نمایش رسانه</string>
<string name="pref_title_proxy_settings">پراکسی</string> <string name="pref_title_proxy_settings">پیشکار</string>
<string name="pref_title_http_proxy_settings">پراکسی HTTP</string> <string name="pref_title_http_proxy_settings">پیشکار HTTP</string>
<string name="pref_title_http_proxy_enable">فعال‌سازی پراکسی HTTP</string> <string name="pref_title_http_proxy_enable">به کار انداختن پیشکار HTTP</string>
<string name="pref_title_http_proxy_server">کارساز پیشکار HTTP</string> <string name="pref_title_http_proxy_server">کارساز پیشکار HTTP</string>
<string name="pref_title_http_proxy_port">درگاه پیشکار HTTP</string> <string name="pref_title_http_proxy_port">درگاه پیشکار HTTP</string>
<string name="pref_default_post_privacy">محرمانگی پیش‌گزیدهٔ فرسته</string> <string name="pref_default_post_privacy">محرمانگی پیش‌گزیدهٔ فرسته</string>
<string name="pref_default_media_sensitivity">همواره رسانه را به عنوان حساس نشانه‌گذاری کن</string> <string name="pref_default_media_sensitivity">علامت‌گذاری همیشگی رسانه به عنوان حساس</string>
<string name="pref_publishing">در حال انتشار (همگام با کارساز)</string> <string name="pref_publishing">در حال انتشار (همگام با کارساز)</string>
<string name="pref_failed_to_sync">ناتوانی در هم‌گام‌سازی تنظیمات</string> <string name="pref_failed_to_sync">ناتوانی در هم‌گام‌سازی تنظیمات</string>
<string name="post_privacy_public">عمومی</string> <string name="post_privacy_public">عمومی</string>
@ -279,7 +279,7 @@
<string name="title_statuses_pinned">سنجاق‌شده</string> <string name="title_statuses_pinned">سنجاق‌شده</string>
<string name="title_domain_mutes">دامنه‌های نهفته</string> <string name="title_domain_mutes">دامنه‌های نهفته</string>
<string name="status_username_format">\@%s</string> <string name="status_username_format">\@%s</string>
<string name="message_empty">این‌حا هیچ‌چیزی نیست.</string> <string name="message_empty">این‌جا هیچ‌چیزی نیست.</string>
<string name="action_unreblog">برداشتن تقویت</string> <string name="action_unreblog">برداشتن تقویت</string>
<string name="action_unfavourite">برداشتن برگزیدگی</string> <string name="action_unfavourite">برداشتن برگزیدگی</string>
<string name="action_delete_and_redraft">حذف و بازنویسی</string> <string name="action_delete_and_redraft">حذف و بازنویسی</string>
@ -289,11 +289,11 @@
<string name="action_add_tab">افزودن زبانه</string> <string name="action_add_tab">افزودن زبانه</string>
<string name="action_links">پیوندها</string> <string name="action_links">پیوندها</string>
<string name="action_mentions">اشاره‌ها</string> <string name="action_mentions">اشاره‌ها</string>
<string name="action_hashtags">هشتگها</string> <string name="action_hashtags">برچسبها</string>
<string name="action_open_reblogger">گشودن تقویت‌کنندهٔ بوق</string> <string name="action_open_reblogger">گشودن تقویت‌کنندهٔ بوق</string>
<string name="action_open_reblogged_by">نمایش تقویت‌ها</string> <string name="action_open_reblogged_by">نمایش تقویت‌ها</string>
<string name="action_open_faved_by">نمایش برگزیده‌ها</string> <string name="action_open_faved_by">نمایش برگزیده‌ها</string>
<string name="title_hashtags_dialog">هشتگها</string> <string name="title_hashtags_dialog">برچسبها</string>
<string name="title_mentions_dialog">اشاره‌ها</string> <string name="title_mentions_dialog">اشاره‌ها</string>
<string name="title_links_dialog">پیوندها</string> <string name="title_links_dialog">پیوندها</string>
<string name="action_open_media_n">گشودن رسانه #%d</string> <string name="action_open_media_n">گشودن رسانه #%d</string>
@ -305,11 +305,11 @@
<string name="dialog_redraft_toot_warning">می‌خواهید این بوق را پاک و بازنویسی کنید؟</string> <string name="dialog_redraft_toot_warning">می‌خواهید این بوق را پاک و بازنویسی کنید؟</string>
<string name="mute_domain_warning_dialog_ok">نهفتن تمام دامنه</string> <string name="mute_domain_warning_dialog_ok">نهفتن تمام دامنه</string>
<string name="pref_title_notification_filter_poll">پایان نظرسنجی‌ها</string> <string name="pref_title_notification_filter_poll">پایان نظرسنجی‌ها</string>
<string name="pref_title_timeline_filters">صافیها</string> <string name="pref_title_timeline_filters">پالایهها</string>
<string name="app_theme_system">استفاده از طرح سیستم</string> <string name="app_theme_system">استفاده از طراحی سامانه</string>
<string name="pref_title_language">زبان</string> <string name="pref_title_language">زبان</string>
<string name="pref_title_bot_overlay">نمایش نشانگر برای بات‌ها</string> <string name="pref_title_bot_overlay">نمایش نشانگر برای بات‌ها</string>
<string name="pref_title_animate_gif_avatars">پویانمایی آواتار gif</string> <string name="pref_title_animate_gif_avatars">پویانمایی آواتارهای جیف</string>
<string name="notification_poll_name">نظرسنجی‌ها</string> <string name="notification_poll_name">نظرسنجی‌ها</string>
<string name="notification_poll_description">آگاهی‌ها دربارهٔ نظرسنجی‌های پایان‌یافته</string> <string name="notification_poll_description">آگاهی‌ها دربارهٔ نظرسنجی‌های پایان‌یافته</string>
<string name="about_tusky_version">تاسکی %s</string> <string name="about_tusky_version">تاسکی %s</string>
@ -364,7 +364,7 @@
<string name="description_visiblity_direct">مستقیم</string> <string name="description_visiblity_direct">مستقیم</string>
<string name="description_poll">نظرسنجی با گزینه‌ها: %1$s، %2$s، %3$s، %4$s؛ %5$s</string> <string name="description_poll">نظرسنجی با گزینه‌ها: %1$s، %2$s، %3$s، %4$s؛ %5$s</string>
<string name="hint_list_name">نام فهرست</string> <string name="hint_list_name">نام فهرست</string>
<string name="edit_hashtag_hint">هشتگ بدون #</string> <string name="edit_hashtag_hint">برچسب بدون #</string>
<string name="notifications_clear">پاک‌سازی</string> <string name="notifications_clear">پاک‌سازی</string>
<string name="notifications_apply_filter">پالایش</string> <string name="notifications_apply_filter">پالایش</string>
<string name="filter_apply">اعمال</string> <string name="filter_apply">اعمال</string>
@ -434,15 +434,15 @@
<string name="no_saved_status">هیچ پیش‌نویسی ندارید.</string> <string name="no_saved_status">هیچ پیش‌نویسی ندارید.</string>
<string name="no_scheduled_status">هیچ وضعیت زمان‌بسته‌ای ندارید.</string> <string name="no_scheduled_status">هیچ وضعیت زمان‌بسته‌ای ندارید.</string>
<string name="warning_scheduling_interval">ماستودون، بازهٔ زمان‌بندی‌ای با کمینهٔ ۵ دقیقه دارد.</string> <string name="warning_scheduling_interval">ماستودون، بازهٔ زمان‌بندی‌ای با کمینهٔ ۵ دقیقه دارد.</string>
<string name="pref_title_confirm_reblogs">نمایش گفت‌وگوی تأیید پیش از تقویت</string> <string name="pref_title_confirm_reblogs">نمایش گفت‌وگوی تأیید، پیش از تقویت</string>
<string name="pref_title_show_cards_in_timelines">پیش‌نمایش پیوندها در خط‌زمانی‌ها</string> <string name="pref_title_show_cards_in_timelines">پیش‌نمایش پیوندها در خط‌زمانی‌ها</string>
<string name="pref_title_enable_swipe_for_tabs">به کار انداختن اشارهٔ کشیدنی برای تعویض بین زبانه‌ها</string> <string name="pref_title_enable_swipe_for_tabs">به کار انداختن اشارهٔ کشیدنی برای تعویض بین زبانه‌ها</string>
<plurals name="poll_info_people"> <plurals name="poll_info_people">
<item quantity="one">%s نفر</item> <item quantity="one">%s نفر</item>
<item quantity="other">%s نفر</item> <item quantity="other">%s نفر</item>
</plurals> </plurals>
<string name="hashtags">هشتگها</string> <string name="hashtags">برچسبها</string>
<string name="add_hashtag_title">افزودن هشتگ</string> <string name="add_hashtag_title">افزودن برچسب</string>
<string name="notification_follow_request_description">آگاهی‌ها دربارهٔ درخواست‌های پی‌گیری</string> <string name="notification_follow_request_description">آگاهی‌ها دربارهٔ درخواست‌های پی‌گیری</string>
<string name="notification_follow_request_name">درخواست‌های پی‌گیری</string> <string name="notification_follow_request_name">درخواست‌های پی‌گیری</string>
<string name="pref_title_notification_filter_follow_requests">درخواست پی‌گیری</string> <string name="pref_title_notification_filter_follow_requests">درخواست پی‌گیری</string>
@ -470,4 +470,8 @@
</plurals> </plurals>
<string name="pref_title_hide_top_toolbar">نهفتن عنوان نوارابزار بالایی</string> <string name="pref_title_hide_top_toolbar">نهفتن عنوان نوارابزار بالایی</string>
<string name="compose_preview_image_description">کنش‌ها برای تصویر %s</string> <string name="compose_preview_image_description">کنش‌ها برای تصویر %s</string>
<string name="account_note_saved">ذخیره شد!</string>
<string name="account_note_hint">یادداشت خصوصیتان دربارهٔ این حساب</string>
<string name="no_announcements">هیچ اعلامیه‌ای وجود ندارد.</string>
<string name="title_announcements">اعلامیه‌ها</string>
</resources> </resources>

View File

@ -39,7 +39,7 @@
<string name="title_saved_toot">Brouillons</string> <string name="title_saved_toot">Brouillons</string>
<string name="title_licenses">Licences</string> <string name="title_licenses">Licences</string>
<string name="status_username_format">\@%s</string> <string name="status_username_format">\@%s</string>
<string name="status_boosted_format">%s a boosté</string> <string name="status_boosted_format">%s a partagé</string>
<string name="status_sensitive_media_title">Contenu sensible</string> <string name="status_sensitive_media_title">Contenu sensible</string>
<string name="status_media_hidden_title">Média caché</string> <string name="status_media_hidden_title">Média caché</string>
<string name="status_sensitive_media_directions">Cliquer pour voir</string> <string name="status_sensitive_media_directions">Cliquer pour voir</string>
@ -49,7 +49,7 @@
<string name="status_content_show_less">Replier</string> <string name="status_content_show_less">Replier</string>
<string name="message_empty">Rien ici.</string> <string name="message_empty">Rien ici.</string>
<string name="footer_empty">Il ny a aucun pouet ici pour linstant. Glissez vers le bas pour actualiser !</string> <string name="footer_empty">Il ny a aucun pouet ici pour linstant. Glissez vers le bas pour actualiser !</string>
<string name="notification_reblog_format">%s a boosté votre pouet</string> <string name="notification_reblog_format">%s a partagé votre pouet</string>
<string name="notification_favourite_format">%s a ajouté votre pouet à ses favoris</string> <string name="notification_favourite_format">%s a ajouté votre pouet à ses favoris</string>
<string name="notification_follow_format">%s vous suit</string> <string name="notification_follow_format">%s vous suit</string>
<string name="report_username_format">Signaler @%s</string> <string name="report_username_format">Signaler @%s</string>
@ -69,8 +69,8 @@
<string name="action_unfollow">Ne plus suivre</string> <string name="action_unfollow">Ne plus suivre</string>
<string name="action_block">Bloquer</string> <string name="action_block">Bloquer</string>
<string name="action_unblock">Débloquer</string> <string name="action_unblock">Débloquer</string>
<string name="action_hide_reblogs">Cacher les boosts</string> <string name="action_hide_reblogs">Cacher les partages</string>
<string name="action_show_reblogs">Afficher les boosts</string> <string name="action_show_reblogs">Afficher les partages</string>
<string name="action_report">Signaler</string> <string name="action_report">Signaler</string>
<string name="action_delete">Supprimer</string> <string name="action_delete">Supprimer</string>
<string name="action_send">POUET</string> <string name="action_send">POUET</string>
@ -109,8 +109,8 @@
<string name="action_links">Liens</string> <string name="action_links">Liens</string>
<string name="action_mentions">Mentions</string> <string name="action_mentions">Mentions</string>
<string name="action_hashtags">Hashtags</string> <string name="action_hashtags">Hashtags</string>
<string name="action_open_reblogger">Afficher lauteur·rice du boost</string> <string name="action_open_reblogger">Afficher lauteur·rice du partage</string>
<string name="action_open_reblogged_by">Afficher les boosts</string> <string name="action_open_reblogged_by">Afficher les partages</string>
<string name="action_open_faved_by">Montrer les favoris</string> <string name="action_open_faved_by">Montrer les favoris</string>
<string name="title_hashtags_dialog">Hashtags</string> <string name="title_hashtags_dialog">Hashtags</string>
<string name="title_mentions_dialog">Mentions</string> <string name="title_mentions_dialog">Mentions</string>
@ -167,10 +167,10 @@
<string name="pref_title_notification_alert_sound">Notifier avec un son</string> <string name="pref_title_notification_alert_sound">Notifier avec un son</string>
<string name="pref_title_notification_alert_vibrate">Notifier avec une vibration</string> <string name="pref_title_notification_alert_vibrate">Notifier avec une vibration</string>
<string name="pref_title_notification_alert_light">Notifier avec une lumière</string> <string name="pref_title_notification_alert_light">Notifier avec une lumière</string>
<string name="pref_title_notification_filters">Me notifier lorsque</string> <string name="pref_title_notification_filters">Me notifier quand</string>
<string name="pref_title_notification_filter_mentions">on me mentionne</string> <string name="pref_title_notification_filter_mentions">on me mentionne</string>
<string name="pref_title_notification_filter_follows">On me suit</string> <string name="pref_title_notification_filter_follows">on vient de me suivre</string>
<string name="pref_title_notification_filter_reblogs">Mes pouets sont boostés</string> <string name="pref_title_notification_filter_reblogs">mes pouets sont partagés</string>
<string name="pref_title_notification_filter_favourites">mes pouets sont mis en favoris</string> <string name="pref_title_notification_filter_favourites">mes pouets sont mis en favoris</string>
<string name="pref_title_appearance_settings">Apparence</string> <string name="pref_title_appearance_settings">Apparence</string>
<string name="pref_title_app_theme">Thème de lapplication</string> <string name="pref_title_app_theme">Thème de lapplication</string>
@ -187,7 +187,7 @@
<string name="pref_title_language">Langue</string> <string name="pref_title_language">Langue</string>
<string name="pref_title_status_filter">Filtrage des fils</string> <string name="pref_title_status_filter">Filtrage des fils</string>
<string name="pref_title_status_tabs">Onglets</string> <string name="pref_title_status_tabs">Onglets</string>
<string name="pref_title_show_boosts">Afficher les boosts</string> <string name="pref_title_show_boosts">Afficher les partages</string>
<string name="pref_title_show_replies">Afficher les réponses</string> <string name="pref_title_show_replies">Afficher les réponses</string>
<string name="pref_title_show_media_preview">Montrer les miniatures des médias</string> <string name="pref_title_show_media_preview">Montrer les miniatures des médias</string>
<string name="pref_title_proxy_settings">Proxy</string> <string name="pref_title_proxy_settings">Proxy</string>
@ -212,8 +212,8 @@
<string name="notification_mention_descriptions">Notifications pour les nouvelles mentions</string> <string name="notification_mention_descriptions">Notifications pour les nouvelles mentions</string>
<string name="notification_follow_name">Nouveaux abonnés</string> <string name="notification_follow_name">Nouveaux abonnés</string>
<string name="notification_follow_description">Notifications pour les nouveaux abonnés</string> <string name="notification_follow_description">Notifications pour les nouveaux abonnés</string>
<string name="notification_boost_name">Boosts</string> <string name="notification_boost_name">Partages</string>
<string name="notification_boost_description">Notifications quand vos pouets sont boostés</string> <string name="notification_boost_description">Notifications quand vos pouets sont partagés</string>
<string name="notification_favourite_name">Favoris</string> <string name="notification_favourite_name">Favoris</string>
<string name="notification_favourite_description">Notifications quand vos pouets sont mis en favoris</string> <string name="notification_favourite_description">Notifications quand vos pouets sont mis en favoris</string>
<string name="notification_mention_format">%s vous a mentionné</string> <string name="notification_mention_format">%s vous a mentionné</string>
@ -316,8 +316,8 @@
<string name="download_failed">Échec du téléchargement</string> <string name="download_failed">Échec du téléchargement</string>
<string name="profile_badge_bot_text">Robot</string> <string name="profile_badge_bot_text">Robot</string>
<string name="account_moved_description">%1$s a déménagé vers :</string> <string name="account_moved_description">%1$s a déménagé vers :</string>
<string name="reblog_private">Booster vers laudience originale</string> <string name="reblog_private">Partager à laudience originale</string>
<string name="unreblog_private">Annuler le boost</string> <string name="unreblog_private">Annuler le partage</string>
<string name="license_description">Yuito contient du code et des ressources issus des projets open source suivants :</string> <string name="license_description">Yuito contient du code et des ressources issus des projets open source suivants :</string>
<string name="license_apache_2">Sous licence Apache (copie ci-dessous)</string> <string name="license_apache_2">Sous licence Apache (copie ci-dessous)</string>
<string name="license_cc_by_4">CC-BY 4.0</string> <string name="license_cc_by_4">CC-BY 4.0</string>
@ -335,10 +335,10 @@
<item quantity="other"><b>%1$s</b> Favoris</item> <item quantity="other"><b>%1$s</b> Favoris</item>
</plurals> </plurals>
<plurals name="reblogs"> <plurals name="reblogs">
<item quantity="one"><b>%s</b> Boost</item> <item quantity="one"><b>%s</b> Partage</item>
<item quantity="other"><b>%s</b> Boosts</item> <item quantity="other"><b>%s</b> Partages</item>
</plurals> </plurals>
<string name="title_reblogged_by">Boosté par</string> <string name="title_reblogged_by">Partagé par</string>
<string name="title_favourited_by">Mis en favoris par</string> <string name="title_favourited_by">Mis en favoris par</string>
<string name="conversation_1_recipients">%1$s</string> <string name="conversation_1_recipients">%1$s</string>
<string name="conversation_2_recipients">%1$s et %2$s</string> <string name="conversation_2_recipients">%1$s et %2$s</string>
@ -362,7 +362,7 @@
<string name="description_visiblity_direct"> Direct <string name="description_visiblity_direct"> Direct
</string> </string>
<string name="hint_list_name">Nom de la liste</string> <string name="hint_list_name">Nom de la liste</string>
<string name="edit_hashtag_hint">Hastags sans #</string> <string name="edit_hashtag_hint">Hashtag sans #</string>
<string name="notifications_clear">Nettoyer</string> <string name="notifications_clear">Nettoyer</string>
<string name="notifications_apply_filter">Filtrer</string> <string name="notifications_apply_filter">Filtrer</string>
<string name="filter_apply">Appliquer</string> <string name="filter_apply">Appliquer</string>
@ -376,7 +376,7 @@
<string name="poll_info_closed">Terminé</string> <string name="poll_info_closed">Terminé</string>
<string name="poll_vote">Voter</string> <string name="poll_vote">Voter</string>
<string name="notification_poll_name">Sondages</string> <string name="notification_poll_name">Sondages</string>
<string name="pref_title_notification_filter_poll">Les sondages sont clos</string> <string name="pref_title_notification_filter_poll">les sondages se terminent</string>
<string name="notification_poll_description">Notifications pour les sondages terminés</string> <string name="notification_poll_description">Notifications pour les sondages terminés</string>
<string name="poll_ended_created">Un sondage que vous avez créé est terminé</string> <string name="poll_ended_created">Un sondage que vous avez créé est terminé</string>
<plurals name="poll_timespan_days"> <plurals name="poll_timespan_days">
@ -403,7 +403,7 @@
<string name="title_domain_mutes">Domaines cachés</string> <string name="title_domain_mutes">Domaines cachés</string>
<string name="action_view_domain_mutes">Domaines cachés</string> <string name="action_view_domain_mutes">Domaines cachés</string>
<string name="action_mute_domain">Masquer %s</string> <string name="action_mute_domain">Masquer %s</string>
<string name="confirmation_domain_unmuted">%s nest plus masqué</string> <string name="confirmation_domain_unmuted">%s nest plus masqué·e</string>
<string name="mute_domain_warning_dialog_ok">Masquer le domaine entier</string> <string name="mute_domain_warning_dialog_ok">Masquer le domaine entier</string>
<string name="caption_notoemoji">Lensemble démojis actuel de Google</string> <string name="caption_notoemoji">Lensemble démojis actuel de Google</string>
<string name="button_continue">Continuer</string> <string name="button_continue">Continuer</string>
@ -452,28 +452,28 @@
<string name="error_audio_upload_size">Les fichiers audio doivent avoir moins de 40 Mo.</string> <string name="error_audio_upload_size">Les fichiers audio doivent avoir moins de 40 Mo.</string>
<string name="no_saved_status">Vous navez aucun brouillon.</string> <string name="no_saved_status">Vous navez aucun brouillon.</string>
<string name="no_scheduled_status">Vous navez aucun pouet planifié.</string> <string name="no_scheduled_status">Vous navez aucun pouet planifié.</string>
<string name="warning_scheduling_interval">Lintervalle minimum de planification sur Mastodon est de5 minutes.</string> <string name="warning_scheduling_interval">Lintervalle minimum de planification sur Mastodon est de 5 minutes.</string>
<string name="notification_follow_request_name">Demandes d\'abonnement</string> <string name="notification_follow_request_name">Demandes d\'abonnement</string>
<string name="dialog_block_warning">Bloquer @%s \?</string> <string name="dialog_block_warning">Bloquer @%s \?</string>
<string name="pref_title_confirm_reblogs">Afficher une boite de confirmation avant de booster</string> <string name="pref_title_confirm_reblogs">Afficher une fenêtre de confirmation avant de partager</string>
<string name="pref_title_show_cards_in_timelines">Afficher des aperçus des liens dans les fils</string> <string name="pref_title_show_cards_in_timelines">Afficher les aperçus des liens dans les fils</string>
<string name="notification_follow_request_format">%s a demandé à vous suivre</string> <string name="notification_follow_request_format">%s a demandé à vous suivre</string>
<string name="notification_follow_request_description">Notifications à propos des demandes dabonnement</string> <string name="notification_follow_request_description">Notifications à propos des demandes dabonnement</string>
<string name="pref_title_notification_filter_follow_requests">Demande dabonnement</string> <string name="pref_title_notification_filter_follow_requests">on demande à me suivre</string>
<string name="dialog_mute_warning">Mettre en sourdine @%s \?</string> <string name="dialog_mute_warning">Mettre en sourdine @%s \?</string>
<string name="action_unmute_conversation">Enlever la sourdine à la conversation</string> <string name="action_unmute_conversation">Enlever la sourdine à la conversation</string>
<string name="action_mute_conversation">Silencer la conversation</string> <string name="action_mute_conversation">Masquer la conversation</string>
<string name="pref_title_enable_swipe_for_tabs">Activer les gestes de glissement pour passer dun onglet à lautre</string> <string name="pref_title_enable_swipe_for_tabs">Activer le glissement pour changer donglet</string>
<string name="hashtags">Hashtags</string> <string name="hashtags">Hashtags</string>
<string name="add_hashtag_title">Ajouter hashtag</string> <string name="add_hashtag_title">Ajouter un hashtag</string>
<string name="pref_title_gradient_for_media">Afficher des dégradés en couleur pour les médias cachés</string> <string name="pref_title_gradient_for_media">Afficher des dégradés en couleur pour les médias cachés</string>
<string name="pref_main_nav_position_option_bottom">Bas</string> <string name="pref_main_nav_position_option_bottom">Bas</string>
<string name="pref_main_nav_position_option_top">Haut</string> <string name="pref_main_nav_position_option_top">Haut</string>
<string name="pref_main_nav_position">Position de navigation principale</string> <string name="pref_main_nav_position">Position de navigation principale</string>
<string name="action_unmute_domain">Ne plus masquer %s</string> <string name="action_unmute_domain">Ne plus masquer %s</string>
<string name="dialog_mute_hide_notifications">Cacher les notifications</string> <string name="dialog_mute_hide_notifications">Cacher les notifications</string>
<string name="action_mute_notifications_desc">Silencier les notifications de %s</string> <string name="action_mute_notifications_desc">Masquer les notifications de %s</string>
<string name="action_unmute_notifications_desc">Ne plus silencier les notifications de %s</string> <string name="action_unmute_notifications_desc">Ne plus masquer les notifications de %s</string>
<string name="action_unmute_desc">Ne plus masquer %s</string> <string name="action_unmute_desc">Ne plus masquer %s</string>
<plurals name="poll_info_people"> <plurals name="poll_info_people">
<item quantity="one">%s personne</item> <item quantity="one">%s personne</item>
@ -484,4 +484,8 @@
<item quantity="one">%s voix</item> <item quantity="one">%s voix</item>
<item quantity="other">%s voix</item> <item quantity="other">%s voix</item>
</plurals> </plurals>
<string name="account_note_saved">Sauvegardé !</string>
<string name="account_note_hint">Votre note privée sur ce compte</string>
<string name="no_announcements">Il ny a pas dannonce.</string>
<string name="title_announcements">Annonces</string>
</resources> </resources>

View File

@ -472,4 +472,8 @@
<string name="action_unmute_notifications_desc">Értesítések némításának feloldása tőle %s</string> <string name="action_unmute_notifications_desc">Értesítések némításának feloldása tőle %s</string>
<string name="notification_follow_request_format">%s kéri, hogy követhessen</string> <string name="notification_follow_request_format">%s kéri, hogy követhessen</string>
<string name="pref_title_hide_top_toolbar">Felső eszköztár címének elrejtése</string> <string name="pref_title_hide_top_toolbar">Felső eszköztár címének elrejtése</string>
<string name="account_note_saved">Elmentve!</string>
<string name="account_note_hint">Saját, mások számára nem látható megjegyzés erről a fiókról</string>
<string name="no_announcements">Nincsenek közlemények.</string>
<string name="title_announcements">Közlemények</string>
</resources> </resources>

View File

@ -415,8 +415,8 @@
<string name="notification_follow_request_name">Fylgjendabeiðnir</string> <string name="notification_follow_request_name">Fylgjendabeiðnir</string>
<string name="hashtags">Myllumerki</string> <string name="hashtags">Myllumerki</string>
<plurals name="favs"> <plurals name="favs">
<item quantity="one"><b>%1$s</b> Eftirlæti</item> <item quantity="one"><b>%1$s</b> eftirlæti</item>
<item quantity="other"><b>%1$s</b> Eftirlæti</item> <item quantity="other"><b>%1$s</b> eftirlæti</item>
</plurals> </plurals>
<plurals name="reblogs"> <plurals name="reblogs">
<item quantity="one"><b>%s</b> Endurbirting</item> <item quantity="one"><b>%s</b> Endurbirting</item>
@ -438,4 +438,33 @@
<item quantity="one">%d dagur eftir</item> <item quantity="one">%d dagur eftir</item>
<item quantity="other">%d dagar eftir</item> <item quantity="other">%d dagar eftir</item>
</plurals> </plurals>
<string name="account_note_saved">Vistað!</string>
<string name="account_note_hint">Þí eigin einkaathugasemd um þennan aðgang</string>
<string name="pref_title_hide_top_toolbar">Fela titil á verkfærastikunni efst</string>
<string name="pref_title_confirm_reblogs">Birta staðfestingarglugga áður en endurbirting fer fram</string>
<string name="pref_title_show_cards_in_timelines">Birta forskoðun tengla á tímalínum</string>
<string name="no_announcements">Það eru engar tilkynningar.</string>
<string name="pref_title_enable_swipe_for_tabs">Virkja strokuhreyfingu til að skipta milli flipa</string>
<plurals name="poll_info_people">
<item quantity="one">%s aðili</item>
<item quantity="other">%s aðilar</item>
</plurals>
<string name="add_hashtag_title">Bæta við myllumerki</string>
<string name="notification_follow_request_description">Tilkynningar um fylgjendabeiðnir</string>
<string name="pref_main_nav_position_option_bottom">Neðst</string>
<string name="pref_main_nav_position_option_top">Efst</string>
<string name="pref_main_nav_position">Aðalstaða leiðsagnar</string>
<string name="pref_title_gradient_for_media">Birta litstigla í stað falins myndefnis</string>
<string name="pref_title_notification_filter_follow_requests">beiðni um að fylgja</string>
<string name="dialog_mute_hide_notifications">Fela tilkynningar</string>
<string name="dialog_mute_warning">Þagga niður í @%s\?</string>
<string name="dialog_block_warning">Loka á @%s\?</string>
<string name="action_unmute_conversation">Hætta að þagga niður í samtölum</string>
<string name="action_mute_conversation">Þagga niður í samtölum</string>
<string name="action_unmute_domain">Afþagga %s</string>
<string name="action_mute_notifications_desc">Þagga tilkynningar frá %s</string>
<string name="action_unmute_notifications_desc">Afþagga tilkynningar frá %s</string>
<string name="action_unmute_desc">Afþagga %s</string>
<string name="notification_follow_request_format">%s bað um að fylgjast með þér</string>
<string name="title_announcements">Tilkynningar</string>
</resources> </resources>

View File

@ -414,8 +414,8 @@
<item quantity="other">%d minuti rimasti</item> <item quantity="other">%d minuti rimasti</item>
</plurals> </plurals>
<plurals name="poll_timespan_seconds"> <plurals name="poll_timespan_seconds">
<item quantity="one">%d secondo</item> <item quantity="one">%d secondo rimasto</item>
<item quantity="other">%d secondi</item> <item quantity="other">%d secondi rimasti</item>
</plurals> </plurals>
<string name="button_continue">Continua</string> <string name="button_continue">Continua</string>
<string name="button_back">Indietro</string> <string name="button_back">Indietro</string>
@ -464,4 +464,23 @@
<string name="error_audio_upload_size">La dimensione dei file audio deve essere inferiore a 40 MB.</string> <string name="error_audio_upload_size">La dimensione dei file audio deve essere inferiore a 40 MB.</string>
<string name="action_unmute_desc">Smetti di silenziare %s</string> <string name="action_unmute_desc">Smetti di silenziare %s</string>
<string name="notification_follow_request_name">Richieste di seguirti</string> <string name="notification_follow_request_name">Richieste di seguirti</string>
<string name="account_note_saved">Salvato!</string>
<string name="account_note_hint">La tua nota privata su questo account</string>
<string name="pref_title_hide_top_toolbar">Nascondi il titolo della barra degli strumenti in alto</string>
<string name="pref_title_confirm_reblogs">Mostra la finestra di dialogo di conferma prima del boosting</string>
<string name="pref_title_show_cards_in_timelines">Mostra le anteprime dei collegamenti nelle sequenze temporali</string>
<string name="warning_scheduling_interval">Mastodon ha un intervallo minimo di programmazione di 5 minuti.</string>
<string name="no_announcements">Non ci sono annunci.</string>
<string name="no_scheduled_status">Non hai stati pianificati.</string>
<string name="pref_title_enable_swipe_for_tabs">Abilita il gesto di scorrimento per passare da una scheda all\'altra</string>
<string name="notification_follow_request_description">Notifiche sulle richieste di essere seguiti</string>
<string name="pref_main_nav_position_option_bottom">Parte inferiore</string>
<string name="pref_main_nav_position_option_top">In cima</string>
<string name="pref_main_nav_position">Posizione di navigazione principale</string>
<string name="pref_title_gradient_for_media">Mostra sfumature colorate per i media nascosti</string>
<string name="dialog_mute_hide_notifications">Nascondi notifiche</string>
<string name="action_mute_notifications_desc">Disattiva le notifiche da %s</string>
<string name="action_unmute_notifications_desc">Riattiva le notifiche da %s</string>
<string name="title_announcements">Annunci</string>
<string name="pref_title_notification_filter_follow_requests">Richieste di seguirti</string>
</resources> </resources>

View File

@ -465,4 +465,6 @@
<string name="pref_title_hide_top_toolbar">Skjul tittelen på den øverste verktøylinjen</string> <string name="pref_title_hide_top_toolbar">Skjul tittelen på den øverste verktøylinjen</string>
<string name="account_note_saved">Lagret!</string> <string name="account_note_saved">Lagret!</string>
<string name="account_note_hint">Ditt private notat om denne kontoen</string> <string name="account_note_hint">Ditt private notat om denne kontoen</string>
<string name="no_announcements">Det er ingen kunngjøringer.</string>
<string name="title_announcements">Kunngjøringer</string>
</resources> </resources>

View File

@ -500,4 +500,9 @@
<string name="action_mute_notifications_desc">Заблокировать уведомления от %s</string> <string name="action_mute_notifications_desc">Заблокировать уведомления от %s</string>
<string name="action_unmute_notifications_desc">Получать уведомления от %s</string> <string name="action_unmute_notifications_desc">Получать уведомления от %s</string>
<string name="action_unmute_desc">Разблокировать %s</string> <string name="action_unmute_desc">Разблокировать %s</string>
<string name="account_note_saved">Сохранено!</string>
<string name="account_note_hint">Ваша личная заметка об этой учётной записи</string>
<string name="pref_title_hide_top_toolbar">Скрыть заголовок в верхней панели</string>
<string name="no_announcements">Объявлений нет.</string>
<string name="title_announcements">Объявления</string>
</resources> </resources>

View File

@ -369,7 +369,6 @@
<string name="pref_title_show_cards_in_timelines">जालस्थानप्रदर्शनं समयतालिकायां दर्शयतु</string> <string name="pref_title_show_cards_in_timelines">जालस्थानप्रदर्शनं समयतालिकायां दर्शयतु</string>
<string name="warning_scheduling_interval">मास्टोडोने पञ्चनिमेषपरिमितो न्यूनतमः कालबद्धसमयः ।</string> <string name="warning_scheduling_interval">मास्टोडोने पञ्चनिमेषपरिमितो न्यूनतमः कालबद्धसमयः ।</string>
<string name="no_scheduled_status">न ते कालबद्धदौत्यानि सन्ति ।</string> <string name="no_scheduled_status">न ते कालबद्धदौत्यानि सन्ति ।</string>
<string name="post_lookup_error_format">प्रकटनान्वेषणे विफलता</string>
<string name="edit_poll">सम्पाद्यताम्</string> <string name="edit_poll">सम्पाद्यताम्</string>
<string name="poll_new_choice_hint">मतम् %d</string> <string name="poll_new_choice_hint">मतम् %d</string>
<string name="poll_allow_multiple_choices">बहूनि मतानि</string> <string name="poll_allow_multiple_choices">बहूनि मतानि</string>

View File

@ -480,4 +480,8 @@
<string name="dialog_mute_hide_notifications">Dölj aviseringar</string> <string name="dialog_mute_hide_notifications">Dölj aviseringar</string>
<string name="action_mute_notifications_desc">Tysta aviseringar från %s</string> <string name="action_mute_notifications_desc">Tysta aviseringar från %s</string>
<string name="action_unmute_notifications_desc">Aktivera aviseringar från %s</string> <string name="action_unmute_notifications_desc">Aktivera aviseringar från %s</string>
<string name="account_note_saved">Sparat!</string>
<string name="account_note_hint">Din privata notering om detta kontot</string>
<string name="no_announcements">Det finns inga meddelanden.</string>
<string name="title_announcements">Meddelanden</string>
</resources> </resources>

View File

@ -39,7 +39,7 @@
<string name="error_no_web_browser_found">Không tìm thấy trình duyệt web.</string> <string name="error_no_web_browser_found">Không tìm thấy trình duyệt web.</string>
<string name="error_invalid_domain">Tài khoản không đúng</string> <string name="error_invalid_domain">Tài khoản không đúng</string>
<string name="error_empty">Không được để trống.</string> <string name="error_empty">Không được để trống.</string>
<string name="error_network">Không có Internet! Xin kiểm tra kết nối và thử lại!</string> <string name="error_network">Rớt mạng! Xin kiểm tra kết nối và thử lại!</string>
<string name="error_generic">Đã có lỗi xảy ra.</string> <string name="error_generic">Đã có lỗi xảy ra.</string>
<string name="error_failed_app_registration">Máy chủ này không cấp quyền truy cập.</string> <string name="error_failed_app_registration">Máy chủ này không cấp quyền truy cập.</string>
<string name="title_lists">Danh sách</string> <string name="title_lists">Danh sách</string>
@ -48,7 +48,7 @@
<string name="action_reset_schedule">Làm tươi</string> <string name="action_reset_schedule">Làm tươi</string>
<string name="action_search">Tìm kiếm</string> <string name="action_search">Tìm kiếm</string>
<string name="action_edit_profile">Trang cá nhân</string> <string name="action_edit_profile">Trang cá nhân</string>
<string name="action_view_account_preferences">Riêng bạn</string> <string name="action_view_account_preferences">Tài khoản</string>
<string name="action_view_preferences">Cài đặt</string> <string name="action_view_preferences">Cài đặt</string>
<string name="action_logout">Đăng xuất</string> <string name="action_logout">Đăng xuất</string>
<string name="button_done">Xong</string> <string name="button_done">Xong</string>
@ -97,7 +97,7 @@
<string name="download_media">Tải về</string> <string name="download_media">Tải về</string>
<string name="action_share_as">Chia sẻ với tư cách …</string> <string name="action_share_as">Chia sẻ với tư cách …</string>
<string name="action_open_as">Mở với tư cách %s</string> <string name="action_open_as">Mở với tư cách %s</string>
<string name="action_copy_link">Sao chép URL</string> <string name="action_copy_link">Chép URL</string>
<string name="download_image">Đang tải %1$s</string> <string name="download_image">Đang tải %1$s</string>
<string name="action_open_media_n">Mở tập tin #%d</string> <string name="action_open_media_n">Mở tập tin #%d</string>
<string name="title_links_dialog">Links</string> <string name="title_links_dialog">Links</string>
@ -174,7 +174,7 @@
<string name="status_content_warning_show_more">Mở rộng</string> <string name="status_content_warning_show_more">Mở rộng</string>
<string name="status_sensitive_media_directions">Hiển thị</string> <string name="status_sensitive_media_directions">Hiển thị</string>
<string name="status_media_hidden_title">Nội dung bị ẩn</string> <string name="status_media_hidden_title">Nội dung bị ẩn</string>
<string name="status_sensitive_media_title">Nội dung nhạy cảm</string> <string name="status_sensitive_media_title">Nhạy cảm</string>
<string name="status_boosted_format">%s chia sẻ</string> <string name="status_boosted_format">%s chia sẻ</string>
<string name="status_username_format">\@%s</string> <string name="status_username_format">\@%s</string>
<string name="title_licenses">Giấy phép</string> <string name="title_licenses">Giấy phép</string>
@ -236,7 +236,7 @@
<string name="pref_title_edit_notification_settings">Thông báo</string> <string name="pref_title_edit_notification_settings">Thông báo</string>
<string name="visibility_direct">Nhắn tin: Chỉ người được nhắc tới mới thấy</string> <string name="visibility_direct">Nhắn tin: Chỉ người được nhắc tới mới thấy</string>
<string name="visibility_private">Người theo dõi: Ai đã theo dõi mới xem được</string> <string name="visibility_private">Người theo dõi: Ai đã theo dõi mới xem được</string>
<string name="visibility_unlisted">Mở: Công khai, không hiện trên bảng tin</string> <string name="visibility_unlisted">Riêng tư: Không hiện trên bảng tin</string>
<string name="visibility_public">Công khai: Mọi người đều có thể thấy</string> <string name="visibility_public">Công khai: Mọi người đều có thể thấy</string>
<string name="dialog_mute_warning">Ẩn @%s\?</string> <string name="dialog_mute_warning">Ẩn @%s\?</string>
<string name="dialog_block_warning">Chặn @%s\?</string> <string name="dialog_block_warning">Chặn @%s\?</string>
@ -253,20 +253,20 @@
<string name="status_text_size_smallest">Nhỏ</string> <string name="status_text_size_smallest">Nhỏ</string>
<string name="pref_status_text_size">Kích thức phông chữ</string> <string name="pref_status_text_size">Kích thức phông chữ</string>
<string name="post_privacy_followers_only">Người theo dõi</string> <string name="post_privacy_followers_only">Người theo dõi</string>
<string name="post_privacy_unlisted">Mở</string> <string name="post_privacy_unlisted">Riêng tư</string>
<string name="post_privacy_public">Công khai</string> <string name="post_privacy_public">Công khai</string>
<string name="pref_main_nav_position_option_bottom">Dưới màn hình</string> <string name="pref_main_nav_position_option_bottom">Dưới màn hình</string>
<string name="pref_main_nav_position_option_top">Trên màn hình</string> <string name="pref_main_nav_position_option_top">Trên màn hình</string>
<string name="pref_main_nav_position">Vị trí menu</string> <string name="pref_main_nav_position">Vị trí menu</string>
<string name="pref_failed_to_sync">Đồng bộ hoá thất bại</string> <string name="pref_failed_to_sync">Đồng bộ hoá thất bại</string>
<string name="pref_publishing">Đăng (đồng bộ với máy chủ)</string> <string name="pref_publishing">Đăng (đồng bộ với máy chủ)</string>
<string name="pref_default_media_sensitivity">Luôn đánh dấu nội dung là nhạy cảm</string> <string name="pref_default_media_sensitivity">Tài khoản nhạy cảm</string>
<string name="pref_default_post_privacy">Trạng thái tút mặc định</string> <string name="pref_default_post_privacy">Trạng thái tút mặc định</string>
<string name="pref_title_http_proxy_server">HTTP proxy server</string> <string name="pref_title_http_proxy_server">Máy chủ proxy</string>
<string name="pref_title_http_proxy_port">HTTP proxy port</string> <string name="pref_title_http_proxy_port">Cổng</string>
<string name="pref_title_http_proxy_enable">Bật HTTP proxy</string> <string name="pref_title_http_proxy_enable">Bật proxy</string>
<string name="pref_title_http_proxy_settings">HTTP proxy</string> <string name="pref_title_http_proxy_settings">Dùng proxy</string>
<string name="pref_title_proxy_settings">Proxy</string> <string name="pref_title_proxy_settings">Vượt tường lửa</string>
<string name="notification_boost_description">Thông báo khi của bạn được chia sẻ</string> <string name="notification_boost_description">Thông báo khi của bạn được chia sẻ</string>
<string name="notification_boost_name">Chia sẻ</string> <string name="notification_boost_name">Chia sẻ</string>
<string name="notification_follow_request_description">Thông báo về lượt yêu cầu theo dõi</string> <string name="notification_follow_request_description">Thông báo về lượt yêu cầu theo dõi</string>
@ -278,7 +278,7 @@
<string name="about_powered_by_tusky">Powered by Tusky</string> <string name="about_powered_by_tusky">Powered by Tusky</string>
<string name="about_tusky_version">Tusky %s</string> <string name="about_tusky_version">Tusky %s</string>
<string name="description_account_locked">Tài khoản bị khóa</string> <string name="description_account_locked">Tài khoản bị khóa</string>
<string name="notification_poll_description">Thông báo khi những cuộc bình chọn kết thúc</string> <string name="notification_poll_description">Thông báo khi một cuộc bình chọn kết thúc</string>
<string name="notification_poll_name">Bình chọn</string> <string name="notification_poll_name">Bình chọn</string>
<string name="notification_favourite_description">Thông báo khi ai đó thích tút của bạn</string> <string name="notification_favourite_description">Thông báo khi ai đó thích tút của bạn</string>
<string name="notification_favourite_name">Lượt thích</string> <string name="notification_favourite_name">Lượt thích</string>
@ -326,7 +326,7 @@
<string name="poll_duration_30_min">30 phút</string> <string name="poll_duration_30_min">30 phút</string>
<string name="poll_duration_5_min">5 phút</string> <string name="poll_duration_5_min">5 phút</string>
<string name="create_poll_title">Bình chọn</string> <string name="create_poll_title">Bình chọn</string>
<string name="pref_title_enable_swipe_for_tabs">Vuốt để chuyển qua lại giữa các tab</string> <string name="pref_title_enable_swipe_for_tabs">Vuốt qua lại giữa các tab</string>
<string name="pref_title_show_notifications_filter">Hiện bộ lọc thông báo</string> <string name="pref_title_show_notifications_filter">Hiện bộ lọc thông báo</string>
<string name="failed_search">Không thể tìm thấy</string> <string name="failed_search">Không thể tìm thấy</string>
<string name="title_accounts">Người</string> <string name="title_accounts">Người</string>
@ -350,7 +350,7 @@
<item quantity="other">%d ngày nữa kết thúc</item> <item quantity="other">%d ngày nữa kết thúc</item>
</plurals> </plurals>
<string name="poll_ended_created">Cuộc bình chọn bạn tạo đã kết thúc</string> <string name="poll_ended_created">Cuộc bình chọn bạn tạo đã kết thúc</string>
<string name="poll_ended_voted">Cuộc bình chọn bạn tham gia đã kết thúc</string> <string name="poll_ended_voted">Cuộc bình chọn của bạn đã kết thúc</string>
<string name="poll_vote">Bình chọn</string> <string name="poll_vote">Bình chọn</string>
<string name="poll_info_closed">Kết thúc</string> <string name="poll_info_closed">Kết thúc</string>
<string name="poll_info_time_absolute">kết thúc lúc %s</string> <string name="poll_info_time_absolute">kết thúc lúc %s</string>
@ -358,9 +358,9 @@
<item quantity="other">%s người</item> <item quantity="other">%s người</item>
</plurals> </plurals>
<plurals name="poll_info_votes"> <plurals name="poll_info_votes">
<item quantity="other">%s phiếu</item> <item quantity="other">%s người</item>
</plurals> </plurals>
<string name="poll_info_format"> <!-- 15 phiếu • 1 tiếng nữa kết thúc --> %1$s • %2$s</string> <string name="poll_info_format"> <!-- 15 người • 1 tiếng nữa kết thúc --> %1$s • %2$s</string>
<string name="compose_preview_image_description">Mô tả cho hình %s</string> <string name="compose_preview_image_description">Mô tả cho hình %s</string>
<string name="compose_shortcut_short_label">Viết</string> <string name="compose_shortcut_short_label">Viết</string>
<string name="compose_shortcut_long_label">Viết tút</string> <string name="compose_shortcut_long_label">Viết tút</string>
@ -373,10 +373,10 @@
<string name="edit_hashtag_hint">Không cần dấu #</string> <string name="edit_hashtag_hint">Không cần dấu #</string>
<string name="add_hashtag_title">Thêm hashtag</string> <string name="add_hashtag_title">Thêm hashtag</string>
<string name="hint_list_name">Tên danh sách</string> <string name="hint_list_name">Tên danh sách</string>
<string name="description_poll">Những lựa chọn: %1$s, %2$s, %3$s, %4$s; %5$s</string> <string name="description_poll">Lượt bình chọn: %1$s, %2$s, %3$s, %4$s; %5$s</string>
<string name="description_visiblity_direct">Tin nhắn</string> <string name="description_visiblity_direct">Tin nhắn</string>
<string name="description_visiblity_private">Người theo dõi</string> <string name="description_visiblity_private">Người theo dõi</string>
<string name="description_visiblity_unlisted">Mở</string> <string name="description_visiblity_unlisted">Riêng tư</string>
<string name="description_visiblity_public">Công khai</string> <string name="description_visiblity_public">Công khai</string>
<string name="description_status_bookmarked">Đã lưu</string> <string name="description_status_bookmarked">Đã lưu</string>
<string name="description_status_favourited">Đã thích</string> <string name="description_status_favourited">Đã thích</string>
@ -455,4 +455,8 @@
<string name="action_unmute_desc">Bỏ ẩn %s</string> <string name="action_unmute_desc">Bỏ ẩn %s</string>
<string name="action_unmute_domain">Bỏ ẩn %s</string> <string name="action_unmute_domain">Bỏ ẩn %s</string>
<string name="pref_title_hide_top_toolbar">Ẩn tiêu đề tab</string> <string name="pref_title_hide_top_toolbar">Ẩn tiêu đề tab</string>
<string name="account_note_saved">Đã lưu!</string>
<string name="account_note_hint">Ghi chú của bạn</string>
<string name="no_announcements">Chưa có thông báo.</string>
<string name="title_announcements">Tin tức</string>
</resources> </resources>

View File

@ -477,8 +477,8 @@
<string name="notification_follow_request_format">%s 请求关注你</string> <string name="notification_follow_request_format">%s 请求关注你</string>
<string name="pref_main_nav_position">导航栏位置</string> <string name="pref_main_nav_position">导航栏位置</string>
<string name="pref_title_hide_top_toolbar">隐藏顶部工具栏标题</string> <string name="pref_title_hide_top_toolbar">隐藏顶部工具栏标题</string>
<plurals name="poll_info_people"> <string name="no_announcements">本站暂无公告。</string>
<item quantity="one">%s 人</item> <string name="title_announcements">公告</string>
<item quantity="other"/> <string name="account_note_saved">已保存</string>
</plurals> <string name="account_note_hint">此账号的备注</string>
</resources> </resources>

View File

@ -81,6 +81,8 @@
<item name="chipStyle">@style/Widget.MaterialComponents.Chip.Choice</item> <item name="chipStyle">@style/Widget.MaterialComponents.Chip.Choice</item>
<item name="preferenceTheme">@style/TuskyPreferenceTheme</item>
<item name="colorInfo">@color/colorInfo</item> <item name="colorInfo">@color/colorInfo</item>
</style> </style>
@ -105,6 +107,10 @@
<item name="tabIndicatorHeight">3dp</item> <item name="tabIndicatorHeight">3dp</item>
</style> </style>
<style name="TuskyPreferenceTheme" parent="@style/PreferenceThemeOverlay.v14.Material">
<item name="android:tint">?iconColor</item>
</style>
<style name="TuskyImageButton" parent="@style/Widget.MaterialComponents.Button.UnelevatedButton"> <style name="TuskyImageButton" parent="@style/Widget.MaterialComponents.Button.UnelevatedButton">
<item name="android:tint">?android:attr/textColorTertiary</item> <item name="android:tint">?android:attr/textColorTertiary</item>
<item name="android:background">?attr/selectableItemBackgroundBorderless</item> <item name="android:background">?attr/selectableItemBackgroundBorderless</item>

View File

@ -17,6 +17,7 @@
package com.keylesspalace.tusky package com.keylesspalace.tusky
import android.content.Intent import android.content.Intent
import android.os.Looper.getMainLooper
import android.text.SpannedString import android.text.SpannedString
import android.widget.EditText import android.widget.EditText
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
@ -41,6 +42,7 @@ import org.junit.runner.RunWith
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.robolectric.Robolectric import org.robolectric.Robolectric
import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config import org.robolectric.annotation.Config
import org.robolectric.fakes.RoboMenuItem import org.robolectric.fakes.RoboMenuItem
@ -76,8 +78,8 @@ class ComposeActivityTest {
notificationVibration = true, notificationVibration = true,
notificationLight = true notificationLight = true
) )
var instanceResponseCallback: (()->Instance)? = null private var instanceResponseCallback: (()->Instance)? = null
var composeOptions: ComposeActivity.ComposeOptions? = null private var composeOptions: ComposeActivity.ComposeOptions? = null
@Before @Before
fun setupActivity() { fun setupActivity() {
@ -185,6 +187,7 @@ class ComposeActivityTest {
val customMaximum = 1000 val customMaximum = 1000
instanceResponseCallback = { getInstanceWithMaximumTootCharacters(customMaximum) } instanceResponseCallback = { getInstanceWithMaximumTootCharacters(customMaximum) }
setupActivity() setupActivity()
shadowOf(getMainLooper()).idle()
assertEquals(customMaximum, activity.maximumTootCharacters) assertEquals(customMaximum, activity.maximumTootCharacters)
} }
@ -230,7 +233,7 @@ class ComposeActivityTest {
editor.setSelection(caretIndex) editor.setSelection(caretIndex)
activity.prependSelectedWordsWith(insertText) activity.prependSelectedWordsWith(insertText)
// Text should be inserted at caret // Text should be inserted at caret
assertEquals("Unexpected value at ${caretIndex}", insertText, editor.text.substring(caretIndex, caretIndex + insertText.length)) assertEquals("Unexpected value at $caretIndex", insertText, editor.text.substring(caretIndex, caretIndex + insertText.length))
// Caret should be placed after inserted text // Caret should be placed after inserted text
assertEquals(caretIndex + insertText.length, editor.selectionStart) assertEquals(caretIndex + insertText.length, editor.selectionStart)

View File

@ -1,11 +1,11 @@
buildscript { buildscript {
ext.kotlin_version = '1.4.10' ext.kotlin_version = '1.4.21'
repositories { repositories {
google() google()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

View File

@ -0,0 +1,10 @@
Tusky v13.0
- support for profile notes (Mastodon 3.2.0 feature)
- support for admin announcements (Mastodon 3.1.0 feature)
- the avatar of your selected account will now be shown in the main toolbar
- clicking the display name in a timeline will now open the profile page of that user
- a lot of bug fixes and small improvements
- improved translations

View File

@ -0,0 +1,10 @@
Tusky v13.0
- privát profilmegjegyzések támogatása (Mastodon 3.2.0 funkció)
- adminisztrátori közlemények támogatása (Mastodon 3.1.0 funkció)
- az éppen használt fiókod avatarja mostantól látszik az eszköztáron
- az idővonalon egy profilra kattintva előjön a felhasználó profiloldala
- rengeteg hibajavítás és apró fejlesztés
- javított fordítások

View File

@ -0,0 +1,10 @@
Tusky útg. 13.0
- stuðningur við minnispunkta í sniðum (Mastodon 3.2.0 eiginleiki)
- stuðningur við tilkynningar frá stjórnendum (Mastodon 3.1.0 eiginleiki)
- auðkennismynd úr völdum aðgangi birist núna í aðalverkfærastikunni
- smellt á birtingarnafn á tímalínu opnar núna notandasniðssíðu þess notanda
- hellingur að villulagfæringum og minni betrumbótum
- bættar þýðingar

View File

@ -0,0 +1,8 @@
Tusky v10.0
- Ora puoi contrassegnare gli stati ed elencare i tuoi segnalibri in Tusky.
- Ora puoi programmare i tuoi toot con Tusky. Tieni presente che il tempo selezionato deve essere di almeno 5 minuti in futuro.
- Ora puoi aggiungere elenchi alla schermata principale.
- Ora puoi pubblicare allegati audio con Tusky.
E molti altri piccoli miglioramenti e correzioni di bug!

View File

@ -0,0 +1,8 @@
Tusky v12.0
- Interfaccia principale migliorata - ora puoi spostare le schede in basso
- Quando si disattiva l'audio di un utente, ora è possibile anche decidere se disattivare l'audio delle sue notifiche
- Ora puoi seguire tutti gli hashtag che desideri in una singola scheda hashtag
- Migliorata la modalità di visualizzazione delle descrizioni dei media in modo che funzioni anche per descrizioni molto lunghe
Log delle modifiche completo: https://github.com/tuskyapp/Tusky/releases

View File

@ -0,0 +1,10 @@
Tusky v13.0
- supporto per le note del profilo (funzionalità di Mastodon 3.2.0)
- supporto per gli annunci dell'amministratore (funzionalità di Mastodon 3.1.0)
- l'avatar del tuo account selezionato verrà ora mostrato nella barra degli strumenti principale
- facendo clic sul nome visualizzato in una sequenza temporale si aprirà ora la pagina del profilo di quell'utente
- molte correzioni di bug e piccoli miglioramenti
- traduzioni migliorate

View File

@ -0,0 +1,10 @@
Tusky v13.0
- støtte for profilnotater (Mastodon 3.2.0-funksjonalitet)
- støtte for administratorkunngjøringer (Mastodon 3.1.0-funksjonalitet)
- avataren som tilhører valgt konto vil nå vises på hovedverktøylinjen
- trykk på en brukers visningsnavn i tidslinjen vil åpne profilen til brukeren
- mange feilrettinger og mindre forbedringer
- forbedrede oversettelser

View File

@ -0,0 +1,8 @@
Tusky v12.0
- Improved main interface - you can now move the tabs to the bottom
- When muting a user, you can now also decide whether to mute their notifications
- You can now follow as many hashtags as you want in one single hashtag tab
- Improved the way media descriptions are displayed so it works even for super long descriptions
Full changelog: https://github.com/tuskyapp/Tusky/releases

View File

@ -0,0 +1,10 @@
Tusky v13.0
- support for profile notes (Mastodon 3.2.0 feature)
- support for admin announcements (Mastodon 3.1.0 feature)
- the avatar of your selected account will now be shown in the main toolbar
- clicking the display name in a timeline will now open the profile page of that user
- a lot of bug fixes and small improvements
- improved translations

View File

@ -0,0 +1,8 @@
Tusky v13.0
- Hỗ trợ ghi chú về một ai đó (tính năng Mastodon 3.2.0)
- Hỗ trợ hiện thông báo máy chủ (tính năng Mastodon 3.1.0)
- Ảnh đại diện của tài khoản từ giờ sẽ hiện trên thanh menu chính
- Nhấn vào tên ai đó trên bảng tin sẽ chuyển tới trang cá nhân của họ
- Sửa lỗi linh tinh và cải thiện hiệu năng
- Trau dồi bản dịch

View File

@ -0,0 +1,10 @@
Tusky v13.0
- 支持账号备注Mastodon 3.2.0 特性)
- 支持公告栏Mastodon 3.1.0特性)
- 当前账号的头像将在导航栏显示
- 在时间线中点击账号名称后打开该用户的资料页
- 其他许多小改进和错误修复
- 改善翻译

View File

@ -0,0 +1 @@
Tusky