sdk 0.74.0. Publish and Publishes pages.
|
@ -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'
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
package="io.lbry.browser"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.content.res.Configuration;
|
|||
import android.content.res.TypedArray;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -30,7 +29,6 @@ import android.util.Log;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
@ -96,6 +94,7 @@ import io.lbry.browser.adapter.UrlSuggestionListAdapter;
|
|||
import io.lbry.browser.data.DatabaseHelper;
|
||||
import io.lbry.browser.dialog.ContentScopeDialogFragment;
|
||||
import io.lbry.browser.exceptions.LbryUriException;
|
||||
import io.lbry.browser.listener.CameraPermissionListener;
|
||||
import io.lbry.browser.listener.DownloadActionListener;
|
||||
import io.lbry.browser.listener.FetchChannelsListener;
|
||||
import io.lbry.browser.listener.SdkStatusListener;
|
||||
|
@ -133,6 +132,8 @@ import io.lbry.browser.ui.following.FileViewFragment;
|
|||
import io.lbry.browser.ui.following.FollowingFragment;
|
||||
import io.lbry.browser.ui.library.LibraryFragment;
|
||||
import io.lbry.browser.ui.other.AboutFragment;
|
||||
import io.lbry.browser.ui.publish.PublishFragment;
|
||||
import io.lbry.browser.ui.publish.PublishesFragment;
|
||||
import io.lbry.browser.ui.search.SearchFragment;
|
||||
import io.lbry.browser.ui.other.SettingsFragment;
|
||||
import io.lbry.browser.ui.allcontent.AllContentFragment;
|
||||
|
@ -164,7 +165,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
public static Claim nowPlayingClaim;
|
||||
public static boolean startingFilePickerActivity = false;
|
||||
public static boolean startingShareActivity = false;
|
||||
public static boolean startingStoragePermissionRequest = false;
|
||||
public static boolean startingPermissionRequest = false;
|
||||
public static boolean startingSignInFlowActivity = false;
|
||||
private boolean enteringPIPMode = false;
|
||||
private boolean fullSyncInProgress = false;
|
||||
|
@ -185,8 +186,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
fragmentClassNavIdMap.put(EditorsChoiceFragment.class, NavMenuItem.ID_ITEM_EDITORS_CHOICE);
|
||||
fragmentClassNavIdMap.put(AllContentFragment.class, NavMenuItem.ID_ITEM_ALL_CONTENT);
|
||||
|
||||
fragmentClassNavIdMap.put(PublishFragment.class, NavMenuItem.ID_ITEM_NEW_PUBLISH);
|
||||
fragmentClassNavIdMap.put(ChannelManagerFragment.class, NavMenuItem.ID_ITEM_CHANNELS);
|
||||
fragmentClassNavIdMap.put(LibraryFragment.class, NavMenuItem.ID_ITEM_LIBRARY);
|
||||
fragmentClassNavIdMap.put(PublishesFragment.class, NavMenuItem.ID_ITEM_PUBLISHES);
|
||||
|
||||
fragmentClassNavIdMap.put(WalletFragment.class, NavMenuItem.ID_ITEM_WALLET);
|
||||
fragmentClassNavIdMap.put(RewardsFragment.class, NavMenuItem.ID_ITEM_REWARDS);
|
||||
|
@ -202,6 +205,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
}
|
||||
|
||||
public static final int REQUEST_STORAGE_PERMISSION = 1001;
|
||||
public static final int REQUEST_CAMERA_PERMISSION = 1002;
|
||||
public static final int REQUEST_SIMPLE_SIGN_IN = 2001;
|
||||
public static final int REQUEST_WALLET_SYNC_SIGN_IN = 2002;
|
||||
public static final int REQUEST_REWARDS_VERIFY_SIGN_IN = 2003;
|
||||
|
@ -270,6 +274,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
@Getter
|
||||
private DatabaseHelper dbHelper;
|
||||
private int selectedMenuItemId = -1;
|
||||
private List<CameraPermissionListener> cameraPermissionListeners;
|
||||
private List<DownloadActionListener> downloadActionListeners;
|
||||
private List<SdkStatusListener> sdkStatusListeners;
|
||||
private List<StoragePermissionListener> 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<Integer> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,14 @@ public class ClaimListAdapter extends RecyclerView.Adapter<ClaimListAdapter.View
|
|||
return new ArrayList<>(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<ClaimListAdapter.View
|
|||
boolean isDownloading = false;
|
||||
int progress = 0;
|
||||
String fileSizeString = claimFile == null ? null : Helper.formatBytes(claimFile.getTotalBytes(), false);
|
||||
if (claimFile != null && !claimFile.isCompleted() && claimFile.getWrittenBytes() < claimFile.getTotalBytes()) {
|
||||
if (claimFile != null &&
|
||||
!Helper.isNullOrEmpty(claimFile.getDownloadPath()) &&
|
||||
!claimFile.isCompleted() &&
|
||||
claimFile.getWrittenBytes() < claimFile.getTotalBytes()) {
|
||||
isDownloading = true;
|
||||
progress = claimFile.getTotalBytes() > 0 ?
|
||||
Double.valueOf(((double) claimFile.getWrittenBytes() / (double) claimFile.getTotalBytes()) * 100.0).intValue() : 0;
|
||||
|
|
|
@ -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<GalleryGridAdapter.ViewHolder> {
|
||||
private Context context;
|
||||
private List<GalleryItem> items;
|
||||
@Setter
|
||||
private GalleryItemClickListener listener;
|
||||
|
||||
public GalleryGridAdapter(List<GalleryItem> 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<GalleryItem> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -159,7 +159,7 @@ public class RewardListAdapter extends RecyclerView.Adapter<RewardListAdapter.Vi
|
|||
});
|
||||
|
||||
vh.textUsdValue.setText(reward.isCustom() || Lbryio.LBCUSDRate == 0 ? null :
|
||||
String.format("≈$%s", Helper.USD_CURRENCY_FORMAT.format(rewardAmount * Lbryio.LBCUSDRate)));
|
||||
String.format("≈$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(rewardAmount * Lbryio.LBCUSDRate)));
|
||||
|
||||
vh.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
|
|
@ -22,7 +22,7 @@ import io.lbry.browser.utils.Helper;
|
|||
import io.lbry.browser.utils.LbryUri;
|
||||
|
||||
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
public static final int DATABASE_VERSION = 1;
|
||||
public static final int DATABASE_VERSION = 2;
|
||||
public static final String DATABASE_NAME = "LbryApp.db";
|
||||
private static DatabaseHelper instance;
|
||||
|
||||
|
@ -40,6 +40,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
", claim_id TEXT" +
|
||||
", claim_name TEXT" +
|
||||
", cost REAL " +
|
||||
", currency TEXT " +
|
||||
", title TEXT " +
|
||||
", publisher_claim_id TEXT" +
|
||||
", publisher_name TEXT" +
|
||||
|
@ -58,6 +59,10 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
"CREATE INDEX idx_view_history_device ON view_history (device)"
|
||||
};
|
||||
|
||||
private static final String[] SQL_V1_V2_UPGRADE = {
|
||||
"ALTER TABLE view_history ADD COLUMN currency TEXT"
|
||||
};
|
||||
|
||||
private static final String SQL_INSERT_SUBSCRIPTION = "REPLACE INTO subscriptions (channel_name, url) VALUES (?, ?)";
|
||||
private static final String SQL_DELETE_SUBSCRIPTION = "DELETE FROM subscriptions WHERE url = ?";
|
||||
private static final String SQL_GET_SUBSCRIPTIONS = "SELECT channel_name, url FROM subscriptions";
|
||||
|
@ -68,9 +73,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
private static final String SQL_GET_RECENT_URL_HISTORY = "SELECT value, url, type FROM url_history ORDER BY timestamp DESC LIMIT 10";
|
||||
|
||||
private static final String SQL_INSERT_VIEW_HISTORY =
|
||||
"REPLACE INTO view_history (url, claim_id, claim_name, cost, title, publisher_claim_id, publisher_name, publisher_title, thumbnail_url, device, release_time, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
"REPLACE INTO view_history (url, claim_id, claim_name, cost, currency, title, publisher_claim_id, publisher_name, publisher_title, thumbnail_url, device, release_time, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String SQL_GET_VIEW_HISTORY =
|
||||
"SELECT url, claim_id, claim_name, cost, title, publisher_claim_id, publisher_name, publisher_title, thumbnail_url, device, release_time, timestamp " +
|
||||
"SELECT url, claim_id, claim_name, cost, currency, title, publisher_claim_id, publisher_name, publisher_title, thumbnail_url, device, release_time, timestamp " +
|
||||
"FROM view_history WHERE '' = ? OR timestamp < ? ORDER BY timestamp DESC LIMIT %d";
|
||||
private static final String SQL_CLEAR_VIEW_HISTORY = "DELETE FROM view_history";
|
||||
private static final String SQL_CLEAR_VIEW_HISTORY_BY_DEVICE = "DELETE FROM view_history WHERE device = ?";
|
||||
|
@ -82,6 +87,8 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
private static final String SQL_UNFOLLOW_TAGS = "UPDATE tags SET is_followed = 0";
|
||||
private static final String SQL_GET_FOLLOWED_TAGS = "SELECT name FROM tags WHERE is_followed = 1";
|
||||
|
||||
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, String.format("%s/%s", context.getFilesDir().getAbsolutePath(), DATABASE_NAME), null, DATABASE_VERSION);
|
||||
instance = this;
|
||||
|
@ -98,7 +105,11 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
}
|
||||
}
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
if (oldVersion < 2) {
|
||||
for (String sql : SQL_V1_V2_UPGRADE) {
|
||||
db.execSQL(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
|
@ -142,6 +153,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
viewHistory.getClaimId(),
|
||||
viewHistory.getClaimName(),
|
||||
viewHistory.getCost() != null ? viewHistory.getCost().doubleValue() : 0,
|
||||
viewHistory.getCurrency(),
|
||||
viewHistory.getTitle(),
|
||||
viewHistory.getPublisherClaimId(),
|
||||
viewHistory.getPublisherName(),
|
||||
|
@ -166,6 +178,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
item.setClaimId(cursor.getString(cursorIndex++));
|
||||
item.setClaimName(cursor.getString(cursorIndex++));
|
||||
item.setCost(new BigDecimal(cursor.getDouble(cursorIndex++)));
|
||||
item.setCurrency(cursor.getString(cursorIndex++));
|
||||
item.setTitle(cursor.getString(cursorIndex++));
|
||||
item.setPublisherClaimId(cursor.getString(cursorIndex++));
|
||||
item.setPublisherName(cursor.getString(cursorIndex++));
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package io.lbry.browser.listener;
|
||||
|
||||
public interface CameraPermissionListener {
|
||||
void onCameraPermissionGranted();
|
||||
void onCameraPermissionRefused();
|
||||
void onRecordAudioPermissionGranted();
|
||||
void onRecordAudioPermissionRefused();
|
||||
}
|
13
app/src/main/java/io/lbry/browser/model/GalleryItem.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package io.lbry.browser.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GalleryItem {
|
||||
private String id;
|
||||
private String name;
|
||||
private String filePath;
|
||||
private String type;
|
||||
private String thumbnailUrl;
|
||||
private long duration;
|
||||
}
|
|
@ -8,6 +8,7 @@ import org.json.JSONException;
|
|||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -18,13 +19,16 @@ import io.lbry.browser.utils.Helper;
|
|||
import io.lbry.browser.utils.Lbry;
|
||||
|
||||
public class ClaimListTask extends AsyncTask<Void, Void, List<Claim>> {
|
||||
private String type;
|
||||
private List<String> 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<String> types, View progressView, ClaimListResultHandler handler) {
|
||||
this.types = types;
|
||||
this.progressView = progressView;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
@ -36,8 +40,8 @@ public class ClaimListTask extends AsyncTask<Void, Void, List<Claim>> {
|
|||
|
||||
try {
|
||||
Map<String, Object> 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);
|
||||
|
|
|
@ -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<Void, GalleryItem, List<GalleryItem>> {
|
||||
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<GalleryItem> doInBackground(Void... params) {
|
||||
List<GalleryItem> items = new ArrayList<>();
|
||||
List<GalleryItem> 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<GalleryItem> items) {
|
||||
if (handler != null) {
|
||||
handler.onAllItemsLoaded(items);
|
||||
}
|
||||
}
|
||||
|
||||
public interface LoadGalleryHandler {
|
||||
void onItemLoaded(GalleryItem item);
|
||||
void onAllItemsLoaded(List<GalleryItem> items);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,34 @@ public class BaseFragment extends Fragment {
|
|||
@Setter
|
||||
private Map<String, Object> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -936,110 +936,113 @@ public class FileViewFragment extends BaseFragment implements
|
|||
loadViewCount();
|
||||
checkIsFollowing();
|
||||
|
||||
getView().findViewById(R.id.file_view_scroll_view).scrollTo(0, 0);
|
||||
Helper.setViewVisibility(layoutDisplayArea, View.VISIBLE);
|
||||
View root = getView();
|
||||
if (root != null) {
|
||||
root.findViewById(R.id.file_view_scroll_view).scrollTo(0, 0);
|
||||
Helper.setViewVisibility(layoutDisplayArea, View.VISIBLE);
|
||||
|
||||
ImageView descIndicator = getView().findViewById(R.id.file_view_desc_toggle_arrow);
|
||||
descIndicator.setImageResource(R.drawable.ic_arrow_dropdown);
|
||||
ImageView descIndicator = root.findViewById(R.id.file_view_desc_toggle_arrow);
|
||||
descIndicator.setImageResource(R.drawable.ic_arrow_dropdown);
|
||||
|
||||
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());
|
||||
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());
|
||||
|
||||
Context context = getContext();
|
||||
RecyclerView descTagsList = getView().findViewById(R.id.file_view_tag_list);
|
||||
FlexboxLayoutManager flm = new FlexboxLayoutManager(context);
|
||||
descTagsList.setLayoutManager(flm);
|
||||
Context context = getContext();
|
||||
RecyclerView descTagsList = root.findViewById(R.id.file_view_tag_list);
|
||||
FlexboxLayoutManager flm = new FlexboxLayoutManager(context);
|
||||
descTagsList.setLayoutManager(flm);
|
||||
|
||||
List<Tag> 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<Tag> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -396,8 +396,12 @@ public class FollowingFragment extends BaseFragment implements
|
|||
}
|
||||
|
||||
private Map<String, Object> 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,
|
||||
|
|
|
@ -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<String> buildUrlsToResolve(List<Claim> claims) {
|
||||
List<String> 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<String> urls) {
|
||||
if (urls.size() > 0) {
|
||||
ResolveTask task = new ResolveTask(urls, Lbry.SDK_CONNECTION_STRING, null, new ClaimListResultHandler() {
|
||||
@Override
|
||||
public void onSuccess(List<Claim> 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) {
|
||||
|
|
|
@ -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<ProcessCameraProvider> 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<GalleryItem> 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;
|
||||
}
|
||||
}
|
|
@ -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<Claim> 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<String, Object> 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<Claim> 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<Claim> selectedClaims) {
|
||||
List<String> 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<String> successfulClaimIds, List<String> failedClaimIds, List<Exception> 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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, String> 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 = "&";
|
||||
}
|
||||
}
|
||||
|
|
14
app/src/main/res/drawable-anydpi/ic_photo.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
|
||||
</vector>
|
11
app/src/main/res/drawable-anydpi/ic_record.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
|
||||
</vector>
|
11
app/src/main/res/drawable-anydpi/ic_upload.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,16h6v-6h4l-7,-7 -7,7h4zM5,18h14v2L5,20z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable-hdpi/ic_photo.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
app/src/main/res/drawable-hdpi/ic_record.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
app/src/main/res/drawable-hdpi/ic_upload.png
Normal file
After Width: | Height: | Size: 171 B |
BIN
app/src/main/res/drawable-mdpi/ic_photo.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
app/src/main/res/drawable-mdpi/ic_record.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
app/src/main/res/drawable-mdpi/ic_upload.png
Normal file
After Width: | Height: | Size: 131 B |
BIN
app/src/main/res/drawable-xhdpi/ic_photo.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
app/src/main/res/drawable-xhdpi/ic_record.png
Normal file
After Width: | Height: | Size: 195 B |
BIN
app/src/main/res/drawable-xhdpi/ic_upload.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_photo.png
Normal file
After Width: | Height: | Size: 662 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_record.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_upload.png
Normal file
After Width: | Height: | Size: 237 B |
|
@ -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"
|
||||
|
|
179
app/src/main/res/layout/fragment_publish.xml
Normal file
|
@ -0,0 +1,179 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/publishBackground">
|
||||
<RelativeLayout
|
||||
android:id="@+id/publish_main_actions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp">
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/publish_camera_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
<RelativeLayout
|
||||
android:id="@+id/publish_record_button"
|
||||
android:background="@android:color/black"
|
||||
android:clickable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="-1.5dp">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:tint="@color/white"
|
||||
android:src="@drawable/ic_record" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/record"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<RelativeLayout
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent">
|
||||
<View
|
||||
android:id="@+id/publish_vertical_divider"
|
||||
android:background="@color/publishBackground"
|
||||
android:layout_width="3dp"
|
||||
android:layout_height="match_parent" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/publish_photo_button"
|
||||
android:clickable="true"
|
||||
android:background="@android:color/black"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:layout_toRightOf="@id/publish_vertical_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="148.5dp">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:tint="@color/white"
|
||||
android:src="@drawable/ic_photo" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/take_photo"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/publish_photo_upload_divider"
|
||||
android:background="@color/publishBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
android:layout_below="@id/publish_photo_button" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/publish_upload_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="148.5dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@id/publish_vertical_divider"
|
||||
android:clickable="true"
|
||||
android:background="@android:color/black"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:tint="@color/white"
|
||||
android:src="@drawable/ic_upload" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/upload_file"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/publish_video_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/publish_main_actions"
|
||||
android:layout_marginTop="3dp" />
|
||||
<TextView
|
||||
android:id="@+id/publish_grid_no_videos"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/publish_main_actions"
|
||||
android:layout_margin="16dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/no_videos_found"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/publish_grid_loading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/publish_main_actions"
|
||||
android:visibility="gone">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="horizontal">
|
||||
<ProgressBar
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/loading_videos"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
75
app/src/main/res/layout/fragment_publishes.xml
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:focusedByDefault="true">
|
||||
<ProgressBar
|
||||
android:id="@+id/publishes_list_big_loading"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone" />
|
||||
<ProgressBar
|
||||
android:id="@+id/publishes_list_loading"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:visibility="gone" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/publishes_list"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/publishes_empty_container"
|
||||
android:background="@color/pageBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:padding="36dp">
|
||||
<ImageView
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="300dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/gerbil_happy" />
|
||||
<TextView
|
||||
android:text="@string/no_channel_created"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:fontFamily="@font/inter"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp"
|
||||
android:textFontWeight="300"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/publishes_create_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:text="@string/new_publish" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<include layout="@layout/container_sdk_initializing" />
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/publishes_fab_new_publish"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/ic_add"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
28
app/src/main/res/layout/list_item_gallery.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:orientation="vertical"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
<ImageView
|
||||
android:id="@+id/gallery_item_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<TextView
|
||||
android:background="@android:color/black"
|
||||
android:id="@+id/gallery_item_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="10sp"
|
||||
android:textFontWeight="300"
|
||||
android:padding="2dp"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
|
@ -15,6 +15,7 @@
|
|||
<color name="smallIconBackground">#55000000</color>
|
||||
<color name="costBackground">#F4E866</color>
|
||||
|
||||
<color name="publishBackground">#333333</color>
|
||||
<color name="playerControlsBackground">#33000000</color>
|
||||
<color name="scrubberColor">@color/nextLbryGreen</color>
|
||||
<color name="playedColor">@color/nextLbryGreen</color>
|
||||
|
|
|
@ -93,6 +93,27 @@
|
|||
<item quantity="other">%1$s followers</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Publish -->
|
||||
<string name="record">Record</string>
|
||||
<string name="take_photo">Take a Photo</string>
|
||||
<string name="upload_file">Upload a file</string>
|
||||
<string name="no_videos_found">We could not find any videos on your device. Take a photo or record a video to get started.</string>
|
||||
<string name="loading_videos">Please wait while we load your videos...</string>
|
||||
<string name="storage_permission_rationale_videos">LBRY requires access to be able to display and publish your videos, images and other files from your device.</string>
|
||||
<string name="camera_permission_rationale_record">LBRY requires access to your camera to record videos.</string>
|
||||
<string name="camera_permission_rationale_photo">LBRY requires access to your camera to take photos.</string>
|
||||
|
||||
<!-- Publishes -->
|
||||
<string name="one_or_more_publishes_failed_abandon">One or more content items could not be deleted at this time. Please try again later.</string>
|
||||
<plurals name="confirm_delete_publishes">
|
||||
<item quantity="one">Are you sure you want to delete the selected content item?</item>
|
||||
<item quantity="other">Are you sure you want to delete the selected content items?</item>
|
||||
</plurals>
|
||||
<plurals name="publishes_deleted">
|
||||
<item quantity="one">The content item was successfully deleted.</item>
|
||||
<item quantity="other">The content items were successfully deleted.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Splash -->
|
||||
<string name="oops_something_went_wrong">Oops! Something went wrong.</string>
|
||||
<string name="installation_id_loaded">Loaded Installation ID.</string>
|
||||
|
@ -323,7 +344,7 @@
|
|||
<string name="item_pending_blockchain">The claim is pending publish on the blockchain. You will be able to access or edit the claim in a few moments.</string>
|
||||
<string name="pending">Pending</string>
|
||||
<string name="create">Create</string>
|
||||
<string name="one_or_more_channels_failed_abandon">One or moe channels could not be deleted at this time. Please try again later.</string>
|
||||
<string name="one_or_more_channels_failed_abandon">One or more channels could not be deleted at this time. Please try again later.</string>
|
||||
<plurals name="min_deposit_required">
|
||||
<item quantity="one">A minimum deposit of %1$s credit is required.</item>
|
||||
<item quantity="other">A minimum deposit of %1$s credits is required.</item>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
>
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceCategory
|
||||
android:title="@string/user_interface"
|
||||
app:iconSpaceReserved="false">
|
||||
|
|