Search cache. File view updates. Floating wallet balance.

This commit is contained in:
Akinwale Ariwodola 2020-05-02 17:41:23 +01:00
parent f4b28c4d90
commit 8cb51f5c17
41 changed files with 707 additions and 45 deletions

View file

@ -11,12 +11,14 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.DateUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.preference.PreferenceManager;
@ -39,6 +41,7 @@ import java.util.List;
import io.lbry.browser.adapter.ClaimListAdapter;
import io.lbry.browser.adapter.TagListAdapter;
import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.ClaimCacheKey;
import io.lbry.browser.model.File;
@ -49,11 +52,14 @@ import io.lbry.browser.tasks.LighthouseSearchTask;
import io.lbry.browser.tasks.ResolveTask;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryUri;
public class FileViewActivity extends AppCompatActivity {
public static FileViewActivity instance = null;
private static final int RELATED_CONTENT_SIZE = 16;
private static final int SHARE_REQUEST_CODE = 3001;
private static boolean startingShareActivity;
private SimpleExoPlayer player;
private boolean loadFilePending;
@ -64,6 +70,14 @@ public class FileViewActivity extends AppCompatActivity {
private BroadcastReceiver sdkReadyReceiver;
private Player.EventListener fileViewPlayerListener;
private View buttonShareAction;
private View buttonTipAction;
private View buttonRepostAction;
private View buttonDownloadAction;
private View buttonEditAction;
private View buttonDeleteAction;
private View buttonReportAction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -233,6 +247,14 @@ public class FileViewActivity extends AppCompatActivity {
public void onSuccess(List<Claim> claims) {
if (claims.size() > 0) {
claim = claims.get(0);
if (Claim.TYPE_REPOST.equalsIgnoreCase(claim.getValueType())) {
claim = claim.getRepostedClaim();
// cache the reposted claim too for subsequent loads
ClaimCacheKey key = ClaimCacheKey.fromClaim(claim);
Lbry.claimCache.put(key, claim);
}
checkAndResetNowPlayingClaim();
loadFile();
renderClaim();
@ -263,6 +285,29 @@ public class FileViewActivity extends AppCompatActivity {
}
});
findViewById(R.id.file_view_action_share).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (claim != null) {
try {
String shareUrl = LbryUri.parse(
!Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()).toTvString();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, shareUrl);
startingShareActivity = true;
Intent shareUrlIntent = Intent.createChooser(shareIntent, getString(R.string.share_lbry_content));
shareUrlIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(shareUrlIntent);
} catch (LbryUriException ex) {
// pass
}
}
}
});
RecyclerView relatedContentList = findViewById(R.id.file_view_related_content_list);
relatedContentList.setNestedScrollingEnabled(false);
LinearLayoutManager llm = new LinearLayoutManager(this);
@ -375,6 +420,10 @@ public class FileViewActivity extends AppCompatActivity {
MainActivity.appPlayer.prepare(mediaSource, true, true);
}
private void loadViewCount() {
}
private void loadRelatedContent() {
// reset the list view
((RecyclerView) findViewById(R.id.file_view_related_content_list)).setAdapter(null);
@ -431,6 +480,16 @@ public class FileViewActivity extends AppCompatActivity {
}
protected void onUserLeaveHint() {
if (startingShareActivity) {
// share activity triggered this, so reset the flag at this point
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startingShareActivity = false;
}
}, 1000);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !MainActivity.mainActive) {
PictureInPictureParams params = new PictureInPictureParams.Builder().build();
enterPictureInPictureMode(params);

View file

@ -175,6 +175,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private NavigationMenuAdapter navMenuAdapter;
private UrlSuggestionListAdapter urlSuggestionListAdapter;
private List<UrlSuggestion> recentHistory;
private boolean hasLoadedFirstBalance;
// broadcast receivers
private BroadcastReceiver serviceActionsReceiver;
@ -500,6 +501,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
}
}
Lbry.walletBalance = walletBalance;
updateFloatingWalletBalance();
}
@Override
@ -855,6 +857,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
} else {
scheduleWalletBalanceUpdate();
scheduleWalletSyncTask();
initFloatingWalletBalance();
}
}
@ -863,9 +866,37 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
checkSyncedWallet();
}
//overrideRemoteWallet();
scheduleWalletBalanceUpdate();
scheduleWalletSyncTask();
initFloatingWalletBalance();
}
public void showFloatingWalletBalance() {
findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE);
}
public void hideFloatingWalletBalance() {
findViewById(R.id.floating_balance_main_container).setVisibility(View.GONE);
}
private void initFloatingWalletBalance() {
findViewById(R.id.floating_balance_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openFragment(WalletFragment.class, true, NavMenuItem.ID_ITEM_WALLET);
}
});
}
private void updateFloatingWalletBalance() {
if (!hasLoadedFirstBalance) {
findViewById(R.id.floating_balance_loading).setVisibility(View.GONE);
findViewById(R.id.floating_balance_value).setVisibility(View.VISIBLE);
hasLoadedFirstBalance = true;
}
((TextView) findViewById(R.id.floating_balance_value)).setText(Helper.shortCurrencyFormat(
Lbry.walletBalance == null ? 0 : Lbry.walletBalance.getAvailable().doubleValue()));
}
private void scheduleWalletBalanceUpdate() {

View file

@ -6,7 +6,6 @@ import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
@ -14,13 +13,10 @@ import androidx.recyclerview.widget.RecyclerView;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import io.lbry.browser.R;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.Transaction;
import io.lbry.browser.model.UrlSuggestion;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.LbryUri;
import lombok.Setter;
@ -76,12 +72,22 @@ public class TransactionListAdapter extends RecyclerView.Adapter<TransactionList
vh.amountView.setText(TX_LIST_AMOUNT_FORMAT.format(item.getValue().doubleValue()));
vh.claimView.setText(item.getClaim());
vh.feeView.setText(context.getString(R.string.tx_list_fee, TX_LIST_AMOUNT_FORMAT.format(item.getFee().doubleValue())));
vh.txidLinkView.setText(item.getTxid().substring(0, 8));
vh.txidLinkView.setText(item.getTxid().substring(0, 7));
vh.dateView.setText(TX_LIST_DATE_FORMAT.format(item.getTxDate()));
vh.infoFeeContainer.setVisibility(!Helper.isNullOrEmpty(item.getClaim()) || Math.abs(item.getFee().doubleValue()) > 0 ?
View.VISIBLE : View.GONE);
vh.claimView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LbryUri claimUrl = item.getClaimUrl();
if (claimUrl != null && listener != null) {
listener.onClaimUrlClicked(claimUrl);
}
}
});
vh.txidLinkView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -122,5 +128,6 @@ public class TransactionListAdapter extends RecyclerView.Adapter<TransactionList
public interface TransactionClickListener {
void onTransactionClicked(Transaction transaction);
void onClaimUrlClicked(LbryUri uri);
}
}

