Native rewrite #878

Merged
akinwale merged 65 commits from native-rewrite into master 2020-05-23 08:49:00 +02:00
41 changed files with 2969 additions and 222 deletions
Showing only changes of commit dc758491a9 - Show all commits

View file

@ -29,6 +29,7 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Menu;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@ -59,6 +60,9 @@ import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.GravityCompat;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@ -95,7 +99,6 @@ import io.lbry.browser.data.DatabaseHelper;
import io.lbry.browser.dialog.ContentScopeDialogFragment;
import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.listener.CameraPermissionListener;
import io.lbry.browser.listener.DarkThemeChangeListener;
import io.lbry.browser.listener.DownloadActionListener;
import io.lbry.browser.listener.FetchChannelsListener;
import io.lbry.browser.listener.SdkStatusListener;
@ -133,6 +136,7 @@ import io.lbry.browser.ui.following.FileViewFragment;
import io.lbry.browser.ui.following.FollowingFragment;
import io.lbry.browser.ui.library.LibraryFragment;
import io.lbry.browser.ui.other.AboutFragment;
import io.lbry.browser.ui.publish.PublishFormFragment;
import io.lbry.browser.ui.publish.PublishFragment;
import io.lbry.browser.ui.publish.PublishesFragment;
import io.lbry.browser.ui.search.SearchFragment;
@ -164,6 +168,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
public static CastContext castContext;
public static CastPlayer castPlayer;
public static Claim nowPlayingClaim;
public static String nowPlayingClaimUrl;
public static boolean startingFilePickerActivity = false;
public static boolean startingShareActivity = false;
public static boolean startingPermissionRequest = false;
@ -340,6 +345,24 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.content_main), new OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
ViewCompat.onApplyWindowInsets(findViewById(R.id.url_suggestions_container),
insets.replaceSystemWindowInsets(0, 0, 0, insets.getSystemWindowInsetBottom()));
return ViewCompat.onApplyWindowInsets(v,
insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
0, insets.getSystemWindowInsetBottom()));
}
});
/*ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.url_suggestions_container), new OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
return ViewCompat.onApplyWindowInsets(v,
insets.replaceSystemWindowInsets(0, 0,0, insets.getSystemWindowInsetBottom()));
}
});*/
// register receivers
registerRequestsReceiver();
registerServiceActionsReceiver();
@ -350,10 +373,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// not fullscreen
View appBarMainContainer = findViewById(R.id.app_bar_main_container);
appBarMainContainer.setPadding(
appBarMainContainer.getPaddingLeft(), appBarMainContainer.getPaddingTop(), appBarMainContainer.getPaddingRight(), 0);
appBarMainContainer.setFitsSystemWindows(true);
}
}
});
@ -434,8 +453,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
findViewById(R.id.global_now_playing_card).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (nowPlayingClaim != null) {
openFileUrl(!Helper.isNullOrEmpty(nowPlayingClaim.getShortUrl()) ? nowPlayingClaim.getShortUrl() : nowPlayingClaim.getPermanentUrl());
if (nowPlayingClaim != null && !Helper.isNullOrEmpty(nowPlayingClaimUrl)) {
openFileUrl(nowPlayingClaimUrl);
}
}
});
@ -622,6 +641,14 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
openFragment(ChannelFormFragment.class, true, NavMenuItem.ID_ITEM_CHANNELS, params);
}
public void openPublishForm(Claim claim) {
Map<String, Object> params = new HashMap<>();
if (claim != null) {
params.put("claim", claim);
}
openFragment(PublishFormFragment.class, true, NavMenuItem.ID_ITEM_NEW_PUBLISH, params);
}
public void openChannelUrl(String url) {
Map<String, Object> params = new HashMap<>();
params.put("url", url);
@ -722,6 +749,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
dbHelper.close();
}
stopExoplayer();
nowPlayingClaim = null;
nowPlayingClaimUrl = null;
super.onDestroy();
}
@ -1229,9 +1258,11 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
}
public void exitFullScreenMode() {
View appBarMainContainer = findViewById(R.id.app_bar_main_container);
View decorView = getWindow().getDecorView();
int flags = isDarkMode() ? (View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE) :
(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE);
appBarMainContainer.setFitsSystemWindows(true);
decorView.setSystemUiVisibility(flags);
if (!Lbry.SDK_READY) {
@ -1262,7 +1293,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
} else if (!appStarted) {
// first run completed, startup
startup();
} else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
return;
}
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
openFragment(FollowingFragment.class, false, NavMenuItem.ID_ITEM_FOLLOWING);
fetchRewards();
}
@ -1707,16 +1741,22 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
} else {
boolean handled = false;
ChannelFormFragment channelFormFragment = null;
PublishFormFragment publishFormFragment = null;
for (Fragment fragment : openNavFragments.values()) {
if (fragment instanceof ChannelFormFragment) {
channelFormFragment = ((ChannelFormFragment) fragment);
break;
}
if (fragment instanceof PublishFormFragment) {
publishFormFragment = ((PublishFormFragment) fragment);
break;
}
}
if (channelFormFragment != null && channelFormFragment.isSaveInProgress()) {
handled = true;
return;
}
//if (publishFormFragment != null && )
if (!handled) {
// check fragment and nav history
@ -1975,17 +2015,20 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
subUrls.add(url.toString());
}
Lbryio.subscriptions = subscriptions;
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_LOADED, true);
// resolve subscriptions
if (subUrls.size() > 0 && Lbryio.cacheResolvedSubscriptions.size() != Lbryio.subscriptions.size()) {
List<Claim> resolvedSubs = Lbry.resolve(subUrls, Lbry.LBRY_TV_CONNECTION_STRING);
Lbryio.cacheResolvedSubscriptions = resolvedSubs;
}
// if no exceptions occurred here, subscriptions have been loaded and resolved
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED, true);
} else {
// user has not subscribed to anything
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_LOADED, true);
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED, true);
}
// if no exceptions occurred here, subscriptions have been loaded and resolved
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_LOADED, true);
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED, true);
} else {
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_LOADED, true);
startupStages.put(STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED, true);
@ -2004,6 +2047,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
if (!startupSuccessful) {
// show which startup stage failed
renderStartupFailed(startupStages);
appStarted = false;
return;
}
@ -2304,8 +2348,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
return flatMenu;
}
public void setNowPlayingClaim(Claim claim) {
public void setNowPlayingClaim(Claim claim, String url) {
nowPlayingClaim = claim;
nowPlayingClaimUrl = url;
if (claim != null) {
((TextView) findViewById(R.id.global_now_playing_title)).setText(nowPlayingClaim.getTitle());
((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(nowPlayingClaim.getPublisherTitle());
@ -2314,6 +2359,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
public void clearNowPlayingClaim() {
nowPlayingClaim = null;
nowPlayingClaimUrl = null;
findViewById(R.id.global_now_playing_card).setVisibility(View.GONE);
((TextView) findViewById(R.id.global_now_playing_title)).setText(null);
((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(null);
@ -2556,16 +2602,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
return (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}
public void onThemeChanged() {
FragmentManager manager = getSupportFragmentManager();
for (int i = 0; i < manager.getFragments().size(); i++) {
Fragment f = manager.getFragments().get(i);
if (f instanceof DarkThemeChangeListener) {
((DarkThemeChangeListener) f).onDarkThemeToggled();
}
}
}
public interface BackPressInterceptor {
boolean onBackPressed();
}

View file

@ -43,6 +43,8 @@ public class ClaimListAdapter extends RecyclerView.Adapter<ClaimListAdapter.View
private Map<String, Boolean> notFoundClaimIdMap;
private Map<String, Boolean> notFoundClaimUrlMap;
@Setter
private boolean hideFee;
@Setter
private boolean canEnterSelectionMode;
private Context context;
@ -421,7 +423,7 @@ public class ClaimListAdapter extends RecyclerView.Adapter<ClaimListAdapter.View
}
BigDecimal cost = item.getActualCost(Lbryio.LBCUSDRate);
vh.feeContainer.setVisibility(cost.doubleValue() > 0 ? View.VISIBLE : View.GONE);
vh.feeContainer.setVisibility(cost.doubleValue() > 0 && !hideFee ? View.VISIBLE : View.GONE);
vh.feeView.setText(cost.doubleValue() > 0 ? Helper.shortCurrencyFormat(cost.doubleValue()) : "Paid");
vh.alphaView.setText(item.getName().substring(0, Math.min(5, item.getName().length() - 1)));
vh.publisherView.setText(signingChannel != null ? signingChannel.getName() : context.getString(R.string.anonymous));

View file

@ -159,7 +159,13 @@ public class CustomizeTagsDialogFragment extends BottomSheetDialogFragment {
}
private void updateKnownTags(String filter, int limit, boolean clearPrevious) {
UpdateSuggestedTagsTask task = new UpdateSuggestedTagsTask(filter, SUGGESTED_LIMIT, followedTagsAdapter, suggestedTagsAdapter, clearPrevious, new UpdateSuggestedTagsTask.KnownTagsHandler() {
UpdateSuggestedTagsTask task = new UpdateSuggestedTagsTask(
filter,
SUGGESTED_LIMIT,
followedTagsAdapter,
suggestedTagsAdapter,
clearPrevious,
false, new UpdateSuggestedTagsTask.KnownTagsHandler() {
@Override
public void onSuccess(List<Tag> tags) {
if (suggestedTagsAdapter == null) {

View file

@ -86,7 +86,7 @@ public class RepostClaimDialogFragment extends BottomSheetDialogFragment impleme
textTitle.setText(getString(R.string.repost_title, claim.getTitle()));
inputName.setText(claim.getName());
inputDeposit.setText(R.string.min_repost_deposit);
inputDeposit.setText(R.string.min_deposit);
channelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {

View file

@ -1,5 +0,0 @@
package io.lbry.browser.listener;
public interface DarkThemeChangeListener {
void onDarkThemeToggled();
}

View file

@ -0,0 +1,16 @@
package io.lbry.browser.model;
import lombok.Data;
@Data
public class Language {
private String code;
private String name;
private int stringResourceId;
public Language(String code, String name, int stringResourceId) {
this.code = code;
this.name = name;
this.stringResourceId = stringResourceId;
}
}

View file

@ -0,0 +1,20 @@
package io.lbry.browser.model;
import lombok.Data;
@Data
public class License {
private String name;
private String url;
private int stringResourceId;
public License(String name, int stringResourceId) {
this.name = name;
this.stringResourceId = stringResourceId;
}
public License(String name, String url, int stringResourceId) {
this.name = name;
this.url = url;
this.stringResourceId = stringResourceId;
}
}

View file

@ -48,13 +48,27 @@ public class ChannelCreateUpdateTask extends AsyncTask<Void, Void, Claim> {
options.put("claim_id", claim.getClaimId());
}
options.put("bid", new DecimalFormat(Helper.SDK_AMOUNT_FORMAT).format(deposit.doubleValue()));
options.put("title", claim.getTitle());
options.put("cover_url", claim.getCoverUrl());
options.put("thumbnail_url", claim.getThumbnailUrl());
options.put("description", claim.getDescription());
options.put("website_url", claim.getWebsiteUrl());
options.put("email", claim.getEmail());
options.put("tags", claim.getTags());
if (!Helper.isNullOrEmpty(claim.getTitle())) {
options.put("title", claim.getTitle());
}
if (!Helper.isNullOrEmpty(claim.getCoverUrl())) {
options.put("cover_url", claim.getCoverUrl());
}
if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
options.put("thumbnail_url", claim.getThumbnailUrl());
}
if (!Helper.isNullOrEmpty(claim.getDescription())) {
options.put("description", claim.getDescription());
}
if (!Helper.isNullOrEmpty(claim.getWebsiteUrl())) {
options.put("website_url", claim.getWebsiteUrl());
}
if (!Helper.isNullOrEmpty(claim.getEmail())) {
options.put("email", claim.getEmail());
}
if (claim.getTags() != null && claim.getTags().size() > 0) {
options.put("tags", claim.getTags());
}
options.put("blocking", true);
Claim claimResult = null;

View file

@ -9,7 +9,7 @@ import java.util.List;
import io.lbry.browser.exceptions.LbryRequestException;
import io.lbry.browser.exceptions.LbryResponseException;
import io.lbry.browser.model.Claim;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lighthouse;
@ -19,11 +19,11 @@ public class LighthouseSearchTask extends AsyncTask<Void, Void, List<Claim>> {
private int from;
private boolean nsfw;
private String relatedTo;
private ClaimSearchTask.ClaimSearchResultHandler handler;
private ClaimSearchResultHandler handler;
private ProgressBar progressBar;
private Exception error;
public LighthouseSearchTask(String rawQuery, int size, int from, boolean nsfw, String relatedTo, ProgressBar progressBar, ClaimSearchTask.ClaimSearchResultHandler handler) {
public LighthouseSearchTask(String rawQuery, int size, int from, boolean nsfw, String relatedTo, ProgressBar progressBar, ClaimSearchResultHandler handler) {
this.rawQuery = rawQuery;
this.size = size;
this.from = from;

View file

@ -14,18 +14,27 @@ import io.lbry.browser.utils.Lbry;
public class UpdateSuggestedTagsTask extends AsyncTask<Void, Void, List<Tag>> {
private boolean clearPrevious;
private boolean excludeMature;
private int limit;
private String filter;
private TagListAdapter addedTagsAdapter;
private TagListAdapter suggestedTagsAdapter;
private KnownTagsHandler handler;
public UpdateSuggestedTagsTask(String filter, int limit, TagListAdapter addedTagsAdapter, TagListAdapter suggestedTagsAdapter, boolean clearPrevious, KnownTagsHandler handler) {
public UpdateSuggestedTagsTask(
String filter,
int limit,
TagListAdapter addedTagsAdapter,
TagListAdapter suggestedTagsAdapter,
boolean clearPrevious,
boolean excludeMature,
KnownTagsHandler handler) {
this.filter = filter;
this.limit = limit;
this.addedTagsAdapter = addedTagsAdapter;
this.suggestedTagsAdapter = suggestedTagsAdapter;
this.clearPrevious = clearPrevious;
this.excludeMature = excludeMature;
this.handler = handler;
}
@ -38,6 +47,9 @@ public class UpdateSuggestedTagsTask extends AsyncTask<Void, Void, List<Tag>> {
}
while (tags.size() < limit) {
Tag randomTag = Lbry.knownTags.get(random.nextInt(Lbry.knownTags.size()));
if (excludeMature && randomTag.isMature()) {
continue;
}
if (!Lbry.followedTags.contains(randomTag) && (addedTagsAdapter == null || !addedTagsAdapter.getTags().contains(randomTag))) {
tags.add(randomTag);
}
@ -49,6 +61,9 @@ public class UpdateSuggestedTagsTask extends AsyncTask<Void, Void, List<Tag>> {
}
for (int i = 0; i < Lbry.knownTags.size() && tags.size() < limit - 1; i++) {
Tag knownTag = Lbry.knownTags.get(i);
if (excludeMature && knownTag.isMature()) {
continue;
}
if ((knownTag.getLowercaseName().startsWith(filter) || knownTag.getLowercaseName().matches(filter)) &&
(!tags.contains(knownTag) &&
!Lbry.followedTags.contains(knownTag) && (addedTagsAdapter == null || !addedTagsAdapter.getTags().contains(knownTag)))) {

View file

@ -42,7 +42,7 @@ public class AbandonChannelTask extends AsyncTask<Void, Void, Boolean> {
try {
Map<String, Object> options = new HashMap<>();
options.put("claim_id", claimId);
options.put("blocking", false);
options.put("blocking", true);
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_CHANNEL_ABANDON, options);
successfulClaimIds.add(claimId);
} catch (ApiCallException ex) {

View file

@ -42,12 +42,10 @@ public class AbandonStreamTask extends AsyncTask<Void, Void, Boolean> {
try {
Map<String, Object> options = new HashMap<>();
options.put("claim_id", claimId);
options.put("blocking", false);
options.put("blocking", true);
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_STREAM_ABANDON, options);
android.util.Log.d("#HELP", result.toString());
successfulClaimIds.add(claimId);
} catch (ApiCallException ex) {
android.util.Log.e("#HELP", ex.getMessage(), ex);
failedClaimIds.add(claimId);
failedExceptions.add(ex);
}

View file

@ -0,0 +1,10 @@
package io.lbry.browser.tasks.claim;
import java.util.List;
import io.lbry.browser.model.Claim;
public interface ClaimSearchResultHandler {
void onSuccess(List<Claim> claims, boolean hasReachedEnd);
void onError(Exception error);
}

View file

@ -2,7 +2,6 @@ package io.lbry.browser.tasks.claim;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ProgressBar;
import java.util.List;
import java.util.Map;
@ -47,8 +46,4 @@ public class ClaimSearchTask extends AsyncTask<Void, Void, List<Claim>> {
}
}
public interface ClaimSearchResultHandler {
void onSuccess(List<Claim> claims, boolean hasReachedEnd);
void onError(Exception error);
}
}

View file

@ -0,0 +1,70 @@
package io.lbry.browser.tasks.claim;
import android.os.AsyncTask;
import android.view.View;
import org.json.JSONArray;
import org.json.JSONException;
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.model.Claim;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
public class PurchaseListTask extends AsyncTask<Void, Void, List<Claim>> {
private int page;
private int pageSize;
private ClaimSearchResultHandler handler;
private View progressView;
private Exception error;
public PurchaseListTask(int page, int pageSize, View progressView, ClaimSearchResultHandler handler) {
this.page = page;
this.pageSize = pageSize;
this.progressView = progressView;
this.handler = handler;
}
protected void onPreExecute() {
Helper.setViewVisibility(progressView, View.VISIBLE);
}
protected List<Claim> doInBackground(Void... params) {
List<Claim> claims = null;
try {
Map<String, Object> options = new HashMap<>();
options.put("page", page);
options.put("page_size", pageSize);
options.put("resolve", true);
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_PURCHASE_LIST, options);
JSONArray items = result.getJSONArray("items");
claims = new ArrayList<>();
for (int i = 0; i < items.length(); i++) {
Claim claim = Claim.fromJSONObject(items.getJSONObject(i).getJSONObject("claim"));
claims.add(claim);
Lbry.addClaimToCache(claim);
}
} catch (ApiCallException | JSONException | ClassCastException ex) {
error = ex;
}
return claims;
}
protected void onPostExecute(List<Claim> claims) {
Helper.setViewVisibility(progressView, View.GONE);
if (handler != null) {
if (claims != null) {
handler.onSuccess(claims, claims.size() < pageSize);
} else {
handler.onError(error);
}
}
}
}

View file

@ -62,9 +62,8 @@ public class LoadGalleryItemsTask extends AsyncTask<Void, GalleryItem, List<Gall
int pathColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
String id = cursor.getString(idColumn);
GalleryItem item = new GalleryItem();
item.setId(id);
item.setId(cursor.getString(idColumn));
item.setName(cursor.getString(nameColumn));
item.setType(cursor.getString(typeColumn));
item.setFilePath(cursor.getString(pathColumn));

View file

@ -1,7 +1,6 @@
package io.lbry.browser.ui.allcontent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
@ -15,7 +14,6 @@ import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.material.snackbar.Snackbar;
import org.json.JSONException;
@ -38,6 +36,7 @@ import io.lbry.browser.listener.TagListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.LbryFile;
import io.lbry.browser.model.Tag;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.tasks.FollowUnfollowTagTask;
import io.lbry.browser.ui.BaseFragment;
@ -443,7 +442,7 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi
contentClaimSearchLoading = true;
Helper.setViewVisibility(noContentView, View.GONE);
Map<String, Object> claimSearchOptions = buildContentOptions();
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
if (contentListAdapter == null) {

View file

@ -1,7 +1,6 @@
package io.lbry.browser.ui.channel;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
@ -32,6 +31,7 @@ import io.lbry.browser.dialog.ContentSortDialogFragment;
import io.lbry.browser.listener.DownloadActionListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.LbryFile;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
@ -254,7 +254,7 @@ public class ChannelContentFragment extends Fragment implements DownloadActionLi
contentClaimSearchLoading = true;
Helper.setViewVisibility(noContentView, View.GONE);
Map<String, Object> claimSearchOptions = buildContentOptions();
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
if (contentListAdapter == null) {

View file

@ -18,6 +18,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
@ -53,6 +54,7 @@ import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryAnalytics;
import io.lbry.browser.utils.LbryUri;
import io.lbry.browser.utils.Predefined;
import lombok.Getter;
public class ChannelFormFragment extends BaseFragment implements
@ -70,6 +72,7 @@ public class ChannelFormFragment extends BaseFragment implements
private TextView linkShowOptional;
private MaterialButton buttonSave;
private NestedScrollView scrollView;
private View inlineBalanceContainer;
private TextView inlineBalanceValue;
private View uploadProgress;
@ -111,6 +114,7 @@ public class ChannelFormFragment extends BaseFragment implements
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_channel_form, container, false);
scrollView = root.findViewById(R.id.channel_form_scroll_view);
linkCancel = root.findViewById(R.id.channel_form_cancel_link);
linkShowOptional = root.findViewById(R.id.channel_form_toggle_optional);
buttonSave = root.findViewById(R.id.channel_form_save_button);
@ -136,6 +140,7 @@ public class ChannelFormFragment extends BaseFragment implements
Context context = getContext();
FlexboxLayoutManager flm1 = new FlexboxLayoutManager(context);
FlexboxLayoutManager flm2 = new FlexboxLayoutManager(context);
FlexboxLayoutManager flm3 = new FlexboxLayoutManager(context);
addedTagsList = root.findViewById(R.id.form_added_tags);
addedTagsList.setLayoutManager(flm1);
suggestedTagsList = root.findViewById(R.id.form_suggested_tags);
@ -145,6 +150,7 @@ public class ChannelFormFragment extends BaseFragment implements
addedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_REMOVE);
addedTagsAdapter.setClickListener(this);
addedTagsList.setAdapter(addedTagsAdapter);
suggestedTagsAdapter = new TagListAdapter(new ArrayList<>(), getContext());
suggestedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
suggestedTagsAdapter.setClickListener(this);
@ -167,6 +173,12 @@ public class ChannelFormFragment extends BaseFragment implements
if (containerOptionalFields.getVisibility() != View.VISIBLE) {
containerOptionalFields.setVisibility(View.VISIBLE);
linkShowOptional.setText(R.string.hide_optional_fields);
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(NestedScrollView.FOCUS_DOWN);
}
});
} else {
containerOptionalFields.setVisibility(View.GONE);
linkShowOptional.setText(R.string.show_optional_fields);
@ -549,8 +561,11 @@ public class ChannelFormFragment extends BaseFragment implements
Snackbar.make(getView(), getString(R.string.tag_already_added, tag.getName()), Snackbar.LENGTH_LONG).show();
return;
}
if (addedTagsAdapter.getItemCount() == 5) {
Snackbar.make(getView(), R.string.tag_limit_reached, Snackbar.LENGTH_LONG).show();
return;
}
tag.setFollowed(true);
addedTagsAdapter.addTag(tag);
if (suggestedTagsAdapter != null) {
suggestedTagsAdapter.removeTag(tag);
@ -561,7 +576,6 @@ public class ChannelFormFragment extends BaseFragment implements
checkNoTagResults();
}
public void removeTag(Tag tag) {
tag.setFollowed(false);
addedTagsAdapter.removeTag(tag);
updateSuggestedTags(currentFilter, SUGGESTED_LIMIT, false);
checkNoAddedTags();
@ -581,7 +595,14 @@ public class ChannelFormFragment extends BaseFragment implements
}
private void updateSuggestedTags(String filter, int limit, boolean clearPrevious) {
UpdateSuggestedTagsTask task = new UpdateSuggestedTagsTask(filter, limit, addedTagsAdapter, suggestedTagsAdapter, clearPrevious, new UpdateSuggestedTagsTask.KnownTagsHandler() {
UpdateSuggestedTagsTask task = new UpdateSuggestedTagsTask(
filter,
limit,
addedTagsAdapter,
suggestedTagsAdapter,
clearPrevious,
false,
new UpdateSuggestedTagsTask.KnownTagsHandler() {
@Override
public void onSuccess(List<Tag> tags) {
if (suggestedTagsAdapter == null) {

View file

@ -257,7 +257,6 @@ public class ChannelManagerFragment extends BaseFragment implements ActionMode.C
if (R.id.action_delete == menuItem.getItemId()) {
if (adapter != null && adapter.getSelectedCount() > 0) {
final List<Claim> selectedClaims = new ArrayList<>(adapter.getSelectedItems());
android.util.Log.d("#HELP", selectedClaims.toString());
String message = getResources().getQuantityString(R.plurals.confirm_delete_channels, selectedClaims.size());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()).
setTitle(R.string.delete_selection).

View file

@ -1,7 +1,6 @@
package io.lbry.browser.ui.editorschoice;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
@ -27,6 +26,7 @@ import io.lbry.browser.R;
import io.lbry.browser.adapter.EditorsChoiceItemAdapter;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.EditorsChoiceItem;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.ui.BaseFragment;
import io.lbry.browser.utils.Helper;
@ -105,7 +105,7 @@ public class EditorsChoiceFragment extends BaseFragment {
}
contentLoading = true;
ClaimSearchTask task = new ClaimSearchTask(buildContentOptions(), Lbry.LBRY_TV_CONNECTION_STRING, loading, new ClaimSearchTask.ClaimSearchResultHandler() {
ClaimSearchTask task = new ClaimSearchTask(buildContentOptions(), Lbry.LBRY_TV_CONNECTION_STRING, loading, new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> items, boolean hasReachedEnd) {
List<EditorsChoiceItem> data = buildDataFromClaims(items);

View file

@ -30,7 +30,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -83,7 +82,6 @@ import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.listener.DownloadActionListener;
import io.lbry.browser.listener.SdkStatusListener;
import io.lbry.browser.listener.StoragePermissionListener;
import io.lbry.browser.listener.WalletBalanceListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.ClaimCacheKey;
import io.lbry.browser.model.Fee;
@ -97,7 +95,7 @@ import io.lbry.browser.tasks.LighthouseSearchTask;
import io.lbry.browser.tasks.ReadTextFileTask;
import io.lbry.browser.tasks.SetSdkSettingTask;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.claim.ResolveTask;
import io.lbry.browser.tasks.file.DeleteFileTask;
import io.lbry.browser.tasks.file.FileListTask;
@ -944,6 +942,15 @@ public class FileViewFragment extends BaseFragment implements
ImageView descIndicator = root.findViewById(R.id.file_view_desc_toggle_arrow);
descIndicator.setImageResource(R.drawable.ic_arrow_dropdown);
boolean hasDescription = !Helper.isNullOrEmpty(claim.getDescription());
boolean hasTags = claim.getTags() != null && claim.getTags().size() > 0;
root.findViewById(R.id.file_view_description).setVisibility(hasDescription ? View.VISIBLE : View.GONE);
root.findViewById(R.id.file_view_tag_area).setVisibility(hasTags ? View.VISIBLE : View.GONE);
if (hasTags && !hasDescription) {
root.findViewById(R.id.file_view_tag_area).setPadding(0, 0, 0, 0);
}
root.findViewById(R.id.file_view_description_area).setVisibility(View.GONE);
((TextView) root.findViewById(R.id.file_view_title)).setText(claim.getTitle());
((TextView) root.findViewById(R.id.file_view_description)).setText(claim.getDescription());
@ -1076,39 +1083,42 @@ public class FileViewFragment extends BaseFragment implements
newPlayerCreated = true;
}
PlayerView view = getView().findViewById(R.id.file_view_exoplayer_view);
view.setShutterBackgroundColor(Color.TRANSPARENT);
view.setPlayer(MainActivity.appPlayer);
view.setUseController(true);
if (context instanceof MainActivity) {
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
if (MainActivity.nowPlayingClaim != null &&
MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId()) &&
!newPlayerCreated) {
// if the claim is already playing, we don't need to reload the media source
return;
}
if (MainActivity.appPlayer != null) {
showBuffering();
if (fileViewPlayerListener != null) {
MainActivity.appPlayer.addListener(fileViewPlayerListener);
}
View root = getView();
if (root != null) {
PlayerView view = root.findViewById(R.id.file_view_exoplayer_view);
view.setShutterBackgroundColor(Color.TRANSPARENT);
view.setPlayer(MainActivity.appPlayer);
view.setUseController(true);
if (context instanceof MainActivity) {
((MainActivity) context).setNowPlayingClaim(claim);
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
MainActivity.appPlayer.setPlayWhenReady(true);
String userAgent = Util.getUserAgent(context, getString(R.string.app_name));
String mediaSourceUrl = getStreamingUrl();
MediaSource mediaSource = new ProgressiveMediaSource.Factory(
new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)),
new DefaultExtractorsFactory()
).createMediaSource(Uri.parse(mediaSourceUrl));
if (MainActivity.nowPlayingClaim != null &&
MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId()) &&
!newPlayerCreated) {
// if the claim is already playing, we don't need to reload the media source
return;
}
MainActivity.appPlayer.prepare(mediaSource, true, true);
if (MainActivity.appPlayer != null) {
showBuffering();
if (fileViewPlayerListener != null) {
MainActivity.appPlayer.addListener(fileViewPlayerListener);
}
if (context instanceof MainActivity) {
((MainActivity) context).setNowPlayingClaim(claim, currentUrl);
}
MainActivity.appPlayer.setPlayWhenReady(true);
String userAgent = Util.getUserAgent(context, getString(R.string.app_name));
String mediaSourceUrl = getStreamingUrl();
MediaSource mediaSource = new ProgressiveMediaSource.Factory(
new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)),
new DefaultExtractorsFactory()
).createMediaSource(Uri.parse(mediaSourceUrl));
MainActivity.appPlayer.prepare(mediaSource, true, true);
}
}
}
@ -1473,7 +1483,7 @@ public class FileViewFragment extends BaseFragment implements
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
LighthouseSearchTask relatedTask = new LighthouseSearchTask(
title, RELATED_CONTENT_SIZE, 0, canShowMatureContent, claimId, relatedLoading, new ClaimSearchTask.ClaimSearchResultHandler() {
title, RELATED_CONTENT_SIZE, 0, canShowMatureContent, claimId, relatedLoading, new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
List<Claim> filteredClaims = new ArrayList<>();
@ -1746,7 +1756,13 @@ public class FileViewFragment extends BaseFragment implements
amountClaimed == 1 ? 1 : 2,
new DecimalFormat(Helper.LBC_CURRENCY_FORMAT_PATTERN).format(amountClaimed));
}
Snackbar.make(getView().findViewById(R.id.file_view_global_layout), message, Snackbar.LENGTH_LONG).show();
View root = getView();
Context context = getContext();
if (root != null) {
Snackbar.make(root.findViewById(R.id.file_view_global_layout), message, Snackbar.LENGTH_LONG).show();
} else if (context instanceof MainActivity) {
((MainActivity) context).showMessage(message);
}
}
@Override
@ -1759,12 +1775,16 @@ public class FileViewFragment extends BaseFragment implements
if (claim == null) {
return;
}
if (claim.getFile() != null && claim.getFile().isCompleted()) {
Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_delete), View.VISIBLE);
Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_download), View.GONE);
} else {
Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_delete), View.GONE);
Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_download), View.VISIBLE);
View root = getView();
if (root != null) {
if (claim.getFile() != null && claim.getFile().isCompleted()) {
Helper.setViewVisibility(root.findViewById(R.id.file_view_action_delete), View.VISIBLE);
Helper.setViewVisibility(root.findViewById(R.id.file_view_action_download), View.GONE);
} else {
Helper.setViewVisibility(root.findViewById(R.id.file_view_action_delete), View.GONE);
Helper.setViewVisibility(root.findViewById(R.id.file_view_action_download), View.VISIBLE);
}
}
}

View file

@ -1,7 +1,6 @@
package io.lbry.browser.ui.following;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
@ -37,11 +36,11 @@ import io.lbry.browser.dialog.ContentFromDialogFragment;
import io.lbry.browser.dialog.ContentSortDialogFragment;
import io.lbry.browser.dialog.DiscoverDialogFragment;
import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.listener.DarkThemeChangeListener;
import io.lbry.browser.listener.DownloadActionListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.LbryFile;
import io.lbry.browser.model.lbryinc.Subscription;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.lbryinc.ChannelSubscribeTask;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
@ -59,7 +58,6 @@ import io.lbry.browser.utils.Predefined;
public class FollowingFragment extends BaseFragment implements
FetchSubscriptionsTask.FetchSubscriptionsHandler,
ChannelItemSelectionListener,
DarkThemeChangeListener,
DownloadActionListener,
SharedPreferences.OnSharedPreferenceChangeListener {
@ -585,7 +583,7 @@ public class FollowingFragment extends BaseFragment implements
contentClaimSearchLoading = true;
Helper.setViewVisibility(noContentView, View.GONE);
Map<String, Object> claimSearchOptions = buildContentOptions();
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
if (contentListAdapter == null) {
@ -651,7 +649,7 @@ public class FollowingFragment extends BaseFragment implements
buildSuggestedOptions(),
Lbry.LBRY_TV_CONNECTION_STRING,
suggestedChannelAdapter == null || suggestedChannelAdapter.getItemCount() == 0 ? bigContentLoading : contentLoading,
new ClaimSearchTask.ClaimSearchResultHandler() {
new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
suggestedHasReachedEnd = hasReachedEnd;
@ -804,13 +802,4 @@ public class FollowingFragment extends BaseFragment implements
// invalid file info for download
}
}
public void onDarkThemeToggled() {
Helper.refreshRecyclerView(contentList);
Helper.refreshRecyclerView(horizontalChannelList);
Helper.refreshRecyclerView(suggestedChannelGrid);
if (discoverDialog != null) {
//discoverDialog.onDarkThemeToggled();
}
}
}

View file

@ -47,6 +47,8 @@ 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.claim.ClaimListResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.claim.PurchaseListTask;
import io.lbry.browser.tasks.claim.ResolveTask;
import io.lbry.browser.tasks.file.BulkDeleteFilesTask;
import io.lbry.browser.tasks.file.DeleteFileTask;
@ -63,7 +65,8 @@ 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 FILTER_PURCHASES = 2;
private static final int FILTER_HISTORY = 3;
private static final int PAGE_SIZE = 50;
private ActionMode actionMode;
@ -74,6 +77,7 @@ public class LibraryFragment extends BaseFragment implements
private ClaimListAdapter contentListAdapter;
private ProgressBar listLoading;
private TextView linkFilterDownloads;
private TextView linkFilterPurchases;
private TextView linkFilterHistory;
private View layoutListEmpty;
private TextView textListEmpty;
@ -119,6 +123,7 @@ public class LibraryFragment extends BaseFragment implements
listLoading = root.findViewById(R.id.library_list_loading);
linkFilterDownloads = root.findViewById(R.id.library_filter_link_downloads);
linkFilterPurchases = root.findViewById(R.id.library_filter_link_purchases);
linkFilterHistory = root.findViewById(R.id.library_filter_link_history);
layoutListEmpty = root.findViewById(R.id.library_empty_container);
@ -131,6 +136,12 @@ public class LibraryFragment extends BaseFragment implements
showDownloads();
}
});
linkFilterPurchases.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showPurchases();
}
});
linkFilterHistory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -247,8 +258,10 @@ public class LibraryFragment extends BaseFragment implements
private void showDownloads() {
currentFilter = FILTER_DOWNLOADS;
linkFilterDownloads.setTypeface(null, Typeface.BOLD);
linkFilterPurchases.setTypeface(null, Typeface.NORMAL);
linkFilterHistory.setTypeface(null, Typeface.NORMAL);
if (contentListAdapter != null) {
contentListAdapter.setHideFee(false);
contentListAdapter.clearItems();
contentListAdapter.setCanEnterSelectionMode(true);
}
@ -262,14 +275,38 @@ public class LibraryFragment extends BaseFragment implements
}
}
private void showPurchases() {
currentFilter = FILTER_PURCHASES;
linkFilterDownloads.setTypeface(null, Typeface.NORMAL);
linkFilterPurchases.setTypeface(null, Typeface.BOLD);
linkFilterHistory.setTypeface(null, Typeface.NORMAL);
if (contentListAdapter != null) {
contentListAdapter.setHideFee(true);
contentListAdapter.clearItems();
contentListAdapter.setCanEnterSelectionMode(true);
}
listReachedEnd = false;
cardStats.setVisibility(View.GONE);
checkStatsLink();
layoutSdkInitializing.setVisibility(Lbry.SDK_READY ? View.GONE : View.VISIBLE);
currentPage = 1;
if (Lbry.SDK_READY) {
fetchPurchases();
}
}
private void showHistory() {
currentFilter = FILTER_HISTORY;
linkFilterDownloads.setTypeface(null, Typeface.NORMAL);
linkFilterPurchases.setTypeface(null, Typeface.NORMAL);
linkFilterHistory.setTypeface(null, Typeface.BOLD);
if (actionMode != null) {
actionMode.finish();
}
if (contentListAdapter != null) {
contentListAdapter.setHideFee(false);
contentListAdapter.clearItems();
contentListAdapter.setCanEnterSelectionMode(false);
}
@ -287,6 +324,7 @@ public class LibraryFragment extends BaseFragment implements
contentListAdapter = new ClaimListAdapter(claims, getContext());
contentListAdapter.setCanEnterSelectionMode(true);
contentListAdapter.setSelectionModeListener(this);
contentListAdapter.setHideFee(currentFilter != FILTER_PURCHASES);
contentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() {
@Override
public void onClaimClicked(Claim claim) {
@ -342,6 +380,36 @@ public class LibraryFragment extends BaseFragment implements
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void fetchPurchases() {
contentListLoading = true;
Helper.setViewVisibility(linkStats, View.GONE);
Helper.setViewVisibility(layoutListEmpty, View.GONE);
PurchaseListTask task = new PurchaseListTask(currentPage, PAGE_SIZE, listLoading, new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
listReachedEnd = hasReachedEnd;
if (contentListAdapter == null) {
initContentListAdapter(claims);
} else {
contentListAdapter.addItems(claims);
}
if (contentList.getAdapter() == null) {
contentList.setAdapter(contentListAdapter);
}
checkListEmpty();
contentListLoading = false;
}
@Override
public void onError(Exception error) {
checkStatsLink();
checkListEmpty();
contentListLoading = false;
}
});
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void fetchHistory() {
contentListLoading = true;
Helper.setViewVisibility(layoutListEmpty, View.GONE);
@ -397,7 +465,13 @@ public class LibraryFragment extends BaseFragment implements
private void checkListEmpty() {
layoutListEmpty.setVisibility(contentListAdapter == null || contentListAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
textListEmpty.setText(currentFilter == FILTER_DOWNLOADS ? R.string.library_no_downloads : R.string.library_no_history);
int stringResourceId;
switch (currentFilter) {
case FILTER_DOWNLOADS: default: stringResourceId = R.string.library_no_downloads; break;
case FILTER_HISTORY: stringResourceId = R.string.library_no_history; break;
case FILTER_PURCHASES: stringResourceId = R.string.library_no_purchases; break;
}
textListEmpty.setText(stringResourceId);
}
private void addFiles(List<LbryFile> files) {
@ -487,7 +561,8 @@ public class LibraryFragment extends BaseFragment implements
private void checkStatsLink() {
linkStats.setVisibility(cardStats.getVisibility() == View.VISIBLE ||
listLoading.getVisibility() == View.VISIBLE ||
currentFilter == FILTER_HISTORY ?
currentFilter != FILTER_DOWNLOADS ||
!Lbry.SDK_READY ?
View.GONE : View.VISIBLE);
}

View file

@ -69,11 +69,6 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
if (key.equalsIgnoreCase(MainActivity.PREFERENCE_KEY_DARK_MODE)) {
boolean darkMode = sp.getBoolean(MainActivity.PREFERENCE_KEY_DARK_MODE, false);
AppCompatDelegate.setDefaultNightMode(darkMode ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context).onThemeChanged();
}
}
}
}

View file

@ -1,26 +1,546 @@
package io.lbry.browser.ui.publish;
import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.AppCompatSpinner;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.android.material.textfield.TextInputEditText;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.lbry.browser.BuildConfig;
import io.lbry.browser.MainActivity;
import io.lbry.browser.R;
import io.lbry.browser.adapter.InlineChannelSpinnerAdapter;
import io.lbry.browser.adapter.TagListAdapter;
import io.lbry.browser.listener.SdkStatusListener;
import io.lbry.browser.listener.StoragePermissionListener;
import io.lbry.browser.listener.WalletBalanceListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.GalleryItem;
import io.lbry.browser.model.NavMenuItem;
import io.lbry.browser.model.Tag;
import io.lbry.browser.model.WalletBalance;
import io.lbry.browser.tasks.ChannelCreateUpdateTask;
import io.lbry.browser.tasks.UpdateSuggestedTagsTask;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
import io.lbry.browser.tasks.claim.ClaimListTask;
import io.lbry.browser.tasks.claim.ClaimResultHandler;
import io.lbry.browser.tasks.lbryinc.LogPublishTask;
import io.lbry.browser.ui.BaseFragment;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryAnalytics;
import io.lbry.browser.utils.LbryUri;
import io.lbry.browser.utils.Predefined;
public class PublishFormFragment extends BaseFragment {
public class PublishFormFragment extends BaseFragment implements
SdkStatusListener, StoragePermissionListener, TagListAdapter.TagClickListener, WalletBalanceListener {
private static final int SUGGESTED_LIMIT = 8;
private boolean editMode;
private boolean fetchingChannels;
private String currentFilter;
private TextInputEditText inputTagFilter;
private RecyclerView addedTagsList;
private RecyclerView suggestedTagsList;
private RecyclerView matureTagsList;
private TagListAdapter addedTagsAdapter;
private TagListAdapter suggestedTagsAdapter;
private TagListAdapter matureTagsAdapter;
private ProgressBar progressLoadingChannels;
private View noTagsView;
private View noTagResultsView;
private InlineChannelSpinnerAdapter channelSpinnerAdapter;
private AppCompatSpinner channelSpinner;
private AppCompatSpinner priceCurrencySpinner;
private AppCompatSpinner languageSpinner;
private AppCompatSpinner licenseSpinner;
private NestedScrollView scrollView;
private View layoutExtraFields;
private TextView linkShowExtraFields;
private View textNoPrice;
private View layoutPrice;
private SwitchMaterial switchPrice;
private TextInputEditText inputTitle;
private TextInputEditText inputDescription;
private TextInputEditText inputPrice;
private TextInputEditText inputAddress;
private TextInputEditText inputDeposit;
private View inlineDepositBalanceContainer;
private TextView inlineDepositBalanceValue;
private View linkCancel;
private MaterialButton buttonPublish;
private View inlineChannelCreator;
private TextInputEditText inlineChannelCreatorInputName;
private TextInputEditText inlineChannelCreatorInputDeposit;
private View inlineChannelCreatorInlineBalance;
private TextView inlineChannelCreatorInlineBalanceValue;
private View inlineChannelCreatorCancelLink;
private View inlineChannelCreatorProgress;
private MaterialButton inlineChannelCreatorCreateButton;
private String uploadedThumbnailUrl;
private boolean editFieldsLoaded;
private Claim currentClaim;
private GalleryItem currentGalleryItem;
private String currentFilePath;
private boolean fileLoaded;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_publishes, container, false);
View root = inflater.inflate(R.layout.fragment_publish_form, container, false);
scrollView = root.findViewById(R.id.publish_form_scroll_view);
progressLoadingChannels = root.findViewById(R.id.publish_form_loading_channels);
channelSpinner = root.findViewById(R.id.publish_form_channel_spinner);
inputTagFilter = root.findViewById(R.id.form_tag_filter_input);
noTagsView = root.findViewById(R.id.form_no_added_tags);
noTagResultsView = root.findViewById(R.id.form_no_tag_results);
layoutExtraFields = root.findViewById(R.id.publish_form_extra_options_container);
linkShowExtraFields = root.findViewById(R.id.publish_form_toggle_extra);
layoutPrice = root.findViewById(R.id.publish_form_price_container);
textNoPrice = root.findViewById(R.id.publish_form_no_price);
switchPrice = root.findViewById(R.id.publish_form_price_switch);
inputTitle = root.findViewById(R.id.publish_form_input_title);
inputDeposit = root.findViewById(R.id.publish_form_input_description);
inputPrice = root.findViewById(R.id.publish_form_input_price);
inputAddress = root.findViewById(R.id.publish_form_input_address);
inputDeposit = root.findViewById(R.id.publish_form_input_deposit);
linkCancel = root.findViewById(R.id.publish_form_cancel);
buttonPublish = root.findViewById(R.id.publish_form_publish_button);
Context context = getContext();
FlexboxLayoutManager flm1 = new FlexboxLayoutManager(context);
FlexboxLayoutManager flm2 = new FlexboxLayoutManager(context);
FlexboxLayoutManager flm3 = new FlexboxLayoutManager(context);
addedTagsList = root.findViewById(R.id.form_added_tags);
addedTagsList.setLayoutManager(flm1);
suggestedTagsList = root.findViewById(R.id.form_suggested_tags);
suggestedTagsList.setLayoutManager(flm2);
root.findViewById(R.id.form_mature_tags_container).setVisibility(View.VISIBLE);
matureTagsList = root.findViewById(R.id.form_mature_tags);
matureTagsList.setLayoutManager(flm3);
addedTagsAdapter = new TagListAdapter(new ArrayList<>(), context);
addedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_REMOVE);
addedTagsAdapter.setClickListener(this);
addedTagsList.setAdapter(addedTagsAdapter);
suggestedTagsAdapter = new TagListAdapter(new ArrayList<>(), getContext());
suggestedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
suggestedTagsAdapter.setClickListener(this);
suggestedTagsList.setAdapter(suggestedTagsAdapter);
matureTagsAdapter = new TagListAdapter(Helper.getTagObjectsForTags(Predefined.MATURE_TAGS), context);
matureTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
matureTagsAdapter.setClickListener(this);
matureTagsList.setAdapter(matureTagsAdapter);
inlineChannelCreator = root.findViewById(R.id.container_inline_channel_form_create);
inlineChannelCreatorInputName = root.findViewById(R.id.inline_channel_form_input_name);
inlineChannelCreatorInputDeposit = root.findViewById(R.id.inline_channel_form_input_deposit);
inlineChannelCreatorInlineBalance = root.findViewById(R.id.inline_channel_form_inline_balance_container);
inlineChannelCreatorInlineBalanceValue = root.findViewById(R.id.inline_channel_form_inline_balance_value);
inlineChannelCreatorProgress = root.findViewById(R.id.inline_channel_form_create_progress);
inlineChannelCreatorCancelLink = root.findViewById(R.id.inline_channel_form_cancel_link);
inlineChannelCreatorCreateButton = root.findViewById(R.id.inline_channel_form_create_button);
initUi();
return root;
}
private void initUi() {
inputAddress.setText(Helper.generateUrl());
switchPrice.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
Helper.setViewVisibility(textNoPrice, checked ? View.GONE : View.VISIBLE);
Helper.setViewVisibility(layoutPrice, checked ? View.VISIBLE : View.GONE);
}
});
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
Helper.setViewVisibility(inlineDepositBalanceContainer, hasFocus ? View.VISIBLE : View.GONE);
}
});
linkShowExtraFields.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (layoutExtraFields.getVisibility() != View.VISIBLE) {
layoutExtraFields.setVisibility(View.VISIBLE);
linkShowExtraFields.setText(R.string.hide_extra_fields);
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(NestedScrollView.FOCUS_DOWN);
}
});
} else {
layoutExtraFields.setVisibility(View.GONE);
linkShowExtraFields.setText(R.string.show_extra_fields);
}
}
});
linkCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context).onBackPressed();
}
}
});
channelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
Object item = adapterView.getItemAtPosition(position);
if (item instanceof Claim) {
Claim claim = (Claim) item;
if (claim.isPlaceholder() && !claim.isPlaceholderAnonymous()) {
if (!fetchingChannels) {
showInlineChannelCreator();
}
} else {
hideInlineChannelCreator();
}
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
inputTagFilter.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
String value = Helper.getValue(charSequence);
setFilter(value);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
buttonPublish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
setupInlineChannelCreator(
inlineChannelCreator,
inlineChannelCreatorInputName,
inlineChannelCreatorInputDeposit,
inlineChannelCreatorInlineBalance,
inlineChannelCreatorInlineBalanceValue,
inlineChannelCreatorCancelLink,
inlineChannelCreatorCreateButton,
inlineChannelCreatorProgress
);
}
@Override
public void onStart() {
super.onStart();
MainActivity activity = (MainActivity) getContext();
if (activity != null) {
activity.hideSearchBar();
activity.showNavigationBackIcon();
activity.lockDrawer();
activity.hideFloatingWalletBalance();
activity.addWalletBalanceListener(this);
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(editMode ? R.string.edit_content : R.string.new_publish);
}
}
}
@Override
public void onStop() {
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) getContext();
activity.removeWalletBalanceListener(this);
activity.restoreToggle();
activity.showFloatingWalletBalance();
if (!MainActivity.startingFilePickerActivity) {
activity.removeNavFragment(PublishFormFragment.class, NavMenuItem.ID_ITEM_NEW_PUBLISH);
}
}
super.onStop();
}
private void checkParams() {
Map<String, Object> params = getParams();
if (params != null) {
if (params.containsKey("claim")) {
Claim claim = (Claim) params.get("claim");
if (claim != null && !claim.equals(this.currentClaim)) {
this.currentClaim = claim;
editFieldsLoaded = false;
}
}
if (params.containsKey("galleryItem")) {
currentGalleryItem = (GalleryItem) params.get("galleryItem");
} else if (params.containsKey("directFilePath")) {
currentFilePath = (String) params.get("directFilePath");
}
} else {
// shouldn't actually happen
cancelOnFatalCondition(getString(R.string.no_file_found));
}
}
private void updateFieldsFromCurrentClaim() {
if (currentClaim != null && !editFieldsLoaded) {
}
}
private void checkPublishFile() {
String filePath = "";
if (currentGalleryItem != null) {
// check gallery item type
filePath = currentGalleryItem.getFilePath();
} else if (currentFilePath != null) {
filePath = currentFilePath;
}
android.util.Log.d("#HELP", "filePath=" + filePath);
File file = new File(filePath);
if (!file.exists()) {
// file doesn't exist. although this shouldn't happen
cancelOnFatalCondition(getString(R.string.no_file_found));
return;
}
// check content type
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
android.util.Log.d("#HELP", "fileType=" + type);
if (!Helper.isNullOrEmpty(type) && type.startsWith("video")) {
// ffmpeg video handling
}
}
private void cancelOnFatalCondition(String message) {
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
activity.showError(message);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
activity.onBackPressed();
}
}, 100);
}
}
public void onResume() {
super.onResume();
if (!Lbry.SDK_READY) {
cancelOnFatalCondition(getString(R.string.sdk_initializing_functionality));
return;
}
checkParams();
updateFieldsFromCurrentClaim();
if (currentClaim == null && (currentGalleryItem != null || (Helper.isNullOrEmpty(currentFilePath)))) {
// load file information
checkPublishFile();
}
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
LbryAnalytics.setCurrentScreen(activity, "Channel Form", "ChannelForm");
activity.addStoragePermissionListener(this);
if (editMode) {
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.edit_content);
}
}
}
if (!Lbry.SDK_READY) {
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
activity.addSdkStatusListener(this);
}
} else {
onSdkReady();
}
String filterText = Helper.getValue(inputTagFilter.getText());
updateSuggestedTags(filterText, SUGGESTED_LIMIT, true);
}
public void onSdkReady() {
fetchChannels();
onWalletBalanceUpdated(Lbry.walletBalance);
}
private void fetchChannels() {
if (Lbry.ownChannels != null && Lbry.ownChannels.size() > 0) {
updateChannelList(Lbry.ownChannels);
return;
}
fetchingChannels = true;
disableChannelSpinner();
ClaimListTask task = new ClaimListTask(Claim.TYPE_CHANNEL, progressLoadingChannels, new ClaimListResultHandler() {
@Override
public void onSuccess(List<Claim> claims) {
Lbry.ownChannels = new ArrayList<>(claims);
updateChannelList(Lbry.ownChannels);
enableChannelSpinner();
fetchingChannels = false;
}
@Override
public void onError(Exception error) {
enableChannelSpinner();
fetchingChannels = false;
}
});
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void disableChannelSpinner() {
Helper.setViewEnabled(channelSpinner, false);
hideInlineChannelCreator();
}
private void enableChannelSpinner() {
Helper.setViewEnabled(channelSpinner, true);
if (channelSpinner != null) {
Claim selectedClaim = (Claim) channelSpinner.getSelectedItem();
if (selectedClaim != null) {
if (selectedClaim.isPlaceholder()) {
showInlineChannelCreator();
} else {
hideInlineChannelCreator();
}
}
}
}
private void showInlineChannelCreator() {
Helper.setViewVisibility(inlineChannelCreator, View.VISIBLE);
}
private void hideInlineChannelCreator() {
Helper.setViewVisibility(inlineChannelCreator, View.GONE);
}
private void updateChannelList(List<Claim> channels) {
if (channelSpinnerAdapter == null) {
Context context = getContext();
if (context != null) {
channelSpinnerAdapter = new InlineChannelSpinnerAdapter(context, R.layout.spinner_item_channel, new ArrayList<>(channels));
channelSpinnerAdapter.addPlaceholder(true);
channelSpinnerAdapter.notifyDataSetChanged();
}
} else {
channelSpinnerAdapter.clear();
channelSpinnerAdapter.addAll(channels);
channelSpinnerAdapter.addPlaceholder(true);
channelSpinnerAdapter.notifyDataSetChanged();
}
if (channelSpinner != null) {
channelSpinner.setAdapter(channelSpinnerAdapter);
}
if (channelSpinnerAdapter != null && channelSpinner != null) {
if (channelSpinnerAdapter.getCount() > 2) {
// if anonymous displayed, select first channel if available
channelSpinner.setSelection(2);
} else if (channelSpinnerAdapter.getCount() > 1) {
// select anonymous
channelSpinner.setSelection(1);
}
}
}
private Claim buildPublishClaim() {
Claim claim = new Claim();
return claim;
}
private boolean validatePublishClaim() {
return false;
}
@Override
public boolean shouldHideGlobalPlayer() {
return true;
@ -30,4 +550,214 @@ public class PublishFormFragment extends BaseFragment {
public boolean shouldSuspendGlobalPlayer() {
return true;
}
@Override
public void onTagClicked(Tag tag, int customizeMode) {
if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_ADD) {
addTag(tag);
} else if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_REMOVE) {
removeTag(tag);
}
}
public void setFilter(String filter) {
currentFilter = filter;
updateSuggestedTags(currentFilter, SUGGESTED_LIMIT, true);
}
private void checkNoAddedTags() {
Helper.setViewVisibility(noTagsView, addedTagsAdapter == null || addedTagsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
private void checkNoTagResults() {
Helper.setViewVisibility(noTagResultsView, suggestedTagsAdapter == null || suggestedTagsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
public void addTag(Tag tag) {
if (addedTagsAdapter.getTags().contains(tag)) {
Snackbar.make(getView(), getString(R.string.tag_already_added, tag.getName()), Snackbar.LENGTH_LONG).show();
return;
}
if (addedTagsAdapter.getItemCount() == 5) {
Snackbar.make(getView(), R.string.tag_limit_reached, Snackbar.LENGTH_LONG).show();
return;
}
addedTagsAdapter.addTag(tag);
if (suggestedTagsAdapter != null) {
suggestedTagsAdapter.removeTag(tag);
}
updateSuggestedTags(currentFilter, SUGGESTED_LIMIT, false);
checkNoAddedTags();
checkNoTagResults();
}
public void removeTag(Tag tag) {
addedTagsAdapter.removeTag(tag);
updateSuggestedTags(currentFilter, SUGGESTED_LIMIT, false);
checkNoAddedTags();
checkNoTagResults();
}
private void updateSuggestedTags(String filter, int limit, boolean clearPrevious) {
UpdateSuggestedTagsTask task = new UpdateSuggestedTagsTask(
filter,
limit,
addedTagsAdapter,
suggestedTagsAdapter,
clearPrevious,
true, new UpdateSuggestedTagsTask.KnownTagsHandler() {
@Override
public void onSuccess(List<Tag> tags) {
if (suggestedTagsAdapter == null) {
suggestedTagsAdapter = new TagListAdapter(tags, getContext());
suggestedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
suggestedTagsAdapter.setClickListener(PublishFormFragment.this);
if (suggestedTagsList != null) {
suggestedTagsList.setAdapter(suggestedTagsAdapter);
}
} else {
suggestedTagsAdapter.setTags(tags);
}
checkNoAddedTags();
checkNoTagResults();
}
});
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public void onWalletBalanceUpdated(WalletBalance walletBalance) {
if (walletBalance != null && inlineDepositBalanceValue != null) {
inlineDepositBalanceValue.setText(Helper.shortCurrencyFormat(walletBalance.getAvailable().doubleValue()));
}
}
private void setupInlineChannelCreator(
View container,
TextInputEditText inputChannelName,
TextInputEditText inputDeposit,
View inlineBalanceView,
TextView inlineBalanceValue,
View linkCancel,
MaterialButton buttonCreate,
View progressView) {
inputDeposit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
Helper.setViewVisibility(inlineBalanceView, hasFocus ? View.VISIBLE : View.INVISIBLE);
}
});
linkCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Helper.setViewText(inputChannelName, null);
Helper.setViewText(inputDeposit, null);
Helper.setViewVisibility(container, View.GONE);
}
});
buttonCreate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// validate deposit and channel name
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
Claim claimToSave = new Claim();
claimToSave.setName(channelNameString);
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
String depositString = Helper.getValue(inputDeposit.getText());
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
showError(getString(R.string.please_enter_channel_name));
return;
}
if (!LbryUri.isNameValid(channelName)) {
showError(getString(R.string.channel_name_invalid_characters));
return;
}
if (Helper.channelExists(channelName)) {
showError(getString(R.string.channel_name_already_created));
return;
}
double depositAmount = 0;
try {
depositAmount = Double.valueOf(depositString);
} catch (NumberFormatException ex) {
// pass
showError(getString(R.string.please_enter_valid_deposit));
return;
}
if (depositAmount == 0) {
String error = getResources().getQuantityString(R.plurals.min_deposit_required, depositAmount == 1 ? 1 : 2, String.valueOf(Helper.MIN_DEPOSIT));
showError(error);
return;
}
if (Lbry.walletBalance == null || Lbry.walletBalance.getAvailable().doubleValue() < depositAmount) {
showError(getString(R.string.deposit_more_than_balance));
return;
}
ChannelCreateUpdateTask task = new ChannelCreateUpdateTask(
claimToSave, new BigDecimal(depositString), false, progressView, new ClaimResultHandler() {
@Override
public void beforeStart() {
Helper.setViewEnabled(inputChannelName, false);
Helper.setViewEnabled(inputDeposit, false);
Helper.setViewEnabled(buttonCreate, false);
Helper.setViewEnabled(linkCancel, false);
}
@Override
public void onSuccess(Claim claimResult) {
if (!BuildConfig.DEBUG) {
LogPublishTask logPublishTask = new LogPublishTask(claimResult);
logPublishTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
// channel created
Bundle bundle = new Bundle();
bundle.putString("claim_id", claimResult.getClaimId());
bundle.putString("claim_name", claimResult.getName());
LbryAnalytics.logEvent(LbryAnalytics.EVENT_CHANNEL_CREATE, bundle);
// add the claim to the channel list and set it as the selected item
channelSpinnerAdapter.add(claimResult);
channelSpinner.setSelection(channelSpinnerAdapter.getCount() - 1);
Helper.setViewEnabled(inputChannelName, true);
Helper.setViewEnabled(inputDeposit, true);
Helper.setViewEnabled(buttonCreate, true);
Helper.setViewEnabled(linkCancel, true);
}
@Override
public void onError(Exception error) {
Helper.setViewEnabled(inputChannelName, true);
Helper.setViewEnabled(inputDeposit, true);
Helper.setViewEnabled(buttonCreate, true);
Helper.setViewEnabled(linkCancel, true);
showError(error.getMessage());
}
});
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
Helper.setViewText(inlineBalanceValue, Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue()));
}
private void showError(String message) {
Context context = getContext();
if (context != null) {
Snackbar.make(getView(), message, Snackbar.LENGTH_LONG).setBackgroundTint(Color.RED).show();
}
}
@Override
public void onStoragePermissionGranted() {
}
@Override
public void onStoragePermissionRefused() {
}
}

