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

View File

@ -15,12 +15,15 @@
package com.keylesspalace.tusky.components.conversation
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.net.ConnectivityManagerCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.paging.PagedList
@ -30,6 +33,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import com.keylesspalace.tusky.AccountActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewTagActivity
import com.keylesspalace.tusky.db.AccountEntity
import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.di.Injectable
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.hide
import kotlinx.android.synthetic.main.fragment_timeline.*
import kotlinx.android.synthetic.main.item_saved_toot.view.*
import javax.inject.Inject
class ConversationsFragment : SFragment(), StatusActionListener, Injectable {
@ -67,10 +72,16 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable {
val useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false)
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.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 defaultMediaSensitivity: Boolean = false,
var alwaysShowSensitiveMedia: Boolean = false,
var mediaPreviewEnabled: Boolean = true,
var mediaPreviewEnabled: Int = MEDIA_PREVIEW_ALWAYS,
var lastNotificationId: String = "0",
var activeNotifications: String = "[]",
var emojis: List<Emoji> = emptyList(),
@ -77,4 +77,10 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
result = 31 * result + accountId.hashCode()
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);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
// TODO
boolean mediaPreviewEnabled = false;//accountManager.getActiveAccount().getMediaPreviewEnabled();
adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime);
@ -573,12 +574,12 @@ public class NotificationsFragment extends SFragment implements
break;
}
case "mediaPreviewEnabled": {
boolean enabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
if (enabled != adapter.isMediaPreviewEnabled()) {
adapter.setMediaPreviewEnabled(enabled);
fullyRefresh();
}
break;
// boolean enabled = accountManager.getActiveAccount().getMediaPreviewEnabled();
// if (enabled != adapter.isMediaPreviewEnabled()) {
// adapter.setMediaPreviewEnabled(enabled);
// fullyRefresh();
// }
// break;
}
}
}

View File

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

View File

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

View File

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

View File

@ -15,17 +15,18 @@
package com.keylesspalace.tusky.fragment.preference
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.preference.SwitchPreference
import android.util.Log
import android.view.View
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import android.util.Log
import android.view.View
import androidx.preference.SwitchPreference
import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.*
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
@ -64,11 +65,26 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
private lateinit var defaultPostPrivacyPreference: ListPreference
private lateinit var defaultMediaSensitivityPreference: 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?) {
// // 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)
notificationPreference = findPreference("notificationPreference")
@ -77,7 +93,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
blockedUsersPreference = findPreference("blockedUsersPreference")
defaultPostPrivacyPreference = findPreference("defaultPostPrivacy") as ListPreference
defaultMediaSensitivityPreference = findPreference("defaultMediaSensitivity") as SwitchPreference
mediaPreviewEnabledPreference = findPreference("mediaPreviewEnabled") as SwitchPreference
mediaPreviewEnabledPreference = findPreference("mediaPreviewEnabled") as ListPreference
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))
@ -107,14 +123,14 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
defaultMediaSensitivityPreference.isChecked = it.defaultMediaSensitivity
defaultMediaSensitivityPreference.icon = getIconForSensitivity(it.defaultMediaSensitivity)
mediaPreviewEnabledPreference.isChecked = it.mediaPreviewEnabled
mediaPreviewEnabledPreference.value = it.mediaPreviewEnabled.toString()
alwaysShowSensitiveMediaPreference.isChecked = it.alwaysShowSensitiveMedia
}
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
when(preference) {
when (preference) {
defaultPostPrivacyPreference -> {
preference.icon = getIconForVisibility(Status.Visibility.byString(newValue as String))
syncWithServer(visibility = newValue)
@ -125,7 +141,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
}
mediaPreviewEnabledPreference -> {
accountManager.activeAccount?.let {
it.mediaPreviewEnabled = newValue as Boolean
it.mediaPreviewEnabled = (newValue as String).toInt()
accountManager.saveAccount(it)
}
}
@ -144,7 +160,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
override fun onPreferenceClick(preference: Preference): Boolean {
when(preference) {
when (preference) {
notificationPreference -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent()
@ -189,13 +205,14 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
private fun syncWithServer(visibility: String? = null, sensitive: Boolean? = null) {
mastodonApi.accountUpdateSource(visibility, sensitive)
.enqueue(object: Callback<Account>{
.enqueue(object : Callback<Account> {
override fun onResponse(call: Call<Account>, response: Response<Account>) {
val account = response.body()
if(response.isSuccessful && account != null) {
if (response.isSuccessful && account != null) {
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
accountManager.saveAccount(it)
}
@ -214,9 +231,9 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
}
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)
.setAction(R.string.action_retry) { syncWithServer( visibility, sensitive)}
.setAction(R.string.action_retry) { syncWithServer(visibility, sensitive) }
.show()
}
}

View File

@ -61,6 +61,15 @@
<item>日本語</item>
</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">
<item>default</item>
<item>ca</item>

View File

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

View File

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