View file

@ -5,7 +5,6 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.sql.SQLInput;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

View file

@ -14,14 +14,11 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.LbryUri;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)

View file

@ -1,5 +1,6 @@
package io.lbry.browser.model;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -7,7 +8,9 @@ import java.math.BigDecimal;
import java.util.Date;
import io.lbry.browser.R;
import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.LbryUri;
import lombok.Data;
@Data
@ -16,6 +19,7 @@ public class Transaction {
private Date txDate;
private String date;
private String claim;
private String claimId;
private String txid;
private BigDecimal value;
private BigDecimal fee;
@ -25,6 +29,17 @@ public class Transaction {
private TransactionInfo claimInfo;
private TransactionInfo supportInfo;
public LbryUri getClaimUrl() {
if (!Helper.isNullOrEmpty(claim) && !Helper.isNullOrEmpty(claimId)) {
try {
return LbryUri.parse(LbryUri.normalize(String.format("%s#%s", claim, claimId)));
} catch (LbryUriException ex) {
// pass
}
}
return null;
}
public static Transaction fromJSONObject(JSONObject jsonObject) {
Transaction transaction = new Transaction();
transaction.setConfirmations(Helper.getJSONInt("confirmations", -1, jsonObject));
@ -39,26 +54,41 @@ public class Transaction {
TransactionInfo info = null;
try {
if (jsonObject.has("abandon_info")) {
info = TransactionInfo.fromJSONObject(jsonObject.getJSONObject("abandon_info"));
JSONArray array = jsonObject.getJSONArray("abandon_info");
if (array.length() > 0) {
info = TransactionInfo.fromJSONObject(array.getJSONObject(0));
descStringId = R.string.abandon;
transaction.setAbandonInfo(info);
} else if (jsonObject.has("claim_info")) {
info = TransactionInfo.fromJSONObject(jsonObject.getJSONObject("claim_info"));
}
}
if (info == null && jsonObject.has("claim_info")) {
JSONArray array = jsonObject.getJSONArray("claim_info");
if (array.length() > 0) {
info = TransactionInfo.fromJSONObject(array.getJSONObject(0));
descStringId = info.getClaimName().startsWith("@") ? R.string.channel : R.string.publish;
transaction.setClaimInfo(info);
} else if (jsonObject.has("support_info")) {
info = TransactionInfo.fromJSONObject(jsonObject.getJSONObject("support_info"));
}
}
if (info == null && jsonObject.has("support_info")) {
JSONArray array = jsonObject.getJSONArray("support_info");
if (array.length() > 0) {
info = TransactionInfo.fromJSONObject(array.getJSONObject(0));
descStringId = info.isTip() ? R.string.tip : R.string.support;
transaction.setSupportInfo(info);
}
}
if (info != null) {
transaction.setClaim(info.getClaimName());
transaction.setClaimId(info.getClaimId());
}
} catch (JSONException ex) {
// pass
}
if (transaction.getValue().doubleValue() == 0 && info != null && info.getBalanceDelta().doubleValue() != 0) {
transaction.setValue(info.getBalanceDelta());
}
if (descStringId == -1) {
descStringId = transaction.getValue().signum() == -1 || transaction.getFee().signum() == -1 ? R.string.spend : R.string.receive;
}
@ -71,6 +101,7 @@ public class Transaction {
public static class TransactionInfo {
private String address;
private BigDecimal amount;
private BigDecimal balanceDelta;
private String claimId;
private String claimName;
private boolean isTip;
@ -81,6 +112,7 @@ public class Transaction {
info.setAddress(Helper.getJSONString("address", null, jsonObject));
info.setAmount(new BigDecimal(Helper.getJSONString("amount", "0", jsonObject)));
info.setBalanceDelta(new BigDecimal(Helper.getJSONString("balance_delta", "0", jsonObject)));
info.setClaimId(Helper.getJSONString("claim_id", null, jsonObject));
info.setClaimName(Helper.getJSONString("claim_name", null, jsonObject));
info.setTip(Helper.getJSONBoolean("is_tip", false, jsonObject));

View file

@ -64,7 +64,7 @@ public class SyncGetTask extends AsyncTask<Void, Void, WalletSync> {
//Lbry.sync_apply({ password, data: response.data, blocking: true });
try {
Map<String, Object> options = new HashMap<>();
options.put("hash", walletSync.getHash());
options.put("password", Helper.isNullOrEmpty(password) ? "" : password);
options.put("data", walletSync.getData());
options.put("blocking", true);

View file

@ -10,7 +10,6 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

View file

@ -3,9 +3,6 @@ package io.lbry.browser.ui.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
@ -21,14 +18,6 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
setPreferencesFromResource(R.xml.settings, rootKey);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
view.setBackgroundColor(getResources().getColor(R.color.pageBackground));
return view;
}
@Override
public void onStart() {
super.onStart();
@ -37,6 +26,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
activity.hideSearchBar();
activity.showNavigationBackIcon();
activity.lockDrawer();
activity.hideFloatingWalletBalance();
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
@ -59,7 +49,9 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
public void onStop() {
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context).restoreToggle();
MainActivity activity = (MainActivity) getContext();
activity.restoreToggle();
activity.showFloatingWalletBalance();
}
super.onStop();
}
@ -68,6 +60,13 @@ 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 activity = (MainActivity) context;
activity.getDelegate().applyDayNight();
activity.recreate();
}
}
}
}

View file

@ -0,0 +1,158 @@
package io.lbry.browser.ui.wallet;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import io.lbry.browser.MainActivity;
import io.lbry.browser.R;
import io.lbry.browser.adapter.TransactionListAdapter;
import io.lbry.browser.model.Transaction;
import io.lbry.browser.tasks.wallet.TransactionListTask;
import io.lbry.browser.ui.BaseFragment;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.LbryUri;
public class TransactionHistoryFragment extends BaseFragment implements TransactionListAdapter.TransactionClickListener {
private static final int TRANSACTION_PAGE_LIMIT = 50;
private boolean transactionsHaveReachedEnd;
private boolean transactionsLoading;
private ProgressBar loading;
private RecyclerView transactionList;
private TransactionListAdapter adapter;
private View noTransactionsView;
private int currentTransactionPage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_transaction_history, container, false);
loading = root.findViewById(R.id.transaction_history_loading);
transactionList = root.findViewById(R.id.transaction_history_list);
noTransactionsView = root.findViewById(R.id.transaction_history_no_transactions);
Context context = getContext();
LinearLayoutManager llm = new LinearLayoutManager(context);
transactionList.setLayoutManager(llm);
transactionList.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
transactionList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (transactionsLoading) {
return;
}
LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
if (lm != null) {
int visibleItemCount = lm.getChildCount();
int totalItemCount = lm.getItemCount();
int pastVisibleItems = lm.findFirstVisibleItemPosition();
if (pastVisibleItems + visibleItemCount >= totalItemCount) {
if (!transactionsHaveReachedEnd) {
// load more
currentTransactionPage++;
loadTransactions();
}
}
}
}
});
return root;
}
@Override
public void onResume() {
super.onResume();
if (adapter != null && adapter.getItemCount() > 0 && transactionList != null) {
transactionList.setAdapter(adapter);
}
loadTransactions();
}
private void checkNoTransactions() {
Helper.setViewVisibility(noTransactionsView, adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
private void loadTransactions() {
currentTransactionPage = currentTransactionPage == 0 ? 1 : currentTransactionPage;
transactionsLoading = true;
TransactionListTask task = new TransactionListTask(currentTransactionPage, TRANSACTION_PAGE_LIMIT, loading, new TransactionListTask.TransactionListHandler() {
@Override
public void onSuccess(List<Transaction> transactions, boolean hasReachedEnd) {
transactionsLoading = false;
transactionsHaveReachedEnd = hasReachedEnd;
if (adapter == null) {
adapter = new TransactionListAdapter(transactions, getContext());
adapter.setListener(TransactionHistoryFragment.this);
if (transactionList != null) {
transactionList.setAdapter(adapter);
}
} else {
adapter.addTransactions(transactions);
}
checkNoTransactions();
}
@Override
public void onError(Exception error) {
transactionsLoading = false;
checkNoTransactions();
}
});
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
public void onStart() {
super.onStart();
MainActivity activity = (MainActivity) getContext();
if (activity != null) {
activity.hideSearchBar();
activity.showNavigationBackIcon();
activity.lockDrawer();
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.transaction_history);
}
}
}
@Override
public void onStop() {
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context).restoreToggle();
}
super.onStop();
}
public void onTransactionClicked(Transaction transaction) {
// Don't do anything? Or open the transaction in a browser?
}
public void onClaimUrlClicked(LbryUri uri) {
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
if (uri.isChannel()) {
activity.openChannelUrl(uri.toString());
} else {
MainActivity.openFileUrl(uri.toString(), context);
}
}
}
}

