Compare commits

...

27 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
Akinwale Ariwodola
9278e74e85 remove reference to bintray 2021-06-25 19:34:58 +01:00
Akinwale Ariwodola
cf6f09c60d fix gitlab CI script 2021-06-25 19:25:29 +01:00
Akinwale Ariwodola
f2cbed48d9 fix git-secret install source 2021-06-25 19:23:30 +01:00
Akinwale Ariwodola
f1ead0c247 bumpversion 0.17.0 --> 0.17.1 2021-06-25 19:08:30 +01:00
Akinwale Ariwodola
5f2c72ec4d sdk 0.100.0 / switch to maven central for lbrysdk Gradle dependency 2021-06-25 19:07:47 +01:00
Javi Rueda
a6869eb2e6
Fix crash for anonymous content or without tags (#1190) 2021-05-10 17:14:22 +02:00
Javi Rueda
cbae6c476a
Claim has source (#1188)
* Pass has_source parameter to claim_search to ignore livestreamings

* Update to SDK 0.94.1 and allow user to view livestream content on Odysee
2021-05-10 17:13:28 +02:00
Javi Rueda
48d257ceaf
Show total wallet balance in USD instead of spendable balance conversion (#1186) 2021-04-19 19:55:49 +02:00
Javi Rueda
5355456498
Don't show link to Bittrex (#1181) 2021-04-12 18:53:59 +02:00
Javi Rueda
1436895ace
Copy file to public Downloads directory (#1180) 2021-04-12 18:53:13 +02:00
Javi Rueda
6e32f7724f
Notification improvements (#1175)
* Stop showing notification list when going from notification's content to related content

* Add is_app_readable parameter to notification_list call

* Return current fragment on main activity
2021-03-29 17:39:27 +02:00
Javi Rueda
3f5104d60a
Hide floating wallet on the Channel fragment (#1177)
* Hide floating wallet on the Channel fragment

* Unregister OnPageChangeCallback when exiting channel fragment
2021-03-29 17:38:51 +02:00
Javi Rueda
d8fdb3b818
Decode and encode urls with non-authorized characters (#1174)
* Decode URL encoded links and unit test it

* Encode UTF8 characters on LBRY.TV links and unit test it
2021-03-19 11:00:24 +01:00
38 changed files with 513 additions and 112 deletions

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

@ -0,0 +1 @@

1
.gitignore vendored
View file

@ -66,3 +66,4 @@ app/twitter.properties
*.hprof *.hprof
app/build app/build
bin bin
app/debuglib

View file

@ -9,8 +9,8 @@ build apk:
image: lbry/android-base:platform-28 image: lbry/android-base:platform-28
before_script: before_script:
- echo "$PGP_PRIVATE_KEY" | gpg --batch --import - echo "$PGP_PRIVATE_KEY" | gpg --batch --import
- echo "deb https://dl.bintray.com/sobolevn/deb git-secret main" | tee -a /etc/apt/sources.list - echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list
- wget -O - https://api.bintray.com/users/sobolevn/keys/gpg/public.key | apt-key add - - wget -qO - 'https://gitsecret.jfrog.io/artifactory/api/gpg/key/public' | apt-key add -
- apt-get -y update && apt-get -y install build-essential ca-certificates curl git gpg-agent openjdk-8-jdk software-properties-common wget zipalign git-secret - apt-get -y update && apt-get -y install build-essential ca-certificates curl git gpg-agent openjdk-8-jdk software-properties-common wget zipalign git-secret
- git secret reveal - git secret reveal
- chmod u+x $CI_PROJECT_DIR/gradlew - chmod u+x $CI_PROJECT_DIR/gradlew
@ -36,8 +36,8 @@ deploy build.lbry.io:
before_script: before_script:
- apt-get -y update && apt-get -y install apt-transport-https - apt-get -y update && apt-get -y install apt-transport-https
- echo "$PGP_PRIVATE_KEY" | gpg --batch --import - echo "$PGP_PRIVATE_KEY" | gpg --batch --import
- echo "deb https://dl.bintray.com/sobolevn/deb git-secret main" | tee -a /etc/apt/sources.list - echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list
- wget -O - https://api.bintray.com/users/sobolevn/keys/gpg/public.key | apt-key add - - wget -qO - 'https://gitsecret.jfrog.io/artifactory/api/gpg/key/public' | apt-key add -
- apt-get -y update && apt-get -y install openjdk-8-jdk git git-secret - apt-get -y update && apt-get -y install openjdk-8-jdk git git-secret
- pip install awscli - pip install awscli
- chmod u+x $CI_PROJECT_DIR/gradlew - chmod u+x $CI_PROJECT_DIR/gradlew
@ -60,8 +60,8 @@ release apk:
before_script: before_script:
- apt-get -y update && apt-get -y install apt-transport-https - apt-get -y update && apt-get -y install apt-transport-https
- echo "$PGP_PRIVATE_KEY" | gpg --batch --import - echo "$PGP_PRIVATE_KEY" | gpg --batch --import
- echo "deb https://dl.bintray.com/sobolevn/deb git-secret main" | tee -a /etc/apt/sources.list - echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list
- wget -O - https://api.bintray.com/users/sobolevn/keys/gpg/public.key | apt-key add - - wget -qO - 'https://gitsecret.jfrog.io/artifactory/api/gpg/key/public' | apt-key add -
- apt-get -y update && apt-get -y install openjdk-8-jdk git git-secret - apt-get -y update && apt-get -y install openjdk-8-jdk git git-secret
- pip install awscli githubrelease - pip install awscli githubrelease
- git secret reveal - git secret reveal

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

@ -16,12 +16,12 @@ android {
applicationId "io.lbry.browser" applicationId "io.lbry.browser"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 1700 versionCode 1701
versionName "0.17.0" versionName "0.17.1"
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,9 @@ 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.91.0' __32bitImplementation 'io.lbry:lbrysdk32:0.102.0'
__64bitImplementation 'io.lbry:lbrysdk64:0.91.0' __64bitImplementation 'io.lbry:lbrysdk64:0.102.0'
//__64bitImplementation(name: 'lbrysdk', ext: 'aar')
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'

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;
@ -2781,15 +2781,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
} }
private Fragment getCurrentFragment() { private Fragment getCurrentFragment() {
int backCount = getSupportFragmentManager().getBackStackEntryCount(); return getSupportFragmentManager().findFragmentById(R.id.content_main);
if (backCount > 0) {
try {
return getSupportFragmentManager().getFragments().get(backCount - 1);
} catch (IndexOutOfBoundsException ex) {
return null;
}
}
return null;
} }
public void hideActionBar() { public void hideActionBar() {
@ -3495,6 +3487,18 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
return; return;
} }
if (currentFragment != null && ((BaseFragment) currentFragment).getParams() != null
&& ((BaseFragment) currentFragment).getParams().containsKey("source")
&& ((BaseFragment) currentFragment).getParams().get("source").equals("notification")) {
Map<String, Object> currentParams = new HashMap<>(1);
if (((BaseFragment) currentFragment).getParams().containsKey("url"))
currentParams.put("url", ((BaseFragment) currentFragment).getParams().get("url"));
((BaseFragment) currentFragment).setParams(currentParams);
}
//fragment.setRetainInstance(true); //fragment.setRetainInstance(true);
FragmentManager manager = getSupportFragmentManager(); FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction().replace(R.id.content_main, fragment); FragmentTransaction transaction = manager.beginTransaction().replace(R.id.content_main, fragment);

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;
@ -137,6 +139,14 @@ public class Claim {
return null; return null;
} }
public boolean hasSource() {
if (value instanceof StreamMetadata) {
StreamMetadata metadata = (StreamMetadata) value;
return metadata.getSource() != null;
}
return false;
}
public boolean isPlayable() { public boolean isPlayable() {
if (value instanceof StreamMetadata) { if (value instanceof StreamMetadata) {
StreamMetadata metadata = (StreamMetadata) value; StreamMetadata metadata = (StreamMetadata) value;
@ -176,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();
@ -483,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

@ -16,8 +16,10 @@ import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import io.lbry.browser.MainActivity; import io.lbry.browser.MainActivity;
import io.lbry.browser.data.DatabaseHelper; import io.lbry.browser.data.DatabaseHelper;
@ -47,7 +49,9 @@ public class NotificationListTask extends AsyncTask<Void, Void, List<LbryNotific
List<LbryNotification> notifications = new ArrayList<>(); List<LbryNotification> notifications = new ArrayList<>();
SQLiteDatabase db = null; SQLiteDatabase db = null;
try { try {
JSONArray array = (JSONArray) Lbryio.parseResponse(Lbryio.call("notification", "list", context)); Map<String, String> parameters = new HashMap<>(1);
parameters.put("is_app_readable", "true");
JSONArray array = (JSONArray) Lbryio.parseResponse(Lbryio.call("notification", "list", parameters, context));
if (array != null) { if (array != null) {
for (int i = 0; i < array.length(); i++) { for (int i = 0; i < array.length(); i++) {
JSONObject item = array.getJSONObject(i); JSONObject item = array.getJSONObject(i);

View file

@ -64,7 +64,7 @@ public class BaseFragment extends Fragment {
} }
} }
if (params != null && params.containsKey("source") && "notification".equalsIgnoreCase(params.get("source").toString())) { if (params != null && params.containsKey("source") && params.get("source") != null && "notification".equalsIgnoreCase(params.get("source").toString())) {
Context context = getContext(); Context context = getContext();
if (context instanceof MainActivity) { if (context instanceof MainActivity) {
((MainActivity) context).navigateBackToNotifications(); ((MainActivity) context).navigateBackToNotifications();

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

@ -230,7 +230,8 @@ public class ChannelContentFragment extends Fragment implements DownloadActionLi
0, 0,
0, 0,
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage, currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
Helper.CONTENT_PAGE_SIZE); Helper.CONTENT_PAGE_SIZE,
true);
} }
private List<String> getContentSortOrder() { private List<String> getContentSortOrder() {

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

@ -73,6 +73,7 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
private TextView textFollowerCount; private TextView textFollowerCount;
private TabLayout tabLayout; private TabLayout tabLayout;
private ViewPager2 tabPager; private ViewPager2 tabPager;
ViewPager2.OnPageChangeCallback opcc;
private View buttonEdit; private View buttonEdit;
private View buttonDelete; private View buttonDelete;
@ -91,6 +92,8 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
// if this is set, scroll to the specific comment on load // if this is set, scroll to the specific comment on load
private String commentHash; private String commentHash;
private float floatingWalletPositionY;
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_channel, container, false); View root = inflater.inflate(R.layout.fragment_channel, container, false);
@ -122,6 +125,25 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
tabLayout = root.findViewById(R.id.channel_view_tabs); tabLayout = root.findViewById(R.id.channel_view_tabs);
tabPager.setSaveEnabled(false); tabPager.setSaveEnabled(false);
View floatingBalance = getActivity().findViewById(R.id.floating_balance_main_container);
floatingWalletPositionY = floatingBalance.getY();
opcc = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position > 0) {
// Hide floating wallet for the About and the Comment tabs as they are mostly text
((MainActivity) getContext()).translateFloatingWallet(floatingWalletPositionY);
} else {
((MainActivity) getContext()).restoreWalletContainerPosition();
}
}
};
tabPager.registerOnPageChangeCallback(opcc);
buttonEdit.setOnClickListener(new View.OnClickListener() { buttonEdit.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -380,6 +402,15 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
super.onPause(); super.onPause();
} }
public void onStop() {
Context context = getContext();
if (context instanceof MainActivity) {
((MainActivity) context ).restoreWalletContainerPosition();
}
tabPager.unregisterOnPageChangeCallback(opcc);
super.onStop();
}
private void checkParams() { private void checkParams() {
boolean updateRequired = false; boolean updateRequired = false;
Map<String, Object> params = getParams(); Map<String, Object> params = getParams();
@ -507,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

@ -421,7 +421,8 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi
0, 0,
0, 0,
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage, currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
Helper.CONTENT_PAGE_SIZE); Helper.CONTENT_PAGE_SIZE,
true);
} }
private List<String> getContentSortOrder() { private List<String> getContentSortOrder() {

View file

@ -79,7 +79,8 @@ public class EditorsChoiceFragment extends BaseFragment {
Arrays.asList(Claim.ORDER_BY_RELEASE_TIME), Arrays.asList(Claim.ORDER_BY_RELEASE_TIME),
null, null,
1, 1,
99); 99,
true);
} }
public void onResume() { public void onResume() {

View file

@ -12,6 +12,7 @@ import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.format.DateUtils; import android.text.format.DateUtils;
@ -87,8 +88,12 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
@ -162,6 +167,10 @@ import io.lbry.lbrysdk.DownloadManager;
import io.lbry.lbrysdk.LbrynetService; import io.lbry.lbrysdk.LbrynetService;
import io.lbry.lbrysdk.Utils; import io.lbry.lbrysdk.Utils;
import static android.os.Environment.DIRECTORY_DOWNLOADS;
import static android.os.Environment.DIRECTORY_MOVIES;
import static android.os.Environment.DIRECTORY_PICTURES;
public class FileViewFragment extends BaseFragment implements public class FileViewFragment extends BaseFragment implements
MainActivity.BackPressInterceptor, MainActivity.BackPressInterceptor,
DownloadActionListener, DownloadActionListener,
@ -307,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) {
@ -1514,7 +1526,7 @@ public class FileViewFragment extends BaseFragment implements
Helper.setViewVisibility(layoutLoadingState, View.GONE); Helper.setViewVisibility(layoutLoadingState, View.GONE);
Helper.setViewVisibility(layoutNothingAtLocation, View.GONE); Helper.setViewVisibility(layoutNothingAtLocation, View.GONE);
if (claim.getTags().contains("disable-support") || claim.getSigningChannel().getTags().contains("disable-support")) if ((claim.getTags() != null && claim.getTags().contains("disable-support")) || (claim.getSigningChannel() != null && claim.getSigningChannel().getTags().contains("disable-support")))
Helper.setViewVisibility(tipButton, View.GONE); Helper.setViewVisibility(tipButton, View.GONE);
else else
Helper.setViewVisibility(tipButton, View.VISIBLE); Helper.setViewVisibility(tipButton, View.VISIBLE);
@ -1557,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)).
@ -1597,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
} }
@ -1617,7 +1630,7 @@ public class FileViewFragment extends BaseFragment implements
root.findViewById(R.id.file_view_open_external_button).setOnClickListener(new View.OnClickListener() { root.findViewById(R.id.file_view_open_external_button).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
openClaimExternally(claim, claim.getMediaType()); openClaimExternally(claim, claim.getMediaType(), !claim.hasSource());
} }
}); });
@ -1675,12 +1688,16 @@ public class FileViewFragment extends BaseFragment implements
restoreMainActionButton(); restoreMainActionButton();
} }
if (Lbry.SDK_READY && !claim.isPlayable() && !claim.isViewable() && Helper.isNullOrEmpty(commentHash)) { if (Lbry.SDK_READY) {
if (claim.getFile() == null) { if (!claim.hasSource()) {
loadFile();
} else {
// file already loaded, but it's unsupported
showUnsupportedView(); showUnsupportedView();
} else if (!claim.isPlayable() && !claim.isViewable() && Helper.isNullOrEmpty(commentHash)) {
if (claim.getFile() == null) {
loadFile();
} else {
// file already loaded, but it's unsupported
showUnsupportedView();
}
} }
} }
@ -1704,7 +1721,7 @@ public class FileViewFragment extends BaseFragment implements
View commentsDisabledText = root.findViewById(R.id.file_view_disabled_comments); View commentsDisabledText = root.findViewById(R.id.file_view_disabled_comments);
View commentForm = root.findViewById(R.id.container_comment_form); View commentForm = root.findViewById(R.id.container_comment_form);
RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list); RecyclerView commentsList = root.findViewById(R.id.file_view_comments_list);
if (claim.getTags().contains("disable-comments") || claim.getSigningChannel().getTags().contains("disable-comments")) { if ((claim.getTags() != null && (claim.getTags().contains("disable-comments")) || (claim.getSigningChannel() != null && claim.getSigningChannel().getTags().contains("disable-comments")))) {
Helper.setViewVisibility(commentsDisabledText, View.VISIBLE); Helper.setViewVisibility(commentsDisabledText, View.VISIBLE);
Helper.setViewVisibility(commentForm, View.GONE); Helper.setViewVisibility(commentForm, View.GONE);
Helper.setViewVisibility(commentsList, View.GONE); Helper.setViewVisibility(commentsList, View.GONE);
@ -1724,13 +1741,19 @@ public class FileViewFragment extends BaseFragment implements
if (root != null) { if (root != null) {
root.findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE); root.findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE);
root.findViewById(R.id.file_view_unsupported_container).setVisibility(View.VISIBLE); root.findViewById(R.id.file_view_unsupported_container).setVisibility(View.VISIBLE);
String fileNameString = ""; if (claim.hasSource()) {
if (claim.getFile() != null && !Helper.isNullOrEmpty(claim.getFile().getDownloadPath())) { String fileNameString = "";
LbryFile lbryFile = claim.getFile(); if (claim.getFile() != null && !Helper.isNullOrEmpty(claim.getFile().getDownloadPath())) {
File file = new File(lbryFile.getDownloadPath()); LbryFile lbryFile = claim.getFile();
fileNameString = String.format("\"%s\" ", file.getName()); File file = new File(lbryFile.getDownloadPath());
fileNameString = String.format("\"%s\" ", file.getName());
}
((TextView) root.findViewById(R.id.file_view_unsupported_text)).setText(getString(R.string.unsupported_content_desc, fileNameString));
((MaterialButton) root.findViewById(R.id.file_view_open_external_button)).setText(getString(R.string.open));
} else {
((TextView) root.findViewById(R.id.file_view_unsupported_text)).setText(getString(R.string.unsupported_content_to_odysee_desc));
((MaterialButton) root.findViewById(R.id.file_view_open_external_button)).setText(getString(R.string.open_on_odysee_com));
} }
((TextView) root.findViewById(R.id.file_view_unsupported_text)).setText(getString(R.string.unsupported_content_desc, fileNameString));
} }
} }
@ -2182,7 +2205,7 @@ public class FileViewFragment extends BaseFragment implements
handled = true; handled = true;
} }
} else { } else {
openClaimExternally(claim, mediaType); openClaimExternally(claim, mediaType, false);
} }
} }
@ -2266,15 +2289,25 @@ public class FileViewFragment extends BaseFragment implements
" </html>"; " </html>";
} }
private void openClaimExternally(Claim claim, String mediaType) { private void openClaimExternally(Claim claim, String mediaType, boolean odyseeLink) {
Uri fileUri = Uri.parse(claim.getFile().getDownloadPath()); if (odyseeLink) {
try {
LbryUri lbryUri = LbryUri.parse(claim.getCanonicalUrl());
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(lbryUri.toOdyseeString()));
startActivity(intent);
} catch (LbryUriException e) {
e.printStackTrace();
}
} else {
Uri fileUri = Uri.parse(claim.getFile().getDownloadPath());
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(fileUri, mediaType.toLowerCase()); intent.setDataAndType(fileUri, mediaType.toLowerCase());
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent chooser = Intent.createChooser(intent, getString(R.string.choose_app)); Intent chooser = Intent.createChooser(intent, getString(R.string.choose_app));
startActivityForResult(chooser, 419); startActivityForResult(chooser, 419);
}
} }
public void showError(String message) { public void showError(String message) {
@ -2844,6 +2877,41 @@ public class FileViewFragment extends BaseFragment implements
downloadInProgress = false; downloadInProgress = false;
downloadProgressView.setProgress(100); downloadProgressView.setProgress(100);
Helper.setViewVisibility(downloadProgressView, View.GONE); Helper.setViewVisibility(downloadProgressView, View.GONE);
// Copy file to shared Downloads folder
// TODO Assign this folder when downloading instead of copying the file
File fileFolder;
if (claimFile.getMimeType().contains("video"))
fileFolder = Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES);
else if (claimFile.getMimeType().contains("image") || claimFile.getMimeType().contains("picture"))
fileFolder = Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES);
else
fileFolder = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS);
InputStream in = null;
OutputStream out;
try {
in = new FileInputStream(claimFile.getDownloadPath());
out = new FileOutputStream(new File(fileFolder, claimFile.getFileName()));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
playOrViewMedia(); playOrViewMedia();
} }
checkIsFileComplete(); checkIsFileComplete();
@ -3179,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

