mirror of
https://github.com/accelforce/Yuito
synced 2025-02-01 16:36:50 +01:00
Merge remote-tracking branch 'tuskyapp/develop'
This commit is contained in:
commit
ea822004dd
@ -58,6 +58,7 @@ android {
|
||||
productFlavors {
|
||||
blue {}
|
||||
green {
|
||||
resValue "string", "app_name", APP_NAME + " Test"
|
||||
applicationIdSuffix ".test"
|
||||
versionNameSuffix "-" + getGitSha()
|
||||
}
|
||||
@ -105,10 +106,10 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||
ext.lifecycleVersion = "2.2.0"
|
||||
ext.roomVersion = '2.2.5'
|
||||
ext.retrofitVersion = '2.9.0'
|
||||
ext.okhttpVersion = '4.8.1'
|
||||
ext.okhttpVersion = '4.9.0'
|
||||
ext.glideVersion = '4.11.0'
|
||||
ext.daggerVersion = '2.28.3'
|
||||
ext.materialdrawerVersion = '8.1.8'
|
||||
ext.daggerVersion = '2.30.1'
|
||||
ext.materialdrawerVersion = '8.2.0'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
@ -120,22 +121,22 @@ repositories {
|
||||
dependencies {
|
||||
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.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.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.preference:preference:1.1.1"
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.sharetarget:sharetarget:1.0.0"
|
||||
implementation "androidx.emoji:emoji:1.1.0"
|
||||
implementation "androidx.emoji:emoji-appcompat:1.1.0"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-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.viewpager2:viewpager2:1.0.0"
|
||||
implementation "androidx.work:work-runtime:2.4.0"
|
||||
@ -151,13 +152,14 @@ dependencies {
|
||||
|
||||
implementation "com.squareup.okhttp3:okhttp:$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: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:rxkotlin:2.4.0"
|
||||
|
||||
@ -170,7 +172,7 @@ dependencies {
|
||||
implementation "com.google.dagger:dagger-android-support:$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"
|
||||
|
||||
@ -182,14 +184,14 @@ dependencies {
|
||||
|
||||
implementation "de.c1710:filemojicompat:1.0.17"
|
||||
|
||||
testImplementation "androidx.test.ext:junit:1.1.1"
|
||||
testImplementation "org.robolectric:robolectric:4.3.1"
|
||||
testImplementation "org.mockito:mockito-inline:3.3.3"
|
||||
testImplementation "androidx.test.ext:junit:1.1.2"
|
||||
testImplementation "org.robolectric:robolectric:4.4"
|
||||
testImplementation "org.mockito:mockito-inline:3.6.28"
|
||||
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.test.ext:junit:1.1.1"
|
||||
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
||||
|
||||
implementation 'net.accelf:easter:1.0.2'
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import androidx.lifecycle.Lifecycle
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.viewpager2.widget.MarginPageTransformer
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestManager
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
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 lateinit var glide: RequestManager
|
||||
|
||||
private val emojiInitCallback = object : InitCallback() {
|
||||
override fun onInitialized() {
|
||||
if (!isDestroyed) {
|
||||
@ -139,7 +142,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (accountManager.activeAccount == null) {
|
||||
|
||||
val activeAccount = accountManager.activeAccount
|
||||
if (activeAccount == null) {
|
||||
// will be redirected to LoginActivity by BaseActivity
|
||||
return
|
||||
}
|
||||
@ -157,11 +162,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
}
|
||||
}
|
||||
val accountRequested = accountId != -1L
|
||||
if (accountRequested) {
|
||||
val account = accountManager.activeAccount
|
||||
if (account == null || accountId != account.id) {
|
||||
accountManager.setActiveAccount(accountId)
|
||||
}
|
||||
if (accountRequested && accountId != activeAccount.id) {
|
||||
accountManager.setActiveAccount(accountId)
|
||||
}
|
||||
if (canHandleMimeType(intent.type)) {
|
||||
// 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 {
|
||||
override fun onAccountSelected(account: AccountEntity) {
|
||||
val requestedId = account.id
|
||||
val activeAccount = accountManager.activeAccount
|
||||
if (activeAccount != null && requestedId == activeAccount.id) {
|
||||
if (requestedId == activeAccount.id) {
|
||||
// The correct account is already active
|
||||
forwardShare(intent)
|
||||
} 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
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
glide = Glide.with(this)
|
||||
|
||||
viewQuickToot.attachViewModel(quickTootViewModel, this)
|
||||
composeButton.setOnClickListener(viewQuickToot::onFABClicked)
|
||||
|
||||
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
||||
mainToolbar.visible(!hideTopToolbar)
|
||||
|
||||
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size)
|
||||
mainToolbar.navigationIcon = FixedSizeDrawable(getDrawable(R.drawable.avatar_default), navIconSize, navIconSize)
|
||||
loadDrawerAvatar(activeAccount.profilePictureUrl, true)
|
||||
|
||||
mainToolbar.menu.add(R.string.action_search).apply {
|
||||
setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
@ -256,8 +258,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
viewQuickToot.handleEvent(event)
|
||||
}
|
||||
|
||||
// Flush old media that was cached for sharing
|
||||
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky"))
|
||||
Schedulers.io().scheduleDirect {
|
||||
// Flush old media that was cached for sharing
|
||||
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -381,13 +385,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
|
||||
if (animateAvatars) {
|
||||
Glide.with(imageView.context)
|
||||
.load(uri)
|
||||
glide.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView)
|
||||
} else {
|
||||
Glide.with(imageView.context)
|
||||
.asBitmap()
|
||||
glide.asBitmap()
|
||||
.load(uri)
|
||||
.placeholder(placeholder)
|
||||
.into(imageView)
|
||||
@ -395,7 +397,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
}
|
||||
|
||||
override fun cancel(imageView: ImageView) {
|
||||
Glide.with(imageView.context).clear(imageView)
|
||||
glide.clear(imageView)
|
||||
}
|
||||
|
||||
override fun placeholder(ctx: Context, tag: String?): Drawable {
|
||||
@ -814,29 +816,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
}
|
||||
|
||||
private fun onFetchUserInfoSuccess(me: Account) {
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
glide.asBitmap()
|
||||
.load(me.header)
|
||||
.into(header.accountHeaderBackground)
|
||||
|
||||
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size)
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
loadDrawerAvatar(me.avatar, false)
|
||||
|
||||
accountManager.updateActiveAccount(me)
|
||||
NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this)
|
||||
@ -861,6 +845,36 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
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() {
|
||||
mastodonApi.listAnnouncements(false)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -877,7 +891,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -25,7 +25,9 @@ import androidx.work.WorkManager
|
||||
import com.keylesspalace.tusky.components.notifications.NotificationWorkerFactory
|
||||
import com.keylesspalace.tusky.di.AppInjector
|
||||
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 dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
@ -38,11 +40,21 @@ class TuskyApplication : Application(), HasAndroidInjector {
|
||||
|
||||
@Inject
|
||||
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
@Inject
|
||||
lateinit var notificationWorkerFactory: NotificationWorkerFactory
|
||||
|
||||
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()
|
||||
|
||||
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
||||
@ -64,16 +76,16 @@ class TuskyApplication : Application(), HasAndroidInjector {
|
||||
val theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT)
|
||||
ThemeUtils.setAppNightMode(theme)
|
||||
|
||||
RxJavaPlugins.setErrorHandler {
|
||||
Log.w("RxJava", "undeliverable exception", it)
|
||||
}
|
||||
|
||||
WorkManager.initialize(
|
||||
this,
|
||||
androidx.work.Configuration.Builder()
|
||||
.setWorkerFactory(notificationWorkerFactory)
|
||||
.build()
|
||||
)
|
||||
|
||||
RxJavaPlugins.setErrorHandler {
|
||||
Log.w("RxJava", "undeliverable exception", it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
|
@ -22,7 +22,6 @@ import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.MastoList
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import kotlinx.android.synthetic.main.item_picker_list.view.*
|
||||
|
||||
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)
|
||||
|
||||
getItem(position)?.let { list ->
|
||||
val title = view.title
|
||||
title.text = list.title
|
||||
val icon = ThemeUtils.getTintedDrawable(context, R.drawable.ic_list, R.attr.iconColor)
|
||||
title.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
|
||||
view.title.text = list.title
|
||||
}
|
||||
|
||||
return view
|
||||
|
@ -22,7 +22,6 @@ import android.widget.TextView
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
|
||||
class PreviewPollOptionsAdapter: RecyclerView.Adapter<PreviewViewHolder>() {
|
||||
|
||||
@ -55,9 +54,7 @@ class PreviewPollOptionsAdapter: RecyclerView.Adapter<PreviewViewHolder>() {
|
||||
R.drawable.ic_radio_button_unchecked_18dp
|
||||
}
|
||||
|
||||
val iconDrawable = ThemeUtils.getTintedDrawable(textView.context, iconId, android.R.attr.textColorTertiary)
|
||||
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, iconDrawable, null, null, null)
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, iconId, 0, 0, 0)
|
||||
|
||||
textView.text = options[position]
|
||||
|
||||
|
@ -60,7 +60,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import at.connyduck.sparkbutton.SparkButton;
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
@ -648,9 +647,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
// Set the icon next to the label.
|
||||
int drawableId = getLabelIcon(attachments.get(0).getType());
|
||||
Drawable drawable = Objects.requireNonNull(context.getDrawable(drawableId));
|
||||
ThemeUtils.setDrawableTint(context, drawable, android.R.attr.textColorTertiary);
|
||||
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
||||
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0);
|
||||
|
||||
setAttachmentClickListener(mediaLabel, listener, i, attachment, false);
|
||||
} else {
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
package com.keylesspalace.tusky.adapter
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
@ -68,8 +69,7 @@ class TabAdapter(private var data: List<TabData>,
|
||||
} else {
|
||||
holder.itemView.textView.setText(tab.text)
|
||||
}
|
||||
val iconDrawable = ThemeUtils.getTintedDrawable(context, tab.icon, android.R.attr.textColorSecondary)
|
||||
holder.itemView.textView.setCompoundDrawablesRelativeWithIntrinsicBounds(iconDrawable, null, null, null)
|
||||
holder.itemView.textView.setCompoundDrawablesRelativeWithIntrinsicBounds(tab.icon, 0, 0, 0)
|
||||
if (small) {
|
||||
holder.itemView.textView.setOnClickListener {
|
||||
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?
|
||||
?: Chip(context).apply {
|
||||
holder.itemView.chipGroup.addView(this, holder.itemView.chipGroup.size - 1)
|
||||
chipIconTint = ColorStateList.valueOf(ThemeUtils.getColor(context, android.R.attr.textColorPrimary))
|
||||
}
|
||||
|
||||
chip.text = arg
|
||||
@ -118,8 +119,7 @@ class TabAdapter(private var data: List<TabData>,
|
||||
chip.chipIcon = null
|
||||
chip.setOnClickListener(null)
|
||||
} else {
|
||||
val cancelIcon = ThemeUtils.getTintedDrawable(context, R.drawable.ic_cancel_24dp, android.R.attr.textColorPrimary)
|
||||
chip.chipIcon = cancelIcon
|
||||
chip.setChipIconResource(R.drawable.ic_cancel_24dp)
|
||||
chip.setOnClickListener {
|
||||
listener.onChipClicked(tab, holder.adapterPosition, i)
|
||||
}
|
||||
|
@ -27,10 +27,12 @@ import com.google.android.material.chip.ChipGroup
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Announcement
|
||||
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 kotlinx.android.synthetic.main.item_announcement.view.*
|
||||
|
||||
interface AnnouncementActionListener {
|
||||
interface AnnouncementActionListener: LinkListener {
|
||||
fun openReactionPicker(announcementId: String, target: View)
|
||||
fun addReaction(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) {
|
||||
|
||||
private val text: TextView = view.text
|
||||
private val chips: ChipGroup = view.chipGroup
|
||||
private val addReactionChip: Chip = view.addReactionChip
|
||||
|
||||
fun bind(item: Announcement) {
|
||||
text.text = item.content
|
||||
LinkHelper.setClickableText(text, item.content, null, listener, false)
|
||||
|
||||
item.reactions.forEachIndexed { i, reaction ->
|
||||
(chips.getChildAt(i)?.takeUnless { it.id == R.id.addReactionChip } as Chip?
|
||||
|
@ -22,11 +22,9 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.PopupWindow
|
||||
import androidx.activity.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.keylesspalace.tusky.BaseActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.*
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter
|
||||
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
||||
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 javax.inject.Inject
|
||||
|
||||
class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable {
|
||||
class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelFactory
|
||||
@ -79,7 +77,7 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
|
||||
announcementsList.addItemDecoration(divider)
|
||||
announcementsList.adapter = adapter
|
||||
|
||||
viewModel.announcements.observe(this, Observer {
|
||||
viewModel.announcements.observe(this) {
|
||||
when (it) {
|
||||
is Success -> {
|
||||
progressBar.hide()
|
||||
@ -104,11 +102,11 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
|
||||
errorMessageView.show()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
viewModel.emojis.observe(this, Observer {
|
||||
viewModel.emojis.observe(this) {
|
||||
picker.adapter = EmojiAdapter(it, this)
|
||||
})
|
||||
}
|
||||
|
||||
viewModel.load()
|
||||
progressBar.show()
|
||||
@ -147,6 +145,24 @@ class AnnouncementsActivity : BaseActivity(), AnnouncementActionListener, OnEmoj
|
||||
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 {
|
||||
fun newIntent(context: Context) = Intent(context, AnnouncementsActivity::class.java)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class AnnouncementsViewModel @Inject constructor(
|
||||
.map<Either<InstanceEntity, Instance>> { Either.Left(it) }
|
||||
.onErrorResumeNext(
|
||||
mastodonApi.getInstance()
|
||||
.map { Either.Right<InstanceEntity, Instance>(it) }
|
||||
.map { Either.Right(it) }
|
||||
)
|
||||
) { emojis, either ->
|
||||
either.asLeftOrNull()?.copy(emojiList = emojis)
|
||||
|
@ -626,8 +626,7 @@ class ComposeActivity : BaseActivity(),
|
||||
Status.Visibility.UNLEAKABLE -> R.drawable.ic_low_vision_24dp
|
||||
else -> R.drawable.ic_lock_open_24dp
|
||||
}
|
||||
val drawable = ThemeUtils.getTintedDrawable(this, iconRes, android.R.attr.textColorTertiary)
|
||||
composeToggleVisibilityButton.setImageDrawable(drawable)
|
||||
composeToggleVisibilityButton.setImageResource(iconRes)
|
||||
}
|
||||
|
||||
private fun showComposeOptions() {
|
||||
|
@ -19,10 +19,8 @@ import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.impl.utils.LiveDataUtils
|
||||
import com.keylesspalace.tusky.adapter.ComposeAutoCompleteAdapter
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity.QueuedMedia
|
||||
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.TootToSend
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import io.reactivex.Observable.empty
|
||||
import io.reactivex.Observable.just
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.rxkotlin.Singles
|
||||
|
@ -26,13 +26,13 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.android.material.datepicker.CalendarConstraints;
|
||||
import com.google.android.material.datepicker.DateValidatorPointForward;
|
||||
import com.google.android.material.datepicker.MaterialDatePicker;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.fragment.TimePickerFragment;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
@ -106,7 +106,7 @@ public class ComposeScheduleView extends ConstraintLayout {
|
||||
}
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ public class NotificationHelper {
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setContentIntent(summary ? summaryResultPendingIntent : eventResultPendingIntent)
|
||||
.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())
|
||||
.setAutoCancel(true)
|
||||
.setShortcutId(Long.toString(account.getId()))
|
||||
|
@ -16,10 +16,10 @@
|
||||
package com.keylesspalace.tusky.components.preference
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.keylesspalace.tusky.*
|
||||
@ -71,7 +71,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
|
||||
preference {
|
||||
setTitle(R.string.title_tab_preferences)
|
||||
icon = getTintedIcon(R.drawable.ic_tabs)
|
||||
setIcon(R.drawable.ic_tabs)
|
||||
setOnPreferenceClickListener {
|
||||
val intent = Intent(context, TabPreferenceActivity::class.java)
|
||||
activity?.startActivity(intent)
|
||||
@ -83,7 +83,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
|
||||
preference {
|
||||
setTitle(R.string.action_view_mutes)
|
||||
icon = getTintedIcon(R.drawable.ic_mute_24dp)
|
||||
setIcon(R.drawable.ic_mute_24dp)
|
||||
setOnPreferenceClickListener {
|
||||
val intent = Intent(context, AccountListActivity::class.java)
|
||||
intent.putExtra("type", AccountListActivity.Type.MUTES)
|
||||
@ -112,7 +112,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
|
||||
preference {
|
||||
setTitle(R.string.title_domain_mutes)
|
||||
icon = getTintedIcon(R.drawable.ic_mute_24dp)
|
||||
setIcon(R.drawable.ic_mute_24dp)
|
||||
setOnPreferenceClickListener {
|
||||
val intent = Intent(context, InstanceListActivity::class.java)
|
||||
activity?.startActivity(intent)
|
||||
@ -132,11 +132,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
val visibility = accountManager.activeAccount?.defaultPostPrivacy
|
||||
?: Status.Visibility.PUBLIC
|
||||
value = visibility.serverString()
|
||||
icon = getIconForVisibility(visibility)
|
||||
setIcon(getIconForVisibility(visibility))
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
icon = getIconForVisibility(
|
||||
Status.Visibility.byString(newValue as String)
|
||||
)
|
||||
setIcon(getIconForVisibility(Status.Visibility.byString(newValue as String)))
|
||||
syncWithServer(visibility = newValue)
|
||||
eventHub.dispatch(PreferenceChangedEvent(key))
|
||||
true
|
||||
@ -151,9 +149,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
val sensitivity = accountManager.activeAccount?.defaultMediaSensitivity
|
||||
?: false
|
||||
setDefaultValue(sensitivity)
|
||||
icon = getIconForSensitivity(sensitivity)
|
||||
setIcon(getIconForSensitivity(sensitivity))
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
icon = getIconForSensitivity(newValue as Boolean)
|
||||
setIcon(getIconForSensitivity(newValue as Boolean))
|
||||
syncWithServer(sensitive = newValue)
|
||||
eventHub.dispatch(PreferenceChangedEvent(key))
|
||||
true
|
||||
@ -303,30 +301,24 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIconForVisibility(visibility: Status.Visibility): Drawable? {
|
||||
val drawableId = when (visibility) {
|
||||
@DrawableRes
|
||||
private fun getIconForVisibility(visibility: Status.Visibility): Int {
|
||||
return when (visibility) {
|
||||
Status.Visibility.PRIVATE -> R.drawable.ic_lock_outline_24dp
|
||||
|
||||
Status.Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp
|
||||
|
||||
else -> R.drawable.ic_public_24dp
|
||||
}
|
||||
|
||||
return getTintedIcon(drawableId)
|
||||
}
|
||||
|
||||
private fun getIconForSensitivity(sensitive: Boolean): Drawable? {
|
||||
val drawableId = if (sensitive) {
|
||||
@DrawableRes
|
||||
private fun getIconForSensitivity(sensitive: Boolean): Int {
|
||||
return if (sensitive) {
|
||||
R.drawable.ic_hide_media_24dp
|
||||
} else {
|
||||
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) {
|
||||
|
@ -42,7 +42,6 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
private var httpProxyPref: Preference? = null
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
val context = requireContext()
|
||||
makePreferenceScreen {
|
||||
lateinit var limitedBandwidthMobilePref: SwitchPreference
|
||||
lateinit var limitedBandwidthTimelinePref: SwitchPreference
|
||||
@ -121,11 +120,8 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
key = PrefKeys.SHOW_BOT_OVERLAY
|
||||
setTitle(R.string.pref_title_bot_overlay)
|
||||
isSingleLineTitle = false
|
||||
icon = ThemeUtils.getTintedDrawable(
|
||||
context,
|
||||
R.drawable.ic_bot_24dp,
|
||||
R.attr.iconColor
|
||||
)
|
||||
setIcon(R.drawable.ic_bot_24dp)
|
||||
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
|
@ -62,7 +62,7 @@ class AccountManager @Inject constructor(db: AppDatabase) {
|
||||
accountDao.insertOrReplace(it)
|
||||
}
|
||||
|
||||
val maxAccountId = accounts.maxBy { it.id }?.id ?: 0
|
||||
val maxAccountId = accounts.maxByOrNull { it.id }?.id ?: 0
|
||||
val newAccountId = maxAccountId + 1
|
||||
activeAccount = AccountEntity(id = newAccountId, domain = domain.toLowerCase(Locale.ROOT), accessToken = accessToken, isActive = true)
|
||||
|
||||
|
@ -25,7 +25,7 @@ import com.keylesspalace.tusky.json.SpannedTypeAdapter
|
||||
import com.keylesspalace.tusky.network.InstanceSwitchAuthInterceptor
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.network.NotestockApi
|
||||
import com.keylesspalace.tusky.util.OkHttpUtils
|
||||
import com.keylesspalace.tusky.util.okhttpClient
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import net.accelf.yuito.HttpToastInterceptor
|
||||
@ -34,6 +34,7 @@ import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.create
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
@ -57,7 +58,7 @@ class NetworkModule {
|
||||
accountManager: AccountManager,
|
||||
context: Context
|
||||
): OkHttpClient {
|
||||
return OkHttpUtils.getCompatibleClientBuilder(context)
|
||||
return okhttpClient(context)
|
||||
.apply {
|
||||
addInterceptor(InstanceSwitchAuthInterceptor(accountManager))
|
||||
if (BuildConfig.DEBUG) {
|
||||
@ -84,13 +85,13 @@ class NetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesApi(retrofit: Retrofit): MastodonApi = retrofit.create(MastodonApi::class.java)
|
||||
fun providesApi(retrofit: Retrofit): MastodonApi = retrofit.create()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesNotestockApi(context: Context,
|
||||
gson: Gson): NotestockApi {
|
||||
val httpClient = OkHttpUtils.getCompatibleClientBuilder(context)
|
||||
val httpClient = okhttpClient(context)
|
||||
.apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC })
|
||||
@ -105,4 +106,4 @@ class NetworkModule {
|
||||
.build()
|
||||
return retrofit.create(NotestockApi::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import kotlinx.android.parcel.Parcelize
|
||||
data class Attachment(
|
||||
val id: 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 type: Type,
|
||||
val description: String?,
|
||||
|
@ -330,6 +330,7 @@ class AccountListFragment : BaseFragment(), AccountActionListener, Injectable {
|
||||
|
||||
private fun fetchRelationships(ids: List<String>) {
|
||||
api.relationships(ids)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(from(this))
|
||||
.subscribe(::onFetchRelationshipsSuccess) {
|
||||
onFetchRelationshipsFailure(ids)
|
||||
|
@ -502,6 +502,7 @@ public class TimelineFragment extends SFragment implements
|
||||
// home, notifications, public, thread
|
||||
switch (kind) {
|
||||
case HOME:
|
||||
case LIST:
|
||||
return filterContext.contains(Filter.HOME);
|
||||
case PUBLIC_FEDERATED:
|
||||
case PUBLIC_LOCAL:
|
||||
|
@ -54,7 +54,7 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View) : CharSequence {
|
||||
while(matcher.find()) {
|
||||
val span = EmojiSpan(WeakReference(view))
|
||||
|
||||
builder.setSpan(span, matcher.start(), matcher.end(), 0);
|
||||
builder.setSpan(span, matcher.start(), matcher.end(), 0)
|
||||
Glide.with(view)
|
||||
.asBitmap()
|
||||
.load(url)
|
||||
@ -89,7 +89,7 @@ class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan()
|
||||
drawable.setBounds(0, 0, emojiSize, emojiSize)
|
||||
|
||||
var transY = bottom - drawable.bounds.bottom
|
||||
transY -= paint.fontMetricsInt.descent / 2;
|
||||
transY -= paint.fontMetricsInt.descent / 2
|
||||
|
||||
canvas.translate(x, transY.toFloat())
|
||||
drawable.draw(canvas)
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
115
app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt
Normal file
115
app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt
Normal 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
|
||||
}
|
@ -23,7 +23,6 @@ import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import com.bumptech.glide.Glide
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
@ -220,9 +219,7 @@ class StatusViewHelper(private val itemView: View) {
|
||||
|
||||
// Set the icon next to the label.
|
||||
val drawableId = getLabelIcon(attachments[0].type)
|
||||
val drawable = AppCompatResources.getDrawable(context, drawableId)
|
||||
ThemeUtils.setDrawableTint(context, drawable!!, android.R.attr.textColorTertiary)
|
||||
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
|
||||
mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0)
|
||||
|
||||
mediaLabel.setOnClickListener { listener.onViewMedia(null, 0) }
|
||||
}
|
||||
|
@ -24,9 +24,7 @@ import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
/**
|
||||
@ -60,17 +58,6 @@ public class ThemeUtils {
|
||||
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) {
|
||||
drawable.setColorFilter(getColor(context, attribute), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
@ -36,4 +36,6 @@
|
||||
tools:src="@drawable/elephant_error"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<include layout="@layout/item_status_bottom_sheet" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -166,10 +166,10 @@
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/composeMediaPreviewBar"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none" />
|
||||
android:scrollbars="none"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.keylesspalace.tusky.components.compose.view.PollPreviewView
|
||||
android:id="@+id/pollPreview"
|
||||
@ -297,9 +297,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="?attr/colorSurface"
|
||||
android:elevation="12dp"
|
||||
android:animateLayoutChanges="true"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
@ -314,8 +314,8 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_add_media"
|
||||
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
|
||||
android:id="@+id/composeToggleVisibilityButton"
|
||||
@ -325,7 +325,8 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_toggle_visibility"
|
||||
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" />
|
||||
|
||||
<ImageButton
|
||||
@ -336,7 +337,7 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_hide_media"
|
||||
android:padding="4dp"
|
||||
android:tooltipText="@string/action_hide_media"
|
||||
app:tooltipText="@string/action_hide_media"
|
||||
tools:src="@drawable/ic_eye_24dp" />
|
||||
|
||||
<ImageButton
|
||||
@ -347,8 +348,8 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_content_warning"
|
||||
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
|
||||
android:id="@+id/composeEmojiButton"
|
||||
@ -358,8 +359,8 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_emoji_keyboard"
|
||||
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
|
||||
android:id="@+id/composeScheduleButton"
|
||||
@ -369,8 +370,8 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/action_schedule_toot"
|
||||
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
|
||||
android:layout_width="0dp"
|
||||
|
@ -29,7 +29,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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
|
||||
android:id="@+id/tabLayout"
|
||||
|
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/hashtag"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:textStyle="normal|bold" />
|
||||
android:textStyle="normal|bold"
|
||||
app:drawableStartCompat="@drawable/ic_list"
|
||||
app:drawableTint="?attr/iconColor" />
|
||||
|
@ -340,6 +340,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -353,6 +354,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
|
||||
|
||||
@ -366,6 +368,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
|
||||
|
||||
@ -379,6 +382,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp">
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<!--This is a thumbnail picture-->
|
||||
<ImageView
|
||||
@ -15,23 +15,25 @@
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="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-->
|
||||
<TextView
|
||||
android:id="@+id/emojicompat_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="72dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="72dp"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/emojicompat_caption"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/emojicompat_thumb"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/system_default" />
|
||||
@ -58,8 +60,8 @@
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="72dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="72dp"
|
||||
android:indeterminate="false"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
@ -7,4 +8,5 @@
|
||||
android:focusableInTouchMode="false"
|
||||
android:gravity="center_vertical"
|
||||
android:lines="1"
|
||||
android:maxEms="20" />
|
||||
android:maxEms="20"
|
||||
app:drawableTint="?android:attr/textColorTertiary" />
|
@ -198,8 +198,8 @@
|
||||
app:layout_constraintLeft_toLeftOf="@+id/status_media_preview_container"
|
||||
app:layout_constraintTop_toTopOf="@+id/status_media_preview_container"
|
||||
app:srcCompat="@drawable/ic_eye_24dp"
|
||||
tools:visibility="visible"
|
||||
app:tint="@color/white" />
|
||||
app:tint="@color/white"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_sensitive_media_warning"
|
||||
@ -231,6 +231,7 @@
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
@ -168,9 +168,9 @@
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:minHeight="80dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button_toggle_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
@ -411,6 +411,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -424,6 +425,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
|
||||
|
||||
@ -437,6 +439,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
|
||||
|
||||
@ -450,6 +453,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />
|
||||
|
||||
|
@ -356,6 +356,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -369,6 +370,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
|
||||
|
||||
@ -382,6 +384,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
|
||||
|
||||
@ -395,6 +398,7 @@
|
||||
android:importantForAccessibility="no"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
android:paddingBottom="8dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="?attr/status_text_large"
|
||||
app:drawableTint="?android:attr/textColorSecondary"
|
||||
app:layout_constraintBottom_toTopOf="@id/chipGroup"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/imageView"
|
||||
|
@ -1,17 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="match_parent"
|
||||
android:drawableStart="@drawable/ic_home_24dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:drawablePadding="12dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:lines="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
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" />
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
android:paddingBottom="16dp"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:drawableTint="?android:attr/textColorTertiary"
|
||||
app:layout_constraintBottom_toTopOf="@id/invalidScheduleWarning"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
@ -39,11 +40,11 @@
|
||||
android:paddingBottom="16dp"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@string/warning_scheduling_interval"
|
||||
android:visibility="gone" />
|
||||
tools:text="@string/warning_scheduling_interval" />
|
||||
|
||||
</merge>
|
@ -381,7 +381,7 @@
|
||||
<string name="poll_vote">ভোট</string>
|
||||
<string name="poll_info_closed">বন্ধ</string>
|
||||
<string name="poll_info_time_absolute">\'%s এ শেষ হবে\'</string>
|
||||
<string name="poll_info_format">" <!-- ১৫ ভোট • ১ ঘন্টা বাকি --> %1$s • %2$s"<!-- 15 votes • 1 hour left -->
|
||||
<string name="poll_info_format"><!-- 15 votes • 1 hour left -->
|
||||
%1$s • %2$s</string>
|
||||
<string name="compose_preview_image_description">ছবি %s এর জন্য ক্রিয়া</string>
|
||||
<string name="notification_clear_text">আপনি কি আপনার সমস্ত বিজ্ঞপ্তি স্থায়ীভাবে মুছে ফেলতে চান\?</string>
|
||||
|
@ -475,11 +475,7 @@
|
||||
<string name="action_unmute_notifications_desc">Odkrýt oznámení od %s</string>
|
||||
<string name="action_unmute_desc">Odkrýt %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="pref_title_confirm_reblogs">Zobrazit dialogové okno s potvrzením při boostování</string>
|
||||
</resources>
|
@ -101,7 +101,7 @@
|
||||
<string name="action_accept">Akzeptieren</string>
|
||||
<string name="action_reject">Ablehnen</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_content_warning">Inhaltswarnung</string>
|
||||
<string name="action_emoji_keyboard">Emoji</string>
|
||||
@ -465,4 +465,9 @@
|
||||
<string name="abbreviated_hours_ago">%d St.</string>
|
||||
<string name="abbreviated_in_days">in %d T.</string>
|
||||
<string name="abbreviated_years_ago">%d J.</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>
|
||||
|
@ -164,9 +164,9 @@
|
||||
<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_filters">Sciigi al mi kiam</string>
|
||||
<string name="pref_title_notification_filter_mentions">menciita</string>
|
||||
<string name="pref_title_notification_filter_follows">sekvita</string>
|
||||
<string name="pref_title_notification_filter_reblogs">viaj mesaĝoj estas diskonigitaj</string>
|
||||
<string name="pref_title_notification_filter_mentions">iu mencias min</string>
|
||||
<string name="pref_title_notification_filter_follows">iu sekvas min</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_appearance_settings">Aspekto</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="notification_poll_name">Enketoj</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_apply_filter">Filtri</string>
|
||||
<string name="filter_apply">Apliki</string>
|
||||
@ -373,15 +373,14 @@
|
||||
<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>
|
||||
<plurals name="poll_info_votes">
|
||||
<item quantity="one"/>
|
||||
<item quantity="other"/>
|
||||
<item quantity="one">%s voĉdono</item>
|
||||
<item quantity="other">%s voĉdonoj</item>
|
||||
</plurals>
|
||||
<string name="poll_info_time_absolute">finiĝos je %s</string>
|
||||
<string name="poll_info_closed">finiĝita</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_created">Enketo kiu vi kreis finiĝis</string>
|
||||
|
||||
<string name="title_domain_mutes">Kaŝitaj domajnoj</string>
|
||||
<string name="action_view_domain_mutes">Kaŝitaj domajnoj</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="notification_follow_request_name">Petoj de sekvado</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>
|
@ -475,4 +475,8 @@
|
||||
<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="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>
|
||||
|
@ -450,10 +450,7 @@
|
||||
<string name="hashtags">Traolak</string>
|
||||
<string name="dialog_mute_hide_notifications">Ez erakutsi jakinarazpenak</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_confirm_reblogs">Erakutsi berrespen-abisua tuta bultzatu aurretik</string>
|
||||
<string name="pref_title_show_cards_in_timelines">Erakutsi esteken aurrebista denbora-lerroetan</string>
|
||||
|
@ -93,7 +93,7 @@
|
||||
<string name="action_accept">پذیرش</string>
|
||||
<string name="action_reject">رد</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_content_warning">هشدار محتوا</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_favourites">فرستههایم برگزیده شدند</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="app_them_dark">روشن</string>
|
||||
<string name="app_theme_light">سیاه</string>
|
||||
<string name="app_them_dark">تاریک</string>
|
||||
<string name="app_theme_light">روشن</string>
|
||||
<string name="app_theme_black">سیاه</string>
|
||||
<string name="app_theme_auto">خودکار در غروب</string>
|
||||
<string name="pref_title_browser_settings">مرورگر</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_tabs">زبانهها</string>
|
||||
<string name="pref_title_show_boosts">نمایش تقویتها</string>
|
||||
<string name="pref_title_show_replies">نمایش پاسخها</string>
|
||||
<string name="pref_title_show_media_preview">بارگیری پیشنمایش رسانه</string>
|
||||
<string name="pref_title_proxy_settings">پراکسی</string>
|
||||
<string name="pref_title_http_proxy_settings">پراکسی HTTP</string>
|
||||
<string name="pref_title_http_proxy_enable">فعالسازی پراکسی HTTP</string>
|
||||
<string name="pref_title_proxy_settings">پیشکار</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_server">کارساز پیشکار HTTP</string>
|
||||
<string name="pref_title_http_proxy_port">درگاه پیشکار HTTP</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_failed_to_sync">ناتوانی در همگامسازی تنظیمات</string>
|
||||
<string name="post_privacy_public">عمومی</string>
|
||||
@ -279,7 +279,7 @@
|
||||
<string name="title_statuses_pinned">سنجاقشده</string>
|
||||
<string name="title_domain_mutes">دامنههای نهفته</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_unfavourite">برداشتن برگزیدگی</string>
|
||||
<string name="action_delete_and_redraft">حذف و بازنویسی</string>
|
||||
@ -289,11 +289,11 @@
|
||||
<string name="action_add_tab">افزودن زبانه</string>
|
||||
<string name="action_links">پیوندها</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_reblogged_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_links_dialog">پیوندها</string>
|
||||
<string name="action_open_media_n">گشودن رسانه #%d</string>
|
||||
@ -305,11 +305,11 @@
|
||||
<string name="dialog_redraft_toot_warning">میخواهید این بوق را پاک و بازنویسی کنید؟</string>
|
||||
<string name="mute_domain_warning_dialog_ok">نهفتن تمام دامنه</string>
|
||||
<string name="pref_title_notification_filter_poll">پایان نظرسنجیها</string>
|
||||
<string name="pref_title_timeline_filters">صافیها</string>
|
||||
<string name="app_theme_system">استفاده از طرح سیستم</string>
|
||||
<string name="pref_title_timeline_filters">پالایهها</string>
|
||||
<string name="app_theme_system">استفاده از طراحی سامانه</string>
|
||||
<string name="pref_title_language">زبان</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_description">آگاهیها دربارهٔ نظرسنجیهای پایانیافته</string>
|
||||
<string name="about_tusky_version">تاسکی %s</string>
|
||||
@ -364,7 +364,7 @@
|
||||
<string name="description_visiblity_direct">مستقیم</string>
|
||||
<string name="description_poll">نظرسنجی با گزینهها: %1$s، %2$s، %3$s، %4$s؛ %5$s</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_apply_filter">پالایش</string>
|
||||
<string name="filter_apply">اعمال</string>
|
||||
@ -434,15 +434,15 @@
|
||||
<string name="no_saved_status">هیچ پیشنویسی ندارید.</string>
|
||||
<string name="no_scheduled_status">هیچ وضعیت زمانبستهای ندارید.</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_enable_swipe_for_tabs">به کار انداختن اشارهٔ کشیدنی برای تعویض بین زبانهها</string>
|
||||
<plurals name="poll_info_people">
|
||||
<item quantity="one">%s نفر</item>
|
||||
<item quantity="other">%s نفر</item>
|
||||
</plurals>
|
||||
<string name="hashtags">هشتگها</string>
|
||||
<string name="add_hashtag_title">افزودن هشتگ</string>
|
||||
<string name="hashtags">برچسبها</string>
|
||||
<string name="add_hashtag_title">افزودن برچسب</string>
|
||||
<string name="notification_follow_request_description">آگاهیها دربارهٔ درخواستهای پیگیری</string>
|
||||
<string name="notification_follow_request_name">درخواستهای پیگیری</string>
|
||||
<string name="pref_title_notification_filter_follow_requests">درخواست پیگیری</string>
|
||||
@ -470,4 +470,8 @@
|
||||
</plurals>
|
||||
<string name="pref_title_hide_top_toolbar">نهفتن عنوان نوارابزار بالایی</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>
|
||||
|
@ -39,7 +39,7 @@
|
||||
<string name="title_saved_toot">Brouillons</string>
|
||||
<string name="title_licenses">Licences</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_media_hidden_title">Média caché</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="message_empty">Rien ici.</string>
|
||||
<string name="footer_empty">Il n’y a aucun pouet ici pour l’instant. 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_follow_format">%s vous suit</string>
|
||||
<string name="report_username_format">Signaler @%s</string>
|
||||
@ -69,8 +69,8 @@
|
||||
<string name="action_unfollow">Ne plus suivre</string>
|
||||
<string name="action_block">Bloquer</string>
|
||||
<string name="action_unblock">Débloquer</string>
|
||||
<string name="action_hide_reblogs">Cacher les boosts</string>
|
||||
<string name="action_show_reblogs">Afficher les boosts</string>
|
||||
<string name="action_hide_reblogs">Cacher les partages</string>
|
||||
<string name="action_show_reblogs">Afficher les partages</string>
|
||||
<string name="action_report">Signaler</string>
|
||||
<string name="action_delete">Supprimer</string>
|
||||
<string name="action_send">POUET</string>
|
||||
@ -109,8 +109,8 @@
|
||||
<string name="action_links">Liens</string>
|
||||
<string name="action_mentions">Mentions</string>
|
||||
<string name="action_hashtags">Hashtags</string>
|
||||
<string name="action_open_reblogger">Afficher l’auteur·rice du boost</string>
|
||||
<string name="action_open_reblogged_by">Afficher les boosts</string>
|
||||
<string name="action_open_reblogger">Afficher l’auteur·rice du partage</string>
|
||||
<string name="action_open_reblogged_by">Afficher les partages</string>
|
||||
<string name="action_open_faved_by">Montrer les favoris</string>
|
||||
<string name="title_hashtags_dialog">Hashtags</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_vibrate">Notifier avec une vibration</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_follows">On me suit</string>
|
||||
<string name="pref_title_notification_filter_reblogs">Mes pouets sont boostés</string>
|
||||
<string name="pref_title_notification_filter_follows">on vient de me suivre</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_appearance_settings">Apparence</string>
|
||||
<string name="pref_title_app_theme">Thème de l’application</string>
|
||||
@ -187,7 +187,7 @@
|
||||
<string name="pref_title_language">Langue</string>
|
||||
<string name="pref_title_status_filter">Filtrage des fils</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_media_preview">Montrer les miniatures des médias</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_follow_name">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_description">Notifications quand vos pouets sont boostés</string>
|
||||
<string name="notification_boost_name">Partages</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_description">Notifications quand vos pouets sont mis en favoris</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="profile_badge_bot_text">Robot</string>
|
||||
<string name="account_moved_description">%1$s a déménagé vers :</string>
|
||||
<string name="reblog_private">Booster vers l’audience originale</string>
|
||||
<string name="unreblog_private">Annuler le boost</string>
|
||||
<string name="reblog_private">Partager à l’audience originale</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_apache_2">Sous licence Apache (copie ci-dessous)</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>
|
||||
</plurals>
|
||||
<plurals name="reblogs">
|
||||
<item quantity="one"><b>%s</b> Boost</item>
|
||||
<item quantity="other"><b>%s</b> Boosts</item>
|
||||
<item quantity="one"><b>%s</b> Partage</item>
|
||||
<item quantity="other"><b>%s</b> Partages</item>
|
||||
</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="conversation_1_recipients">%1$s</string>
|
||||
<string name="conversation_2_recipients">%1$s et %2$s</string>
|
||||
@ -362,7 +362,7 @@
|
||||
<string name="description_visiblity_direct"> Direct
|
||||
</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_apply_filter">Filtrer</string>
|
||||
<string name="filter_apply">Appliquer</string>
|
||||
@ -376,7 +376,7 @@
|
||||
<string name="poll_info_closed">Terminé</string>
|
||||
<string name="poll_vote">Voter</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="poll_ended_created">Un sondage que vous avez créé est terminé</string>
|
||||
<plurals name="poll_timespan_days">
|
||||
@ -403,7 +403,7 @@
|
||||
<string name="title_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="confirmation_domain_unmuted">%s n’est plus masqué</string>
|
||||
<string name="confirmation_domain_unmuted">%s n’est plus masqué·e</string>
|
||||
<string name="mute_domain_warning_dialog_ok">Masquer le domaine entier</string>
|
||||
<string name="caption_notoemoji">L’ensemble d’émojis actuel de Google</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="no_saved_status">Vous n’avez aucun brouillon.</string>
|
||||
<string name="no_scheduled_status">Vous n’avez aucun pouet planifié.</string>
|
||||
<string name="warning_scheduling_interval">L’intervalle minimum de planification sur Mastodon est de5 minutes.</string>
|
||||
<string name="warning_scheduling_interval">L’intervalle minimum de planification sur Mastodon est de 5 minutes.</string>
|
||||
<string name="notification_follow_request_name">Demandes d\'abonnement</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_show_cards_in_timelines">Afficher des aperçus des liens dans les fils</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 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_description">Notifications à propos des demandes d’abonnement</string>
|
||||
<string name="pref_title_notification_filter_follow_requests">Demande d’abonnement</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="action_unmute_conversation">Enlever la sourdine à la conversation</string>
|
||||
<string name="action_mute_conversation">Silencer la conversation</string>
|
||||
<string name="pref_title_enable_swipe_for_tabs">Activer les gestes de glissement pour passer d’un onglet à l’autre</string>
|
||||
<string name="action_mute_conversation">Masquer la conversation</string>
|
||||
<string name="pref_title_enable_swipe_for_tabs">Activer le glissement pour changer d’onglet</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_main_nav_position_option_bottom">Bas</string>
|
||||
<string name="pref_main_nav_position_option_top">Haut</string>
|
||||
<string name="pref_main_nav_position">Position de navigation principale</string>
|
||||
<string name="action_unmute_domain">Ne plus masquer %s</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_unmute_notifications_desc">Ne plus 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 masquer les notifications de %s</string>
|
||||
<string name="action_unmute_desc">Ne plus masquer %s</string>
|
||||
<plurals name="poll_info_people">
|
||||
<item quantity="one">%s personne</item>
|
||||
@ -484,4 +484,8 @@
|
||||
<item quantity="one">%s voix</item>
|
||||
<item quantity="other">%s voix</item>
|
||||
</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 n’y a pas d’annonce.</string>
|
||||
<string name="title_announcements">Annonces</string>
|
||||
</resources>
|
||||
|
@ -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="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="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>
|
||||
|
@ -415,8 +415,8 @@
|
||||
<string name="notification_follow_request_name">Fylgjendabeiðnir</string>
|
||||
<string name="hashtags">Myllumerki</string>
|
||||
<plurals name="favs">
|
||||
<item quantity="one"><b>%1$s</b> Eftirlæti</item>
|
||||
<item quantity="other"><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>
|
||||
</plurals>
|
||||
<plurals name="reblogs">
|
||||
<item quantity="one"><b>%s</b> Endurbirting</item>
|
||||
@ -438,4 +438,33 @@
|
||||
<item quantity="one">%d dagur eftir</item>
|
||||
<item quantity="other">%d dagar eftir</item>
|
||||
</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>
|
@ -414,8 +414,8 @@
|
||||
<item quantity="other">%d minuti rimasti</item>
|
||||
</plurals>
|
||||
<plurals name="poll_timespan_seconds">
|
||||
<item quantity="one">%d secondo</item>
|
||||
<item quantity="other">%d secondi</item>
|
||||
<item quantity="one">%d secondo rimasto</item>
|
||||
<item quantity="other">%d secondi rimasti</item>
|
||||
</plurals>
|
||||
<string name="button_continue">Continua</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="action_unmute_desc">Smetti di silenziare %s</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>
|
@ -465,4 +465,6 @@
|
||||
<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_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>
|
@ -500,4 +500,9 @@
|
||||
<string name="action_mute_notifications_desc">Заблокировать уведомления от %s</string>
|
||||
<string name="action_unmute_notifications_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>
|
@ -369,7 +369,6 @@
|
||||
<string name="pref_title_show_cards_in_timelines">जालस्थानप्रदर्शनं समयतालिकायां दर्शयतु</string>
|
||||
<string name="warning_scheduling_interval">मास्टोडोने पञ्चनिमेषपरिमितो न्यूनतमः कालबद्धसमयः ।</string>
|
||||
<string name="no_scheduled_status">न ते कालबद्धदौत्यानि सन्ति ।</string>
|
||||
<string name="post_lookup_error_format">प्रकटनान्वेषणे विफलता</string>
|
||||
<string name="edit_poll">सम्पाद्यताम्</string>
|
||||
<string name="poll_new_choice_hint">मतम् %d</string>
|
||||
<string name="poll_allow_multiple_choices">बहूनि मतानि</string>
|
||||
|
@ -480,4 +480,8 @@
|
||||
<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_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>
|
@ -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_invalid_domain">Tài khoản không đú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_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>
|
||||
@ -48,7 +48,7 @@
|
||||
<string name="action_reset_schedule">Làm tươi</string>
|
||||
<string name="action_search">Tìm kiếm</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_logout">Đăng xuất</string>
|
||||
<string name="button_done">Xong</string>
|
||||
@ -97,7 +97,7 @@
|
||||
<string name="download_media">Tải về</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_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="action_open_media_n">Mở tập tin #%d</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_sensitive_media_directions">Hiển thị</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_username_format">\@%s</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="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_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="dialog_mute_warning">Ẩ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="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_unlisted">Mở</string>
|
||||
<string name="post_privacy_unlisted">Riêng tư</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_top">Trên màn hình</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_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_title_http_proxy_server">HTTP proxy server</string>
|
||||
<string name="pref_title_http_proxy_port">HTTP proxy port</string>
|
||||
<string name="pref_title_http_proxy_enable">Bật HTTP proxy</string>
|
||||
<string name="pref_title_http_proxy_settings">HTTP proxy</string>
|
||||
<string name="pref_title_proxy_settings">Proxy</string>
|
||||
<string name="pref_title_http_proxy_server">Máy chủ proxy</string>
|
||||
<string name="pref_title_http_proxy_port">Cổng</string>
|
||||
<string name="pref_title_http_proxy_enable">Bật proxy</string>
|
||||
<string name="pref_title_http_proxy_settings">Dùng 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_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>
|
||||
@ -278,7 +278,7 @@
|
||||
<string name="about_powered_by_tusky">Powered by Tusky</string>
|
||||
<string name="about_tusky_version">Tusky %s</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_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>
|
||||
@ -326,7 +326,7 @@
|
||||
<string name="poll_duration_30_min">30 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="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="failed_search">Không thể tìm thấy</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>
|
||||
</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_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_info_closed">Kết thúc</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>
|
||||
</plurals>
|
||||
<plurals name="poll_info_votes">
|
||||
<item quantity="other">%s phiếu</item>
|
||||
<item quantity="other">%s người</item>
|
||||
</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_shortcut_short_label">Viế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="add_hashtag_title">Thêm hashtag</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_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_status_bookmarked">Đã lưu</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_domain">Bỏ ẩn %s</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>
|
@ -477,8 +477,8 @@
|
||||
<string name="notification_follow_request_format">%s 请求关注你</string>
|
||||
<string name="pref_main_nav_position">导航栏位置</string>
|
||||
<string name="pref_title_hide_top_toolbar">隐藏顶部工具栏标题</string>
|
||||
<plurals name="poll_info_people">
|
||||
<item quantity="one">%s 人</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<string name="no_announcements">本站暂无公告。</string>
|
||||
<string name="title_announcements">公告</string>
|
||||
<string name="account_note_saved">已保存</string>
|
||||
<string name="account_note_hint">此账号的备注</string>
|
||||
</resources>
|
||||
|
@ -81,6 +81,8 @@
|
||||
|
||||
<item name="chipStyle">@style/Widget.MaterialComponents.Chip.Choice</item>
|
||||
|
||||
<item name="preferenceTheme">@style/TuskyPreferenceTheme</item>
|
||||
|
||||
<item name="colorInfo">@color/colorInfo</item>
|
||||
</style>
|
||||
|
||||
@ -105,6 +107,10 @@
|
||||
<item name="tabIndicatorHeight">3dp</item>
|
||||
</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">
|
||||
<item name="android:tint">?android:attr/textColorTertiary</item>
|
||||
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.keylesspalace.tusky
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Looper.getMainLooper
|
||||
import android.text.SpannedString
|
||||
import android.widget.EditText
|
||||
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.mock
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.Shadows.shadowOf
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.fakes.RoboMenuItem
|
||||
|
||||
@ -76,8 +78,8 @@ class ComposeActivityTest {
|
||||
notificationVibration = true,
|
||||
notificationLight = true
|
||||
)
|
||||
var instanceResponseCallback: (()->Instance)? = null
|
||||
var composeOptions: ComposeActivity.ComposeOptions? = null
|
||||
private var instanceResponseCallback: (()->Instance)? = null
|
||||
private var composeOptions: ComposeActivity.ComposeOptions? = null
|
||||
|
||||
@Before
|
||||
fun setupActivity() {
|
||||
@ -185,6 +187,7 @@ class ComposeActivityTest {
|
||||
val customMaximum = 1000
|
||||
instanceResponseCallback = { getInstanceWithMaximumTootCharacters(customMaximum) }
|
||||
setupActivity()
|
||||
shadowOf(getMainLooper()).idle()
|
||||
assertEquals(customMaximum, activity.maximumTootCharacters)
|
||||
}
|
||||
|
||||
@ -230,7 +233,7 @@ class ComposeActivityTest {
|
||||
editor.setSelection(caretIndex)
|
||||
activity.prependSelectedWordsWith(insertText)
|
||||
// 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
|
||||
assertEquals(caretIndex + insertText.length, editor.selectionStart)
|
||||
|
@ -1,11 +1,11 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.4.10'
|
||||
ext.kotlin_version = '1.4.21'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
10
fastlane/metadata/android/en-US/changelogs/77.txt
Normal file
10
fastlane/metadata/android/en-US/changelogs/77.txt
Normal 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
|
10
fastlane/metadata/android/hu/changelogs/77.txt
Normal file
10
fastlane/metadata/android/hu/changelogs/77.txt
Normal 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
|
10
fastlane/metadata/android/is/changelogs/77.txt
Normal file
10
fastlane/metadata/android/is/changelogs/77.txt
Normal 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
|
8
fastlane/metadata/android/it/changelogs/70.txt
Normal file
8
fastlane/metadata/android/it/changelogs/70.txt
Normal 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!
|
8
fastlane/metadata/android/it/changelogs/74.txt
Normal file
8
fastlane/metadata/android/it/changelogs/74.txt
Normal 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
|
10
fastlane/metadata/android/it/changelogs/77.txt
Normal file
10
fastlane/metadata/android/it/changelogs/77.txt
Normal 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
|
10
fastlane/metadata/android/nb_NO/changelogs/77.txt
Normal file
10
fastlane/metadata/android/nb_NO/changelogs/77.txt
Normal 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
|
8
fastlane/metadata/android/sv/changelogs/74.txt
Normal file
8
fastlane/metadata/android/sv/changelogs/74.txt
Normal 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
|
10
fastlane/metadata/android/sv/changelogs/77.txt
Normal file
10
fastlane/metadata/android/sv/changelogs/77.txt
Normal 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
|
8
fastlane/metadata/android/vi/changelogs/77.txt
Normal file
8
fastlane/metadata/android/vi/changelogs/77.txt
Normal 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
|
10
fastlane/metadata/android/zh_Hans/changelogs/77.txt
Normal file
10
fastlane/metadata/android/zh_Hans/changelogs/77.txt
Normal file
@ -0,0 +1,10 @@
|
||||
Tusky v13.0
|
||||
|
||||
- 支持账号备注(Mastodon 3.2.0 特性)
|
||||
- 支持公告栏(Mastodon 3.1.0特性)
|
||||
|
||||
- 当前账号的头像将在导航栏显示
|
||||
- 在时间线中点击账号名称后打开该用户的资料页
|
||||
|
||||
- 其他许多小改进和错误修复
|
||||
- 改善翻译
|
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
@ -0,0 +1 @@
|
||||
Tusky
|
Loading…
x
Reference in New Issue
Block a user