View file

@ -4,7 +4,6 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.gesture.Gesture;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
@ -19,7 +18,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -38,6 +36,7 @@ import io.lbry.browser.R;
import io.lbry.browser.adapter.TransactionListAdapter;
import io.lbry.browser.listener.SdkStatusListener;
import io.lbry.browser.listener.WalletBalanceListener;
import io.lbry.browser.model.NavMenuItem;
import io.lbry.browser.model.Transaction;
import io.lbry.browser.model.WalletBalance;
import io.lbry.browser.tasks.wallet.TransactionListTask;
@ -219,7 +218,6 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
recentTransactionsList.setLayoutManager(llm);
recentTransactionsList.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
buttonGetNewAddress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -272,6 +270,16 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
}
});
linkViewAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context).openFragment(TransactionHistoryFragment.class, true, NavMenuItem.ID_ITEM_WALLET);
}
}
});
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
final boolean walletSyncEnabled = sp.getBoolean(MainActivity.PREFERENCE_KEY_INTERNAL_WALLET_SYNC_ENABLED, false);
switchSyncStatus.setChecked(walletSyncEnabled);
@ -398,12 +406,21 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
hasFetchedRecentTransactions = false;
super.onPause();
}
public void onStart() {
super.onStart();
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
activity.hideFloatingWalletBalance();
}
}
public void onStop() {
Context context = getContext();
if (context instanceof MainActivity) {
MainActivity activity = (MainActivity) context;
activity.removeWalletBalanceListener(this);
activity.showFloatingWalletBalance();
}
super.onStop();
}

