diff --git a/app/src/main/java/io/lbry/browser/MainActivity.java b/app/src/main/java/io/lbry/browser/MainActivity.java index 2bd3538b..1129c0b7 100644 --- a/app/src/main/java/io/lbry/browser/MainActivity.java +++ b/app/src/main/java/io/lbry/browser/MainActivity.java @@ -11,6 +11,7 @@ import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ComponentName; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -36,6 +37,7 @@ import android.text.style.TypefaceSpan; import android.util.Base64; import android.util.Log; import android.view.KeyEvent; +import android.view.MenuItem; import android.view.View; import android.view.Menu; import android.view.WindowManager; @@ -75,7 +77,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.view.ActionMode; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; @@ -98,6 +102,7 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; @@ -142,6 +147,7 @@ import io.lbry.browser.listener.FilePickerListener; import io.lbry.browser.listener.PIPModeListener; import io.lbry.browser.listener.ScreenOrientationListener; import io.lbry.browser.listener.SdkStatusListener; +import io.lbry.browser.listener.SelectionModeListener; import io.lbry.browser.listener.StoragePermissionListener; import io.lbry.browser.listener.WalletBalanceListener; import io.lbry.browser.model.Claim; @@ -165,6 +171,7 @@ import io.lbry.browser.tasks.lbryinc.FetchRewardsTask; import io.lbry.browser.tasks.LighthouseAutoCompleteTask; import io.lbry.browser.tasks.MergeSubscriptionsTask; import io.lbry.browser.tasks.claim.ResolveTask; +import io.lbry.browser.tasks.lbryinc.NotificationDeleteTask; import io.lbry.browser.tasks.lbryinc.NotificationListTask; import io.lbry.browser.tasks.lbryinc.NotificationUpdateTask; import io.lbry.browser.tasks.localdata.FetchRecentUrlHistoryTask; @@ -209,7 +216,9 @@ import lombok.Setter; import lombok.SneakyThrows; import okhttp3.OkHttpClient; -public class MainActivity extends AppCompatActivity implements SdkStatusListener, SharedPreferences.OnSharedPreferenceChangeListener { +public class MainActivity extends AppCompatActivity implements SdkStatusListener, + SharedPreferences.OnSharedPreferenceChangeListener, + ActionMode.Callback, SelectionModeListener { private static final String CHANNEL_ID_PLAYBACK = "io.lbry.browser.LBRY_PLAYBACK_CHANNEL"; private static final int PLAYBACK_NOTIFICATION_ID = 3; private static final String SPECIAL_URL_PREFIX = "lbry://?"; @@ -244,6 +253,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener public static boolean startingPermissionRequest = false; public static boolean startingSignInFlowActivity = false; + private ActionMode actionMode; private BillingClient billingClient; @Getter private boolean enteringPIPMode = false; @@ -366,6 +376,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener private MediaSessionCompat mediaSession; private boolean receivedStopService; private ActionBarDrawerToggle toggle; + private SwipeRefreshLayout notificationsSwipeContainer; private SyncSetTask syncSetTask = null; private List pendingSyncSetQueue; @Getter @@ -581,6 +592,16 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } }); + notificationsSwipeContainer = findViewById(R.id.notifications_list_swipe_container); + notificationsSwipeContainer.setColorSchemeResources(R.color.nextLbryGreen); + notificationsSwipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + notificationsSwipeContainer.setRefreshing(true); + loadRemoteNotifications(false); + } + }); + findViewById(R.id.global_now_playing_card).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -1874,6 +1895,103 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } } + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + this.actionMode = mode; + if (isDarkMode()) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + + actionMode.getMenuInflater().inflate(R.menu.menu_notification, menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (R.id.action_delete == item.getItemId()) { + if (notificationListAdapter != null && notificationListAdapter.getSelectedCount() > 0) { + + final List selectedNotifications = new ArrayList<>(notificationListAdapter.getSelectedItems()); + String message = getResources().getQuantityString(R.plurals.confirm_delete_notifications, selectedNotifications.size()); + AlertDialog.Builder builder = new AlertDialog.Builder(this). + setTitle(R.string.delete_selection). + setMessage(message) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + handleDeleteSelectedNotifications(selectedNotifications); + } + }).setNegativeButton(R.string.no, null); + builder.show(); + return true; + } + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + if (notificationListAdapter != null) { + notificationListAdapter.clearSelectedItems(); + notificationListAdapter.setInSelectionMode(false); + notificationListAdapter.notifyDataSetChanged(); + } + if (isDarkMode()) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + this.actionMode = null; + } + + @Override + public void onEnterSelectionMode() { + startSupportActionMode(this); + } + + @Override + public void onExitSelectionMode() { + if (actionMode != null) { + actionMode.finish(); + } + } + + @Override + public void onItemSelectionToggled() { + if (actionMode != null) { + actionMode.setTitle(notificationListAdapter != null ? String.valueOf(notificationListAdapter.getSelectedCount()) : ""); + actionMode.invalidate(); + } + } + + private void handleDeleteSelectedNotifications(List notifications) { + List remoteIds = new ArrayList<>(); + for (LbryNotification notification : notifications) { + remoteIds.add(notification.getRemoteId()); + } + (new AsyncTask() { + protected Void doInBackground(Void... params) { + try { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + DatabaseHelper.deleteNotifications(notifications, db); + } catch (Exception ex) { + // pass + } + return null; + } + }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new NotificationDeleteTask(remoteIds).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if (notificationListAdapter != null) { + notificationListAdapter.removeNotifications(notifications); + } + if (actionMode != null) { + actionMode.finish(); + } + } + private class PlayerNotificationDescriptionAdapter implements PlayerNotificationManager.MediaDescriptionAdapter { @Override @@ -2713,12 +2831,11 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener JSONObject item = array.getJSONObject(i); String claimId = item.getString("claim_id"); String channelName = item.getString("channel_name"); - boolean isNotificationsDisabled = item.getBoolean("is_notifications_disabled"); LbryUri url = new LbryUri(); url.setChannelName(channelName); url.setClaimId(claimId); - subscriptions.add(new Subscription(channelName, url.toString(), isNotificationsDisabled)); + subscriptions.add(new Subscription(channelName, url.toString())); subUrls.add(url.toString()); } Lbryio.subscriptions = subscriptions; @@ -3391,6 +3508,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener if (markRead && findViewById(R.id.notifications_container).getVisibility() == View.VISIBLE) { markNotificationsRead(); } + + if (notificationsSwipeContainer != null) { + notificationsSwipeContainer.setRefreshing(false); + } } @Override @@ -3398,6 +3519,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener // pass Log.e(TAG, "error loading remote notifications", exception); loadLocalNotifications(); + if (notificationsSwipeContainer != null) { + notificationsSwipeContainer.setRefreshing(false); + } } }); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -3427,6 +3551,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener if (notificationListAdapter == null) { notificationListAdapter = new NotificationListAdapter(notifications, MainActivity.this); + notificationListAdapter.setSelectionModeListener(MainActivity.this); ((RecyclerView) findViewById(R.id.notifications_list)).setAdapter(notificationListAdapter); } else { notificationListAdapter.addNotifications(notifications); diff --git a/app/src/main/java/io/lbry/browser/adapter/NotificationListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/NotificationListAdapter.java index cfdba94c..3865eb5b 100644 --- a/app/src/main/java/io/lbry/browser/adapter/NotificationListAdapter.java +++ b/app/src/main/java/io/lbry/browser/adapter/NotificationListAdapter.java @@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; +import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; import java.util.Calendar; @@ -24,6 +25,7 @@ import java.util.List; import java.util.TimeZone; import io.lbry.browser.R; +import io.lbry.browser.listener.SelectionModeListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.lbryinc.LbryNotification; import io.lbry.browser.ui.controls.SolidIconView; @@ -43,15 +45,19 @@ public class NotificationListAdapter extends RecyclerView.Adapter items; + private List selectedItems; @Setter private NotificationClickListener clickListener; @Getter @Setter - private int customizeMode; + private boolean inSelectionMode; + @Setter + private SelectionModeListener selectionModeListener; public NotificationListAdapter(List notifications, Context context) { this.context = context; this.items = new ArrayList<>(notifications); + this.selectedItems = new ArrayList<>(); Collections.sort(items, Collections.reverseOrder(new LbryNotification())); } @@ -62,6 +68,7 @@ public class NotificationListAdapter extends RecyclerView.Adapter getSelectedItems() { + return this.selectedItems; + } + public int getSelectedCount() { + return selectedItems != null ? selectedItems.size() : 0; + } + public void clearSelectedItems() { + this.selectedItems.clear(); + } + public boolean isNotificationSelected(LbryNotification notification) { + return selectedItems.contains(notification); + } public void insertNotification(LbryNotification notification, int index) { if (!items.contains(notification)) { @@ -90,6 +110,12 @@ public class NotificationListAdapter extends RecyclerView.Adapter notifications) { + for (LbryNotification notification : notifications) { + items.remove(notification); + } + notifyDataSetChanged(); + } public List getAuthorUrls() { List urls = new ArrayList<>(); @@ -158,9 +184,8 @@ public class NotificationListAdapter extends RecyclerView.Adapter notifications, SQLiteDatabase db) { + StringBuilder sb = new StringBuilder("DELETE FROM notifications WHERE remote_id IN ("); + List remoteIds = new ArrayList<>(); + String delim = ""; + for (int i = 0; i < notifications.size(); i++) { + remoteIds.add(String.valueOf(notifications.get(i).getRemoteId())); + sb.append(delim).append("?"); + delim = ","; + } + sb.append(")"); + + String sql = sb.toString(); + db.execSQL(sql, remoteIds.toArray()); + } public static int getUnreadNotificationsCount(SQLiteDatabase db) { int count = 0; Cursor cursor = null; diff --git a/app/src/main/java/io/lbry/browser/model/lbryinc/Subscription.java b/app/src/main/java/io/lbry/browser/model/lbryinc/Subscription.java index 6d302e52..30f2412a 100644 --- a/app/src/main/java/io/lbry/browser/model/lbryinc/Subscription.java +++ b/app/src/main/java/io/lbry/browser/model/lbryinc/Subscription.java @@ -11,21 +11,17 @@ public class Subscription { @Getter @Setter private String url; - @Getter - @Setter - private boolean isNotificationsDisabled; public Subscription() { } - public Subscription(String channelName, String url, boolean isNotificationsDisabled) { + public Subscription(String channelName, String url) { this.channelName = channelName; this.url = url; - this.isNotificationsDisabled = isNotificationsDisabled; } public static Subscription fromClaim(Claim claim) { - return new Subscription(claim.getName(), claim.getPermanentUrl(), false); + return new Subscription(claim.getName(), claim.getPermanentUrl()); } public String toString() { return url; diff --git a/app/src/main/java/io/lbry/browser/tasks/MergeSubscriptionsTask.java b/app/src/main/java/io/lbry/browser/tasks/MergeSubscriptionsTask.java index 842c381e..2d516e13 100644 --- a/app/src/main/java/io/lbry/browser/tasks/MergeSubscriptionsTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/MergeSubscriptionsTask.java @@ -76,15 +76,13 @@ public class MergeSubscriptionsTask extends AsyncTask { options.put("claim_id", channelClaimId); if (!isUnsubscribing) { options.put("channel_name", subscription.getChannelName()); - options.put("notifications_disabled", String.valueOf(subscription.isNotificationsDisabled()).toLowerCase()); } String action = isUnsubscribing ? "delete" : "new"; - Object response = Lbryio.parseResponse(Lbryio.call("subscription", action, options, context)); + Lbryio.call("subscription", action, options, context); + if (!isUnsubscribing) { Lbryio.addSubscription(subscription); } else { diff --git a/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchSubscriptionsTask.java b/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchSubscriptionsTask.java index e3c2a1f8..da886beb 100644 --- a/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchSubscriptionsTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchSubscriptionsTask.java @@ -49,12 +49,11 @@ public class FetchSubscriptionsTask extends AsyncTask { + private List ids; + + public NotificationDeleteTask(List ids) { + this.ids = ids; + } + + protected Boolean doInBackground(Void... params) { + Map options = new HashMap<>(); + options.put("notification_ids", Helper.joinL(ids, ",")); + + try { + Object result = Lbryio.parseResponse(Lbryio.call("notification", "delete", options, null)); + return "ok".equalsIgnoreCase(result.toString()); + } catch (LbryioResponseException | LbryioRequestException ex) { + // pass + } + return false; + } +} diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java index 722b84c9..9149e0c4 100644 --- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java @@ -80,8 +80,6 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen private View buttonShare; private View buttonTip; private View buttonFollowUnfollow; - private View buttonBell; - private SolidIconView iconBell; private int subCount; private OutlineIconView iconFollow; private SolidIconView iconUnfollow; @@ -114,8 +112,6 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen buttonFollowUnfollow = root.findViewById(R.id.channel_view_follow_unfollow); iconFollow = root.findViewById(R.id.channel_view_icon_follow); iconUnfollow = root.findViewById(R.id.channel_view_icon_unfollow); - buttonBell = root.findViewById(R.id.channel_view_subscribe_notify); - iconBell = root.findViewById(R.id.channel_view_icon_bell); tabPager = root.findViewById(R.id.channel_view_pager); tabLayout = root.findViewById(R.id.channel_view_tabs); @@ -206,39 +202,6 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen } }); - buttonBell.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (claim != null) { - boolean isNotificationsDisabled = Lbryio.isNotificationsDisabled(claim); - final Subscription subscription = Subscription.fromClaim(claim); - subscription.setNotificationsDisabled(!isNotificationsDisabled); - view.setEnabled(false); - Context context = getContext(); - new ChannelSubscribeTask(context, claim.getClaimId(), subscription, false, new ChannelSubscribeTask.ChannelSubscribeHandler() { - @Override - public void onSuccess() { - view.setEnabled(true); - Lbryio.updateSubscriptionNotificationsDisabled(subscription); - - Context context = getContext(); - if (context instanceof MainActivity) { - ((MainActivity) context).showMessage(subscription.isNotificationsDisabled() ? - R.string.receive_no_notifications : R.string.receive_all_notifications); - } - - checkIsFollowing(); - } - - @Override - public void onError(Exception exception) { - view.setEnabled(true); - } - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - } - }); - buttonFollowUnfollow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -250,7 +213,7 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen subscribing = true; boolean isFollowing = Lbryio.isFollowing(claim); Subscription subscription = Subscription.fromClaim(claim); - view.setEnabled(false); + buttonFollowUnfollow.setEnabled(false); new ChannelSubscribeTask(getContext(), claim.getClaimId(), subscription, isFollowing, new ChannelSubscribeTask.ChannelSubscribeHandler() { @Override public void onSuccess() { @@ -317,14 +280,8 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen private void checkIsFollowing() { if (claim != null) { boolean isFollowing = Lbryio.isFollowing(claim); - boolean notificationsDisabled = Lbryio.isNotificationsDisabled(claim); Helper.setViewVisibility(iconFollow, !isFollowing ? View.VISIBLE : View.GONE); Helper.setViewVisibility(iconUnfollow, isFollowing ? View.VISIBLE : View.GONE); - Helper.setViewVisibility(buttonBell, isFollowing ? View.VISIBLE : View.GONE); - - if (iconBell != null) { - iconBell.setText(notificationsDisabled ? R.string.fa_bell : R.string.fa_bell_slash); - } } } diff --git a/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java b/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java index b53e5833..de9ce019 100644 --- a/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/findcontent/FileViewFragment.java @@ -785,38 +785,6 @@ public class FileViewFragment extends BaseFragment implements } } - private View.OnClickListener bellIconListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - if (claim != null && claim.getSigningChannel() != null) { - Claim publisher = claim.getSigningChannel(); - boolean isNotificationsDisabled = Lbryio.isNotificationsDisabled(publisher); - final Subscription subscription = Subscription.fromClaim(publisher); - subscription.setNotificationsDisabled(!isNotificationsDisabled); - view.setEnabled(false); - Context context = getContext(); - new ChannelSubscribeTask(context, publisher.getClaimId(), subscription, false, new ChannelSubscribeTask.ChannelSubscribeHandler() { - @Override - public void onSuccess() { - view.setEnabled(true); - Lbryio.updateSubscriptionNotificationsDisabled(subscription); - Context context = getContext(); - if (context instanceof MainActivity) { - ((MainActivity) context).showMessage(subscription.isNotificationsDisabled() ? - R.string.receive_no_notifications : R.string.receive_all_notifications); - } - checkIsFollowing(); - } - - @Override - public void onError(Exception exception) { - view.setEnabled(true); - } - }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - } - }; - private View.OnClickListener followUnfollowListener = new View.OnClickListener() { @Override public void onClick(View view) { @@ -1202,10 +1170,8 @@ public class FileViewFragment extends BaseFragment implements View buttonFollow = root.findViewById(R.id.file_view_icon_follow); View buttonUnfollow = root.findViewById(R.id.file_view_icon_unfollow); - View buttonBell = root.findViewById(R.id.file_view_icon_bell); buttonFollow.setOnClickListener(followUnfollowListener); buttonUnfollow.setOnClickListener(followUnfollowListener); - buttonBell.setOnClickListener(bellIconListener); commentChannelSpinnerAdapter = new InlineChannelSpinnerAdapter(getContext(), R.layout.spinner_item_channel, new ArrayList<>()); commentChannelSpinnerAdapter.addPlaceholder(false); @@ -2558,18 +2524,13 @@ public class FileViewFragment extends BaseFragment implements private void checkIsFollowing() { if (claim != null && claim.getSigningChannel() != null) { boolean isFollowing = Lbryio.isFollowing(claim.getSigningChannel()); - boolean notificationsDisabled = Lbryio.isNotificationsDisabled(claim.getSigningChannel()); Context context = getContext(); View root = getView(); if (context != null && root != null) { OutlineIconView iconFollow = root.findViewById(R.id.file_view_icon_follow); SolidIconView iconUnfollow = root.findViewById(R.id.file_view_icon_unfollow); - SolidIconView iconBell = root.findViewById(R.id.file_view_icon_bell); - Helper.setViewVisibility(iconFollow, !isFollowing ? View.VISIBLE: View.GONE); - Helper.setViewVisibility(iconUnfollow, isFollowing ? View.VISIBLE : View.GONE); - Helper.setViewVisibility(iconBell, isFollowing ? View.VISIBLE : View.GONE); - - iconBell.setText(notificationsDisabled ? R.string.fa_bell : R.string.fa_bell_slash); + Helper.setViewVisibility(iconFollow, !isFollowing ? View.VISIBLE: View.INVISIBLE); + Helper.setViewVisibility(iconUnfollow, isFollowing ? View.VISIBLE : View.INVISIBLE); } } } diff --git a/app/src/main/java/io/lbry/browser/utils/Lbryio.java b/app/src/main/java/io/lbry/browser/utils/Lbryio.java index 51f99eb4..796ac65d 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbryio.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbryio.java @@ -333,15 +333,6 @@ public final class Lbryio { } } - public static void updateSubscriptionNotificationsDisabled(Subscription subscription) { - synchronized (lock) { - int index = subscriptions.indexOf(subscription); - if (index > -1) { - subscriptions.get(index).setNotificationsDisabled(subscription.isNotificationsDisabled()); - } - } - } - public static void addSubscription(Subscription subscription) { synchronized (lock) { if (!subscriptions.contains(subscription)) { @@ -373,15 +364,6 @@ public final class Lbryio { public static boolean isFollowing(Claim claim) { return subscriptions.contains(Subscription.fromClaim(claim)); } - public static boolean isNotificationsDisabled(Claim claim) { - Subscription sub = Subscription.fromClaim(claim); - int index = subscriptions.indexOf(sub); - if (index > -1) { - Subscription actual = subscriptions.get(subscriptions.indexOf(sub)); - return actual.isNotificationsDisabled(); - } - return false; - } public static void updateRewardsLists(List rewards) { synchronized (lock) { diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index ed30a9f0..0edffd26 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -71,13 +71,18 @@ android:textSize="16sp" android:textAlignment="center" /> - + android:layout_height="match_parent"> + + diff --git a/app/src/main/res/layout/fragment_channel.xml b/app/src/main/res/layout/fragment_channel.xml index 84797cb4..9cd5b5a1 100644 --- a/app/src/main/res/layout/fragment_channel.xml +++ b/app/src/main/res/layout/fragment_channel.xml @@ -224,27 +224,9 @@ android:layout_width="24dp" android:layout_height="24dp" android:text="@string/fa_heart_broken" - android:textColor="@color/foreground" android:textSize="20dp" android:visibility="invisible"/> - - - diff --git a/app/src/main/res/layout/fragment_file_view.xml b/app/src/main/res/layout/fragment_file_view.xml index d62cbbfc..97fa2df9 100644 --- a/app/src/main/res/layout/fragment_file_view.xml +++ b/app/src/main/res/layout/fragment_file_view.xml @@ -503,6 +503,7 @@ android:id="@+id/file_view_publisher_area" android:layout_width="match_parent" android:layout_height="wrap_content"> + + android:layout_toStartOf="@id/file_view_icon_follow"> - - + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:text="@string/fa_heart" + android:textColor="@color/red" + android:textSize="20dp" /> - - - - + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f9bccf2d..e9a83772 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -117,8 +117,6 @@ Content Website reposted - You will receive all notifications - You will not receive notifications for this channel %1$s follower %1$s followers @@ -384,7 +382,6 @@ Channel to show support as Make this a tip Send Revocable Support - Tip %1$s Tip %1$s Credit Tip %1$s Credits @@ -631,6 +628,10 @@ It\'s quiet here! New notifications will be displayed when you receive them. + + Are you sure you want to remove the selected notification? + Are you sure you want to remove the selected notifications? + @@ -660,7 +661,4 @@ - - -