Compare commits

...

14 commits

Author SHA1 Message Date
jessopb
fdd759b241
Merge pull request #1236 from ktprograms/readme-google-services
Add google-services.json instructions to README
2022-11-29 13:07:52 -05:00
jessopb
57cd649c02
Update README.md 2022-11-29 13:07:30 -05:00
jessopb
7250435d7f
Create deploy.yml 2022-11-25 14:03:02 -05:00
jessopb
b81abf74a1
Merge pull request #1244 from Coolguy3289/patch-1
Update LBRY_TV_CONNECTION_STRING to new Odysee Backend
2022-11-23 13:59:38 -05:00
Ralph
208e2c2d42
Update LBRY_TV_CONNECTION_STRING to new Odysee Backend 2022-11-23 11:29:52 -05:00
kt programs
a5bdd1c042 Add google-services.json instructions to README 2022-04-18 12:14:25 +08:00
Alex Grin
1e3a74cae1
Update README.md 2021-09-28 10:19:37 -04:00
Akinwale Ariwodola
ca08f71a72 sdk 0.102.0 2021-08-20 15:32:14 +01:00
Akinwale Ariwodola
b60ca39df1 fix crash bug when trying to play content 2021-08-19 12:27:18 +01:00
soup-jingle
696bc86b7c
Added QR scanner to wallet send card (#1194)
* Added QR scanner to wallet send card

* * app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java:

Changed orientation of QR scanner, along with some style corrections

* Revert "* app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java:"

This reverts commit 519c45ae0d.

* Fixed orientation of QR scanner activity, plus style corrections
2021-08-13 09:01:53 +01:00
Akinwale Ariwodola
4c163c6244
Merge pull request #1216 from lbryio/new_cdn_url
Use the new CDN url scheme for thumbnails
2021-08-13 09:01:09 +01:00
Akinwale Ariwodola
2ad49ca281
Merge pull request #1208 from lbryio/claimid-modifier-char
Accept colon or octoshape as claimID modifier character
2021-08-11 10:20:58 +01:00
Javi Rueda
56caeef72b Use the new CDN url scheme for thumbnails 2021-08-10 18:28:20 +02:00
Javi Rueda
84bb014557 Accept colon or octoshape as claimID modifier character and add unit tests 2021-07-29 00:55:45 +02:00
26 changed files with 166 additions and 51 deletions

1
.github/workflows/deploy.yml vendored Normal file
View file

@ -0,0 +1 @@

View file

@ -28,6 +28,8 @@ twitterConsumerKey=XXXXXX
twitterConsumerSecret=XXXXXX twitterConsumerSecret=XXXXXX
``` ```
Copy the file 'google-services.sample.json' to 'google-services.json' in the app/ folder.
Click the Sync button and when process finishes, the Run button to launch the app on your simulator or connected debugging device after the build process is complete. Click the Sync button and when process finishes, the Run button to launch the app on your simulator or connected debugging device after the build process is complete.
## Contributing ## Contributing
@ -37,7 +39,7 @@ Contributions to this project are welcome, encouraged, and compensated. For more
This project is MIT licensed. For the full license, see [LICENSE](LICENSE). This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
## Security ## Security
We take security seriously. Please contact security@lbry.com regarding any security issues. Our PGP key is [here](https://keybase.io/lbry/key.asc) if you need it. We take security seriously. Please contact security@lbry.com regarding any security issues. Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it.
## Contact ## Contact
The primary contact for this project is [@akinwale](https://github.com/akinwale) (akinwale@lbry.com) The primary contact for this project is [@akinwale](https://github.com/akinwale) (akinwale@lbry.com)

View file

@ -21,7 +21,7 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
packagingOptions { packagingOptions {
exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/DEPENDENCIES'
exclude 'lib/x86_64/darwin/libscrypt.dylib' exclude 'lib/x86_64/darwin/libscrypt.dylib'
} }
@ -122,6 +122,9 @@ dependencies {
implementation 'org.bitcoinj:bitcoinj-tools:0.14.7' implementation 'org.bitcoinj:bitcoinj-tools:0.14.7'
implementation 'org.java-websocket:Java-WebSocket:1.5.1' implementation 'org.java-websocket:Java-WebSocket:1.5.1'
implementation ('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
implementation 'com.google.zxing:core:3.3.0'
compileOnly 'org.projectlombok:lombok:1.18.10' compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10' annotationProcessor 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
@ -132,8 +135,8 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
__32bitImplementation 'io.lbry:lbrysdk32:0.100.0' __32bitImplementation 'io.lbry:lbrysdk32:0.102.0'
__64bitImplementation 'io.lbry:lbrysdk64:0.100.0' __64bitImplementation 'io.lbry:lbrysdk64:0.102.0'
//__64bitImplementation(name: 'lbrysdk', ext: 'aar') //__64bitImplementation(name: 'lbrysdk', ext: 'aar')
} }

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.lbry.browser" package="io.lbry.browser"
android:installLocation="auto"> android:installLocation="auto">
@ -13,6 +14,8 @@
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@ -98,6 +101,11 @@
android:theme="@style/AppTheme.NoActionBarTranslucent" android:theme="@style/AppTheme.NoActionBarTranslucent"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="screenOrientation" />
<service <service
android:name="io.lbry.browser.LbrynetMessagingService" android:name="io.lbry.browser.LbrynetMessagingService"
android:exported="false"> android:exported="false">

View file

@ -2102,7 +2102,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
if (nowPlayingClaimBitmap == null && if (nowPlayingClaimBitmap == null &&
nowPlayingClaim != null && nowPlayingClaim != null &&
!Helper.isNullOrEmpty(nowPlayingClaim.getThumbnailUrl())) { !Helper.isNullOrEmpty(nowPlayingClaim.getThumbnailUrl())) {
Glide.with(getApplicationContext()).asBitmap().load(nowPlayingClaim.getThumbnailUrl()).into(new CustomTarget<Bitmap>() { Glide.with(getApplicationContext()).asBitmap().load(nowPlayingClaim.getThumbnailUrl(0, 0, 75)).into(new CustomTarget<Bitmap>() {
@Override @Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
nowPlayingClaimBitmap = resource; nowPlayingClaimBitmap = resource;

View file

@ -95,7 +95,7 @@ public class ChannelFilterListAdapter extends RecyclerView.Adapter<ChannelFilter
vh.allView.setVisibility(claim.isPlaceholder() ? View.VISIBLE : View.GONE); vh.allView.setVisibility(claim.isPlaceholder() ? View.VISIBLE : View.GONE);
vh.titleView.setText(Helper.isNullOrEmpty(claim.getTitle()) ? claim.getName() : claim.getTitle()); vh.titleView.setText(Helper.isNullOrEmpty(claim.getTitle()) ? claim.getName() : claim.getTitle());
String thumbnailUrl = claim.getThumbnailUrl(); String thumbnailUrl = claim.getThumbnailUrl(vh.thumbnailView.getLayoutParams().width, vh.thumbnailView.getLayoutParams().height, 85);
if (!Helper.isNullOrEmpty(thumbnailUrl) && context != null) { if (!Helper.isNullOrEmpty(thumbnailUrl) && context != null) {
Glide.with(context.getApplicationContext()).load(thumbnailUrl).apply(RequestOptions.circleCropTransform()).into(vh.thumbnailView); Glide.with(context.getApplicationContext()).load(thumbnailUrl).apply(RequestOptions.circleCropTransform()).into(vh.thumbnailView);
} }

View file

@ -334,7 +334,8 @@ public class ClaimListAdapter extends RecyclerView.Adapter<ClaimListAdapter.View
if (metadata instanceof Claim.StreamMetadata) { if (metadata instanceof Claim.StreamMetadata) {
streamMetadata = (Claim.StreamMetadata) metadata; streamMetadata = (Claim.StreamMetadata) metadata;
} }
String thumbnailUrl = item.getThumbnailUrl();
String thumbnailUrl = item.getThumbnailUrl(vh.thumbnailView.getLayoutParams().width, vh.thumbnailView.getLayoutParams().height, 85);
long publishTime = (streamMetadata != null && streamMetadata.getReleaseTime() > 0) ? streamMetadata.getReleaseTime() * 1000 : item.getTimestamp() * 1000; long publishTime = (streamMetadata != null && streamMetadata.getReleaseTime() > 0) ? streamMetadata.getReleaseTime() * 1000 : item.getTimestamp() * 1000;
int bgColor = Helper.generateRandomColorForValue(item.getClaimId()); int bgColor = Helper.generateRandomColorForValue(item.getClaimId());
if (bgColor == 0) { if (bgColor == 0) {

View file

@ -190,7 +190,7 @@ public class CommentListAdapter extends RecyclerView.Adapter<CommentListAdapter.
int bgColor = Helper.generateRandomColorForValue(comment.getChannelId()); int bgColor = Helper.generateRandomColorForValue(comment.getChannelId());
Helper.setIconViewBackgroundColor(holder.noThumbnailView, bgColor, false, context); Helper.setIconViewBackgroundColor(holder.noThumbnailView, bgColor, false, context);
if (hasThumbnail) { if (hasThumbnail) {
Glide.with(context.getApplicationContext()).asBitmap().load(comment.getPoster().getThumbnailUrl()). Glide.with(context.getApplicationContext()).asBitmap().load(comment.getPoster().getThumbnailUrl(holder.thumbnailView.getLayoutParams().width, holder.thumbnailView.getLayoutParams().height, 85)).
apply(RequestOptions.circleCropTransform()).into(holder.thumbnailView); apply(RequestOptions.circleCropTransform()).into(holder.thumbnailView);
} }
holder.alphaView.setText(comment.getChannelName() != null ? comment.getChannelName().substring(1, 2).toUpperCase() : null); holder.alphaView.setText(comment.getChannelName() != null ? comment.getChannelName().substring(1, 2).toUpperCase() : null);

View file

@ -193,7 +193,7 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
vh.thumbnailView.setVisibility(notification.getCommentAuthor() == null ? View.INVISIBLE : View.VISIBLE); vh.thumbnailView.setVisibility(notification.getCommentAuthor() == null ? View.INVISIBLE : View.VISIBLE);
if (notification.getCommentAuthor() != null) { if (notification.getCommentAuthor() != null) {
Glide.with(context.getApplicationContext()).load( Glide.with(context.getApplicationContext()).load(
notification.getCommentAuthor().getThumbnailUrl()).apply(RequestOptions.circleCropTransform()).into(vh.thumbnailView); notification.getCommentAuthor().getThumbnailUrl(vh.thumbnailView.getLayoutParams().width, vh.thumbnailView.getLayoutParams().height, 85)).apply(RequestOptions.circleCropTransform()).into(vh.thumbnailView);
} }
vh.iconView.setVisibility(notification.getCommentAuthor() != null ? View.INVISIBLE : View.VISIBLE); vh.iconView.setVisibility(notification.getCommentAuthor() != null ? View.INVISIBLE : View.VISIBLE);

View file

@ -89,7 +89,8 @@ public class SuggestedChannelGridAdapter extends RecyclerView.Adapter<SuggestedC
@Override @Override
public void onBindViewHolder(SuggestedChannelGridAdapter.ViewHolder vh, int position) { public void onBindViewHolder(SuggestedChannelGridAdapter.ViewHolder vh, int position) {
Claim claim = items.get(position); Claim claim = items.get(position);
String thumbnailUrl = claim.getThumbnailUrl(); ViewGroup.LayoutParams lp = vh.thumbnailView.getLayoutParams();
String thumbnailUrl = claim.getThumbnailUrl(lp.width, lp.height, 85);
int bgColor = Helper.generateRandomColorForValue(claim.getClaimId()); int bgColor = Helper.generateRandomColorForValue(claim.getClaimId());
Helper.setIconViewBackgroundColor(vh.noThumbnailView, bgColor, false, context); Helper.setIconViewBackgroundColor(vh.noThumbnailView, bgColor, false, context);

View file

@ -1,5 +1,7 @@
package io.lbry.browser.model; package io.lbry.browser.model;
import androidx.annotation.Nullable;
import com.google.gson.FieldNamingPolicy; import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -184,6 +186,21 @@ public class Claim {
return null; return null;
} }
/**
* Gets the URL from the CDN where getting the image file
* @param width Pass zero for width and height for the full size image file
* @param height Pass zero for width and height for the full size image file
* @param q Desired quality for the image to be retrieved
* @return URL from the CDN from where image can be retrieved
*/
public String getThumbnailUrl(int width, int height, int q) {
if (value != null && value.getThumbnail() != null) {
ImageCDNUrl imageCDNUrl = new ImageCDNUrl(Math.max(width, 0), Math.max(height, 0), q, null, value.getThumbnail().getUrl());
return imageCDNUrl.toString();
}
return null;
}
public String getCoverUrl() { public String getCoverUrl() {
if (TYPE_CHANNEL.equals(valueType) && value != null && value instanceof ChannelMetadata && ((ChannelMetadata) value).getCover() != null) { if (TYPE_CHANNEL.equals(valueType) && value != null && value instanceof ChannelMetadata && ((ChannelMetadata) value).getCover() != null) {
return ((ChannelMetadata) value).getCover().getUrl(); return ((ChannelMetadata) value).getCover().getUrl();
@ -491,6 +508,30 @@ public class Claim {
private String url; private String url;
} }
/**
* Object to be instantiated. In order to get the URLto the CDN, call toString() on it
*/
static class ImageCDNUrl {
private String appendedPath = "";
public ImageCDNUrl(int width, int height, int quality, @Nullable String format, String thumbnailUrl) {
if (width != 0 && height != 0)
appendedPath = "s:".concat(String.valueOf(width)).concat(":").concat(String.valueOf(height)).concat("/");
appendedPath = appendedPath.concat("quality:").concat(String.valueOf(quality)).concat("/");
appendedPath = appendedPath.concat("plain/").concat(thumbnailUrl);
if (format != null)
appendedPath = appendedPath.concat("@").concat(format);
}
@Override
public String toString() {
String url = "https://image-processor.vanwanet.com/optimize/";
return url.concat(appendedPath);
}
}
@Data @Data
public static class StreamInfo { public static class StreamInfo {
private long duration; // video / audio private long duration; // video / audio

View file

@ -467,7 +467,7 @@ public class ChannelCommentsFragment extends Fragment implements SdkStatusListen
if (hasThumbnail && context != null) { if (hasThumbnail && context != null) {
Glide.with(context.getApplicationContext()). Glide.with(context.getApplicationContext()).
asBitmap(). asBitmap().
load(channel.getThumbnailUrl()). load(channel.getThumbnailUrl(commentPostAsThumbnail.getLayoutParams().width, commentPostAsThumbnail.getLayoutParams().height, 85)).
apply(RequestOptions.circleCropTransform()). apply(RequestOptions.circleCropTransform()).
into(commentPostAsThumbnail); into(commentPostAsThumbnail);
} }

View file

@ -285,7 +285,7 @@ public class ChannelFormFragment extends BaseFragment implements
coverUrl = currentClaim.getCoverUrl(); coverUrl = currentClaim.getCoverUrl();
} }
if (!Helper.isNullOrEmpty(currentClaim.getThumbnailUrl())) { if (!Helper.isNullOrEmpty(currentClaim.getThumbnailUrl())) {
Glide.with(context.getApplicationContext()).load(currentClaim.getThumbnailUrl()).apply(RequestOptions.circleCropTransform()).into(imageThumbnail); Glide.with(context.getApplicationContext()).load(currentClaim.getThumbnailUrl(imageThumbnail.getLayoutParams().width, imageThumbnail.getLayoutParams().height, 85)).apply(RequestOptions.circleCropTransform()).into(imageThumbnail);
thumbnailUrl = currentClaim.getThumbnailUrl(); thumbnailUrl = currentClaim.getThumbnailUrl();
} }
} }

View file

@ -538,11 +538,15 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
else else
buttonTip.setVisibility(View.VISIBLE); buttonTip.setVisibility(View.VISIBLE);
String thumbnailUrl = claim.getThumbnailUrl(); String thumbnailUrl = "";
String coverUrl = claim.getCoverUrl(); String coverUrl = claim.getCoverUrl();
textTitle.setText(Helper.isNullOrEmpty(claim.getTitle()) ? claim.getName() : claim.getTitle()); textTitle.setText(Helper.isNullOrEmpty(claim.getTitle()) ? claim.getName() : claim.getTitle());
Context context = getContext(); Context context = getContext();
if (context != null) {
thumbnailUrl = claim.getThumbnailUrl(imageThumbnail.getLayoutParams().width, imageThumbnail.getLayoutParams().height, 85);
}
if (context != null && !Helper.isNullOrEmpty(coverUrl)) { if (context != null && !Helper.isNullOrEmpty(coverUrl)) {
Glide.with(context.getApplicationContext()).load(coverUrl).centerCrop().into(imageCover); Glide.with(context.getApplicationContext()).load(coverUrl).centerCrop().into(imageCover);
} }

View file

@ -316,7 +316,10 @@ public class FileViewFragment extends BaseFragment implements
hideBuffering(); hideBuffering();
if (loadingNewClaim) { if (loadingNewClaim) {
MainActivity.appPlayer.setPlayWhenReady(Objects.requireNonNull((MainActivity) (getActivity())).isMediaAutoplayEnabled()); Context context = getContext();
if (context instanceof MainActivity) {
MainActivity.appPlayer.setPlayWhenReady(((MainActivity) context).isMediaAutoplayEnabled());
}
loadingNewClaim = false; loadingNewClaim = false;
} }
} else if (playbackState == Player.STATE_BUFFERING) { } else if (playbackState == Player.STATE_BUFFERING) {
@ -1566,7 +1569,8 @@ public class FileViewFragment extends BaseFragment implements
int bgColor = Helper.generateRandomColorForValue(signingChannel.getClaimId()); int bgColor = Helper.generateRandomColorForValue(signingChannel.getClaimId());
Helper.setIconViewBackgroundColor(root.findViewById(R.id.file_view_publisher_no_thumbnail), bgColor, false, context); Helper.setIconViewBackgroundColor(root.findViewById(R.id.file_view_publisher_no_thumbnail), bgColor, false, context);
if (hasPublisherThumbnail && context != null) { if (hasPublisherThumbnail && context != null) {
Glide.with(context.getApplicationContext()).load(signingChannel.getThumbnailUrl()). ViewGroup.LayoutParams lp = root.findViewById(R.id.file_view_publisher_thumbnail).getLayoutParams();
Glide.with(context.getApplicationContext()).load(signingChannel.getThumbnailUrl(lp.width, lp.height, 85)).
apply(RequestOptions.circleCropTransform()).into((ImageView) root.findViewById(R.id.file_view_publisher_thumbnail)); apply(RequestOptions.circleCropTransform()).into((ImageView) root.findViewById(R.id.file_view_publisher_thumbnail));
} }
((TextView) root.findViewById(R.id.file_view_publisher_thumbnail_alpha)). ((TextView) root.findViewById(R.id.file_view_publisher_thumbnail_alpha)).
@ -1606,7 +1610,7 @@ public class FileViewFragment extends BaseFragment implements
Claim.GenericMetadata metadata = claim.getValue(); Claim.GenericMetadata metadata = claim.getValue();
if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) { if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
ImageView thumbnailView = root.findViewById(R.id.file_view_thumbnail); ImageView thumbnailView = root.findViewById(R.id.file_view_thumbnail);
Glide.with(context.getApplicationContext()).asBitmap().load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView); Glide.with(context.getApplicationContext()).asBitmap().load(claim.getThumbnailUrl(context.getResources().getDisplayMetrics().widthPixels, thumbnailView.getLayoutParams().height, 85)).centerCrop().into(thumbnailView);
} else { } else {
// display first x letters of claim name, with random background // display first x letters of claim name, with random background
} }
@ -3243,7 +3247,7 @@ public class FileViewFragment extends BaseFragment implements
if (hasThumbnail && context != null) { if (hasThumbnail && context != null) {
Glide.with(context.getApplicationContext()). Glide.with(context.getApplicationContext()).
asBitmap(). asBitmap().
load(channel.getThumbnailUrl()). load(channel.getThumbnailUrl(commentPostAsThumbnail.getLayoutParams().width, commentPostAsThumbnail.getLayoutParams().height, 85)).
apply(RequestOptions.circleCropTransform()). apply(RequestOptions.circleCropTransform()).
into(commentPostAsThumbnail); into(commentPostAsThumbnail);
} }

View file

@ -583,7 +583,9 @@ public class PublishFormFragment extends BaseFragment implements
Context context = getContext(); Context context = getContext();
try { try {
Claim.StreamMetadata metadata = (Claim.StreamMetadata) currentClaim.getValue(); Claim.StreamMetadata metadata = (Claim.StreamMetadata) currentClaim.getValue();
uploadedThumbnailUrl = currentClaim.getThumbnailUrl(); if (context != null) {
uploadedThumbnailUrl = currentClaim.getThumbnailUrl(imageThumbnail.getLayoutParams().width, imageThumbnail.getLayoutParams().height, 85);
}
if (context != null && !Helper.isNullOrEmpty(uploadedThumbnailUrl)) { if (context != null && !Helper.isNullOrEmpty(uploadedThumbnailUrl)) {
Glide.with(context.getApplicationContext()).load(uploadedThumbnailUrl).centerCrop().into(imageThumbnail); Glide.with(context.getApplicationContext()).load(uploadedThumbnailUrl).centerCrop().into(imageThumbnail);
} }

View file

@ -3,6 +3,7 @@ package io.lbry.browser.ui.wallet;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
@ -60,6 +61,9 @@ import java.util.concurrent.Future;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import io.lbry.browser.MainActivity; import io.lbry.browser.MainActivity;
import io.lbry.browser.R; import io.lbry.browser.R;
import io.lbry.browser.adapter.TransactionListAdapter; import io.lbry.browser.adapter.TransactionListAdapter;
@ -117,6 +121,7 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
private ImageButton buttonCopyReceiveAddress; private ImageButton buttonCopyReceiveAddress;
private MaterialButton buttonGetNewAddress; private MaterialButton buttonGetNewAddress;
private TextInputEditText inputSendAddress; private TextInputEditText inputSendAddress;
private ImageButton buttonQRScanAddress;
private TextInputEditText inputSendAmount; private TextInputEditText inputSendAmount;
private MaterialButton buttonSend; private MaterialButton buttonSend;
private TextView textConnectedEmail; private TextView textConnectedEmail;
@ -162,6 +167,7 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
buttonCopyReceiveAddress = root.findViewById(R.id.wallet_copy_receive_address); buttonCopyReceiveAddress = root.findViewById(R.id.wallet_copy_receive_address);
buttonGetNewAddress = root.findViewById(R.id.wallet_get_new_address); buttonGetNewAddress = root.findViewById(R.id.wallet_get_new_address);
inputSendAddress = root.findViewById(R.id.wallet_input_send_address); inputSendAddress = root.findViewById(R.id.wallet_input_send_address);
buttonQRScanAddress = root.findViewById(R.id.wallet_qr_scan_address);
inputSendAmount = root.findViewById(R.id.wallet_input_amount); inputSendAmount = root.findViewById(R.id.wallet_input_amount);
buttonSend = root.findViewById(R.id.wallet_send); buttonSend = root.findViewById(R.id.wallet_send);
textConnectedEmail = root.findViewById(R.id.wallet_connected_email); textConnectedEmail = root.findViewById(R.id.wallet_connected_email);
@ -368,6 +374,13 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
copyReceiveAddress(); copyReceiveAddress();
} }
}); });
buttonQRScanAddress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IntentIntegrator intentIntegrator = IntentIntegrator.forSupportFragment(WalletFragment.this);
intentIntegrator.setOrientationLocked(false).initiateScan();
}
});
buttonSend.setOnClickListener(new View.OnClickListener() { buttonSend.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -800,4 +813,12 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
checkRewardsDriverCard(rewardsDriverText, 0); checkRewardsDriverCard(rewardsDriverText, 0);
} }
} }
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult intentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
String code = intentResult.getContents();
inputSendAddress.setText(code);
}
}
} }