View file

@ -10,6 +10,7 @@ import lombok.Data;
@Data
public class LbryUri {
public static final String LBRY_TV_BASE_URL = "https://lbry.tv";
public static final String PROTO_DEFAULT = "lbry://";
public static final String REGEX_INVALID_URI = "[ =&#:$@%?;/\\\\\"<>%\\{\\}|^~\\[\\]`\u0000-\u0008\u000b-\u000c\u000e-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]";
public static final String REGEX_ADDRESS = "^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$";
@ -38,6 +39,10 @@ public class LbryUri {
private String contentName;
private String queryString;
private boolean isChannelUrl() {
return (!Helper.isNullOrEmpty(channelName) && Helper.isNullOrEmpty(streamName)) || (!Helper.isNullOrEmpty(claimName) && claimName.startsWith("@"));
}
public static LbryUri parse(String url) throws LbryUriException {
return parse(url, false);
}
@ -209,6 +214,59 @@ public class LbryUri {
return sb.toString();
}
public String toTvString() {
String formattedChannelName = null;
if (channelName != null) {
formattedChannelName = channelName.startsWith("@") ? channelName : String.format("@%s", channelName);
}
String primaryClaimName = claimName;
if (Helper.isNullOrEmpty(primaryClaimName)) {
primaryClaimName = contentName;
}
if (Helper.isNullOrEmpty(primaryClaimName)) {
primaryClaimName = formattedChannelName;
}
if (Helper.isNullOrEmpty(primaryClaimName)) {
primaryClaimName = streamName;
}
String primaryClaimId = claimId;
if (Helper.isNullOrEmpty(primaryClaimId)) {
primaryClaimId = !Helper.isNullOrEmpty(formattedChannelName) ? channelClaimId : streamClaimId;
}
StringBuilder sb = new StringBuilder();
sb.append(LBRY_TV_BASE_URL).append('/');
sb.append(primaryClaimName);
String secondaryClaimName = null;
if (Helper.isNullOrEmpty(claimName) && !Helper.isNullOrEmpty(contentName)) {
secondaryClaimName = contentName;
}
if (Helper.isNullOrEmpty(secondaryClaimName)) {
secondaryClaimName = !Helper.isNullOrEmpty(formattedChannelName) ? streamName : null;
}
String secondaryClaimId = !Helper.isNullOrEmpty(secondaryClaimName) ? streamClaimId : null;
if (!Helper.isNullOrEmpty(primaryClaimId)) {
sb.append('#').append(primaryClaimId);
}
if (primaryClaimSequence > 0) {
sb.append(':').append(primaryClaimSequence);
}
if (!Helper.isNullOrEmpty(secondaryClaimName)) {
sb.append('/').append(secondaryClaimName);
}
if (!Helper.isNullOrEmpty(secondaryClaimId)) {
sb.append('#').append(secondaryClaimId);
}
if (secondaryClaimSequence > 0) {
sb.append(':').append(secondaryClaimSequence);
}
return sb.toString();
}
public static String normalize(String url) throws LbryUriException {
return parse(url).toString();
}

View file

@ -22,6 +22,19 @@ import okhttp3.Response;
public class Lighthouse {
public static final String CONNECTION_STRING = "https://lighthouse.lbry.com";
public static Map<String, List<UrlSuggestion>> autocompleteCache = new HashMap<>();
public static Map<Map<String, Object>, List<Claim>> searchCache = new HashMap<>();
private static Map<String, Object> buildSearchOptionsKey(String rawQuery, int size, int from, boolean nsfw, String relatedTo) {
Map<String, Object> options = new HashMap<>();
options.put("s", rawQuery);
options.put("size", size);
options.put("from", from);
options.put("nsfw", nsfw);
if (!Helper.isNullOrEmpty(relatedTo)) {
options.put("related_to", relatedTo);
}
return options;
}
public static List<Claim> search(String rawQuery, int size, int from, boolean nsfw, String relatedTo) throws LbryRequestException, LbryResponseException {
Uri.Builder uriBuilder = Uri.parse(String.format("%s/search", CONNECTION_STRING)).buildUpon().
@ -34,6 +47,11 @@ public class Lighthouse {
uriBuilder.appendQueryParameter("related_to", relatedTo);
}
Map<String, Object> cacheKey = buildSearchOptionsKey(rawQuery, size, from, nsfw, relatedTo);
if (searchCache.containsKey(cacheKey)) {
return searchCache.get(cacheKey);
}
List<Claim> results = new ArrayList<>();
Request request = new Request.Builder().url(uriBuilder.toString()).build();
OkHttpClient client = new OkHttpClient();
@ -45,6 +63,7 @@ public class Lighthouse {
Claim claim = Claim.fromSearchJSONObject(array.getJSONObject(i));
results.add(claim);
}
searchCache.put(cacheKey, results);
} else {
throw new LbryResponseException(response.message());
}

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<path
android:fillColor="#FF000000"
android:pathData="M15.41,16.09l-4.58,-4.59 4.58,-4.59L14,5.5l-6,6 6,6z"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<path
android:fillColor="#FF000000"
android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<path
android:fillColor="#FF000000"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<path
android:fillColor="#FF000000"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/lbryGreen" />
<corners android:radius="24dp" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/brighterLbryGreen" />
<corners android:radius="24dp" />
</shape>

View file

@ -39,13 +39,20 @@
android:layout_weight="10"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible">
android:visibility="visible">
<RelativeLayout
android:id="@+id/file_view_media_container"
android:background="@color/mediaContainerBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3.25">
<!--RelativeLayout
android:id="@+id/file_view_media_meta_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout-->
<RelativeLayout
android:id="@+id/file_view_exoplayer_container"
android:background="@android:color/black"
@ -196,7 +203,112 @@
<TextView
android:fontFamily="@font/inter"
android:textSize="12sp"
android:text="Share"
android:text="@string/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/file_vew_action_tip"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<io.lbry.browser.ui.controls.SolidIconView
android:textColor="@color/foreground"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:textSize="20dp"
android:text="@string/fa_gift"/>
<TextView
android:fontFamily="@font/inter"
android:textSize="12sp"
android:text="@string/tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/file_vew_action_repost"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<io.lbry.browser.ui.controls.SolidIconView
android:textColor="@color/foreground"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:textSize="20dp"
android:text="@string/fa_repost"/>
<TextView
android:fontFamily="@font/inter"
android:textSize="12sp"
android:text="@string/repost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/file_view_action_edit"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:visibility="gone"
>
<ImageView
android:tint="@color/foreground"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_edit" />
<TextView
android:fontFamily="@font/inter"
android:textSize="12sp"
android:text="@string/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/file_view_action_delete"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:visibility="gone">
<ImageView
android:tint="@color/foreground"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_delete" />
<TextView
android:fontFamily="@font/inter"
android:textSize="12sp"
android:text="@string/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />

View file

@ -29,6 +29,7 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:fontFamily="@font/inter"
android:text="@string/view_all"

View file

@ -28,17 +28,18 @@
android:layout_height="match_parent" />
</RelativeLayout>
<include layout="@layout/floating_wallet_balance" />
<androidx.cardview.widget.CardView
android:id="@+id/global_now_playing_card"
android:clickable="true"
android:elevation="4dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:visibility="gone"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent">
<RelativeLayout
android:orientation="horizontal"
@ -100,7 +101,4 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="invisible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/floating_balance_main_container"
android:background="@android:color/transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginRight="8dp"
android:elevation="4dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/floating_reward_container"
android:clickable="true"
android:background="@drawable/bg_floating_reward"
android:foreground="?attr/selectableItemBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingLeft="8dp"
android:paddingRight="44dp"
android:visibility="invisible">
<io.lbry.browser.ui.controls.SolidIconView
android:layout_width="16dp"
android:layout_height="16dp"
android:textSize="10dp"
android:layout_gravity="center_vertical"
android:textColor="@color/white"
android:text="@string/fa_award" />
<TextView
android:id="@+id/floating_reward_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_gravity="center_vertical"
android:fontFamily="@font/inter"
android:textColor="@color/white"
android:text="@string/zero"
android:textSize="14sp"
android:textStyle="bold"
android:textFontWeight="300" />
</LinearLayout>
<LinearLayout
android:id="@+id/floating_balance_container"
android:clickable="true"
android:background="@drawable/bg_floating_balance"
android:foreground="?attr/selectableItemBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/floating_reward_container"
android:layout_marginLeft="-36dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingLeft="12dp"
android:paddingRight="16dp">
<io.lbry.browser.ui.controls.SolidIconView
android:layout_width="16dp"
android:layout_height="16dp"
android:textSize="10dp"
android:layout_gravity="center_vertical"
android:textColor="@color/white"
android:text="@string/fa_coins" />
<TextView
android:id="@+id/floating_balance_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_gravity="center_vertical"
android:fontFamily="@font/inter"
android:textColor="@color/white"
android:text="@string/zero"
android:textSize="14sp"
android:textStyle="bold"
android:textFontWeight="300"
android:visibility="gone" />
<ProgressBar
android:id="@+id/floating_balance_loading"
android:layout_gravity="center_vertical"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginLeft="2dp" />
</LinearLayout>
</RelativeLayout>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/transaction_history_no_transactions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:fontFamily="@font/inter"
android:textSize="14sp"
android:text="@string/no_transactions"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/transaction_history_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/transaction_history_loading"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="16dp"
android:layout_centerHorizontal="true" />
</RelativeLayout>

View file

@ -58,6 +58,7 @@
<string name="report">Report</string>
<string name="loading_decentralized_data">Loading decentralized data...</string>
<string name="related_content">Related Content</string>
<string name="share_lbry_content">Share LBRY content</string>
<string name="unsupported_content">Unsupported Content</string>
<string name="unsupported_content_desc">Sorry, we are unable to display this content in the app. You can find the file named %1$s in your downloads folder.</string>
@ -156,7 +157,9 @@
<string name="send_credit_error">Your credits could not be sent at this time. Please try again later.</string>
<string name="loading_transactions">Loading transactions...</string>
<string name="no_recent_transactions">There are no recent transactions to display.</string>
<string name="no_transactions">There are no transactions to display at this time.</string>
<string name="tx_list_fee">fee %1$s</string>
<string name="transaction_history">Transaction History</string>
<plurals name="you_sent_credits">
<item quantity="one">You sent %1$s credit</item>