diff --git a/app/build.gradle b/app/build.gradle
index 76eeffe..5f65147 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -62,6 +62,10 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'androidx.preference:preference:1.1.1'
+ implementation 'androidx.camera:camera-camera2:1.0.0-beta03'
+ implementation 'androidx.camera:camera-lifecycle:1.0.0-beta03'
+ implementation 'androidx.camera:camera-view:1.0.0-alpha10'
+
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
implementation 'com.google.firebase:firebase-analytics:17.4.0'
@@ -91,8 +95,8 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
- __32bitImplementation files('libs/lbrysdk-0.73.1-release__arm.aar')
- __64bitImplementation files('libs/lbrysdk-0.73.1-release__arm64.aar')
+ __32bitImplementation files('libs/lbrysdk-0.74.0-release__arm.aar')
+ __64bitImplementation files('libs/lbrysdk-0.74.0-release__arm64.aar')
}
apply plugin: 'com.google.gms.google-services'
diff --git a/app/libs/lbrysdk-0.73.1-release__arm.aar b/app/libs/lbrysdk-0.74.0-release__arm.aar
similarity index 70%
rename from app/libs/lbrysdk-0.73.1-release__arm.aar
rename to app/libs/lbrysdk-0.74.0-release__arm.aar
index 025cce9..f917e37 100644
Binary files a/app/libs/lbrysdk-0.73.1-release__arm.aar and b/app/libs/lbrysdk-0.74.0-release__arm.aar differ
diff --git a/app/libs/lbrysdk-0.73.1-release__arm64.aar b/app/libs/lbrysdk-0.74.0-release__arm64.aar
similarity index 71%
rename from app/libs/lbrysdk-0.73.1-release__arm64.aar
rename to app/libs/lbrysdk-0.74.0-release__arm64.aar
index 7d5e4b9..fe87414 100644
Binary files a/app/libs/lbrysdk-0.73.1-release__arm64.aar and b/app/libs/lbrysdk-0.74.0-release__arm64.aar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index aa76201..f682d17 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,11 +3,12 @@
package="io.lbry.browser"
android:installLocation="auto">
+
+
-
cameraPermissionListeners;
private List downloadActionListeners;
private List sdkStatusListeners;
private List storagePermissionListeners;
@@ -296,25 +301,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private static final int STARTUP_STAGE_SUBSCRIPTIONS_LOADED = 6;
private static final int STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED = 7;
- private final List supportedMenuItemIds = Arrays.asList(
- // find content
- NavMenuItem.ID_ITEM_FOLLOWING,
- NavMenuItem.ID_ITEM_EDITORS_CHOICE,
- NavMenuItem.ID_ITEM_ALL_CONTENT,
-
- // your content
- NavMenuItem.ID_ITEM_CHANNELS,
- NavMenuItem.ID_ITEM_LIBRARY,
-
- // wallet
- NavMenuItem.ID_ITEM_WALLET,
- NavMenuItem.ID_ITEM_REWARDS,
- NavMenuItem.ID_ITEM_INVITES,
-
- NavMenuItem.ID_ITEM_SETTINGS,
- NavMenuItem.ID_ITEM_ABOUT
- );
-
public boolean isDarkMode() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
return sp.getBoolean(PREFERENCE_KEY_DARK_MODE, false);
@@ -391,6 +377,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
// other
pendingSyncSetQueue = new ArrayList<>();
openNavFragments = new HashMap<>();
+ cameraPermissionListeners = new ArrayList<>();
downloadActionListeners = new ArrayList<>();
sdkStatusListeners = new ArrayList<>();
storagePermissionListeners = new ArrayList<>();
@@ -468,13 +455,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
return;
}
- if (!supportedMenuItemIds.contains(menuItem.getId())) {
- Snackbar.make(navItemsView, R.string.not_yet_implemented, Snackbar.LENGTH_LONG).show();
- } else {
- navMenuAdapter.setCurrentItem(menuItem);
- shouldOpenUserSelectedMenuItem = true;
- selectedMenuItemId = menuItem.getId();
- }
+ navMenuAdapter.setCurrentItem(menuItem);
+ shouldOpenUserSelectedMenuItem = true;
+ selectedMenuItemId = menuItem.getId();
closeDrawer();
}
});
@@ -496,8 +479,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
specialRouteFragmentClassMap.put("invite", InvitesFragment.class);
specialRouteFragmentClassMap.put("invites", InvitesFragment.class);
specialRouteFragmentClassMap.put("library", LibraryFragment.class);
- //specialRouteFragmentClassMap.put("publish", PublishFragment.class);
- //specialRouteFragmentClassMap.put("publishes", PublishesFragment.class);
+ specialRouteFragmentClassMap.put("publish", PublishFragment.class);
+ specialRouteFragmentClassMap.put("publishes", PublishesFragment.class);
specialRouteFragmentClassMap.put("following", FollowingFragment.class);
specialRouteFragmentClassMap.put("rewards", RewardsFragment.class);
specialRouteFragmentClassMap.put("settings", SettingsFragment.class);
@@ -512,6 +495,16 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
checkNotificationOpenIntent(intent);
}
+ public void addCameraPermissionListener(CameraPermissionListener listener) {
+ if (!cameraPermissionListeners.contains(listener)) {
+ cameraPermissionListeners.add(listener);
+ }
+ }
+
+ public void removeCameraPermissionListener(CameraPermissionListener listener) {
+ cameraPermissionListeners.remove(listener);
+ }
+
public void addDownloadActionListener(DownloadActionListener listener) {
if (!downloadActionListeners.contains(listener)) {
downloadActionListeners.add(listener);
@@ -581,12 +574,18 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
openFragment(AllContentFragment.class, true, NavMenuItem.ID_ITEM_ALL_CONTENT);
break;
+ case NavMenuItem.ID_ITEM_NEW_PUBLISH:
+ openFragment(PublishFragment.class, true, NavMenuItem.ID_ITEM_NEW_PUBLISH);
+ break;
case NavMenuItem.ID_ITEM_CHANNELS:
openFragment(ChannelManagerFragment.class, true, NavMenuItem.ID_ITEM_CHANNELS);
break;
case NavMenuItem.ID_ITEM_LIBRARY:
openFragment(LibraryFragment.class, true, NavMenuItem.ID_ITEM_LIBRARY);
break;
+ case NavMenuItem.ID_ITEM_PUBLISHES:
+ openFragment(PublishesFragment.class, true, NavMenuItem.ID_ITEM_PUBLISHES);
+ break;
case NavMenuItem.ID_ITEM_WALLET:
openFragment(WalletFragment.class, true, NavMenuItem.ID_ITEM_WALLET);
@@ -818,6 +817,20 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
super.onPause();
}
+ public static void suspendGlobalPlayer(Context context) {
+ if (MainActivity.appPlayer != null) {
+ MainActivity.appPlayer.setPlayWhenReady(false);
+ }
+ if (context instanceof MainActivity) {
+ ((MainActivity) context).hideGlobalNowPlaying();
+ }
+ }
+ public static void resumeGlobalPlayer(Context context) {
+ if (context instanceof MainActivity) {
+ ((MainActivity) context).checkNowPlaying();
+ }
+ }
+
private void toggleUrlSuggestions(boolean visible) {
View container = findViewById(R.id.url_suggestions_container);
View closeIcon = findViewById(R.id.wunderbar_close);
@@ -830,7 +843,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
public int getScaledValue(int value) {
float scale = getResources().getDisplayMetrics().density;
- return (int) (value * scale + 0.5f);
+ return Helper.getScaledValue(value, scale);
}
private void setupUriBar() {
@@ -1249,6 +1262,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
startup();
} else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
openFragment(FollowingFragment.class, false, NavMenuItem.ID_ITEM_FOLLOWING);
+ fetchRewards();
}
}
@@ -1340,7 +1354,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
if (navMenuAdapter != null) {
navMenuAdapter.setExtraLabelForItem(
NavMenuItem.ID_ITEM_WALLET,
- Lbryio.LBCUSDRate > 0 ? String.format("$%s", Helper.USD_CURRENCY_FORMAT.format(usdBalance)) : null
+ Lbryio.LBCUSDRate > 0 ? String.format("$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(usdBalance)) : null
);
}
}
@@ -1750,9 +1764,21 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
listener.onStoragePermissionRefused();
}
}
- startingStoragePermissionRequest = false;
+ startingPermissionRequest = false;
break;
+ case REQUEST_CAMERA_PERMISSION:
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ for (CameraPermissionListener listener : cameraPermissionListeners) {
+ listener.onCameraPermissionGranted();
+ }
+ } else {
+ for (CameraPermissionListener listener : cameraPermissionListeners) {
+ listener.onCameraPermissionRefused();
+ }
+ }
+ startingPermissionRequest = false;
+ break;
}
}
@@ -2015,7 +2041,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
if (navMenuAdapter != null) {
navMenuAdapter.setExtraLabelForItem(
NavMenuItem.ID_ITEM_REWARDS,
- Lbryio.LBCUSDRate > 0 ? String.format("$%s", Helper.USD_CURRENCY_FORMAT.format(usdRewardAmount)) : null
+ Lbryio.LBCUSDRate > 0 ? String.format("$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(usdRewardAmount)) : null
);
}
}
@@ -2115,7 +2141,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
}, 1000);
return;
}
- if (startingStoragePermissionRequest) {
+ if (startingPermissionRequest) {
return;
}
enterPIPMode();
@@ -2241,10 +2267,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
));
yourContentGroup.setItems(Arrays.asList(
- //new NavMenuItem(NavMenuItem.ID_ITEM_NEW_PUBLISH, R.string.fa_upload, R.string.new_publish, "NewPublish", context),
+ new NavMenuItem(NavMenuItem.ID_ITEM_NEW_PUBLISH, R.string.fa_upload, R.string.new_publish, "NewPublish", context),
new NavMenuItem(NavMenuItem.ID_ITEM_CHANNELS, R.string.fa_at, R.string.channels, "Channels", context),
- new NavMenuItem(NavMenuItem.ID_ITEM_LIBRARY, R.string.fa_download, R.string.library, "Library", context)
- //new NavMenuItem(NavMenuItem.ID_ITEM_PUBLISHES, R.string.fa_cloud_upload, R.string.publishes, "Publishes", context)
+ new NavMenuItem(NavMenuItem.ID_ITEM_LIBRARY, R.string.fa_download, R.string.library, "Library", context),
+ new NavMenuItem(NavMenuItem.ID_ITEM_PUBLISHES, R.string.fa_cloud_upload, R.string.publishes, "Publishes", context)
));
walletGroup.setItems(Arrays.asList(
@@ -2518,7 +2544,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
if (!forceRequest && ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission)) {
Toast.makeText(context, rationale, Toast.LENGTH_LONG).show();
} else {
- startingStoragePermissionRequest = true;
+ startingPermissionRequest = true;
ActivityCompat.requestPermissions((Activity) context, new String[] { permission }, requestCode);
}
}
diff --git a/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java
index 23f9532..75a64bd 100644
--- a/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java
+++ b/app/src/main/java/io/lbry/browser/adapter/ClaimListAdapter.java
@@ -96,6 +96,14 @@ public class ClaimListAdapter extends RecyclerView.Adapter(this.items);
}
+ public void updateSigningChannelForClaim(Claim resolvedClaim) {
+ for (Claim claim : items) {
+ if (claim.getClaimId().equalsIgnoreCase(resolvedClaim.getClaimId())) {
+ claim.setSigningChannel(resolvedClaim.getSigningChannel());
+ }
+ }
+ }
+
public void clearItems() {
clearSelectedItems();
this.items.clear();
@@ -413,7 +421,10 @@ public class ClaimListAdapter extends RecyclerView.Adapter 0 ?
Double.valueOf(((double) claimFile.getWrittenBytes() / (double) claimFile.getTotalBytes()) * 100.0).intValue() : 0;
diff --git a/app/src/main/java/io/lbry/browser/adapter/GalleryGridAdapter.java b/app/src/main/java/io/lbry/browser/adapter/GalleryGridAdapter.java
new file mode 100644
index 0000000..285f767
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/adapter/GalleryGridAdapter.java
@@ -0,0 +1,122 @@
+package io.lbry.browser.adapter;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.lbry.browser.R;
+import io.lbry.browser.listener.ChannelItemSelectionListener;
+import io.lbry.browser.model.Claim;
+import io.lbry.browser.model.GalleryItem;
+import io.lbry.browser.utils.Helper;
+import lombok.Setter;
+
+public class GalleryGridAdapter extends RecyclerView.Adapter {
+ private Context context;
+ private List items;
+ @Setter
+ private GalleryItemClickListener listener;
+
+ public GalleryGridAdapter(List items, Context context) {
+ this.items = new ArrayList<>(items);
+ this.context = context;
+ }
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ protected ImageView thumbnailView;
+ protected TextView durationView;
+ public ViewHolder(View v) {
+ super(v);
+ thumbnailView = v.findViewById(R.id.gallery_item_thumbnail);
+ durationView = v.findViewById(R.id.gallery_item_duration);
+ }
+ }
+
+ public int getItemCount() {
+ return items != null ? items.size() : 0;
+ }
+
+ public void addItem(GalleryItem item) {
+ if (!items.contains(item)) {
+ items.add(item);
+ notifyDataSetChanged();
+ }
+ }
+
+ public void addItems(List items) {
+ for (GalleryItem item : items) {
+ if (!this.items.contains(item)) {
+ this.items.add(item);
+ notifyDataSetChanged();
+ }
+ }
+ }
+
+ public void clearItems() {
+ items.clear();
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public GalleryGridAdapter.ViewHolder onCreateViewHolder(ViewGroup root, int viewType) {
+ View v = LayoutInflater.from(context).inflate(R.layout.list_item_gallery, root, false);
+ return new GalleryGridAdapter.ViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(GalleryGridAdapter.ViewHolder vh, int position) {
+ GalleryItem item = items.get(position);
+ String thumbnailUrl = item.getThumbnailUrl();
+ Glide.with(context.getApplicationContext()).load(thumbnailUrl).centerCrop().into(vh.thumbnailView);
+ vh.durationView.setVisibility(item.getDuration() > 0 ? View.VISIBLE : View.INVISIBLE);
+ vh.durationView.setText(item.getDuration() > 0 ? Helper.formatDuration(Double.valueOf(item.getDuration() / 1000.0).longValue()) : null);
+
+ vh.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.onGalleryItemClicked(item);
+ }
+ }
+ });
+ }
+
+ public interface GalleryItemClickListener {
+ void onGalleryItemClicked(GalleryItem item);
+ }
+
+ public static class GalleryGridItemDecoration extends RecyclerView.ItemDecoration {
+
+ private int spanCount;
+ private int spacing;
+
+ public GalleryGridItemDecoration(int spanCount, int spacing) {
+ this.spanCount = spanCount;
+ this.spacing = spacing;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ int position = parent.getChildAdapterPosition(view); // item position
+ int column = position % spanCount; // item column
+
+ outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
+ outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
+ if (position >= spanCount) {
+ outRect.top = spacing; // item top
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/io/lbry/browser/adapter/RewardListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/RewardListAdapter.java
index e5ea6c4..71d1bee 100644
--- a/app/src/main/java/io/lbry/browser/adapter/RewardListAdapter.java
+++ b/app/src/main/java/io/lbry/browser/adapter/RewardListAdapter.java
@@ -159,7 +159,7 @@ public class RewardListAdapter extends RecyclerView.Adapter> {
- private String type;
+ private List types;
private View progressView;
private ClaimListResultHandler handler;
private Exception error;
public ClaimListTask(String type, View progressView, ClaimListResultHandler handler) {
- this.type = type;
+ this(Arrays.asList(type), progressView, handler);
+ }
+ public ClaimListTask(List types, View progressView, ClaimListResultHandler handler) {
+ this.types = types;
this.progressView = progressView;
this.handler = handler;
}
@@ -36,8 +40,8 @@ public class ClaimListTask extends AsyncTask> {
try {
Map options = new HashMap<>();
- if (!Helper.isNullOrEmpty(type)) {
- options.put("claim_type", type);
+ if (types != null && types.size() > 0) {
+ options.put("claim_type", types);
}
options.put("page", 1);
options.put("page_size", 999);
diff --git a/app/src/main/java/io/lbry/browser/tasks/localdata/LoadGalleryItemsTask.java b/app/src/main/java/io/lbry/browser/tasks/localdata/LoadGalleryItemsTask.java
new file mode 100644
index 0000000..154a5dc
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/tasks/localdata/LoadGalleryItemsTask.java
@@ -0,0 +1,137 @@
+package io.lbry.browser.tasks.localdata;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.View;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import io.lbry.browser.model.GalleryItem;
+import io.lbry.browser.utils.Helper;
+
+public class LoadGalleryItemsTask extends AsyncTask> {
+ private static final String TAG = "LoadGalleryItemsTask";
+ private LoadGalleryHandler handler;
+ private View progressView;
+ private Context context;
+
+ public LoadGalleryItemsTask(View progressView, Context context, LoadGalleryHandler handler) {
+ this.progressView = progressView;
+ this.context = context;
+ this.handler = handler;
+ }
+
+ protected void onPreExecute(Void... params) {
+ Helper.setViewVisibility(progressView, View.VISIBLE);
+ }
+
+ protected List doInBackground(Void... params) {
+ List items = new ArrayList<>();
+ List itemsWithThumbnails = new ArrayList<>();
+ Cursor cursor = null;
+ if (context != null) {
+ ContentResolver resolver = context.getContentResolver();
+ try {
+ String[] projection = {
+ MediaStore.MediaColumns._ID,
+ MediaStore.MediaColumns.DATA,
+ MediaStore.MediaColumns.DISPLAY_NAME,
+ MediaStore.MediaColumns.MIME_TYPE,
+ MediaStore.Video.Media.DURATION
+ };
+ cursor = resolver.query(
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+ projection, null, null,
+ String.format("%s DESC", MediaStore.MediaColumns.DATE_MODIFIED));
+ while (cursor.moveToNext()) {
+ int idColumn = cursor.getColumnIndex(MediaStore.MediaColumns._ID);
+ int nameColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
+ int typeColumn = cursor.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE);
+ int pathColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
+ int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
+
+ String id = cursor.getString(idColumn);
+ GalleryItem item = new GalleryItem();
+ item.setId(id);
+ item.setName(cursor.getString(nameColumn));
+ item.setType(cursor.getString(typeColumn));
+ item.setFilePath(cursor.getString(pathColumn));
+ item.setDuration(cursor.getLong(durationColumn));
+ items.add(item);
+ }
+ } catch (SQLiteException ex) {
+
+ // failed to load videos. log and pass
+ Log.e(TAG, ex.getMessage(), ex);
+ } finally {
+ Helper.closeCursor(cursor);
+ }
+
+ // load (or generate) thumbnail for each item
+ for (GalleryItem item : items) {
+ String id = item.getId();
+ File cacheDir = context.getExternalCacheDir();
+ File thumbnailsDir = new File(String.format("%s/thumbnails", cacheDir.getAbsolutePath()));
+ if (!thumbnailsDir.isDirectory()) {
+ thumbnailsDir.mkdirs();
+ }
+
+ String thumbnailPath = String.format("%s/%s.png", thumbnailsDir.getAbsolutePath(), id);
+ File file = new File(thumbnailPath);
+ if (!file.exists()) {
+ // save the thumbnail to the path
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = 1;
+ Bitmap thumbnail = MediaStore.Video.Thumbnails.getThumbnail(
+ resolver, Long.parseLong(id), MediaStore.Video.Thumbnails.MINI_KIND, options);
+ if (thumbnail != null) {
+ try (FileOutputStream os = new FileOutputStream(thumbnailPath)) {
+ thumbnail.compress(Bitmap.CompressFormat.PNG, 80, os);
+ } catch (IOException ex) {
+ // skip
+ }
+ }
+ }
+
+ if (file.exists() && file.length() > 0) {
+ item.setThumbnailUrl(Uri.fromFile(file).toString());
+ itemsWithThumbnails.add(item);
+ publishProgress(item);
+ }
+ }
+ }
+
+ return itemsWithThumbnails;
+ }
+
+ protected void onProgressUpdate(GalleryItem... items) {
+ if (handler != null) {
+ for (GalleryItem item : items) {
+ handler.onItemLoaded(item);
+ }
+ }
+ }
+
+ protected void onPostExecute(List items) {
+ if (handler != null) {
+ handler.onAllItemsLoaded(items);
+ }
+ }
+
+ public interface LoadGalleryHandler {
+ void onItemLoaded(GalleryItem item);
+ void onAllItemsLoaded(List items);
+ }
+}
diff --git a/app/src/main/java/io/lbry/browser/ui/BaseFragment.java b/app/src/main/java/io/lbry/browser/ui/BaseFragment.java
index bc3afeb..9e16adc 100644
--- a/app/src/main/java/io/lbry/browser/ui/BaseFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/BaseFragment.java
@@ -16,6 +16,34 @@ public class BaseFragment extends Fragment {
@Setter
private Map params;
+ public boolean shouldHideGlobalPlayer() {
+ return false;
+ }
+
+ public boolean shouldSuspendGlobalPlayer() {
+ return false;
+ }
+
+ public void onStart() {
+ super.onStart();
+ if (shouldSuspendGlobalPlayer()) {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity.suspendGlobalPlayer(context);
+ }
+ }
+ }
+
+ public void onStop() {
+ if (shouldSuspendGlobalPlayer()) {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity.resumeGlobalPlayer(context);
+ }
+ }
+ super.onStop();
+ }
+
public void onResume() {
super.onResume();
Context context = getContext();
@@ -23,12 +51,11 @@ public class BaseFragment extends Fragment {
MainActivity activity = (MainActivity) context;
activity.setSelectedMenuItemForFragment(this);
- if (this instanceof FileViewFragment) {
+ if (shouldHideGlobalPlayer()) {
activity.hideGlobalNowPlaying();
} else {
activity.checkNowPlaying();
}
}
}
-
}
diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java
index e00d673..6c88ccf 100644
--- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java
@@ -214,7 +214,7 @@ public class ChannelContentFragment extends Fragment implements DownloadActionLi
Context context = getContext();
boolean canShowMatureContent = false;
if (context != null) {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
}
diff --git a/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java
index e8c84eb..7284631 100644
--- a/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java
@@ -935,111 +935,114 @@ public class FileViewFragment extends BaseFragment implements
loadViewCount();
checkIsFollowing();
+
+ View root = getView();
+ if (root != null) {
+ root.findViewById(R.id.file_view_scroll_view).scrollTo(0, 0);
+ Helper.setViewVisibility(layoutDisplayArea, View.VISIBLE);
- getView().findViewById(R.id.file_view_scroll_view).scrollTo(0, 0);
- Helper.setViewVisibility(layoutDisplayArea, View.VISIBLE);
+ ImageView descIndicator = root.findViewById(R.id.file_view_desc_toggle_arrow);
+ descIndicator.setImageResource(R.drawable.ic_arrow_dropdown);
- ImageView descIndicator = getView().findViewById(R.id.file_view_desc_toggle_arrow);
- descIndicator.setImageResource(R.drawable.ic_arrow_dropdown);
+ root.findViewById(R.id.file_view_description_area).setVisibility(View.GONE);
+ ((TextView) root.findViewById(R.id.file_view_title)).setText(claim.getTitle());
+ ((TextView) root.findViewById(R.id.file_view_description)).setText(claim.getDescription());
+ ((TextView) root.findViewById(R.id.file_view_publisher_name)).setText(
+ Helper.isNullOrEmpty(claim.getPublisherName()) ? getString(R.string.anonymous) : claim.getPublisherName());
- getView().findViewById(R.id.file_view_description_area).setVisibility(View.GONE);
- ((TextView) getView().findViewById(R.id.file_view_title)).setText(claim.getTitle());
- ((TextView) getView().findViewById(R.id.file_view_description)).setText(claim.getDescription());
- ((TextView) getView().findViewById(R.id.file_view_publisher_name)).setText(
- Helper.isNullOrEmpty(claim.getPublisherName()) ? getString(R.string.anonymous) : claim.getPublisherName());
+ Context context = getContext();
+ RecyclerView descTagsList = root.findViewById(R.id.file_view_tag_list);
+ FlexboxLayoutManager flm = new FlexboxLayoutManager(context);
+ descTagsList.setLayoutManager(flm);
- Context context = getContext();
- RecyclerView descTagsList = getView().findViewById(R.id.file_view_tag_list);
- FlexboxLayoutManager flm = new FlexboxLayoutManager(context);
- descTagsList.setLayoutManager(flm);
-
- List tags = claim.getTagObjects();
- TagListAdapter tagListAdapter = new TagListAdapter(tags, context);
- tagListAdapter.setClickListener(new TagListAdapter.TagClickListener() {
- @Override
- public void onTagClicked(Tag tag, int customizeMode) {
- if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_NONE) {
- Context ctx = getContext();
- if (ctx instanceof MainActivity) {
- ((MainActivity) ctx).openAllContentFragmentWithTag(tag.getName());
+ List tags = claim.getTagObjects();
+ TagListAdapter tagListAdapter = new TagListAdapter(tags, context);
+ tagListAdapter.setClickListener(new TagListAdapter.TagClickListener() {
+ @Override
+ public void onTagClicked(Tag tag, int customizeMode) {
+ if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_NONE) {
+ Context ctx = getContext();
+ if (ctx instanceof MainActivity) {
+ ((MainActivity) ctx).openAllContentFragmentWithTag(tag.getName());
+ }
}
}
+ });
+ descTagsList.setAdapter(tagListAdapter);
+ root.findViewById(R.id.file_view_tag_area).setVisibility(tags.size() > 0 ? View.VISIBLE : View.GONE);
+
+ root.findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE);
+ root.findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE);
+ root.findViewById(R.id.file_view_media_meta_container).setVisibility(View.VISIBLE);
+
+ Claim.GenericMetadata metadata = claim.getValue();
+ if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
+ ImageView thumbnailView = root.findViewById(R.id.file_view_thumbnail);
+ Glide.with(getContext().getApplicationContext()).load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView);
+ } else {
+ // display first x letters of claim name, with random background
}
- });
- descTagsList.setAdapter(tagListAdapter);
- getView().findViewById(R.id.file_view_tag_area).setVisibility(tags.size() > 0 ? View.VISIBLE : View.GONE);
- getView().findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE);
- getView().findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE);
- getView().findViewById(R.id.file_view_media_meta_container).setVisibility(View.VISIBLE);
-
- Claim.GenericMetadata metadata = claim.getValue();
- if (!Helper.isNullOrEmpty(claim.getThumbnailUrl())) {
- ImageView thumbnailView = getView().findViewById(R.id.file_view_thumbnail);
- Glide.with(getContext().getApplicationContext()).load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView);
- } else {
- // display first x letters of claim name, with random background
- }
-
- getView().findViewById(R.id.file_view_main_action_button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onMainActionButtonClicked();
- }
- });
- getView().findViewById(R.id.file_view_media_meta_container).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onMainActionButtonClicked();
- }
- });
-
- if (metadata instanceof Claim.StreamMetadata) {
- Claim.StreamMetadata streamMetadata = (Claim.StreamMetadata) metadata;
- long publishTime = streamMetadata.getReleaseTime() > 0 ? streamMetadata.getReleaseTime() * 1000 : claim.getTimestamp() * 1000;
- ((TextView) getView().findViewById(R.id.file_view_publish_time)).setText(DateUtils.getRelativeTimeSpanString(
- publishTime, System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
-
- Fee fee = streamMetadata.getFee();
- if (fee != null && Helper.parseDouble(fee.getAmount(), 0) > 0) {
- getView().findViewById(R.id.file_view_fee_container).setVisibility(View.VISIBLE);
- ((TextView) getView().findViewById(R.id.file_view_fee)).setText(
- Helper.shortCurrencyFormat(claim.getActualCost(Lbryio.LBCUSDRate).doubleValue()));
- }
- }
-
- getView().findViewById(R.id.file_view_icon_follow_unfollow).setVisibility(claim.getSigningChannel() != null ? View.VISIBLE : View.GONE);
-
- MaterialButton mainActionButton = getView().findViewById(R.id.file_view_main_action_button);
- if (claim.isPlayable()) {
- mainActionButton.setText(R.string.play);
- } else if (claim.isViewable()) {
- mainActionButton.setText(R.string.view);
- } else {
- mainActionButton.setText(R.string.download);
- }
-
- if (claim.isFree()) {
- if (claim.isPlayable()) {
- if (MainActivity.nowPlayingClaim != null && MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId())) {
- // claim already playing
- showExoplayerView();
- playMedia();
- } else {
+ root.findViewById(R.id.file_view_main_action_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
onMainActionButtonClicked();
}
- } else if (claim.isViewable() && Lbry.SDK_READY) {
- onMainActionButtonClicked();
- } else if (!Lbry.SDK_READY) {
+ });
+ root.findViewById(R.id.file_view_media_meta_container).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onMainActionButtonClicked();
+ }
+ });
+
+ if (metadata instanceof Claim.StreamMetadata) {
+ Claim.StreamMetadata streamMetadata = (Claim.StreamMetadata) metadata;
+ long publishTime = streamMetadata.getReleaseTime() > 0 ? streamMetadata.getReleaseTime() * 1000 : claim.getTimestamp() * 1000;
+ ((TextView) root.findViewById(R.id.file_view_publish_time)).setText(DateUtils.getRelativeTimeSpanString(
+ publishTime, System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
+
+ Fee fee = streamMetadata.getFee();
+ if (fee != null && Helper.parseDouble(fee.getAmount(), 0) > 0) {
+ root.findViewById(R.id.file_view_fee_container).setVisibility(View.VISIBLE);
+ ((TextView) root.findViewById(R.id.file_view_fee)).setText(
+ Helper.shortCurrencyFormat(claim.getActualCost(Lbryio.LBCUSDRate).doubleValue()));
+ }
+ }
+
+ root.findViewById(R.id.file_view_icon_follow_unfollow).setVisibility(claim.getSigningChannel() != null ? View.VISIBLE : View.GONE);
+
+ MaterialButton mainActionButton = root.findViewById(R.id.file_view_main_action_button);
+ if (claim.isPlayable()) {
+ mainActionButton.setText(R.string.play);
+ } else if (claim.isViewable()) {
+ mainActionButton.setText(R.string.view);
+ } else {
+ mainActionButton.setText(R.string.download);
+ }
+
+ if (claim.isFree()) {
+ if (claim.isPlayable()) {
+ if (MainActivity.nowPlayingClaim != null && MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId())) {
+ // claim already playing
+ showExoplayerView();
+ playMedia();
+ } else {
+ onMainActionButtonClicked();
+ }
+ } else if (claim.isViewable() && Lbry.SDK_READY) {
+ onMainActionButtonClicked();
+ } else if (!Lbry.SDK_READY) {
+ restoreMainActionButton();
+ }
+ } else {
restoreMainActionButton();
}
- } else {
- restoreMainActionButton();
- }
- RecyclerView relatedContentList = getView().findViewById(R.id.file_view_related_content_list);
- if (relatedContentList == null || relatedContentList.getAdapter() == null || relatedContentList.getAdapter().getItemCount() == 0) {
- loadRelatedContent();
+ RecyclerView relatedContentList = root.findViewById(R.id.file_view_related_content_list);
+ if (relatedContentList == null || relatedContentList.getAdapter() == null || relatedContentList.getAdapter().getItemCount() == 0) {
+ loadRelatedContent();
+ }
}
}
@@ -1067,7 +1070,7 @@ public class FileViewFragment extends BaseFragment implements
boolean newPlayerCreated = false;
Context context = getContext();
- if (MainActivity.appPlayer == null) {
+ if (MainActivity.appPlayer == null && context != null) {
MainActivity.appPlayer = new SimpleExoPlayer.Builder(context).build();
MainActivity.playerCache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 256), new ExoDatabaseProvider(context));
newPlayerCreated = true;
@@ -1081,7 +1084,6 @@ public class FileViewFragment extends BaseFragment implements
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
-
if (MainActivity.nowPlayingClaim != null &&
MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId()) &&
!newPlayerCreated) {
@@ -1089,23 +1091,25 @@ public class FileViewFragment extends BaseFragment implements
return;
}
- showBuffering();
- if (fileViewPlayerListener != null) {
- MainActivity.appPlayer.addListener(fileViewPlayerListener);
- }
- if (context instanceof MainActivity) {
- ((MainActivity) context).setNowPlayingClaim(claim);
- }
+ if (MainActivity.appPlayer != null) {
+ showBuffering();
+ if (fileViewPlayerListener != null) {
+ MainActivity.appPlayer.addListener(fileViewPlayerListener);
+ }
+ if (context instanceof MainActivity) {
+ ((MainActivity) context).setNowPlayingClaim(claim);
+ }
- MainActivity.appPlayer.setPlayWhenReady(true);
- String userAgent = Util.getUserAgent(context, getString(R.string.app_name));
- String mediaSourceUrl = getStreamingUrl();
- MediaSource mediaSource = new ProgressiveMediaSource.Factory(
- new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)),
- new DefaultExtractorsFactory()
- ).createMediaSource(Uri.parse(mediaSourceUrl));
+ MainActivity.appPlayer.setPlayWhenReady(true);
+ String userAgent = Util.getUserAgent(context, getString(R.string.app_name));
+ String mediaSourceUrl = getStreamingUrl();
+ MediaSource mediaSource = new ProgressiveMediaSource.Factory(
+ new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)),
+ new DefaultExtractorsFactory()
+ ).createMediaSource(Uri.parse(mediaSourceUrl));
- MainActivity.appPlayer.prepare(mediaSource, true, true);
+ MainActivity.appPlayer.prepare(mediaSource, true, true);
+ }
}
private void setCurrentPlayer(Player currentPlayer) {
@@ -1174,9 +1178,12 @@ public class FileViewFragment extends BaseFragment implements
public void onSuccess(int count) {
try {
String displayText = getResources().getQuantityString(R.plurals.view_count, count, NumberFormat.getInstance().format(count));
- TextView textViewCount = getView().findViewById(R.id.file_view_view_count);
- Helper.setViewText(textViewCount, displayText);
- Helper.setViewVisibility(textViewCount, View.VISIBLE);
+ View root = getView();
+ if (root != null) {
+ TextView textViewCount = root.findViewById(R.id.file_view_view_count);
+ Helper.setViewText(textViewCount, displayText);
+ Helper.setViewVisibility(textViewCount, View.VISIBLE);
+ }
} catch (IllegalStateException ex) {
// pass
}
@@ -1218,7 +1225,12 @@ public class FileViewFragment extends BaseFragment implements
if (claim != null) {
Fee fee = ((Claim.StreamMetadata) claim.getValue()).getFee();
double cost = claim.getActualCost(Lbryio.LBCUSDRate).doubleValue();
- String message = getResources().getQuantityString(R.plurals.confirm_purchase_message, cost == 1 ? 1 : 2, claim.getTitle(), cost);
+ String formattedCost = Helper.LBC_CURRENCY_FORMAT.format(cost);
+ String message = getResources().getQuantityString(
+ R.plurals.confirm_purchase_message,
+ cost == 1 ? 1 : 2,
+ claim.getTitle(),
+ formattedCost.equals("0") ? Helper.FULL_LBC_CURRENCY_FORMAT.format(cost) : formattedCost);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()).
setTitle(R.string.confirm_purchase).
setMessage(message)
@@ -1445,10 +1457,10 @@ public class FileViewFragment extends BaseFragment implements
}
public void showError(String message) {
- Snackbar.make(getView().findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG).
- setTextColor(Color.WHITE).
- setBackgroundTint(Color.RED).
- show();
+ View root = getView();
+ if (root != null) {
+ Snackbar.make(root, message, Snackbar.LENGTH_LONG).setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
+ }
}
private void loadRelatedContent() {
@@ -1884,4 +1896,9 @@ public class FileViewFragment extends BaseFragment implements
// invalid file info for download
}
}
+
+ @Override
+ public boolean shouldHideGlobalPlayer() {
+ return true;
+ }
}
diff --git a/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java b/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java
index 089ca60..59988c9 100644
--- a/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java
@@ -396,8 +396,12 @@ public class FollowingFragment extends BaseFragment implements
}
private Map buildSuggestedOptions() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
+ Context context = getContext();
+ boolean canShowMatureContent = false;
+ if (context != null) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
+ }
return Lbry.buildClaimSearchOptions(
Claim.TYPE_CHANNEL,
diff --git a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java
index 6b69ef1..e661d73 100644
--- a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java
@@ -46,6 +46,8 @@ import io.lbry.browser.model.NavMenuItem;
import io.lbry.browser.model.ViewHistory;
import io.lbry.browser.tasks.claim.AbandonChannelTask;
import io.lbry.browser.tasks.claim.AbandonHandler;
+import io.lbry.browser.tasks.claim.ClaimListResultHandler;
+import io.lbry.browser.tasks.claim.ResolveTask;
import io.lbry.browser.tasks.file.BulkDeleteFilesTask;
import io.lbry.browser.tasks.file.DeleteFileTask;
import io.lbry.browser.tasks.file.FileListTask;
@@ -55,6 +57,7 @@ import io.lbry.browser.ui.channel.ChannelFormFragment;
import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryAnalytics;
+import io.lbry.browser.utils.LbryUri;
public class LibraryFragment extends BaseFragment implements
ActionMode.Callback, DownloadActionListener, SelectionModeListener, SdkStatusListener {
@@ -320,7 +323,10 @@ public class LibraryFragment extends BaseFragment implements
} else {
contentListAdapter.addItems(claims);
}
- contentList.setAdapter(contentListAdapter);
+ if (contentList.getAdapter() == null) {
+ contentList.setAdapter(contentListAdapter);
+ }
+ resolveMissingChannelNames(buildUrlsToResolve(claims));
checkListEmpty();
contentListLoading = false;
}
@@ -355,7 +361,9 @@ public class LibraryFragment extends BaseFragment implements
} else {
contentListAdapter.addItems(claims);
}
- contentList.setAdapter(contentListAdapter);
+ if (contentList.getAdapter() == null) {
+ contentList.setAdapter(contentListAdapter);
+ }
checkListEmpty();
contentListLoading = false;
}
@@ -564,6 +572,50 @@ public class LibraryFragment extends BaseFragment implements
}
}
+ private List buildUrlsToResolve(List claims) {
+ List urls = new ArrayList<>();
+ for (Claim claim : claims) {
+ Claim channel = claim.getSigningChannel();
+ if (channel != null && Helper.isNullOrEmpty(channel.getName()) && !Helper.isNullOrEmpty(channel.getClaimId())) {
+ LbryUri uri = LbryUri.tryParse(String.format("%s#%s", claim.getName(), claim.getClaimId()));
+ if (uri != null) {
+ urls.add(uri.toString());
+ }
+ }
+ }
+ return urls;
+ }
+
+ private void resolveMissingChannelNames(List urls) {
+ if (urls.size() > 0) {
+ ResolveTask task = new ResolveTask(urls, Lbry.SDK_CONNECTION_STRING, null, new ClaimListResultHandler() {
+ @Override
+ public void onSuccess(List claims) {
+ boolean updated = false;
+ for (Claim claim : claims) {
+ if (claim.getClaimId() == null) {
+ continue;
+ }
+
+ if (contentListAdapter != null) {
+ contentListAdapter.updateSigningChannelForClaim(claim);
+ updated = true;
+ }
+ }
+ if (updated) {
+ contentListAdapter.notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public void onError(Exception error) {
+
+ }
+ });
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+
public void onEnterSelectionMode() {
Context context = getContext();
if (context instanceof MainActivity) {
diff --git a/app/src/main/java/io/lbry/browser/ui/publish/PublishFragment.java b/app/src/main/java/io/lbry/browser/ui/publish/PublishFragment.java
new file mode 100644
index 0000000..48c45bb
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/ui/publish/PublishFragment.java
@@ -0,0 +1,316 @@
+package io.lbry.browser.ui.publish;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.Camera;
+import androidx.camera.core.CameraSelector;
+import androidx.camera.core.CameraX;
+import androidx.camera.core.Preview;
+import androidx.camera.lifecycle.ProcessCameraProvider;
+import androidx.camera.view.PreviewView;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.material.snackbar.Snackbar;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import io.lbry.browser.MainActivity;
+import io.lbry.browser.R;
+import io.lbry.browser.adapter.GalleryGridAdapter;
+import io.lbry.browser.listener.CameraPermissionListener;
+import io.lbry.browser.listener.StoragePermissionListener;
+import io.lbry.browser.model.GalleryItem;
+import io.lbry.browser.tasks.localdata.LoadGalleryItemsTask;
+import io.lbry.browser.ui.BaseFragment;
+import io.lbry.browser.utils.Helper;
+import io.lbry.browser.utils.LbryAnalytics;
+
+public class PublishFragment extends BaseFragment implements CameraPermissionListener, StoragePermissionListener {
+
+ private boolean loadGalleryItemsPending;
+ private PreviewView cameraPreview;
+ private RecyclerView galleryGrid;
+ private GalleryGridAdapter adapter;
+ private TextView noVideosLoaded;
+ private View loading;
+
+ private View buttonRecord;
+ private View buttonTakePhoto;
+ private View buttonUpload;
+
+ private boolean recordPending;
+ private boolean takePhotoPending;
+ private ListenableFuture cameraProviderFuture;
+
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_publish, container, false);
+
+ noVideosLoaded = root.findViewById(R.id.publish_grid_no_videos);
+ loading = root.findViewById(R.id.publish_grid_loading);
+ cameraPreview = root.findViewById(R.id.publish_camera_preview);
+
+ Context context = getContext();
+ galleryGrid = root.findViewById(R.id.publish_video_grid);
+ GridLayoutManager glm = new GridLayoutManager(context, 3);
+ galleryGrid.setLayoutManager(glm);
+ galleryGrid.addItemDecoration(new GalleryGridAdapter.GalleryGridItemDecoration(
+ 3, Helper.getScaledValue(3, context.getResources().getDisplayMetrics().density)));
+
+ buttonRecord = root.findViewById(R.id.publish_record_button);
+ buttonTakePhoto = root.findViewById(R.id.publish_photo_button);
+ buttonUpload = root.findViewById(R.id.publish_upload_button);
+
+ buttonRecord.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ checkCameraPermissionAndRecord();
+ }
+ });
+ buttonTakePhoto.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ checkCameraPermissionAndTakePhoto();
+ }
+ });
+
+ return root;
+ }
+
+ private boolean cameraAvailable() {
+ Context context = getContext();
+ return context != null && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
+ }
+
+ private void showCameraPreview() {
+ buttonRecord.setBackgroundColor(Color.TRANSPARENT);
+ buttonTakePhoto.setBackgroundColor(Color.TRANSPARENT);
+ displayPreviewWithCameraX();
+ }
+
+ private void displayPreviewWithCameraX() {
+ Context context = getContext();
+ if (context != null) {
+ cameraProviderFuture = ProcessCameraProvider.getInstance(context);
+ cameraProviderFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
+ if (cameraProvider != null) {
+ Preview preview = new Preview.Builder().build();
+ CameraSelector cameraSelector = new CameraSelector.Builder()
+ .requireLensFacing(CameraSelector.LENS_FACING_BACK)
+ .build();
+
+ Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, preview);
+ preview.setSurfaceProvider(cameraPreview.createSurfaceProvider(camera.getCameraInfo()));
+ } else {
+ android.util.Log.d("#HELP", "camera provider future is null?");
+ }
+ } catch (ExecutionException | InterruptedException ex) {
+ // pass
+ }
+ }
+ }, ContextCompat.getMainExecutor(context));
+ }
+ }
+
+ private void checkCameraPermissionAndRecord() {
+ Context context = getContext();
+ if (!MainActivity.hasPermission(Manifest.permission.CAMERA, context)) {
+ recordPending = true;
+ MainActivity.requestPermission(
+ Manifest.permission.CAMERA,
+ MainActivity.REQUEST_CAMERA_PERMISSION,
+ getString(R.string.camera_permission_rationale_record),
+ context,
+ true);
+ } else {
+ // start video record intent
+ }
+ }
+
+ private void checkCameraPermissionAndTakePhoto() {
+ Context context = getContext();
+ if (!MainActivity.hasPermission(Manifest.permission.CAMERA, context)) {
+ takePhotoPending = true;
+ MainActivity.requestPermission(
+ Manifest.permission.CAMERA,
+ MainActivity.REQUEST_CAMERA_PERMISSION,
+ getString(R.string.camera_permission_rationale_photo),
+ context,
+ true);
+ } else {
+ // start video record intent
+ }
+ }
+
+ public void onResume() {
+ super.onResume();
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ LbryAnalytics.setCurrentScreen(activity, "Publish", "Publish");
+ activity.addCameraPermissionListener(this);
+ activity.addStoragePermissionListener(this);
+ activity.hideFloatingWalletBalance();
+
+
+ if (cameraAvailable() && MainActivity.hasPermission(Manifest.permission.CAMERA, context)) {
+ showCameraPreview();
+ }
+ }
+
+ checkStoragePermissionAndLoadVideos();
+ }
+
+ @SuppressLint("RestrictedApi")
+ public void onStop() {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ activity.removeCameraPermissionListener(this);
+ activity.removeStoragePermissionListener(this);
+ activity.showFloatingWalletBalance();
+ }
+ CameraX.unbindAll();
+ super.onStop();
+ }
+
+ private void checkStoragePermissionAndLoadVideos() {
+ Context context = getContext();
+ if (MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) {
+ loadGalleryItems();
+ } else {
+ loadGalleryItemsPending = true;
+ MainActivity.requestPermission(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ MainActivity.REQUEST_STORAGE_PERMISSION,
+ getString(R.string.storage_permission_rationale_download),
+ context,
+ true);
+ }
+ }
+
+ private void loadGalleryItems() {
+ Context context = getContext();
+ Helper.setViewVisibility(noVideosLoaded, View.GONE);
+ LoadGalleryItemsTask task = new LoadGalleryItemsTask(loading, context, new LoadGalleryItemsTask.LoadGalleryHandler() {
+ @Override
+ public void onItemLoaded(GalleryItem item) {
+ if (context != null) {
+ if (adapter == null) {
+ adapter = new GalleryGridAdapter(Arrays.asList(item), context);
+ } else {
+ adapter.addItem(item);
+ }
+
+ if (galleryGrid.getAdapter() == null) {
+ galleryGrid.setAdapter(adapter);
+ }
+ Helper.setViewVisibility(loading, adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ @Override
+ public void onAllItemsLoaded(List items) {
+ if (context != null) {
+ if (adapter == null) {
+ adapter = new GalleryGridAdapter(items, context);
+ } else {
+ adapter.addItems(items);
+ }
+
+ if (galleryGrid.getAdapter() == null) {
+ galleryGrid.setAdapter(adapter);
+ }
+ }
+ checkNoVideosLoaded();
+ }
+ });
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ public void checkNoVideosLoaded() {
+ Helper.setViewVisibility(noVideosLoaded, adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public void onCameraPermissionGranted() {
+ if (recordPending) {
+ // record video
+ recordPending = false;
+ } else if (takePhotoPending) {
+ // take a photo
+ takePhotoPending = false;
+ }
+ }
+
+ @Override
+ public void onCameraPermissionRefused() {
+ if (takePhotoPending) {
+ takePhotoPending = false;
+ Snackbar.make(getView(), R.string.camera_permission_rationale_photo, Toast.LENGTH_LONG).
+ setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
+ return;
+ }
+
+ recordPending = false;
+ Snackbar.make(getView(), R.string.camera_permission_rationale_record, Toast.LENGTH_LONG).
+ setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
+ }
+
+ @Override
+ public void onRecordAudioPermissionGranted() {
+
+ }
+
+ @Override
+ public void onRecordAudioPermissionRefused() {
+
+ }
+
+ @Override
+ public void onStoragePermissionGranted() {
+ if (loadGalleryItemsPending) {
+ loadGalleryItemsPending = false;
+ loadGalleryItems();
+ }
+ }
+
+ @Override
+ public void onStoragePermissionRefused() {
+ Snackbar.make(getView(), R.string.storage_permission_rationale_videos, Snackbar.LENGTH_LONG).setBackgroundTint(
+ ContextCompat.getColor(getContext(), R.color.red)
+ ).show();
+ }
+
+ @Override
+ public boolean shouldHideGlobalPlayer() {
+ return true;
+ }
+
+ @Override
+ public boolean shouldSuspendGlobalPlayer() {
+ return true;
+ }
+}
diff --git a/app/src/main/java/io/lbry/browser/ui/publish/PublishesFragment.java b/app/src/main/java/io/lbry/browser/ui/publish/PublishesFragment.java
new file mode 100644
index 0000000..3420f5f
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/ui/publish/PublishesFragment.java
@@ -0,0 +1,321 @@
+package io.lbry.browser.ui.publish;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ProgressBar;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.view.ActionMode;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.lbry.browser.MainActivity;
+import io.lbry.browser.R;
+import io.lbry.browser.adapter.ClaimListAdapter;
+import io.lbry.browser.listener.SdkStatusListener;
+import io.lbry.browser.listener.SelectionModeListener;
+import io.lbry.browser.model.Claim;
+import io.lbry.browser.tasks.claim.AbandonChannelTask;
+import io.lbry.browser.tasks.claim.AbandonHandler;
+import io.lbry.browser.tasks.claim.ClaimListResultHandler;
+import io.lbry.browser.tasks.claim.ClaimListTask;
+import io.lbry.browser.ui.BaseFragment;
+import io.lbry.browser.utils.Helper;
+import io.lbry.browser.utils.Lbry;
+import io.lbry.browser.utils.LbryAnalytics;
+
+public class PublishesFragment extends BaseFragment implements ActionMode.Callback, SelectionModeListener, SdkStatusListener {
+
+ private Button buttonNewPublish;
+ private FloatingActionButton fabNewPublish;
+ private ActionMode actionMode;
+ private View emptyView;
+ private View layoutSdkInitializing;
+ private ProgressBar loading;
+ private ProgressBar bigLoading;
+ private RecyclerView contentList;
+ private ClaimListAdapter adapter;
+
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_publishes, container, false);
+
+ buttonNewPublish = root.findViewById(R.id.publishes_create_button);
+ fabNewPublish = root.findViewById(R.id.publishes_fab_new_publish);
+ buttonNewPublish.setOnClickListener(newPublishClickListener);
+ fabNewPublish.setOnClickListener(newPublishClickListener);
+
+ emptyView = root.findViewById(R.id.publishes_empty_container);
+ layoutSdkInitializing = root.findViewById(R.id.container_sdk_initializing);
+ contentList = root.findViewById(R.id.publishes_list);
+ LinearLayoutManager llm = new LinearLayoutManager(getContext());
+ contentList.setLayoutManager(llm);
+ loading = root.findViewById(R.id.publishes_list_loading);
+ bigLoading = root.findViewById(R.id.publishes_list_big_loading);
+
+ layoutSdkInitializing.setVisibility(Lbry.SDK_READY ? View.GONE : View.VISIBLE);
+
+ return root;
+ }
+
+ private View.OnClickListener newPublishClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ //((MainActivity) context).openPublishForm(null);
+ }
+ }
+ };
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Context context = getContext();
+ if (context != null) {
+ MainActivity activity = (MainActivity) context;
+ activity.hideFloatingWalletBalance();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ activity.showFloatingWalletBalance();
+ }
+ super.onStop();
+ }
+
+ public void onResume() {
+ super.onResume();
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ activity.setWunderbarValue(null);
+ LbryAnalytics.setCurrentScreen(activity, "Publishes", "Publishes");
+ }
+
+ if (!Lbry.SDK_READY) {
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ activity.addSdkStatusListener(this);
+ }
+ } else {
+ onSdkReady();
+ }
+ }
+
+ public void onSdkReady() {
+ Helper.setViewVisibility(layoutSdkInitializing, View.GONE);
+ Helper.setViewVisibility(fabNewPublish, View.VISIBLE);
+ if (adapter != null && contentList != null) {
+ contentList.setAdapter(adapter);
+ }
+ fetchPublishes();
+ }
+
+ public View getLoading() {
+ return (adapter == null || adapter.getItemCount() == 0) ? bigLoading : loading;
+ }
+
+ private void checkNoPublishes() {
+ Helper.setViewVisibility(emptyView, adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+
+ private void fetchPublishes() {
+ Helper.setViewVisibility(emptyView, View.GONE);
+ ClaimListTask task = new ClaimListTask(Arrays.asList(Claim.TYPE_STREAM, Claim.TYPE_REPOST), getLoading(), new ClaimListResultHandler() {
+ @Override
+ public void onSuccess(List claims) {
+ Lbry.ownClaims = Helper.filterDeletedClaims(new ArrayList<>(claims));
+ Context context = getContext();
+ if (adapter == null) {
+ adapter = new ClaimListAdapter(claims, context);
+ adapter.setCanEnterSelectionMode(true);
+ adapter.setSelectionModeListener(PublishesFragment.this);
+ adapter.setListener(new ClaimListAdapter.ClaimListItemListener() {
+ @Override
+ public void onClaimClicked(Claim claim) {
+ if (context instanceof MainActivity) {
+ ((MainActivity) context).openFileClaim(claim);
+ }
+ }
+ });
+ if (contentList != null) {
+ contentList.setAdapter(adapter);
+ }
+ } else {
+ adapter.setItems(claims);
+ }
+
+ checkNoPublishes();
+ }
+
+ @Override
+ public void onError(Exception error) {
+ checkNoPublishes();
+ }
+ });
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ public void onEnterSelectionMode() {
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ activity.startSupportActionMode(this);
+ }
+ }
+ public void onItemSelectionToggled() {
+ if (actionMode != null) {
+ actionMode.setTitle(String.valueOf(adapter.getSelectedCount()));
+ actionMode.invalidate();
+ }
+ }
+ public void onExitSelectionMode() {
+ if (actionMode != null) {
+ actionMode.finish();
+ }
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+ this.actionMode = actionMode;
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ MainActivity activity = (MainActivity) context;
+ if (!activity.isDarkMode()) {
+ activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+ }
+ }
+
+ actionMode.getMenuInflater().inflate(R.menu.menu_claim_list, menu);
+ return true;
+ }
+ @Override
+ public void onDestroyActionMode(ActionMode actionMode) {
+ if (adapter != null) {
+ adapter.clearSelectedItems();
+ adapter.setInSelectionMode(false);
+ adapter.notifyDataSetChanged();
+ }
+ Context context = getContext();
+ if (context != null) {
+ MainActivity activity = (MainActivity) context;
+ if (!activity.isDarkMode()) {
+ activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ }
+ }
+ this.actionMode = null;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(androidx.appcompat.view.ActionMode actionMode, Menu menu) {
+ int selectionCount = adapter != null ? adapter.getSelectedCount() : 0;
+ menu.findItem(R.id.action_edit).setVisible(selectionCount == 1);
+ return true;
+ }
+
+ @Override
+ public boolean onActionItemClicked(androidx.appcompat.view.ActionMode actionMode, MenuItem menuItem) {
+ if (R.id.action_edit == menuItem.getItemId()) {
+ if (adapter != null && adapter.getSelectedCount() > 0) {
+ Claim claim = adapter.getSelectedItems().get(0);
+ // start channel editor with the claim
+ Context context = getContext();
+ if (context instanceof MainActivity) {
+ Map params = new HashMap<>();
+ params.put("claim", claim);
+ /*((MainActivity) context).openFragment(PublishFormFragment.class, true, NavMenuItem.ID_ITEM_NEW_PUBLISH, params);*/
+ }
+
+ actionMode.finish();
+ return true;
+ }
+ }
+ if (R.id.action_delete == menuItem.getItemId()) {
+ if (adapter != null && adapter.getSelectedCount() > 0) {
+ final List selectedClaims = new ArrayList<>(adapter.getSelectedItems());
+ String message = getResources().getQuantityString(R.plurals.confirm_delete_publishes, selectedClaims.size());
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext()).
+ setTitle(R.string.delete_selection).
+ setMessage(message)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ handleDeleteSelectedClaims(selectedClaims);
+ }
+ }).setNegativeButton(R.string.no, null);
+ builder.show();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void handleDeleteSelectedClaims(List selectedClaims) {
+ List claimIds = new ArrayList<>();
+
+ for (Claim claim : selectedClaims) {
+ claimIds.add(claim.getClaimId());
+ }
+
+ if (actionMode != null) {
+ actionMode.finish();
+ }
+
+ Helper.setViewVisibility(contentList, View.INVISIBLE);
+ Helper.setViewVisibility(fabNewPublish, View.INVISIBLE);
+ AbandonChannelTask task = new AbandonChannelTask(claimIds, bigLoading, new AbandonHandler() {
+ @Override
+ public void onComplete(List successfulClaimIds, List failedClaimIds, List errors) {
+ View root = getView();
+ if (root != null) {
+ if (failedClaimIds.size() > 0) {
+ Snackbar.make(root, R.string.one_or_more_publishes_failed_abandon, Snackbar.LENGTH_LONG).
+ setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show();
+ } else if (successfulClaimIds.size() == claimIds.size()) {
+ try {
+ String message = getResources().getQuantityString(R.plurals.publishes_deleted, successfulClaimIds.size());
+ Snackbar.make(root, message, Snackbar.LENGTH_LONG).show();
+ } catch (IllegalStateException ex) {
+ // pass
+ }
+ }
+ }
+
+ Lbry.abandonedClaimIds.addAll(successfulClaimIds);
+ if (adapter != null) {
+ adapter.setItems(Helper.filterDeletedClaims(adapter.getItems()));
+ }
+
+ Helper.setViewVisibility(contentList, View.VISIBLE);
+ Helper.setViewVisibility(fabNewPublish, View.VISIBLE);
+ checkNoPublishes();
+ }
+ });
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+}
diff --git a/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java b/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java
index bfbfe29..6f9a09b 100644
--- a/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java
@@ -214,8 +214,13 @@ public class SearchFragment extends BaseFragment implements
}
searchLoading = true;
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
+ Context context = getContext();
+ boolean canShowMatureContent = false;
+ if (context != null) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+ canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
+ }
+
LighthouseSearchTask task = new LighthouseSearchTask(
currentQuery, PAGE_SIZE, currentFrom, canShowMatureContent, null, loadingView, new ClaimSearchTask.ClaimSearchResultHandler() {
@Override
diff --git a/app/src/main/java/io/lbry/browser/ui/wallet/RewardsFragment.java b/app/src/main/java/io/lbry/browser/ui/wallet/RewardsFragment.java
index 3851969..b0b2791 100644
--- a/app/src/main/java/io/lbry/browser/ui/wallet/RewardsFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/wallet/RewardsFragment.java
@@ -233,7 +233,7 @@ public class RewardsFragment extends BaseFragment implements RewardListAdapter.R
Helper.shortCurrencyFormat(Lbryio.totalUnclaimedRewardAmount));
double unclaimedRewardAmountUsd = Lbryio.totalUnclaimedRewardAmount * Lbryio.LBCUSDRate;
Helper.setViewText(textAccountDriverTitle, accountDriverTitle);
- Helper.setViewText(textFreeCreditsWorth, getString(R.string.free_credits_worth, Helper.USD_CURRENCY_FORMAT.format(unclaimedRewardAmountUsd)));
+ Helper.setViewText(textFreeCreditsWorth, getString(R.string.free_credits_worth, Helper.SIMPLE_CURRENCY_FORMAT.format(unclaimedRewardAmountUsd)));
} catch (IllegalStateException ex) {
// pass
}
diff --git a/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java b/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java
index c435e05..c1d035f 100644
--- a/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java
+++ b/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java
@@ -398,8 +398,12 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
}
private void checkReceiveAddress() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- String receiveAddress = sp.getString(MainActivity.PREFERENCE_KEY_INTERNAL_WALLET_RECEIVE_ADDRESS, null);
+ Context context = getContext();
+ String receiveAddress = null;
+ if (context != null) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+ receiveAddress = sp.getString(MainActivity.PREFERENCE_KEY_INTERNAL_WALLET_RECEIVE_ADDRESS, null);
+ }
if (Helper.isNullOrEmpty(receiveAddress)) {
if (Lbry.SDK_READY) {
generateNewAddress();
@@ -505,15 +509,16 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W
double tipsBalance = walletBalance.getTips().doubleValue();
double tipsUsdBalance = tipsBalance * Lbryio.LBCUSDRate;
- Helper.setViewText(textWalletBalance, Helper.LBC_CURRENCY_FORMAT.format(balance));
+ String formattedBalance = Helper.SIMPLE_CURRENCY_FORMAT.format(balance);
+ Helper.setViewText(textWalletBalance, balance > 0 && formattedBalance.equals("0") ? Helper.FULL_LBC_CURRENCY_FORMAT.format(balance) : formattedBalance);
Helper.setViewText(textTipsBalance, Helper.shortCurrencyFormat(tipsBalance));
Helper.setViewText(textClaimsBalance, Helper.shortCurrencyFormat(walletBalance.getClaims().doubleValue()));
Helper.setViewText(textSupportsBalance, Helper.shortCurrencyFormat(walletBalance.getSupports().doubleValue()));
Helper.setViewText(textWalletInlineBalance, Helper.shortCurrencyFormat(balance));
if (Lbryio.LBCUSDRate > 0) {
// only update display usd values if the rate is loaded
- Helper.setViewText(textWalletBalanceUSD, String.format("≈$%s", Helper.USD_CURRENCY_FORMAT.format(usdBalance)));
- Helper.setViewText(textTipsBalanceUSD, String.format("≈$%s", Helper.USD_CURRENCY_FORMAT.format(tipsUsdBalance)));
+ Helper.setViewText(textWalletBalanceUSD, String.format("≈$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(usdBalance)));
+ Helper.setViewText(textTipsBalanceUSD, String.format("≈$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(tipsUsdBalance)));
}
}
}
diff --git a/app/src/main/java/io/lbry/browser/utils/Helper.java b/app/src/main/java/io/lbry/browser/utils/Helper.java
index b1e5434..edca68f 100644
--- a/app/src/main/java/io/lbry/browser/utils/Helper.java
+++ b/app/src/main/java/io/lbry/browser/utils/Helper.java
@@ -67,7 +67,8 @@ public final class Helper {
public static final String LBC_CURRENCY_FORMAT_PATTERN = "#,###.##";
public static final String FILE_SIZE_FORMAT_PATTERN = "#,###.#";
public static final DecimalFormat LBC_CURRENCY_FORMAT = new DecimalFormat(LBC_CURRENCY_FORMAT_PATTERN);
- public static final DecimalFormat USD_CURRENCY_FORMAT = new DecimalFormat("#,##0.00");
+ public static final DecimalFormat FULL_LBC_CURRENCY_FORMAT = new DecimalFormat("#,###.########");
+ public static final DecimalFormat SIMPLE_CURRENCY_FORMAT = new DecimalFormat("#,##0.00");
public static final String EXPLORER_TX_PREFIX = "https://explorer.lbry.com/tx";
public static boolean isNull(String value) {
@@ -300,7 +301,7 @@ public final class Helper {
return "0";
}
- return format.format(value);
+ return format.format(value).equals("0") ? FULL_LBC_CURRENCY_FORMAT.format(value) : format.format(value);
}
public static String getValue(CharSequence cs) {
@@ -680,4 +681,8 @@ public final class Helper {
}
return channelName;
}
+
+ public static int getScaledValue(int value, float scale) {
+ return (int) (value * scale + 0.5f);
+ }
}
diff --git a/app/src/main/java/io/lbry/browser/utils/Lbryio.java b/app/src/main/java/io/lbry/browser/utils/Lbryio.java
index 2a180c1..85ed74e 100644
--- a/app/src/main/java/io/lbry/browser/utils/Lbryio.java
+++ b/app/src/main/java/io/lbry/browser/utils/Lbryio.java
@@ -44,7 +44,7 @@ import okhttp3.Response;
public final class Lbryio {
// TODO: Get this from the bundled aar
- public static String SDK_VERSION = "0.73.1";
+ public static String SDK_VERSION = "0.74.0";
public static User currentUser;
public static boolean userHasSyncedWallet = false;
@@ -121,7 +121,7 @@ public final class Lbryio {
if (options != null) {
for (Map.Entry option : options.entrySet()) {
- qs.append(delim).append(option.getKey()).append("=").append(URLEncoder.encode(option.getValue(), "UTF8"));
+ qs.append(delim).append(option.getKey()).append("=").append(URLEncoder.encode(Helper.isNull(option.getValue()) ? "" : option.getValue(), "UTF8"));
delim = "&";
}
}
diff --git a/app/src/main/res/drawable-anydpi/ic_photo.xml b/app/src/main/res/drawable-anydpi/ic_photo.xml
new file mode 100644
index 0000000..e234376
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_photo.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_record.xml b/app/src/main/res/drawable-anydpi/ic_record.xml
new file mode 100644
index 0000000..42f62d5
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_record.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_upload.xml b/app/src/main/res/drawable-anydpi/ic_upload.xml
new file mode 100644
index 0000000..faebc4a
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_upload.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_photo.png b/app/src/main/res/drawable-hdpi/ic_photo.png
new file mode 100644
index 0000000..b94ccbd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_photo.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_record.png b/app/src/main/res/drawable-hdpi/ic_record.png
new file mode 100644
index 0000000..6b81b67
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_record.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_upload.png b/app/src/main/res/drawable-hdpi/ic_upload.png
new file mode 100644
index 0000000..6edf2fd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_upload.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_photo.png b/app/src/main/res/drawable-mdpi/ic_photo.png
new file mode 100644
index 0000000..668c633
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_photo.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_record.png b/app/src/main/res/drawable-mdpi/ic_record.png
new file mode 100644
index 0000000..eb6412b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_record.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_upload.png b/app/src/main/res/drawable-mdpi/ic_upload.png
new file mode 100644
index 0000000..c914b14
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_upload.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_photo.png b/app/src/main/res/drawable-xhdpi/ic_photo.png
new file mode 100644
index 0000000..5165e58
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_photo.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_record.png b/app/src/main/res/drawable-xhdpi/ic_record.png
new file mode 100644
index 0000000..f8c501c
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_record.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_upload.png b/app/src/main/res/drawable-xhdpi/ic_upload.png
new file mode 100644
index 0000000..904b34e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_upload.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_photo.png b/app/src/main/res/drawable-xxhdpi/ic_photo.png
new file mode 100644
index 0000000..9a0ecd7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_photo.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_record.png b/app/src/main/res/drawable-xxhdpi/ic_record.png
new file mode 100644
index 0000000..256cc26
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_record.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_upload.png b/app/src/main/res/drawable-xxhdpi/ic_upload.png
new file mode 100644
index 0000000..4416762
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_upload.png differ
diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml
index 93a043b..44fd8b9 100644
--- a/app/src/main/res/layout/app_bar_main.xml
+++ b/app/src/main/res/layout/app_bar_main.xml
@@ -40,6 +40,7 @@
android:layout_height="wrap_content"
android:hint="@string/uri_placeholder"
android:imeOptions="actionGo"
+ android:inputType="textNoSuggestions"
android:selectAllOnFocus="true"
android:singleLine="true"
android:textFontWeight="300"
diff --git a/app/src/main/res/layout/fragment_publish.xml b/app/src/main/res/layout/fragment_publish.xml
new file mode 100644
index 0000000..fcc1983
--- /dev/null
+++ b/app/src/main/res/layout/fragment_publish.xml
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_publishes.xml b/app/src/main/res/layout/fragment_publishes.xml
new file mode 100644
index 0000000..e3af5bb
--- /dev/null
+++ b/app/src/main/res/layout/fragment_publishes.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_gallery.xml b/app/src/main/res/layout/list_item_gallery.xml
new file mode 100644
index 0000000..d18d75e
--- /dev/null
+++ b/app/src/main/res/layout/list_item_gallery.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 8f93dac..d35fef9 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -15,6 +15,7 @@
#55000000
#F4E866
+ #333333
#33000000
@color/nextLbryGreen
@color/nextLbryGreen
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index db9bc4e..698db21 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -93,6 +93,27 @@
- %1$s followers
+
+ Record
+ Take a Photo
+ Upload a file
+ We could not find any videos on your device. Take a photo or record a video to get started.
+ Please wait while we load your videos...
+ LBRY requires access to be able to display and publish your videos, images and other files from your device.
+ LBRY requires access to your camera to record videos.
+ LBRY requires access to your camera to take photos.
+
+
+ One or more content items could not be deleted at this time. Please try again later.
+
+ - Are you sure you want to delete the selected content item?
+ - Are you sure you want to delete the selected content items?
+
+
+ - The content item was successfully deleted.
+ - The content items were successfully deleted.
+
+
Oops! Something went wrong.
Loaded Installation ID.
@@ -323,7 +344,7 @@
The claim is pending publish on the blockchain. You will be able to access or edit the claim in a few moments.
Pending
Create
- One or moe channels could not be deleted at this time. Please try again later.
+ One or more channels could not be deleted at this time. Please try again later.
- A minimum deposit of %1$s credit is required.
- A minimum deposit of %1$s credits is required.
diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml
index a241c71..9999c44 100644
--- a/app/src/main/res/xml/settings.xml
+++ b/app/src/main/res/xml/settings.xml
@@ -1,8 +1,7 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto">