Media previews improvements (in progress)

This commit is contained in:
charlag 2019-03-10 19:52:19 +01:00
parent 596baa4d55
commit d6288db492
11 changed files with 122 additions and 50 deletions

View File

@ -414,15 +414,26 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
@NonNull @NonNull
private static String getLabelTypeText(Context context, Attachment.Type type) { private static CharSequence getLabelTypeText(Context context, List<Attachment> attachments,
switch (type) { boolean sensitive) {
default: StringBuilder text = new StringBuilder();
case IMAGE: for (int i = 0; i < attachments.size(); i++) {
return context.getString(R.string.status_media_images); Attachment attachment = attachments.get(i);
case GIFV: if (TextUtils.isEmpty(attachment.getDescription())) {
case VIDEO: text.append(context.getString(
return context.getString(R.string.status_media_video); R.string.description_status_media_no_description_placeholder));
} else {
text.append(attachment.getDescription());
}
if (i != attachments.size() - 1) {
text.append('\n');
}
} }
if (sensitive) {
String sensitiveText = context.getString(R.string.status_sensitive_media_title);
text.append(String.format(" (%s)", sensitiveText));
}
return text;
} }
@DrawableRes @DrawableRes
@ -447,11 +458,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
// Set the label's text. // Set the label's text.
Context context = itemView.getContext(); Context context = itemView.getContext();
String labelText = getLabelTypeText(context, attachments.get(0).getType()); CharSequence labelText = getLabelTypeText(context, attachments, sensitive);
if (sensitive) {
String sensitiveText = context.getString(R.string.status_sensitive_media_title);
labelText += String.format(" (%s)", sensitiveText);
}
mediaLabel.setText(labelText); mediaLabel.setText(labelText);
// Set the icon next to the label. // Set the icon next to the label.

View File

@ -15,12 +15,15 @@
package com.keylesspalace.tusky.components.conversation package com.keylesspalace.tusky.components.conversation
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.ConnectivityManager
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.net.ConnectivityManagerCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.paging.PagedList import androidx.paging.PagedList
@ -30,6 +33,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import com.keylesspalace.tusky.AccountActivity import com.keylesspalace.tusky.AccountActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewTagActivity import com.keylesspalace.tusky.ViewTagActivity
import com.keylesspalace.tusky.db.AccountEntity
import com.keylesspalace.tusky.db.AppDatabase import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.di.ViewModelFactory
@ -40,6 +44,7 @@ import com.keylesspalace.tusky.util.NetworkState
import com.keylesspalace.tusky.util.ThemeUtils import com.keylesspalace.tusky.util.ThemeUtils
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import kotlinx.android.synthetic.main.fragment_timeline.* import kotlinx.android.synthetic.main.fragment_timeline.*
import kotlinx.android.synthetic.main.item_saved_toot.view.*
import javax.inject.Inject import javax.inject.Inject
class ConversationsFragment : SFragment(), StatusActionListener, Injectable { class ConversationsFragment : SFragment(), StatusActionListener, Injectable {
@ -67,10 +72,16 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable {
val useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false) val useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false)
val account = accountManager.activeAccount val account = accountManager.activeAccount
val mediaPreviewEnabled = account?.mediaPreviewEnabled ?: true
adapter = ConversationAdapter(useAbsoluteTime, mediaPreviewEnabled,this, ::onTopLoaded, viewModel::retry) val isMetered = ConnectivityManagerCompat.isActiveNetworkMetered(
view.context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
val mediaPreviewEnabled = account != null
&& (account.mediaPreviewEnabled == AccountEntity.MEDIA_PREVIEW_ALWAYS
|| (account.mediaPreviewEnabled == AccountEntity.MEDIA_PREVIEW_ON_UNMETERED
&& !isMetered))
adapter = ConversationAdapter(useAbsoluteTime, mediaPreviewEnabled, this, ::onTopLoaded,
viewModel::retry)
recyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) recyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
recyclerView.layoutManager = LinearLayoutManager(view.context) recyclerView.layoutManager = LinearLayoutManager(view.context)

View File

@ -47,7 +47,7 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
var defaultPostPrivacy: Status.Visibility = Status.Visibility.PUBLIC, var defaultPostPrivacy: Status.Visibility = Status.Visibility.PUBLIC,
var defaultMediaSensitivity: Boolean = false, var defaultMediaSensitivity: Boolean = false,
var alwaysShowSensitiveMedia: Boolean = false, var alwaysShowSensitiveMedia: Boolean = false,
var mediaPreviewEnabled: Boolean = true, var mediaPreviewEnabled: Int = MEDIA_PREVIEW_ALWAYS,
var lastNotificationId: String = "0", var lastNotificationId: String = "0",
var activeNotifications: String = "[]", var activeNotifications: String = "[]",
var emojis: List<Emoji> = emptyList(), var emojis: List<Emoji> = emptyList(),
@ -77,4 +77,10 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
result = 31 * result + accountId.hashCode() result = 31 * result + accountId.hashCode()
return result return result
} }
companion object {
const val MEDIA_PREVIEW_ALWAYS = 1
const val MEDIA_PREVIEW_NEVER = 0
const val MEDIA_PREVIEW_ON_UNMETERED = 2
}
} }