@ -415,7 +415,8 @@ public class FollowingFragment extends BaseFragment implements
Arrays.asList(Claim.ORDER_BY_EFFECTIVE_AMOUNT), Arrays.asList(Claim.ORDER_BY_EFFECTIVE_AMOUNT),
null, null,
currentSuggestedPage == 0 ? 1 : currentSuggestedPage, currentSuggestedPage == 0 ? 1 : currentSuggestedPage,
SUGGESTED_PAGE_SIZE); SUGGESTED_PAGE_SIZE,
true);
} }
private Map<String, Object> buildContentOptions() { private Map<String, Object> buildContentOptions() {
@ -437,7 +438,8 @@ public class FollowingFragment extends BaseFragment implements
0, 0,
0, 0,
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage, currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
Helper.CONTENT_PAGE_SIZE); Helper.CONTENT_PAGE_SIZE,
true);
} }
private List<String> getChannelIds() { private List<String> getChannelIds() {

View file

@ -210,7 +210,8 @@ public class ShuffleFragment extends BaseFragment {
121, // 2 minutes or less 121, // 2 minutes or less
1, 1,
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage, currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
PAGE_SIZE); PAGE_SIZE,
true);
} }
public void onStart() { public void onStart() {

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;
@ -33,6 +34,14 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.switchmaterial.SwitchMaterial; import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import org.json.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.URLEncoder; import java.net.URLEncoder;
@ -44,10 +53,17 @@ import java.text.DecimalFormatSymbols;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
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;
@ -105,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;
@ -150,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);
@ -291,6 +309,44 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
} }
}); });
ExecutorService executor = Executors.newSingleThreadExecutor();
// This will return /true/ if user IP is **not** on the US or the request fails
Future<Boolean> localeFuture = executor.submit(() -> {
Request request = new Request.Builder().url("https://api.lbry.com/locale/get").build();
OkHttpClient okHttpClient = new OkHttpClient();
try (Response response = okHttpClient.newCall(request).execute()){
ResponseBody responseBody = response.body();
JSONObject responseJson;
if (responseBody != null)
responseJson = new JSONObject(responseBody.string());
else
return false;
if (responseJson.has("data") && responseJson.getBoolean("success")) {
JSONObject dataJson = (JSONObject) responseJson.get("data");
return !dataJson.getString("country").equals("US");
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
});
try {
Boolean isNotUS = localeFuture.get();
if (isNotUS)
textConvertCreditsBittrex.setVisibility(View.VISIBLE);
else
textConvertCreditsBittrex.setVisibility(View.GONE);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
buttonSignUp.setOnClickListener(new View.OnClickListener() { buttonSignUp.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -318,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) {
@ -638,7 +701,7 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
double totalBalance = walletBalance.getTotal().doubleValue(); double totalBalance = walletBalance.getTotal().doubleValue();
double spendableBalance = walletBalance.getAvailable().doubleValue(); double spendableBalance = walletBalance.getAvailable().doubleValue();
double supportingBalance = walletBalance.getClaims().doubleValue() + walletBalance.getTips().doubleValue() + walletBalance.getSupports().doubleValue(); double supportingBalance = walletBalance.getClaims().doubleValue() + walletBalance.getTips().doubleValue() + walletBalance.getSupports().doubleValue();
double usdBalance = spendableBalance * Lbryio.LBCUSDRate; double usdBalance = totalBalance * Lbryio.LBCUSDRate;
double tipsBalance = walletBalance.getTips().doubleValue(); double tipsBalance = walletBalance.getTips().doubleValue();
if (detailRows == null) if (detailRows == null)
@ -750,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
@ -373,7 +373,7 @@ public final class Lbry {
// build claim search for surf mode // build claim search for surf mode
public static Map<String, Object> buildClaimSearchOptions( public static Map<String, Object> buildClaimSearchOptions(
String claimType, List<String> notTags, List<String> channelIds, List<String> orderBy, long maxDuration, int limitClaimsPerChannel, int page, int pageSize) { String claimType, List<String> notTags, List<String> channelIds, List<String> orderBy, long maxDuration, int limitClaimsPerChannel, int page, int pageSize, boolean hasSource) {
return buildClaimSearchOptions( return buildClaimSearchOptions(
Collections.singletonList(claimType), Collections.singletonList(claimType),
null, null,
@ -385,7 +385,8 @@ public final class Lbry {
maxDuration, maxDuration,
limitClaimsPerChannel, limitClaimsPerChannel,
page, page,
pageSize); pageSize,
hasSource);
} }
public static Map<String, Object> buildClaimSearchOptions( public static Map<String, Object> buildClaimSearchOptions(
@ -397,7 +398,8 @@ public final class Lbry {
List<String> orderBy, List<String> orderBy,
String releaseTime, String releaseTime,
int page, int page,
int pageSize) { int pageSize,
boolean hasSource) {
return buildClaimSearchOptions( return buildClaimSearchOptions(
Collections.singletonList(claimType), Collections.singletonList(claimType),
anyTags, anyTags,
@ -409,7 +411,8 @@ public final class Lbry {
0, 0,
0, 0,
page, page,
pageSize); pageSize,
hasSource);
} }
public static Map<String, Object> buildClaimSearchOptions( public static Map<String, Object> buildClaimSearchOptions(
@ -423,7 +426,8 @@ public final class Lbry {
long maxDuration, long maxDuration,
int limitClaimsPerChannel, int limitClaimsPerChannel,
int page, int page,
int pageSize) { int pageSize,
boolean hasSource) {
Map<String, Object> options = new HashMap<>(); Map<String, Object> options = new HashMap<>();
if (claimType != null && claimType.size() > 0) { if (claimType != null && claimType.size() > 0) {
options.put("claim_type", claimType); options.put("claim_type", claimType);
@ -441,6 +445,12 @@ public final class Lbry {
options.put("limit_claims_per_channel", limitClaimsPerChannel); options.put("limit_claims_per_channel", limitClaimsPerChannel);
} }
if (hasSource) {
options.put("has_source", true);
} else {
options.put("has_no_source", true);
}
addClaimSearchListOption("any_tags", anyTags, options); addClaimSearchListOption("any_tags", anyTags, options);
addClaimSearchListOption("not_tags", notTags, options); addClaimSearchListOption("not_tags", notTags, options);
addClaimSearchListOption("channel_ids", channelIds, options); addClaimSearchListOption("channel_ids", channelIds, options);

View file

@ -1,5 +1,8 @@
package io.lbry.browser.utils; package io.lbry.browser.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -8,9 +11,12 @@ import java.util.regex.Pattern;
import io.lbry.browser.exceptions.LbryUriException; import io.lbry.browser.exceptions.LbryUriException;
import lombok.Data; import lombok.Data;
import static org.apache.commons.codec.CharEncoding.UTF_8;
@Data @Data
public class LbryUri { public class LbryUri {
public static final String LBRY_TV_BASE_URL = "https://lbry.tv/"; public static final String LBRY_TV_BASE_URL = "https://lbry.tv/";
public static final String ODYSEE_COM_BASE_URL = "https://odysee.com/";
public static final String PROTO_DEFAULT = "lbry://"; 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_INVALID_URI = "[ =&#:$@%?;/\\\\\"<>%\\{\\}|^~\\[\\]`\u0000-\u0008\u000b-\u000c\u000e-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]";
public static final String REGEX_ADDRESS = "^(b)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$"; public static final String REGEX_ADDRESS = "^(b)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$";
@ -117,10 +123,17 @@ public class LbryUri {
} }
} }
String streamOrChannelName = components.get(2); String streamOrChannelName = null;
String possibleStreamName = null;
try {
// Using java.net.URLDecoder to be able to quickly unit test
streamOrChannelName = URLDecoder.decode(components.get(2), UTF_8);
possibleStreamName = URLDecoder.decode(components.get(6), UTF_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String primaryModSeparator = components.get(3); String primaryModSeparator = components.get(3);
String primaryModValue = components.get(4); String primaryModValue = components.get(4);
String possibleStreamName = components.get(6);
String secondaryModSeparator = components.get(7); String secondaryModSeparator = components.get(7);
String secondaryModValue = components.get(8); String secondaryModValue = components.get(8);
@ -128,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 @.");
@ -188,7 +187,18 @@ public class LbryUri {
if (channelName != null) { if (channelName != null) {
formattedChannelName = channelName.startsWith("@") ? channelName : String.format("@%s", channelName); formattedChannelName = channelName.startsWith("@") ? channelName : String.format("@%s", channelName);
} }
String primaryClaimName = claimName; String primaryClaimName = null;
if ((protocol.equals(LBRY_TV_BASE_URL) || protocol.equals(ODYSEE_COM_BASE_URL)) && Helper.isNullOrEmpty(formattedChannelName)) {
try {
primaryClaimName = URLEncoder.encode(claimName, UTF_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
primaryClaimName = claimName;
}
if (Helper.isNullOrEmpty(primaryClaimName)) { if (Helper.isNullOrEmpty(primaryClaimName)) {
primaryClaimName = contentName; primaryClaimName = contentName;
} }
@ -218,12 +228,20 @@ public class LbryUri {
secondaryClaimName = contentName; secondaryClaimName = contentName;
} }
if (Helper.isNullOrEmpty(secondaryClaimName)) { if (Helper.isNullOrEmpty(secondaryClaimName)) {
secondaryClaimName = !Helper.isNullOrEmpty(formattedChannelName) ? streamName : null; if (protocol.equals(LBRY_TV_BASE_URL) || protocol.equals(ODYSEE_COM_BASE_URL)) {
try {
secondaryClaimName = !Helper.isNullOrEmpty(formattedChannelName) ? URLEncoder.encode(streamName, UTF_8) : null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
secondaryClaimName = !Helper.isNullOrEmpty(formattedChannelName) ? streamName : null;
}
} }
String secondaryClaimId = !Helper.isNullOrEmpty(secondaryClaimName) ? streamClaimId : null; String secondaryClaimId = !Helper.isNullOrEmpty(secondaryClaimName) ? streamClaimId : null;
if (!Helper.isNullOrEmpty(primaryClaimId)) { if (!Helper.isNullOrEmpty(primaryClaimId)) {
if (protocol.equals(LBRY_TV_BASE_URL)) if (protocol.equals(LBRY_TV_BASE_URL) || protocol.equals(ODYSEE_COM_BASE_URL))
sb.append(':').append(primaryClaimId); sb.append(':').append(primaryClaimId);
else else
sb.append('#').append(primaryClaimId); sb.append('#').append(primaryClaimId);
@ -238,7 +256,7 @@ public class LbryUri {
} }
if (!Helper.isNullOrEmpty(secondaryClaimId)) { if (!Helper.isNullOrEmpty(secondaryClaimId)) {
if (protocol.equals(LBRY_TV_BASE_URL)) if (protocol.equals(LBRY_TV_BASE_URL) || protocol.equals(ODYSEE_COM_BASE_URL))
sb.append(':').append(secondaryClaimId); sb.append(':').append(secondaryClaimId);
else else
sb.append('#').append(secondaryClaimId); sb.append('#').append(secondaryClaimId);
@ -258,6 +276,9 @@ public class LbryUri {
public String toTvString() { public String toTvString() {
return build(true, LBRY_TV_BASE_URL, false); return build(true, LBRY_TV_BASE_URL, false);
} }
public String toOdyseeString() {
return build(true, ODYSEE_COM_BASE_URL, false);
}
public String toVanityString() { public String toVanityString() {
return build(true, PROTO_DEFAULT, true); return build(true, PROTO_DEFAULT, true);
} }
@ -294,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

@ -155,6 +155,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:visibility="gone"
android:fontFamily="@font/inter" android:fontFamily="@font/inter"
android:text="@string/convert_credits_bittrex" android:text="@string/convert_credits_bittrex"
android:textColorLink="@color/lbryGreen" android:textColorLink="@color/lbryGreen"

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

@ -57,6 +57,7 @@
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="download">Download</string> <string name="download">Download</string>
<string name="open">Open</string> <string name="open">Open</string>
<string name="open_on_odysee_com">Open on ODYSEE.COM</string>
<string name="report">Report</string> <string name="report">Report</string>
<string name="loading_decentralized_data">Loading decentralized data…</string> <string name="loading_decentralized_data">Loading decentralized data…</string>
<string name="related_content">Related Content</string> <string name="related_content">Related Content</string>
@ -71,6 +72,7 @@
<string name="play">Play</string> <string name="play">Play</string>
<string name="unsupported_content">Unsupported 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 %1$sin your downloads folder.</string> <string name="unsupported_content_desc">Sorry, we are unable to display this content in the app. You can find the file %1$sin your downloads folder.</string>
<string name="unsupported_content_to_odysee_desc">Sorry, we are unable to display this content in the app. Click the button to open it on the Odysee website.</string>
<string name="nothing_at_this_location">There\'s nothing at this location.</string> <string name="nothing_at_this_location">There\'s nothing at this location.</string>
<string name="dmca_complaint_blocked">In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. &lt;a href="https://lbry.com/faq/dmca"&gt;Read more&lt;/a&gt;</string> <string name="dmca_complaint_blocked">In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. &lt;a href="https://lbry.com/faq/dmca"&gt;Read more&lt;/a&gt;</string>
<string name="dmca_complaint_channel_blocked">In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this channel from our applications. &lt;a href="https://lbry.com/faq/dmca"&gt;Read more&lt;/a&gt;</string> <string name="dmca_complaint_channel_blocked">In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this channel from our applications. &lt;a href="https://lbry.com/faq/dmca"&gt;Read more&lt;/a&gt;</string>

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();
@ -113,6 +121,32 @@ public class LbryUriTest {
assertEquals(expectedForChannel, obtained); assertEquals(expectedForChannel, obtained);
} }
@Test
public void parseLbryTvWithEncodedChars() {
LbryUri obtained = new LbryUri();
try {
obtained = LbryUri.parse("https://lbry.tv/@Content_I_Like:1/DR.-ASTRID-ST%C3%9CCKELBERGER:2",false);
} catch (LbryUriException e) {
e.printStackTrace();
}
expected = new LbryUri();
expected.setChannelName("@Content_I_Like");
expected.setStreamName("DR.-ASTRID-STÜCKELBERGER");
try {
LbryUri.UriModifier primaryMod = LbryUri.UriModifier.parse("#", "1");
LbryUri.UriModifier secondaryMod = LbryUri.UriModifier.parse("#", "2");
expected.setChannelClaimId(primaryMod.getClaimId());
expected.setStreamClaimId(secondaryMod.getClaimId());
} catch (LbryUriException e) {
e.printStackTrace();
}
assertEquals(expected, obtained);
}
@Test @Test
public void lbryToTvString() { public void lbryToTvString() {
LbryUri obtained = new LbryUri(); LbryUri obtained = new LbryUri();
@ -126,8 +160,47 @@ public class LbryUriTest {
assertEquals("https://lbry.tv/@lbry:3f/lbryturns4:6", obtained.toTvString()); assertEquals("https://lbry.tv/@lbry:3f/lbryturns4:6", obtained.toTvString());
} }
@Test
public void lbryToTvStringWithEncodedChars() {
LbryUri obtained = new LbryUri();
try {
obtained = LbryUri.parse("lbry://La-Peur,-Nos-Attentats,-c'est-VOTRE-Sécurité!-Les-Guignols#6",false);
} catch (LbryUriException e) {
e.printStackTrace();
}
assertEquals("https://lbry.tv/La-Peur%2C-Nos-Attentats%2C-c%27est-VOTRE-Se%CC%81curite%CC%81%21-Les-Guignols:6", obtained.toTvString());
}
@Test
public void lbryToTvStringWithChannelAndEncodedChars() {
LbryUri obtained = new LbryUri();
try {
obtained = LbryUri.parse("lbry://@test#1/La-Peur,-Nos-Attentats,-c'est-VOTRE-Sécurité!-Les-Guignols#6",false);
} catch (LbryUriException e) {
e.printStackTrace();
}
assertEquals("https://lbry.tv/@test:1/La-Peur%2C-Nos-Attentats%2C-c%27est-VOTRE-Se%CC%81curite%CC%81%21-Les-Guignols:6", obtained.toTvString());
}
@Test
public void lbryToOdyseeString() {
LbryUri obtained = new LbryUri();
try {
obtained = LbryUri.parse("lbry://@lbry#3f/lbryturns4#6",false);
} catch (LbryUriException e) {
e.printStackTrace();
}
assertEquals("https://odysee.com/@lbry:3f/lbryturns4:6", obtained.toOdyseeString());
}
@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);

View file

@ -5,7 +5,7 @@ buildscript {
repositories { repositories {
google() google()
jcenter() jcenter()
mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.4' classpath 'com.android.tools.build:gradle:3.6.4'
@ -20,7 +20,11 @@ allprojects {
repositories { repositories {
google() google()
jcenter() jcenter()
mavenCentral()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
/*flatDir {
dirs 'debuglib'
}*/
} }
} }