Tab customization & direct messages tab (#1012)
* custom tabs * custom tabs interface * implement custom tab functionality * add database migration * fix bugs, improve ThemeUtils nullability handling * implement conversationsfragment * setup ConversationViewHolder * implement favs * add button functionality * revert 10.json * revert item_status_notification.xml * implement more menu, replying, fix stuff, clean up * fix tests * fix bug with expanding statuses * min and max number of tabs * settings support, fix bugs * database migration * fix scrolling to top after refresh * fix bugs * fix warning in item_conversation
This commit is contained in:
parent
adf573646e
commit
e371fa0e24
75 changed files with 3663 additions and 296 deletions
|
@ -72,10 +72,10 @@ class AccountListFragment : BaseFragment(), AccountActionListener, Injectable {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
recyclerView.setHasFixedSize(true)
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
val layoutManager = LinearLayoutManager(view.context)
|
||||
recyclerView.layoutManager = layoutManager
|
||||
val divider = DividerItemDecoration(context, layoutManager.orientation)
|
||||
val drawable = ThemeUtils.getDrawable(context, R.attr.status_divider_drawable, R.drawable.status_divider_dark)
|
||||
val divider = DividerItemDecoration(view.context, layoutManager.orientation)
|
||||
val drawable = ThemeUtils.getDrawable(view.context, R.attr.status_divider_drawable, R.drawable.status_divider_dark)
|
||||
divider.setDrawable(drawable)
|
||||
recyclerView.addItemDecoration(divider)
|
||||
|
||||
|
|
|
@ -81,9 +81,10 @@ class AccountMediaFragment : BaseFragment(), Injectable {
|
|||
private val callback = object : Callback<List<Status>> {
|
||||
override fun onFailure(call: Call<List<Status>>?, t: Throwable?) {
|
||||
fetchingStatus = FetchingStatus.NOT_FETCHING
|
||||
if (isAdded) {
|
||||
swipe_refresh_layout.isRefreshing = false
|
||||
progress_bar.visibility = View.GONE
|
||||
|
||||
if(isAdded) {
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
progressBar.visibility = View.GONE
|
||||
statusView.show()
|
||||
if (t is IOException) {
|
||||
statusView.setup(R.drawable.elephant_offline, R.string.error_network) {
|
||||
|
@ -101,9 +102,9 @@ class AccountMediaFragment : BaseFragment(), Injectable {
|
|||
|
||||
override fun onResponse(call: Call<List<Status>>, response: Response<List<Status>>) {
|
||||
fetchingStatus = FetchingStatus.NOT_FETCHING
|
||||
if (isAdded) {
|
||||
swipe_refresh_layout.isRefreshing = false
|
||||
progress_bar.visibility = View.GONE
|
||||
if(isAdded) {
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
progressBar.visibility = View.GONE
|
||||
|
||||
val body = response.body()
|
||||
body?.let { fetched ->
|
||||
|
@ -114,6 +115,7 @@ class AccountMediaFragment : BaseFragment(), Injectable {
|
|||
result.addAll(AttachmentViewData.list(status))
|
||||
}
|
||||
adapter.addTop(result)
|
||||
|
||||
if (statuses.isEmpty()) {
|
||||
statusView.show()
|
||||
statusView.setup(R.drawable.elephant_friend_empty, R.string.message_empty,
|
||||
|
@ -159,19 +161,19 @@ class AccountMediaFragment : BaseFragment(), Injectable {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
||||
val columnCount = context?.resources?.getInteger(R.integer.profile_media_column_count) ?: 2
|
||||
val layoutManager = GridLayoutManager(context, columnCount)
|
||||
val columnCount = view.context.resources.getInteger(R.integer.profile_media_column_count)
|
||||
val layoutManager = GridLayoutManager(view.context, columnCount)
|
||||
|
||||
val bgRes = ThemeUtils.getColorId(context, R.attr.window_background)
|
||||
val bgRes = ThemeUtils.getColorId(view.context, R.attr.window_background)
|
||||
|
||||
adapter.baseItemColor = ContextCompat.getColor(recycler_view.context, bgRes)
|
||||
adapter.baseItemColor = ContextCompat.getColor(recyclerView.context, bgRes)
|
||||
|
||||
recycler_view.layoutManager = layoutManager
|
||||
recycler_view.adapter = adapter
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
val accountId = arguments?.getString(ACCOUNT_ID_ARG)
|
||||
|
||||
swipe_refresh_layout.setOnRefreshListener {
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
statusView.hide()
|
||||
if (fetchingStatus != FetchingStatus.NOT_FETCHING) return@setOnRefreshListener
|
||||
currentCall = if (statuses.isEmpty()) {
|
||||
|
@ -184,12 +186,12 @@ class AccountMediaFragment : BaseFragment(), Injectable {
|
|||
currentCall?.enqueue(callback)
|
||||
|
||||
}
|
||||
swipe_refresh_layout.setColorSchemeResources(R.color.tusky_blue)
|
||||
swipe_refresh_layout.setProgressBackgroundColorSchemeColor(ThemeUtils.getColor(context, android.R.attr.colorBackground))
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ThemeUtils.getColor(view.context, android.R.attr.colorBackground))
|
||||
|
||||
statusView.visibility = View.GONE
|
||||
|
||||
recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
|
||||
override fun onScrolled(recycler_view: RecyclerView, dx: Int, dy: Int) {
|
||||
if (dy > 0) {
|
||||
|
|
|
@ -176,9 +176,9 @@ public class NotificationsFragment extends SFragment implements
|
|||
|
||||
@NonNull Context context = inflater.getContext(); // from inflater to silence warning
|
||||
// Setup the SwipeRefreshLayout.
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh_layout);
|
||||
recyclerView = rootView.findViewById(R.id.recycler_view);
|
||||
progressBar = rootView.findViewById(R.id.progress_bar);
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
|
||||
recyclerView = rootView.findViewById(R.id.recyclerView);
|
||||
progressBar = rootView.findViewById(R.id.progressBar);
|
||||
statusView = rootView.findViewById(R.id.statusView);
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
@ -417,13 +417,13 @@ public class NotificationsFragment extends SFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMore(View view, int position) {
|
||||
public void onMore(@NonNull View view, int position) {
|
||||
Notification notification = notifications.get(position).asRight();
|
||||
super.more(notification.getStatus(), view, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewMedia(int position, int attachmentIndex, View view) {
|
||||
public void onViewMedia(int position, int attachmentIndex, @NonNull View view) {
|
||||
Notification notification = notifications.get(position).asRightOrNull();
|
||||
if (notification == null || notification.getStatus() == null) return;
|
||||
super.viewMedia(attachmentIndex, notification.getStatus(), view);
|
||||
|
|
|
@ -98,7 +98,7 @@ public abstract class SFragment extends BaseFragment {
|
|||
}
|
||||
|
||||
protected void viewThread(Status status) {
|
||||
bottomSheetActivity.viewThread(status);
|
||||
bottomSheetActivity.viewThread(status.getActionableId(), status.getUrl());
|
||||
}
|
||||
|
||||
protected void viewAccount(String accountId) {
|
||||
|
|
|
@ -182,14 +182,14 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onMore(view: View?, position: Int) {
|
||||
override fun onMore(view: View, position: Int) {
|
||||
val status = searchAdapter.getStatusAtPosition(position)
|
||||
if (status != null) {
|
||||
more(status, view, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) {
|
||||
override fun onViewMedia(position: Int, attachmentIndex: Int, view: View) {
|
||||
val status = searchAdapter.getStatusAtPosition(position) ?: return
|
||||
viewMedia(attachmentIndex, status, view)
|
||||
}
|
||||
|
|
|
@ -219,9 +219,9 @@ public class TimelineFragment extends SFragment implements
|
|||
Bundle savedInstanceState) {
|
||||
final View rootView = inflater.inflate(R.layout.fragment_timeline, container, false);
|
||||
|
||||
recyclerView = rootView.findViewById(R.id.recycler_view);
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh_layout);
|
||||
progressBar = rootView.findViewById(R.id.progress_bar);
|
||||
recyclerView = rootView.findViewById(R.id.recyclerView);
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
|
||||
progressBar = rootView.findViewById(R.id.progressBar);
|
||||
statusView = rootView.findViewById(R.id.statusView);
|
||||
|
||||
setupSwipeRefreshLayout();
|
||||
|
@ -608,7 +608,7 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMore(View view, final int position) {
|
||||
public void onMore(@NonNull View view, final int position) {
|
||||
super.more(statuses.get(position).asRight(), view, position);
|
||||
}
|
||||
|
||||
|
@ -689,7 +689,7 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onViewMedia(int position, int attachmentIndex, View view) {
|
||||
public void onViewMedia(int position, int attachmentIndex, @NonNull View view) {
|
||||
Status status = statuses.get(position).asRightOrNull();
|
||||
if (status == null) return;
|
||||
super.viewMedia(attachmentIndex, status, view);
|
||||
|
|
|
@ -137,13 +137,13 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
View rootView = inflater.inflate(R.layout.fragment_view_thread, container, false);
|
||||
|
||||
Context context = getContext();
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipe_refresh_layout);
|
||||
swipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue);
|
||||
swipeRefreshLayout.setProgressBackgroundColorSchemeColor(
|
||||
ThemeUtils.getColor(context, android.R.attr.colorBackground));
|
||||
|
||||
recyclerView = rootView.findViewById(R.id.recycler_view);
|
||||
recyclerView = rootView.findViewById(R.id.recyclerView);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
@ -284,12 +284,12 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMore(View view, int position) {
|
||||
public void onMore(@NonNull View view, int position) {
|
||||
super.more(statuses.get(position), view, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewMedia(int position, int attachmentIndex, View view) {
|
||||
public void onViewMedia(int position, int attachmentIndex, @NonNull View view) {
|
||||
Status status = statuses.get(position);
|
||||
super.viewMedia(attachmentIndex, status, view);
|
||||
}
|
||||
|
|
|
@ -26,10 +26,7 @@ import androidx.preference.Preference
|
|||
import androidx.preference.PreferenceFragmentCompat
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import com.keylesspalace.tusky.AccountListActivity
|
||||
import com.keylesspalace.tusky.BuildConfig
|
||||
import com.keylesspalace.tusky.PreferencesActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.*
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
|
||||
import com.keylesspalace.tusky.db.AccountManager
|
||||
|
@ -60,6 +57,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
lateinit var eventHub: EventHub
|
||||
|
||||
private lateinit var notificationPreference: Preference
|
||||
private lateinit var tabPreference: Preference
|
||||
private lateinit var mutedUsersPreference: Preference
|
||||
private lateinit var blockedUsersPreference: Preference
|
||||
|
||||
|
@ -74,6 +72,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
addPreferencesFromResource(R.xml.account_preferences)
|
||||
|
||||
notificationPreference = findPreference("notificationPreference")
|
||||
tabPreference = findPreference("tabPreference")
|
||||
mutedUsersPreference = findPreference("mutedUsersPreference")
|
||||
blockedUsersPreference = findPreference("blockedUsersPreference")
|
||||
defaultPostPrivacyPreference = findPreference("defaultPostPrivacy") as ListPreference
|
||||
|
@ -81,11 +80,12 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
mediaPreviewEnabledPreference = findPreference("mediaPreviewEnabled") as SwitchPreference
|
||||
alwaysShowSensitiveMediaPreference = findPreference("alwaysShowSensitiveMedia") as SwitchPreference
|
||||
|
||||
notificationPreference.icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_notifications).sizePx(iconSize).color(ThemeUtils.getColor(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))
|
||||
mutedUsersPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
|
||||
blockedUsersPreference.icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_block).sizePx(iconSize).color(ThemeUtils.getColor(context, R.attr.toolbar_icon_tint))
|
||||
blockedUsersPreference.icon = IconicsDrawable(blockedUsersPreference.context, GoogleMaterial.Icon.gmd_block).sizePx(iconSize).color(ThemeUtils.getColor(blockedUsersPreference.context, R.attr.toolbar_icon_tint))
|
||||
|
||||
notificationPreference.onPreferenceClickListener = this
|
||||
tabPreference.onPreferenceClickListener = this
|
||||
mutedUsersPreference.onPreferenceClickListener = this
|
||||
blockedUsersPreference.onPreferenceClickListener = this
|
||||
|
||||
|
@ -161,6 +161,12 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
|
|||
}
|
||||
return true
|
||||
}
|
||||
tabPreference -> {
|
||||
val intent = Intent(context, TabPreferenceActivity::class.java)
|
||||
activity?.startActivity(intent)
|
||||
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
|
||||
return true
|
||||
}
|
||||
mutedUsersPreference -> {
|
||||
val intent = Intent(context, AccountListActivity::class.java)
|
||||
intent.putExtra("type", AccountListActivity.Type.MUTES)
|
||||
|
|
|
@ -34,13 +34,13 @@ class PreferencesFragment : PreferenceFragmentCompat() {
|
|||
addPreferencesFromResource(R.xml.preferences)
|
||||
|
||||
val themePreference: Preference = findPreference("appTheme")
|
||||
themePreference.icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_palette).sizePx(iconSize).color(ThemeUtils.getColor(context, R.attr.toolbar_icon_tint))
|
||||
themePreference.icon = IconicsDrawable(themePreference.context, GoogleMaterial.Icon.gmd_palette).sizePx(iconSize).color(ThemeUtils.getColor(themePreference.context, R.attr.toolbar_icon_tint))
|
||||
|
||||
val emojiPreference: Preference = findPreference("emojiCompat")
|
||||
emojiPreference.icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_sentiment_satisfied).sizePx(iconSize).color(ThemeUtils.getColor(context, R.attr.toolbar_icon_tint))
|
||||
emojiPreference.icon = IconicsDrawable(emojiPreference.context, GoogleMaterial.Icon.gmd_sentiment_satisfied).sizePx(iconSize).color(ThemeUtils.getColor(emojiPreference.context, R.attr.toolbar_icon_tint))
|
||||
|
||||
val textSizePreference: Preference = findPreference("statusTextSize")
|
||||
textSizePreference.icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_format_size).sizePx(iconSize).color(ThemeUtils.getColor(context, R.attr.toolbar_icon_tint))
|
||||
textSizePreference.icon = IconicsDrawable(textSizePreference.context, GoogleMaterial.Icon.gmd_format_size).sizePx(iconSize).color(ThemeUtils.getColor(textSizePreference.context, R.attr.toolbar_icon_tint))
|
||||
|
||||
val timelineFilterPreferences: Preference = findPreference("timelineFilterPreferences")
|
||||
timelineFilterPreferences.setOnPreferenceClickListener {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue