diff --git a/app/src/main/java/io/lbry/browser/MainActivity.java b/app/src/main/java/io/lbry/browser/MainActivity.java index 8af3048..6cd3e5b 100644 --- a/app/src/main/java/io/lbry/browser/MainActivity.java +++ b/app/src/main/java/io/lbry/browser/MainActivity.java @@ -823,7 +823,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener closeIcon.setVisibility(visible ? View.VISIBLE : View.GONE); } - private int getScaledValue(int value) { + public int getScaledValue(int value) { float scale = getResources().getDisplayMetrics().density; return (int) (value * scale + 0.5f); } diff --git a/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java index fa53df3..414c218 100644 --- a/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java +++ b/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.listener.SelectionModeListener; import io.lbry.browser.model.Claim; @@ -54,6 +55,7 @@ public class ClaimListAdapter extends RecyclerView.Adapter items, Context context) { this.context = context; @@ -63,6 +65,9 @@ public class ClaimListAdapter extends RecyclerView.Adapter(); notFoundClaimIdMap = new HashMap<>(); notFoundClaimUrlMap = new HashMap<>(); + if (context != null) { + scale = context.getResources().getDisplayMetrics().density; + } } public List getSelectedItems() { @@ -87,6 +92,10 @@ public class ClaimListAdapter extends RecyclerView.Adapter getItems() { + return new ArrayList<>(this.items); + } + public void clearItems() { clearSelectedItems(); this.items.clear(); @@ -122,6 +131,11 @@ public class ClaimListAdapter extends RecyclerView.Adapter claims) { + items.removeAll(claims); + notifyDataSetChanged(); + } + public void removeItem(Claim claim) { items.remove(claim); selectedItems.remove(claim); @@ -261,9 +275,18 @@ public class ClaimListAdapter extends RecyclerView.Adapter youtubeChannels; + private List youtubeChannels; private List deviceTypes; + + @Data + public static class YoutubeChannel { + String ytChannelName; + String lbryChannelName; + String channelClaimId; + String syncStatus; + String statusToken; + boolean transferable; + String transferState; + List publishToAddress; + String publicKey; + } } diff --git a/app/src/main/java/io/lbry/browser/tasks/claim/AbandonChannelTask.java b/app/src/main/java/io/lbry/browser/tasks/claim/AbandonChannelTask.java new file mode 100644 index 0000000..38d3803 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/claim/AbandonChannelTask.java @@ -0,0 +1,63 @@ +package io.lbry.browser.tasks.claim; + +import android.os.AsyncTask; +import android.view.View; + +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.lbry.browser.exceptions.ApiCallException; +import io.lbry.browser.tasks.GenericTaskHandler; +import io.lbry.browser.utils.Helper; +import io.lbry.browser.utils.Lbry; + +public class AbandonChannelTask extends AsyncTask { + private List claimIds; + private List successfulClaimIds; + private List failedClaimIds; + private List failedExceptions; + private View progressView; + private AbandonHandler handler; + + public AbandonChannelTask(List claimIds, View progressView, AbandonHandler handler) { + this.claimIds = claimIds; + this.progressView = progressView; + this.handler = handler; + } + + protected void onPreExecute() { + Helper.setViewVisibility(progressView, View.VISIBLE); + } + + public Boolean doInBackground(Void... params) { + successfulClaimIds = new ArrayList<>(); + failedClaimIds = new ArrayList<>(); + failedExceptions = new ArrayList<>(); + + for (String claimId : claimIds) { + try { + Map options = new HashMap<>(); + options.put("claim_id", claimId); + options.put("blocking", false); + JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_CHANNEL_ABANDON, options); + successfulClaimIds.add(claimId); + } catch (ApiCallException ex) { + failedClaimIds.add(claimId); + failedExceptions.add(ex); + } + } + + return true; + } + + protected void onPostExecute(Boolean result) { + Helper.setViewVisibility(progressView, View.GONE); + if (handler != null) { + handler.onComplete(successfulClaimIds, failedClaimIds, failedExceptions); + } + } +} diff --git a/app/src/main/java/io/lbry/browser/tasks/claim/AbandonHandler.java b/app/src/main/java/io/lbry/browser/tasks/claim/AbandonHandler.java new file mode 100644 index 0000000..706eaeb --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/claim/AbandonHandler.java @@ -0,0 +1,7 @@ +package io.lbry.browser.tasks.claim; + +import java.util.List; + +public interface AbandonHandler { + void onComplete(List successfulClaimIds, List failedClaimIds, List errors); +} diff --git a/app/src/main/java/io/lbry/browser/tasks/file/BulkDeleteFilesTask.java b/app/src/main/java/io/lbry/browser/tasks/file/BulkDeleteFilesTask.java new file mode 100644 index 0000000..b05ec9d --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/file/BulkDeleteFilesTask.java @@ -0,0 +1,32 @@ +package io.lbry.browser.tasks.file; + +import android.os.AsyncTask; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.lbry.browser.exceptions.ApiCallException; +import io.lbry.browser.tasks.GenericTaskHandler; +import io.lbry.browser.utils.Lbry; + +// Just run delete on the specified claim IDs (no need for a handler) +public class BulkDeleteFilesTask extends AsyncTask { + private List claimIds; + public BulkDeleteFilesTask(List claimIds) { + this.claimIds = claimIds; + } + protected Boolean doInBackground(Void... params) { + for (String claimId : claimIds) { + try { + Map options = new HashMap<>(); + options.put("claim_id", claimId); + options.put("delete_from_download_dir", true); + Lbry.genericApiCall(Lbry.METHOD_FILE_DELETE, options); + } catch (ApiCallException ex) { + // pass + } + } + return true; + } +} diff --git a/app/src/main/java/io/lbry/browser/tasks/file/DeleteFileTask.java b/app/src/main/java/io/lbry/browser/tasks/file/DeleteFileTask.java index ba587bb..bdc50bc 100644 --- a/app/src/main/java/io/lbry/browser/tasks/file/DeleteFileTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/file/DeleteFileTask.java @@ -26,6 +26,7 @@ public class DeleteFileTask extends AsyncTask { options.put("delete_from_download_dir", true); return (boolean) Lbry.genericApiCall(Lbry.METHOD_FILE_DELETE, options); } catch (ApiCallException ex) { + error = ex; return false; } } diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelManagerFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelManagerFragment.java index 62c1b38..4f2454e 100644 --- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelManagerFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelManagerFragment.java @@ -2,6 +2,7 @@ package io.lbry.browser.ui.channel; import android.content.Context; import android.content.DialogInterface; +import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.view.LayoutInflater; @@ -19,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; import java.util.HashMap; @@ -32,6 +34,8 @@ import io.lbry.browser.listener.SdkStatusListener; import io.lbry.browser.listener.SelectionModeListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.NavMenuItem; +import io.lbry.browser.tasks.claim.AbandonChannelTask; +import io.lbry.browser.tasks.claim.AbandonHandler; import io.lbry.browser.tasks.claim.ClaimListResultHandler; import io.lbry.browser.tasks.claim.ClaimListTask; import io.lbry.browser.ui.BaseFragment; @@ -144,7 +148,7 @@ public class ChannelManagerFragment extends BaseFragment implements ActionMode.C ClaimListTask task = new ClaimListTask(Claim.TYPE_CHANNEL, getLoading(), new ClaimListResultHandler() { @Override public void onSuccess(List claims) { - Lbry.ownChannels = new ArrayList<>(claims); + Lbry.ownChannels = Helper.filterDeletedClaims(new ArrayList<>(claims)); Context context = getContext(); if (adapter == null) { adapter = new ClaimListAdapter(claims, context); @@ -260,7 +264,7 @@ public class ChannelManagerFragment extends BaseFragment implements ActionMode.C .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - //handleDeleteSelectedClaims(selectedClaims); + handleDeleteSelectedClaims(selectedClaims); } }).setNegativeButton(R.string.no, null); builder.show(); @@ -270,4 +274,48 @@ public class ChannelManagerFragment extends BaseFragment implements ActionMode.C return false; } + + private void handleDeleteSelectedClaims(List selectedClaims) { + List claimIds = new ArrayList<>(); + + for (Claim claim : selectedClaims) { + claimIds.add(claim.getClaimId()); + } + + if (actionMode != null) { + actionMode.finish(); + } + + Helper.setViewVisibility(channelList, View.INVISIBLE); + Helper.setViewVisibility(fabNewChannel, View.INVISIBLE); + AbandonChannelTask task = new AbandonChannelTask(claimIds, bigLoading, new AbandonHandler() { + @Override + public void onComplete(List successfulClaimIds, List failedClaimIds, List errors) { + View root = getView(); + if (root != null) { + if (failedClaimIds.size() > 0) { + Snackbar.make(root, R.string.one_or_more_channels_failed_abandon, Snackbar.LENGTH_LONG). + setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show(); + } else if (successfulClaimIds.size() == claimIds.size()) { + try { + String message = getResources().getQuantityString(R.plurals.channels_deleted, successfulClaimIds.size()); + Snackbar.make(root, message, Snackbar.LENGTH_LONG).show(); + } catch (IllegalStateException ex) { + // pass + } + } + } + + Lbry.abandonedClaimIds.addAll(successfulClaimIds); + if (adapter != null) { + adapter.setItems(Helper.filterDeletedClaims(adapter.getItems())); + } + + Helper.setViewVisibility(channelList, View.VISIBLE); + Helper.setViewVisibility(fabNewChannel, View.VISIBLE); + checkNoChannels(); + } + }); + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } diff --git a/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java index a5aa660..9a00d2e 100644 --- a/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java @@ -237,6 +237,7 @@ public class FileViewFragment extends BaseFragment implements } resetViewCount(); + resetFee(); checkNewClaimAndUrl(newClaim, newUrl); if (newClaim != null) { @@ -364,6 +365,7 @@ public class FileViewFragment extends BaseFragment implements currentUrl = url; logUrlEvent(url); resetViewCount(); + resetFee(); View root = getView(); if (root != null) { ((RecyclerView) root.findViewById(R.id.file_view_related_content_list)).setAdapter(null); @@ -431,6 +433,7 @@ public class FileViewFragment extends BaseFragment implements public void openClaimUrl(String url) { resetViewCount(); + resetFee(); currentUrl = url; ClaimCacheKey key = new ClaimCacheKey(); @@ -508,6 +511,7 @@ public class FileViewFragment extends BaseFragment implements View root = getView(); if (root != null) { PlayerView view = root.findViewById(R.id.file_view_exoplayer_view); + view.setPlayer(null); view.setPlayer(MainActivity.appPlayer); } } @@ -896,6 +900,10 @@ public class FileViewFragment extends BaseFragment implements getView().findViewById(R.id.file_view_action_download).setVisibility(View.VISIBLE); getView().findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); actionDelete.setEnabled(true); + + claim.setFile(null); + Lbry.unsetFilesForCachedClaims(Arrays.asList(claim.getClaimId())); + restoreMainActionButton(); } @@ -1135,9 +1143,20 @@ public class FileViewFragment extends BaseFragment implements } private void resetViewCount() { - TextView textViewCount = getView().findViewById(R.id.file_view_view_count); - Helper.setViewText(textViewCount, null); - Helper.setViewVisibility(textViewCount, View.GONE); + View root = getView(); + if (root != null) { + TextView textViewCount = root.findViewById(R.id.file_view_view_count); + Helper.setViewText(textViewCount, null); + Helper.setViewVisibility(textViewCount, View.GONE); + } + } + private void resetFee() { + View root = getView(); + if (root != null) { + TextView feeView = root.findViewById(R.id.file_view_fee); + feeView.setText(null); + Helper.setViewVisibility(root.findViewById(R.id.file_view_fee_container), View.GONE); + } } private void loadViewCount() { diff --git a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java index 0bf8eb7..6b69ef1 100644 --- a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java @@ -1,10 +1,13 @@ package io.lbry.browser.ui.library; import android.content.Context; +import android.content.DialogInterface; import android.graphics.Typeface; import android.os.AsyncTask; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -12,16 +15,23 @@ import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.view.ActionMode; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.snackbar.Snackbar; + import org.json.JSONException; import org.json.JSONObject; +import java.nio.channels.AsynchronousChannel; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import io.lbry.browser.MainActivity; import io.lbry.browser.R; @@ -29,22 +39,31 @@ import io.lbry.browser.adapter.ClaimListAdapter; import io.lbry.browser.data.DatabaseHelper; import io.lbry.browser.listener.DownloadActionListener; import io.lbry.browser.listener.SdkStatusListener; +import io.lbry.browser.listener.SelectionModeListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.LbryFile; +import io.lbry.browser.model.NavMenuItem; import io.lbry.browser.model.ViewHistory; +import io.lbry.browser.tasks.claim.AbandonChannelTask; +import io.lbry.browser.tasks.claim.AbandonHandler; +import io.lbry.browser.tasks.file.BulkDeleteFilesTask; +import io.lbry.browser.tasks.file.DeleteFileTask; import io.lbry.browser.tasks.file.FileListTask; import io.lbry.browser.tasks.localdata.FetchViewHistoryTask; import io.lbry.browser.ui.BaseFragment; +import io.lbry.browser.ui.channel.ChannelFormFragment; import io.lbry.browser.utils.Helper; import io.lbry.browser.utils.Lbry; import io.lbry.browser.utils.LbryAnalytics; -public class LibraryFragment extends BaseFragment implements DownloadActionListener, SdkStatusListener { +public class LibraryFragment extends BaseFragment implements + ActionMode.Callback, DownloadActionListener, SelectionModeListener, SdkStatusListener { private static final int FILTER_DOWNLOADS = 1; private static final int FILTER_HISTORY = 2; private static final int PAGE_SIZE = 50; + private ActionMode actionMode; private int currentFilter; private List currentFiles; private View layoutSdkInitializing; @@ -244,6 +263,9 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe currentFilter = FILTER_HISTORY; linkFilterDownloads.setTypeface(null, Typeface.NORMAL); linkFilterHistory.setTypeface(null, Typeface.BOLD); + if (actionMode != null) { + actionMode.finish(); + } if (contentListAdapter != null) { contentListAdapter.clearItems(); contentListAdapter.setCanEnterSelectionMode(false); @@ -261,6 +283,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe private void initContentListAdapter(List claims) { contentListAdapter = new ClaimListAdapter(claims, getContext()); contentListAdapter.setCanEnterSelectionMode(true); + contentListAdapter.setSelectionModeListener(this); contentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() { @Override public void onClaimClicked(Claim claim) { @@ -459,4 +482,104 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe currentFilter == FILTER_HISTORY ? View.GONE : View.VISIBLE); } + + @Override + public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { + this.actionMode = actionMode; + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + if (!activity.isDarkMode()) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + } + + actionMode.getMenuInflater().inflate(R.menu.menu_claim_list, menu); + return true; + } + @Override + public void onDestroyActionMode(ActionMode actionMode) { + if (contentListAdapter != null) { + contentListAdapter.clearSelectedItems(); + contentListAdapter.setInSelectionMode(false); + contentListAdapter.notifyDataSetChanged(); + } + Context context = getContext(); + if (context != null) { + MainActivity activity = (MainActivity) context; + if (!activity.isDarkMode()) { + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + } + this.actionMode = null; + } + + @Override + public boolean onPrepareActionMode(androidx.appcompat.view.ActionMode actionMode, Menu menu) { + menu.findItem(R.id.action_edit).setVisible(false); + return true; + } + + @Override + public boolean onActionItemClicked(androidx.appcompat.view.ActionMode actionMode, MenuItem menuItem) { + if (R.id.action_delete == menuItem.getItemId()) { + if (contentListAdapter != null && contentListAdapter.getSelectedCount() > 0) { + final List selectedClaims = new ArrayList<>(contentListAdapter.getSelectedItems()); + String message = getResources().getQuantityString(R.plurals.confirm_delete_files, selectedClaims.size()); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()). + setTitle(R.string.delete_selection). + setMessage(message) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + handleDeleteSelectedClaims(selectedClaims); + } + }).setNegativeButton(R.string.no, null); + builder.show(); + return true; + } + } + + return false; + } + + private void handleDeleteSelectedClaims(List selectedClaims) { + List claimIds = new ArrayList<>(); + for (Claim claim : selectedClaims) { + claimIds.add(claim.getClaimId()); + } + + new BulkDeleteFilesTask(claimIds).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + Lbry.unsetFilesForCachedClaims(claimIds); + if (currentFilter == FILTER_DOWNLOADS) { + contentListAdapter.removeItems(selectedClaims); + } + if (actionMode != null) { + actionMode.finish(); + } + View root = getView(); + if (root != null) { + String message = getResources().getQuantityString(R.plurals.files_deleted, claimIds.size()); + Snackbar.make(root, message, Snackbar.LENGTH_LONG).show(); + } + } + + public void onEnterSelectionMode() { + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + activity.startSupportActionMode(this); + } + } + public void onItemSelectionToggled() { + if (actionMode != null) { + actionMode.setTitle(String.valueOf(contentListAdapter.getSelectedCount())); + actionMode.invalidate(); + } + } + public void onExitSelectionMode() { + if (actionMode != null) { + actionMode.finish(); + } + } } diff --git a/app/src/main/java/io/lbry/browser/utils/Helper.java b/app/src/main/java/io/lbry/browser/utils/Helper.java index 0a7140e..968a0e9 100644 --- a/app/src/main/java/io/lbry/browser/utils/Helper.java +++ b/app/src/main/java/io/lbry/browser/utils/Helper.java @@ -402,6 +402,15 @@ public final class Helper { } return followedTags; } + public static List filterDeletedClaims(List claims) { + List filtered = new ArrayList<>(); + for (Claim claim : claims) { + if (!Lbry.abandonedClaimIds.contains(claim.getClaimId())) { + filtered.add(claim); + } + } + return filtered; + } public static void setWunderbarValue(String value, Context context) { if (context instanceof MainActivity) { diff --git a/app/src/main/java/io/lbry/browser/utils/Lbry.java b/app/src/main/java/io/lbry/browser/utils/Lbry.java index 14ae413..b5397f7 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbry.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbry.java @@ -44,6 +44,7 @@ public final class Lbry { public static List followedTags = new ArrayList<>(); public static List ownClaims = new ArrayList<>(); public static List ownChannels = new ArrayList<>(); // Make this a subset of ownClaims? + public static List abandonedClaimIds = new ArrayList<>(); public static final int TTL_CLAIM_SEARCH_VALUE = 120000; // 2-minute TTL for cache public static final String SDK_CONNECTION_STRING = "http://127.0.0.1:5279"; @@ -97,6 +98,7 @@ public final class Lbry { public static boolean SDK_READY = false; public static void startupInit() { + abandonedClaimIds = new ArrayList<>(); ownChannels = new ArrayList<>(); ownClaims = new ArrayList<>(); knownTags = new ArrayList<>(); @@ -474,4 +476,14 @@ public final class Lbry { claimCache.put(shortUrlKey, claim); } } + + public static void unsetFilesForCachedClaims(List claimIds) { + for (String claimId : claimIds) { + ClaimCacheKey key = new ClaimCacheKey(); + key.setClaimId(claimId); + if (claimCache.containsKey(key)) { + claimCache.get(key).setFile(null); + } + } + } } 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 12fab55..2a180c1 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbryio.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbryio.java @@ -192,8 +192,9 @@ public final class Lbryio { Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); User user = gson.fromJson(object.toString(), type); return user; - } catch (LbryioRequestException | LbryioResponseException | ClassCastException ex) { - android.util.Log.e(TAG, "Cannot retrieve the current user", ex); + } catch (LbryioRequestException | LbryioResponseException | ClassCastException | IllegalStateException ex) { + LbryAnalytics.logException(String.format("/user/me failed: %s", ex.getMessage()), ex.getClass().getName()); + android.util.Log.e(TAG, "Could not retrieve the current user", ex); return null; } } diff --git a/app/src/main/res/layout/fragment_channel.xml b/app/src/main/res/layout/fragment_channel.xml index 3fd3504..bfac609 100644 --- a/app/src/main/res/layout/fragment_channel.xml +++ b/app/src/main/res/layout/fragment_channel.xml @@ -54,6 +54,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="12dp" + android:layout_marginRight="12dp" android:layout_above="@+id/channel_view_tabs" android:layout_toRightOf="@id/channel_view_icon_container" android:orientation="vertical"> @@ -66,7 +67,9 @@ android:paddingRight="4dp" android:paddingTop="2dp" android:paddingBottom="2dp" + android:ellipsize="end" android:fontFamily="@font/inter" + android:maxLines="2" android:textSize="20sp" android:textColor="@color/white" /> + android:layout_height="match_parent" /> + android:foreground="?attr/selectableItemBackground" + android:background="@drawable/bg_selected_list_item"> The claim is pending publish on the blockchain. You will be able to access or edit the claim in a few moments. Pending Create + One or moe channels could not be deleted at this time. Please try again later. A minimum deposit of %1$s credit is required. A minimum deposit of %1$s credits is required. @@ -331,6 +332,10 @@ Are you sure you want to delete the selected channel? Are you sure you want to delete the selected channels? + + The channel was successfully deleted. + The channels were successfully deleted. + LBRY credits allow you to publish or purchase content. @@ -388,6 +393,14 @@ KB GB 0MB + + Are you sure you want to remove the selected file from your device? + Are you sure you want to remove the selected files from your device? + + + The file was successfully deleted. + The files were successfully deleted. + About LBRY