View file

@ -51,7 +51,7 @@ public final class Lbry {
public static final int TTL_CLAIM_SEARCH_VALUE = 120000; // 2-minute TTL for cache public static final int TTL_CLAIM_SEARCH_VALUE = 120000; // 2-minute TTL for cache
public static final String SDK_CONNECTION_STRING = "http://127.0.0.1:5279"; public static final String SDK_CONNECTION_STRING = "http://127.0.0.1:5279";
public static final String LBRY_TV_CONNECTION_STRING = "https://api.lbry.tv/api/v1/proxy"; public static final String LBRY_TV_CONNECTION_STRING = "https://api.na-backend.odysee.com/api/v1/proxy";
public static final String TAG = "Lbry"; public static final String TAG = "Lbry";
// Values to obtain from LBRY SDK status // Values to obtain from LBRY SDK status

View file

@ -141,20 +141,6 @@ public class LbryUri {
boolean isChannel = includesChannel && Helper.isNullOrEmpty(possibleStreamName); boolean isChannel = includesChannel && Helper.isNullOrEmpty(possibleStreamName);
String channelName = includesChannel && streamOrChannelName.length() > 1 ? streamOrChannelName.substring(1) : null; String channelName = includesChannel && streamOrChannelName.length() > 1 ? streamOrChannelName.substring(1) : null;
/*
* It would have thrown already on the RegEx parser if protocol value was incorrect
* or HTTPS host was unknown to us.
*
* [https://] hosts use ':' as ModSeparators while [lbry://] protocol expects '#'
*/
if (!components.get(1).isEmpty()) {
if (primaryModSeparator.equals(":"))
primaryModSeparator = "#";
if (secondaryModSeparator.equals(":"))
secondaryModSeparator = "#";
}
if (includesChannel) { if (includesChannel) {
if (Helper.isNullOrEmpty(channelName)) { if (Helper.isNullOrEmpty(channelName)) {
throw new LbryUriException("No channel name after @."); throw new LbryUriException("No channel name after @.");
@ -329,9 +315,9 @@ public class LbryUri {
throw new LbryUriException(String.format("No modifier provided after separator %s", modSeparator)); throw new LbryUriException(String.format("No modifier provided after separator %s", modSeparator));
} }
if ("#".equals(modSeparator)) { if ("#".equals(modSeparator) || ":".equals(modSeparator)) {
claimId = modValue; claimId = modValue;
} else if (":".equals(modSeparator)) { } else if ("*".equals(modSeparator)) {
claimSequence = Helper.parseInt(modValue, -1); claimSequence = Helper.parseInt(modValue, -1);
} else if ("$".equals(modSeparator)) { } else if ("$".equals(modSeparator)) {
bidPosition = Helper.parseInt(modValue, -1); bidPosition = Helper.parseInt(modValue, -1);

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M9.5,6.5v3h-3v-3H9.5M11,5H5v6h6V5L11,5zM9.5,14.5v3h-3v-3H9.5M11,13H5v6h6V13L11,13zM17.5,6.5v3h-3v-3H17.5M19,5h-6v6h6V5L19,5zM13,13h1.5v1.5H13V13zM14.5,14.5H16V16h-1.5V14.5zM16,13h1.5v1.5H16V13zM13,16h1.5v1.5H13V16zM14.5,17.5H16V19h-1.5V17.5zM16,16h1.5v1.5H16V16zM17.5,14.5H19V16h-1.5V14.5zM17.5,17.5H19V19h-1.5V17.5zM22,7h-2V4h-3V2h5V7zM22,22v-5h-2v3h-3v2H22zM2,22h5v-2H4v-3H2V22zM2,2v5h2V4h3V2H2z"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

View file

@ -19,18 +19,41 @@
android:text="@string/send_credits" android:text="@string/send_credits"
android:textSize="20sp"/> android:textSize="20sp"/>
<com.google.android.material.textfield.TextInputLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:hint="@string/recipient_address"> android:layout_marginTop="8dp"
<com.google.android.material.textfield.TextInputEditText android:orientation="horizontal">
android:id="@+id/wallet_input_send_address"
android:fontFamily="@font/inter" <com.google.android.material.textfield.TextInputLayout
android:textSize="14sp" android:layout_centerVertical="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:imeOptions="actionNext" /> android:layout_weight="1"
</com.google.android.material.textfield.TextInputLayout> android:hint="@string/recipient_address"
android:layout_toStartOf="@id/wallet_qr_scan_address">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/wallet_input_send_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:imeOptions="actionNext"
android:textSize="14sp" />
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/wallet_qr_scan_address"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="8dp"
android:background="@null"
android:src="@drawable/ic_qr_scanner"
android:tint="@color/lbryGreen" />
</RelativeLayout>
<RelativeLayout <RelativeLayout
android:layout_marginTop="16dp" android:layout_marginTop="16dp"

View file

@ -10,6 +10,7 @@ import static org.junit.Assert.assertEquals;
public class LbryUriTest { public class LbryUriTest {
private LbryUri expected; private LbryUri expected;
private LbryUri expectedOctoshape;
/* /*
* Create an LbryUri object and assign fields manually using class methods. This object will be * Create an LbryUri object and assign fields manually using class methods. This object will be
@ -18,14 +19,21 @@ public class LbryUriTest {
@Before @Before
public void createExpected() { public void createExpected() {
expected = new LbryUri(); expected = new LbryUri();
expectedOctoshape = new LbryUri();
expected.setChannelName("@lbry"); expected.setChannelName("@lbry");
expected.setStreamName("lbryturns4"); expected.setStreamName("lbryturns4");
expectedOctoshape.setChannelName("@lbry");
expectedOctoshape.setStreamName("lbryturns4");
try { try {
LbryUri.UriModifier primaryMod = LbryUri.UriModifier.parse("#", "3f"); LbryUri.UriModifier primaryMod = LbryUri.UriModifier.parse(":", "3f");
LbryUri.UriModifier secondaryMod = LbryUri.UriModifier.parse("#", "6"); LbryUri.UriModifier secondaryMod = LbryUri.UriModifier.parse(":", "6");
LbryUri.UriModifier primaryModOctoshape = LbryUri.UriModifier.parse("#", "3f");
LbryUri.UriModifier secondaryModOctoshape = LbryUri.UriModifier.parse("#", "6");
expected.setChannelClaimId(primaryMod.getClaimId()); expected.setChannelClaimId(primaryMod.getClaimId());
expected.setStreamClaimId(secondaryMod.getClaimId()); expected.setStreamClaimId(secondaryMod.getClaimId());
expectedOctoshape.setChannelClaimId(primaryModOctoshape.getClaimId());
expectedOctoshape.setStreamClaimId(secondaryModOctoshape.getClaimId());
} catch (LbryUriException e) { } catch (LbryUriException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -71,7 +79,7 @@ public class LbryUriTest {
} }
@Test @Test
public void parseLbryProtocolWithChannel() { public void parseLbryProtocolWithChannelOctoshape() {
LbryUri obtained = new LbryUri(); LbryUri obtained = new LbryUri();
try { try {
@ -80,12 +88,12 @@ public class LbryUriTest {
e.printStackTrace(); e.printStackTrace();
} }
assertEquals(expected, obtained); assertEquals(expectedOctoshape, obtained);
} }
@Test @Test
public void parseLbryProtocolOnlyChannel() { public void parseLbryProtocolOnlyChannel() {
LbryUri expectedForChannel = sinthesizeExpected(); LbryUri expectedForChannel = sinthesizeExpectedChannelOctoshape();
LbryUri obtained = new LbryUri(); LbryUri obtained = new LbryUri();
@ -100,7 +108,7 @@ public class LbryUriTest {
@Test @Test
public void parseLbryTvProtocolOnlyChannel() { public void parseLbryTvProtocolOnlyChannel() {
LbryUri expectedForChannel = sinthesizeExpected(); LbryUri expectedForChannel = sinthesizeExpectedChannelOctoshape();
LbryUri obtained = new LbryUri(); LbryUri obtained = new LbryUri();
@ -192,7 +200,7 @@ public class LbryUriTest {
} }
@NotNull @NotNull
private LbryUri sinthesizeExpected() { private LbryUri sinthesizeExpectedChannelOctoshape() {
LbryUri expectedForChannel = new LbryUri(); LbryUri expectedForChannel = new LbryUri();
expectedForChannel.setChannelName("@UCBerkeley"); expectedForChannel.setChannelName("@UCBerkeley");
expectedForChannel.setChannel(true); expectedForChannel.setChannel(true);