View file

@ -29,7 +29,9 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import io.lbry.browser.MainActivity;
@ -38,9 +40,11 @@ import io.lbry.browser.adapter.GalleryGridAdapter;
import io.lbry.browser.listener.CameraPermissionListener;
import io.lbry.browser.listener.StoragePermissionListener;
import io.lbry.browser.model.GalleryItem;
import io.lbry.browser.model.NavMenuItem;
import io.lbry.browser.tasks.localdata.LoadGalleryItemsTask;
import io.lbry.browser.ui.BaseFragment;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryAnalytics;
public class PublishFragment extends BaseFragment implements CameraPermissionListener, StoragePermissionListener {
@ -123,8 +127,6 @@ public class PublishFragment extends BaseFragment implements CameraPermissionLis
Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, preview);
preview.setSurfaceProvider(cameraPreview.createSurfaceProvider(camera.getCameraInfo()));
} else {
android.util.Log.d("#HELP", "camera provider future is null?");
}
} catch (ExecutionException | InterruptedException ex) {
// pass
@ -220,6 +222,22 @@ public class PublishFragment extends BaseFragment implements CameraPermissionLis
if (context != null) {
if (adapter == null) {
adapter = new GalleryGridAdapter(Arrays.asList(item), context);
adapter.setListener(new GalleryGridAdapter.GalleryItemClickListener() {
@Override
public void onGalleryItemClicked(GalleryItem item) {
if (!Lbry.SDK_READY) {
Snackbar.make(getView(), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show();
return;
}
Context context = getContext();
if (context instanceof MainActivity) {
Map<String, Object> params = new HashMap<>();
params.put("galleryItem", item);
((MainActivity) context).openFragment(PublishFormFragment.class, true, NavMenuItem.ID_ITEM_NEW_PUBLISH, params);
}
}
});
} else {
adapter.addItem(item);
}

View file

@ -34,7 +34,6 @@ import io.lbry.browser.adapter.ClaimListAdapter;
import io.lbry.browser.listener.SdkStatusListener;
import io.lbry.browser.listener.SelectionModeListener;
import io.lbry.browser.model.Claim;
import io.lbry.browser.tasks.claim.AbandonChannelTask;
import io.lbry.browser.tasks.claim.AbandonHandler;
import io.lbry.browser.tasks.claim.AbandonStreamTask;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;

View file

@ -15,8 +15,6 @@ import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.offline.Download;
import org.json.JSONException;
import org.json.JSONObject;
@ -30,7 +28,7 @@ import io.lbry.browser.model.Claim;
import io.lbry.browser.model.ClaimCacheKey;
import io.lbry.browser.model.LbryFile;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
import io.lbry.browser.tasks.claim.ClaimSearchTask;
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
import io.lbry.browser.tasks.LighthouseSearchTask;
import io.lbry.browser.tasks.claim.ResolveTask;
import io.lbry.browser.ui.BaseFragment;
@ -232,7 +230,7 @@ public class SearchFragment extends BaseFragment implements
}
LighthouseSearchTask task = new LighthouseSearchTask(
currentQuery, PAGE_SIZE, currentFrom, canShowMatureContent, null, loadingView, new ClaimSearchTask.ClaimSearchResultHandler() {
currentQuery, PAGE_SIZE, currentFrom, canShowMatureContent, null, loadingView, new ClaimSearchResultHandler() {
@Override
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
contentHasReachedEnd = hasReachedEnd;

View file

@ -470,15 +470,12 @@ public class InvitesFragment extends BaseFragment implements SdkStatusListener,
@Override
public void onClick(View view) {
// validate deposit and channel name
String channelNameString = Helper.getValue(inputChannelName.getText());
if (!channelNameString.startsWith("@")) {
channelNameString = String.format("@%s", channelNameString);
}
String channelNameString = Helper.normalizeChannelName(Helper.getValue(inputChannelName.getText()));
Claim claimToSave = new Claim();
claimToSave.setName(channelNameString);
String channelName = claimToSave.getName().startsWith("@") ? claimToSave.getName().substring(1) : claimToSave.getName();
String depositString = Helper.getValue(inputDeposit.getText());
if (Helper.isNullOrEmpty(channelName)) {
if ("@".equals(channelName) || Helper.isNullOrEmpty(channelName)) {
showError(getString(R.string.please_enter_channel_name));
return;
}

View file

@ -690,13 +690,20 @@ public final class Helper {
return (int) (value * scale + 0.5f);
}
public static String generateUrl() {
Random random = new Random();
StringBuilder sb = new StringBuilder();
sb.append(Predefined.ADJECTIVES.get(random.nextInt(Predefined.ADJECTIVES.size()))).append("-").
append(Predefined.ADJECTIVES.get(random.nextInt(Predefined.ADJECTIVES.size()))).append("-").
append(Predefined.ANIMALS.get(random.nextInt(Predefined.ANIMALS.size())));
return sb.toString().toLowerCase();
}
public static void refreshRecyclerView(RecyclerView rv) {
if (rv == null) {
android.util.Log.d("#HELP", "rv is null?");
return;
}
android.util.Log.d("#HELP", "Refereshing recycler view...");
RecyclerView.Adapter adapter = rv.getAdapter();
int prevScrollPosition = 0;

View file

@ -93,6 +93,7 @@ public final class Lbry {
public static final String METHOD_CLAIM_LIST = "claim_list";
public static final String METHOD_PURCHASE_LIST = "purchase_list";
public static final String METHOD_STREAM_ABANDON = "stream_abandon";
public static final String METHOD_STREAM_REPOST = "stream_repost";

File diff suppressed because it is too large Load diff

View file

@ -32,10 +32,11 @@
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inline_channel_form_input_deposit"
android:fontFamily="@font/inter"
android:singleLine="true"
android:textSize="14sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textSize="14sp"
android:text="@string/min_deposit"
android:inputType="numberDecimal" />
</com.google.android.material.textfield.TextInputLayout>

View file

@ -33,7 +33,7 @@
android:id="@+id/form_mature_tags_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
android:visibility="gone">
<TextView

View file

@ -11,8 +11,10 @@
<FrameLayout
android:id="@+id/content_main"
android:background="@color/pageBackground"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -21,6 +23,7 @@
android:id="@+id/url_suggestions_container"
android:background="@color/pageBackground"
android:elevation="6dp"
android:fitsSystemWindows="true"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">

View file

@ -123,6 +123,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.core.widget.NestedScrollView
android:id="@+id/channel_form_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout

View file

@ -541,7 +541,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:layout_marginTop="36dp"
android:paddingTop="36dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp">
<TextView

View file

@ -25,6 +25,17 @@
android:fontFamily="@font/inter"
android:text="@string/downloads"
android:textStyle="bold" />
<TextView
android:id="@+id/library_filter_link_purchases"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="24dp"
android:layout_toRightOf="@id/library_filter_link_downloads"
android:fontFamily="@font/inter"
android:text="@string/purchases" />
<TextView
android:id="@+id/library_filter_link_history"
android:background="?attr/selectableItemBackground"
@ -32,8 +43,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:layout_toRightOf="@id/library_filter_link_downloads"
android:layout_marginLeft="24dp"
android:layout_toRightOf="@id/library_filter_link_purchases"
android:fontFamily="@font/inter"
android:text="@string/history"
android:textSize="14sp" />

View file

@ -4,76 +4,73 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/pageBackground">
<LinearLayout
android:id="@+id/publish_form_display_area"
android:elevation="4dp"
android:orientation="vertical"
android:weightSum="10"
<androidx.core.widget.NestedScrollView
android:id="@+id/publish_form_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/publish_form_media_container"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3.55"
android:background="@android:color/black">
<ImageView
android:id="@+id/publish_form_thumbnail_preview"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/publish_form_media_container"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="240dp"
android:background="@android:color/black">
<LinearLayout
android:id="@+id/publish_form_thumbnail_upload_progress"
android:background="@color/channelCoverBackground"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginTop="4dp"
android:orientation="horizontal"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:visibility="gone">
<ProgressBar
android:layout_width="16dp"
android:layout_height="16dp" />
<TextView
<ImageView
android:id="@+id/publish_form_thumbnail_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/publish_form_thumbnail_upload_progress"
android:background="@color/channelCoverBackground"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:fontFamily="@font/inter"
android:text="@string/uploading"
android:textColor="@color/white"
android:textFontWeight="300"
android:textSize="12sp" />
</LinearLayout>
android:layout_marginTop="4dp"
android:orientation="horizontal"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:visibility="gone">
<ProgressBar
android:layout_width="16dp"
android:layout_height="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:fontFamily="@font/inter"
android:text="@string/uploading"
android:textColor="@color/white"
android:textFontWeight="300"
android:textSize="12sp" />
</LinearLayout>
<RelativeLayout
android:background="@drawable/bg_small_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="16dp"
android:layout_marginBottom="16dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_edit"
android:tint="@color/white" />
<RelativeLayout
android:background="@drawable/bg_small_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="16dp"
android:layout_marginBottom="16dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_edit"
android:tint="@color/white" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6.45">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -149,23 +146,319 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="@font/inter"
android:textSize="20sp"
android:text="@string/channel" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/inter"
android:textSize="20sp"
android:text="@string/channel" />
<ProgressBar
android:id="@+id/publish_form_loading_channels"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:visibility="gone" />
</RelativeLayout>
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/invites_channel_spinner"
android:id="@+id/publish_form_channel_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp" />
<include layout="@layout/container_inline_channel_form" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_centerVertical="true"
android:fontFamily="@font/inter"
android:textSize="20sp"
android:text="@string/price" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/publish_form_price_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
<TextView
android:id="@+id/publish_form_no_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:text="@string/free_publish"
android:textFontWeight="300"
android:textSize="14sp" />
<RelativeLayout
android:id="@+id/publish_form_price_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/publish_form_price_layout"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:hint="@string/price">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/publish_form_input_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:textFontWeight="300"
android:textSize="14sp"
android:inputType="numberDecimal" />
</com.google.android.material.textfield.TextInputLayout>
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/publish_form_currency_spinner"
android:entries="@array/publish_currencies"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/publish_form_price_layout"
android:layout_marginLeft="4dp"
android:layout_marginTop="24dp" />
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="@font/inter"
android:textSize="20sp"
android:text="@string/content_address" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:text="@string/content_address_desc"
android:textFontWeight="300"
android:textSize="14sp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="@string/address">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/publish_form_input_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:inputType="textNoSuggestions"
android:textFontWeight="300"
android:textSize="14sp" />
</com.google.android.material.textfield.TextInputLayout>
<RelativeLayout
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/publish_form_input_layout_deposit"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:hint="@string/deposit">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/publish_form_input_deposit"
android:fontFamily="@font/inter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/min_deposit"
android:textSize="14sp"
android:inputType="numberDecimal" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/publish_form_input_currency"
android:layout_toRightOf="@id/publish_form_input_layout_deposit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="30dp"
android:fontFamily="@font/inter"
android:text="@string/lbc"
android:textAllCaps="true"
android:textSize="10sp"
android:textFontWeight="300" />
<LinearLayout
android:id="@+id/publish_form_inline_balance_container"
android:layout_toRightOf="@id/publish_form_input_currency"
android:layout_marginLeft="24dp"
android:layout_marginTop="28dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="invisible">
<io.lbry.browser.ui.controls.SolidIconView
android:layout_width="18dp"
android:layout_height="18dp"
android:text="@string/fa_coins" />
<TextView
android:id="@+id/publish_form_inline_balance_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:textFontWeight="300"
android:layout_marginLeft="2dp" />
</LinearLayout>
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:fontFamily="@font/inter"
android:text="@string/deposit_remains_yours"
android:textFontWeight="300"
android:textSize="12sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/publish_form_extra_options_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="@font/inter"
android:textSize="20sp"
android:text="@string/additional_options" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:text="@string/language"
android:textFontWeight="300"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/publish_form_language_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="@font/inter"
android:text="@string/license"
android:textFontWeight="300"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/publish_form_license_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/publish_form_license_desc_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="@string/license_desc"
android:visibility="gone">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/publish_form_license_desc_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:inputType="textNoSuggestions"
android:textFontWeight="300"
android:textSize="14sp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/publish_form_toggle_extra"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="24dp"
android:layout_marginRight="16dp"
android:fontFamily="@font/inter"
android:text="@string/show_extra_fields"
android:textFontWeight="300" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_marginTop="24dp">
<TextView
android:id="@+id/publish_form_cancel"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginTop="24dp"
android:fontFamily="@font/inter"
android:text="@string/cancel"
android:textFontWeight="300" />
<com.google.android.material.button.MaterialButton
android:id="@+id/publish_form_publish_button"
android:enabled="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/publish"
android:fontFamily="@font/inter" />
</RelativeLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -102,7 +102,62 @@
<string name="storage_permission_rationale_videos">LBRY requires access to be able to display and publish your videos, images and other files from your device.</string>
<string name="camera_permission_rationale_record">LBRY requires access to your camera to record videos.</string>
<string name="camera_permission_rationale_photo">LBRY requires access to your camera to take photos.</string>
<string name="edit_content">Edit content</string>
<string name="mature_tags">Mature tags</string>
<string name="price">Price</string>
<string name="free_publish">Your content will be free. Press the toggle to set a price.</string>
<string name="content_address">Content address</string>
<string name="address">Address</string>
<string name="content_address_desc">The address where people can find your content (ex. lbry://myvideo)</string>
<string name="license">License</string>
<string name="license_desc">License description</string>
<string name="additional_options">Additional Options</string>
<string name="show_extra_fields">Show extra fields</string>
<string name="hide_extra_fields">Hide extra fields</string>
<string name="no_file_found">No file found to publish.</string>
<string name="sdk_initializing_publish">You cannot publish content right now beceause the background service is still initializing.</string>
<string name="language">Language</string>
<string name="english">English</string>
<string name="chinese">Chinese</string>
<string name="french">French</string>
<string name="german">German</string>
<string name="japanese">Japanese</string>
<string name="russian">Russian</string>
<string name="spanish">Spanish</string>
<string name="indonesian">Indonesian</string>
<string name="italian">Italian</string>
<string name="dutch">Dutch</string>
<string name="turkish">Turkish</string>
<string name="polish">Polish</string>
<string name="malay">Malay</string>
<string name="portuguese">Portuguese</string>
<string name="vietnamese">Vietnamese</string>
<string name="thai">Thai</string>
<string name="arabic">Arabic</string>
<string name="czech">Czech</string>
<string name="croatian">Croatian</string>
<string name="cambodian">Cambodian</string>
<string name="korean">Korean</string>
<string name="norwegian">Norwegian</string>
<string name="romanian">Romanian</string>
<string name="hindi">Hindi</string>
<string name="greek">Greek</string>
<string name="none">None</string>
<string name="public_domain">Public Domain</string>
<string name="copyright">Copyright</string>
<string name="cca_4_0_international">Creative Commons Attribution 4.0 International</string>
<string name="cca_sa_4_0_international">Creative Commons Attribution-ShareAlike 4.0 International</string>
<string name="cca_nd_4_0_international">Creative Commons Attribution-NoDerivatives 4.0 International</string>
<string name="cca_nc_4_0_international">Creative Commons Attribution-NonCommercial 4.0 International</string>
<string name="cca_nc_sa_4_0_international">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</string>
<string name="cca_nc_nd_4_0_international">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International</string>
<string-array name="publish_currencies">
<item>LBC</item>
<item>USD</item>
</string-array>
<!-- Publishes -->
<string name="one_or_more_publishes_failed_abandon">One or more content items could not be deleted at this time. Please try again later.</string>
@ -174,7 +229,7 @@
<string name="receive_credits">Receive Credits</string>
<string name="use_this_address_hint">Use this wallet address to receive credits sent by another user (or yourself).</string>
<string name="get_new_address">Get new address</string>
<string name="generate_address_hint">You can generate a new address at any time, and any previous addresses will conintue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.</string>
<string name="generate_address_hint">You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.</string>
<string name="send_credits">Send Credits</string>
<string name="recipient_address">Recipient address</string>
@ -253,6 +308,7 @@
<string name="no_followed_tags">You have not followed any tags yet. Get started by adding tags that you are interested in!</string>
<string name="no_tag_results">We could not find new tags that you\'re not following.</string>
<string name="tag_already_added">The \'%1$s\' tag has already been added.</string>
<string name="tag_limit_reached">You cannot add more than 5 tags.</string>
<string name="send_a_tip">Send a tip</string>
<string name="send_a_tip_to">Send a tip to %1$s</string>
<string name="send_tip_info_content">This will appear as a tip for %1$s, which will boost its ability to be discovered while active. &lt;a href="https://lbry.com/faq/tipping"&gt;Learn more&lt;/a&gt;.</string>
@ -264,7 +320,7 @@
<string name="show_advanced">Show advanced</string>
<string name="hide_advanced">Hide advanced</string>
<string name="name">Name</string>
<string name="min_repost_deposit">0.01</string>
<string name="min_deposit">0.01</string>
<string name="content_successfully_reposted">The content was successfully reposted!</string>
<string name="repost_name_invalid_characters">The repost name contains invalid characters.</string>
<plurals name="you_sent_a_tip">
@ -317,8 +373,6 @@
<string name="description">Description</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="show_extra">Show extra</string>
<string name="hide_extra">Hide extra</string>
<string name="show_optional_fields">Show optional fields</string>
<string name="hide_optional_fields">Hide optional fields</string>
<string name="save">Save</string>
@ -403,9 +457,11 @@
<!-- Library -->
<string name="downloads">Downloads</string>
<string name="purchases">Purchases</string>
<string name="history">History</string>
<string name="library_no_downloads">You have not downloaded any content to this device.</string>
<string name="library_no_history">You have not viewed any content on this device.</string>
<string name="library_no_purchases">You have not purchased any content on your account.</string>
<string name="hide">Hide</string>
<string name="stats">Stats</string>
<string name="video">Video</string>