View File

@ -209,7 +209,8 @@ public class NotificationsFragment extends SFragment implements
adapter = new NotificationsAdapter(dataSource, this, this); adapter = new NotificationsAdapter(dataSource, this, this);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia(); alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); // TODO
boolean mediaPreviewEnabled = false;//accountManager.getActiveAccount().getMediaPreviewEnabled();
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime); adapter.setUseAbsoluteTime(useAbsoluteTime);
@ -573,12 +574,12 @@ public class NotificationsFragment extends SFragment implements
break; break;
} }
case "mediaPreviewEnabled": { case "mediaPreviewEnabled": {
boolean enabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); // boolean enabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
if (enabled != adapter.isMediaPreviewEnabled()) { // if (enabled != adapter.isMediaPreviewEnabled()) {
adapter.setMediaPreviewEnabled(enabled); // adapter.setMediaPreviewEnabled(enabled);
fullyRefresh(); // fullyRefresh();
} // }
break; // break;
} }
} }
} }

View File

@ -65,7 +65,8 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable {
val account = accountManager.activeAccount val account = accountManager.activeAccount
alwaysShowSensitiveMedia = account?.alwaysShowSensitiveMedia ?: false alwaysShowSensitiveMedia = account?.alwaysShowSensitiveMedia ?: false
mediaPreviewEnabled = account?.mediaPreviewEnabled ?: true // TODO
mediaPreviewEnabled = false
searchRecyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) searchRecyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
searchRecyclerView.layoutManager = LinearLayoutManager(view.context) searchRecyclerView.layoutManager = LinearLayoutManager(view.context)

View File

@ -18,6 +18,7 @@ package com.keylesspalace.tusky.fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
@ -41,6 +42,7 @@ import com.keylesspalace.tusky.appstore.ReblogEvent;
import com.keylesspalace.tusky.appstore.StatusComposedEvent; import com.keylesspalace.tusky.appstore.StatusComposedEvent;
import com.keylesspalace.tusky.appstore.StatusDeletedEvent; import com.keylesspalace.tusky.appstore.StatusDeletedEvent;
import com.keylesspalace.tusky.appstore.UnfollowEvent; import com.keylesspalace.tusky.appstore.UnfollowEvent;
import com.keylesspalace.tusky.db.AccountEntity;
import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.db.AccountManager;
import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.di.Injectable;
import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.entity.Status;
@ -76,6 +78,7 @@ import javax.inject.Inject;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.arch.core.util.Function; import androidx.arch.core.util.Function;
import androidx.core.net.ConnectivityManagerCompat;
import androidx.core.util.Pair; import androidx.core.util.Pair;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.recyclerview.widget.AsyncDifferConfig; import androidx.recyclerview.widget.AsyncDifferConfig;
@ -319,7 +322,15 @@ public class TimelineFragment extends SFragment implements
private void setupTimelinePreferences() { private void setupTimelinePreferences() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia(); alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); AccountEntity account = accountManager.getActiveAccount();
boolean isMetered = ConnectivityManagerCompat.isActiveNetworkMetered(
(ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE));
boolean mediaPreviewEnabled = account != null
&& (account.getMediaPreviewEnabled() == AccountEntity.MEDIA_PREVIEW_ALWAYS
|| (account.getMediaPreviewEnabled() == AccountEntity.MEDIA_PREVIEW_ON_UNMETERED
&& !isMetered));
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime); adapter.setUseAbsoluteTime(useAbsoluteTime);
@ -743,13 +754,13 @@ public class TimelineFragment extends SFragment implements
break; break;
} }
case "mediaPreviewEnabled": { case "mediaPreviewEnabled": {
boolean enabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); // int state = accountManager.getActiveAccount().getMediaPreviewEnabled();
boolean oldMediaPreviewEnabled = adapter.getMediaPreviewEnabled(); // boolean oldMediaPreviewEnabled = adapter.getMediaPreviewEnabled();
if (enabled != oldMediaPreviewEnabled) { // if (enabled != oldMediaPreviewEnabled) {
adapter.setMediaPreviewEnabled(enabled); // adapter.setMediaPreviewEnabled(enabled);
fullyRefresh(); // fullyRefresh();
} // }
break; // break;
} }
case "tabFilterHomeReplies": { case "tabFilterHomeReplies": {
boolean filter = sharedPreferences.getBoolean("tabFilterHomeReplies", true); boolean filter = sharedPreferences.getBoolean("tabFilterHomeReplies", true);

View File

@ -161,7 +161,8 @@ public final class ViewThreadFragment extends SFragment implements
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
getActivity()); getActivity());
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia(); alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); // TODO
boolean mediaPreviewEnabled = false; //accountManager.getActiveAccount().getMediaPreviewEnabled();
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime); adapter.setUseAbsoluteTime(useAbsoluteTime);

View File

@ -15,17 +15,18 @@
package com.keylesspalace.tusky.fragment.preference package com.keylesspalace.tusky.fragment.preference
import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import com.google.android.material.snackbar.Snackbar import android.util.Log
import androidx.preference.SwitchPreference import android.view.View
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import android.util.Log import androidx.preference.SwitchPreference
import android.view.View import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.* import com.keylesspalace.tusky.*
import com.keylesspalace.tusky.appstore.EventHub import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
@ -64,11 +65,26 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
private lateinit var defaultPostPrivacyPreference: ListPreference private lateinit var defaultPostPrivacyPreference: ListPreference
private lateinit var defaultMediaSensitivityPreference: SwitchPreference private lateinit var defaultMediaSensitivityPreference: SwitchPreference
private lateinit var alwaysShowSensitiveMediaPreference: SwitchPreference private lateinit var alwaysShowSensitiveMediaPreference: SwitchPreference
private lateinit var mediaPreviewEnabledPreference: SwitchPreference private lateinit var mediaPreviewEnabledPreference: ListPreference
private val iconSize by lazy {resources.getDimensionPixelSize(R.dimen.preference_icon_size)} private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) }
@SuppressLint("ApplySharedPref")
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
// // Migrate preference type
// val valueIndex = when (accountManager.activeAccount!!.mediaPreviewEnabled) {
// AccountEntity.MEDIA_PREVIEW_ALWAYS -> 0
// AccountEntity.MEDIA_PREVIEW_NEVER -> 2
// AccountEntity.MEDIA_PREVIEW_ON_UNMETERED -> 1
// else -> throw AssertionError("Unknown value index")
// }
// val stringValue = context!!.resources.getStringArray(R.array.pref_previews_values)[valueIndex]
// context!!.getSharedPreferences(context!!.getString(R.string.preferences_file_key), Context.MODE_PRIVATE)
// .edit()
// .remove("mediaPreviewEnabled")
// .putString("mediaPreviewEnabled", stringValue)
// .commit()
addPreferencesFromResource(R.xml.account_preferences) addPreferencesFromResource(R.xml.account_preferences)
notificationPreference = findPreference("notificationPreference") notificationPreference = findPreference("notificationPreference")
@ -77,7 +93,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
blockedUsersPreference = findPreference("blockedUsersPreference") blockedUsersPreference = findPreference("blockedUsersPreference")
defaultPostPrivacyPreference = findPreference("defaultPostPrivacy") as ListPreference defaultPostPrivacyPreference = findPreference("defaultPostPrivacy") as ListPreference
defaultMediaSensitivityPreference = findPreference("defaultMediaSensitivity") as SwitchPreference defaultMediaSensitivityPreference = findPreference("defaultMediaSensitivity") as SwitchPreference
mediaPreviewEnabledPreference = findPreference("mediaPreviewEnabled") as SwitchPreference mediaPreviewEnabledPreference = findPreference("mediaPreviewEnabled") as ListPreference
alwaysShowSensitiveMediaPreference = findPreference("alwaysShowSensitiveMedia") as SwitchPreference alwaysShowSensitiveMediaPreference = findPreference("alwaysShowSensitiveMedia") as SwitchPreference
notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).sizePx(iconSize).color(ThemeUtils.getColor(notificationPreference.context, R.attr.toolbar_icon_tint)) notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).sizePx(iconSize).color(ThemeUtils.getColor(notificationPreference.context, R.attr.toolbar_icon_tint))
@ -107,14 +123,14 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
defaultMediaSensitivityPreference.isChecked = it.defaultMediaSensitivity defaultMediaSensitivityPreference.isChecked = it.defaultMediaSensitivity
defaultMediaSensitivityPreference.icon = getIconForSensitivity(it.defaultMediaSensitivity) defaultMediaSensitivityPreference.icon = getIconForSensitivity(it.defaultMediaSensitivity)
mediaPreviewEnabledPreference.isChecked = it.mediaPreviewEnabled mediaPreviewEnabledPreference.value = it.mediaPreviewEnabled.toString()
alwaysShowSensitiveMediaPreference.isChecked = it.alwaysShowSensitiveMedia alwaysShowSensitiveMediaPreference.isChecked = it.alwaysShowSensitiveMedia
} }
} }
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean { override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
when(preference) { when (preference) {
defaultPostPrivacyPreference -> { defaultPostPrivacyPreference -> {
preference.icon = getIconForVisibility(Status.Visibility.byString(newValue as String)) preference.icon = getIconForVisibility(Status.Visibility.byString(newValue as String))
syncWithServer(visibility = newValue) syncWithServer(visibility = newValue)
@ -125,7 +141,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
} }
mediaPreviewEnabledPreference -> { mediaPreviewEnabledPreference -> {
accountManager.activeAccount?.let { accountManager.activeAccount?.let {
it.mediaPreviewEnabled = newValue as Boolean it.mediaPreviewEnabled = (newValue as String).toInt()
accountManager.saveAccount(it) accountManager.saveAccount(it)
} }
} }
@ -144,7 +160,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
override fun onPreferenceClick(preference: Preference): Boolean { override fun onPreferenceClick(preference: Preference): Boolean {
when(preference) { when (preference) {
notificationPreference -> { notificationPreference -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent() val intent = Intent()
@ -189,13 +205,14 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
private fun syncWithServer(visibility: String? = null, sensitive: Boolean? = null) { private fun syncWithServer(visibility: String? = null, sensitive: Boolean? = null) {
mastodonApi.accountUpdateSource(visibility, sensitive) mastodonApi.accountUpdateSource(visibility, sensitive)
.enqueue(object: Callback<Account>{ .enqueue(object : Callback<Account> {
override fun onResponse(call: Call<Account>, response: Response<Account>) { override fun onResponse(call: Call<Account>, response: Response<Account>) {
val account = response.body() val account = response.body()
if(response.isSuccessful && account != null) { if (response.isSuccessful && account != null) {
accountManager.activeAccount?.let { accountManager.activeAccount?.let {
it.defaultPostPrivacy = account.source?.privacy ?: Status.Visibility.PUBLIC it.defaultPostPrivacy = account.source?.privacy
?: Status.Visibility.PUBLIC
it.defaultMediaSensitivity = account.source?.sensitive ?: false it.defaultMediaSensitivity = account.source?.sensitive ?: false
accountManager.saveAccount(it) accountManager.saveAccount(it)
} }
@ -214,9 +231,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
} }
private fun showErrorSnackbar(visibility: String?, sensitive: Boolean?) { private fun showErrorSnackbar(visibility: String?, sensitive: Boolean?) {
view?.let {view -> view?.let { view ->
Snackbar.make(view, R.string.pref_failed_to_sync, Snackbar.LENGTH_LONG) Snackbar.make(view, R.string.pref_failed_to_sync, Snackbar.LENGTH_LONG)
.setAction(R.string.action_retry) { syncWithServer( visibility, sensitive)} .setAction(R.string.action_retry) { syncWithServer(visibility, sensitive) }
.show() .show()
} }
} }

View File

@ -61,6 +61,15 @@
<item>日本語</item> <item>日本語</item>
</string-array> </string-array>
<string-array name="pref_previews_values">
<!-- Always -->
<item>1</item>
<!-- On unmetered -->
<item>2</item>
<!-- Never -->
<item>0</item>
</string-array>
<string-array name="language_values"> <string-array name="language_values">
<item>default</item> <item>default</item>
<item>ca</item> <item>ca</item>

View File

@ -435,4 +435,10 @@
%s; %s; %s, %s, %s; %s, %s, %s, %s; %s, %s, %s %s; %s; %s, %s, %s; %s, %s, %s, %s; %s, %s, %s
</string> </string>
<string-array name="pref_previews_names">
<item>Always</item>
<item>On unmetered networks</item>
<item>Never</item>
</string-array>
</resources> </resources>

View File

@ -38,8 +38,10 @@
<PreferenceCategory android:title="@string/pref_title_timelines"> <PreferenceCategory android:title="@string/pref_title_timelines">
<SwitchPreference <ListPreference
android:key="mediaPreviewEnabled" android:key="mediaPreviewEnabled"
android:entries="@array/pref_previews_names"
android:entryValues="@array/pref_previews_values"
android:title="@string/pref_title_show_media_preview" /> android:title="@string/pref_title_show_media_preview" />
<SwitchPreference <SwitchPreference