diff --git a/app/libs/lbrysdk-0.73.1-release__arm.aar b/app/libs/lbrysdk-0.73.1-release__arm.aar index 6058d44a..025cce96 100644 Binary files a/app/libs/lbrysdk-0.73.1-release__arm.aar and b/app/libs/lbrysdk-0.73.1-release__arm.aar differ diff --git a/app/libs/lbrysdk-0.73.1-release__arm64.aar b/app/libs/lbrysdk-0.73.1-release__arm64.aar index 525e693d..7d5e4b98 100644 Binary files a/app/libs/lbrysdk-0.73.1-release__arm64.aar and b/app/libs/lbrysdk-0.73.1-release__arm64.aar differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ea66be0f..aa76201e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -67,13 +67,6 @@ android:parentActivityName=".MainActivity" android:theme="@style/AppTheme.NoActionBarTranslucent" android:windowSoftInputMode="adjustResize" /> - specialRouteFragmentClassMap; private boolean inPictureInPictureMode; public static SimpleExoPlayer appPlayer; + public static Cache playerCache; + public static boolean playerReassigned; public static CastContext castContext; public static CastPlayer castPlayer; public static Claim nowPlayingClaim; public static boolean startingFilePickerActivity = false; public static boolean startingShareActivity = false; - public static boolean startingFileViewActivity = false; + public static boolean startingStoragePermissionRequest = false; public static boolean startingSignInFlowActivity = false; - public static boolean mainActive = false; private boolean enteringPIPMode = false; + private boolean fullSyncInProgress = false; + private int queuedSyncCount = 0; + + @Setter + private BackPressInterceptor backPressInterceptor; @Getter private String firebaseMessagingToken; @@ -243,18 +253,20 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener // broadcast receivers private BroadcastReceiver serviceActionsReceiver; private BroadcastReceiver requestsReceiver; - private BroadcastReceiver userActionsReceiver; private static boolean appStarted; private boolean serviceRunning; private CheckSdkReadyTask checkSdkReadyTask; private boolean receivedStopService; private ActionBarDrawerToggle toggle; + private SyncSetTask syncSetTask = null; + private List pendingSyncSetQueue; @Getter private DatabaseHelper dbHelper; private int selectedMenuItemId = -1; private List downloadActionListeners; private List sdkStatusListeners; + private List storagePermissionListeners; private List walletBalanceListeners; private List fetchChannelsListeners; @Getter @@ -338,15 +350,44 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener // register receivers registerRequestsReceiver(); registerServiceActionsReceiver(); - registerUserActionsReceiver(); + + View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + // not fullscreen + View appBarMainContainer = findViewById(R.id.app_bar_main_container); + appBarMainContainer.setPadding( + appBarMainContainer.getPaddingLeft(), appBarMainContainer.getPaddingTop(), appBarMainContainer.getPaddingRight(), 0); + appBarMainContainer.setFitsSystemWindows(true); + } + } + }); // setup uri bar setupUriBar(); + /*View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { + findViewById(R.id.app_bar_main_container).setFitsSystemWindows(false); + findViewById(R.id.drawer_layout).setFitsSystemWindows(false); + } else { + findViewById(R.id.app_bar_main_container).setFitsSystemWindows(true); + findViewById(R.id.drawer_layout).setFitsSystemWindows(true); + } + } + });*/ + // other + pendingSyncSetQueue = new ArrayList<>(); openNavFragments = new HashMap<>(); downloadActionListeners = new ArrayList<>(); sdkStatusListeners = new ArrayList<>(); + storagePermissionListeners = new ArrayList<>(); walletBalanceListeners = new ArrayList<>(); fetchChannelsListeners = new ArrayList<>(); @@ -400,12 +441,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener @Override public void onClick(View view) { if (nowPlayingClaim != null) { - Intent intent = new Intent(MainActivity.this, FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", nowPlayingClaim.getClaimId()); - intent.putExtra("url", nowPlayingClaim.getPermanentUrl()); - startingFileViewActivity = true; - startActivity(intent); + openFileUrl(!Helper.isNullOrEmpty(nowPlayingClaim.getShortUrl()) ? nowPlayingClaim.getShortUrl() : nowPlayingClaim.getPermanentUrl()); } } }); @@ -438,7 +474,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener }); navItemsView.setAdapter(navMenuAdapter); - findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener() { + findViewById(R.id.sign_in_button_container).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { walletSyncSignIn(); @@ -490,6 +526,16 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener sdkStatusListeners.remove(listener); } + public void addStoragePermissionListener(StoragePermissionListener listener) { + if (!storagePermissionListeners.contains(listener)) { + storagePermissionListeners.add(listener); + } + } + + public void removeStoragePermissionListener(StoragePermissionListener listener) { + storagePermissionListeners.remove(listener); + } + public void addWalletBalanceListener(WalletBalanceListener listener) { if (!walletBalanceListeners.contains(listener)) { walletBalanceListeners.add(listener); @@ -501,7 +547,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } public void removeNavFragment(Class fragmentClass, int navItemId) { - String key = buildNavFragmentKey(fragmentClass, navItemId); + String key = buildNavFragmentKey(fragmentClass, navItemId, null); if (openNavFragments.containsKey(key)) { openNavFragments.remove(key); } @@ -589,27 +635,23 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener wunderbar.setSelection(0); } - private void openAllContentFragmentWithTag(String tag) { + public void openAllContentFragmentWithTag(String tag) { Map params = new HashMap<>(); params.put("singleTag", tag); openFragment(AllContentFragment.class, true, NavMenuItem.ID_ITEM_ALL_CONTENT, params); } - public static void openFileUrl(String url, Context context) { - Intent intent = new Intent(context, FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("url", url); - startingFileViewActivity = true; - context.startActivity(intent); + public void openFileUrl(String url) { + Map params = new HashMap<>(); + params.put("url", url); + openFragment(FileViewFragment.class, true, NavMenuItem.ID_ITEM_FOLLOWING, params); } - public static void openFileClaim(Claim claim, Context context) { - Intent intent = new Intent(context, FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", claim.getClaimId()); - intent.putExtra("url", !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()); - startingFileViewActivity = true; - context.startActivity(intent); + public void openFileClaim(Claim claim) { + Map params = new HashMap<>(); + params.put("claimId", claim.getClaimId()); + params.put("url", !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()); + openFragment(FileViewFragment.class, true, NavMenuItem.ID_ITEM_FOLLOWING, params); } private FragmentManager.OnBackStackChangedListener backStackChangedListener = new FragmentManager.OnBackStackChangedListener() { @@ -636,21 +678,31 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener findViewById(R.id.content_main).setVisibility(View.GONE); findViewById(R.id.floating_balance_main_container).setVisibility(View.GONE); findViewById(R.id.global_now_playing_card).setVisibility(View.GONE); + findViewById(R.id.global_sdk_initializing_status).setVisibility(View.GONE); getSupportActionBar().hide(); PlayerView pipPlayer = findViewById(R.id.pip_player); pipPlayer.setVisibility(View.VISIBLE); pipPlayer.setPlayer(appPlayer); + pipPlayer.setUseController(false); + playerReassigned = true; } private void renderFullMode() { getSupportActionBar().show(); findViewById(R.id.content_main).setVisibility(View.VISIBLE); findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE); - findViewById(R.id.global_now_playing_card).setVisibility(View.VISIBLE); + Fragment fragment = getCurrentFragment(); + if (!(fragment instanceof FileViewFragment)) { + findViewById(R.id.global_now_playing_card).setVisibility(View.VISIBLE); + } + if (!Lbry.SDK_READY) { + findViewById(R.id.global_sdk_initializing_status).setVisibility(View.VISIBLE); + } PlayerView pipPlayer = findViewById(R.id.pip_player); pipPlayer.setVisibility(View.INVISIBLE); pipPlayer.setPlayer(null); + playerReassigned = true; } @Override @@ -673,6 +725,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener appPlayer.release(); appPlayer = null; } + if (playerCache != null) { + playerCache.release(); + playerCache = null; + } } @Override @@ -709,8 +765,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener @Override protected void onResume() { super.onResume(); - mainActive = true; + applyNavbarSigninPadding(); checkFirstRun(); checkNowPlaying(); @@ -750,7 +806,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener @Override protected void onPause() { - mainActive = false; + if (!enteringPIPMode && appPlayer != null) { + appPlayer.setPlayWhenReady(false); + } super.onPause(); } @@ -824,7 +882,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener clearWunderbarFocus(wunderbar); handled = true; } else { - openFileUrl(uri.toString(), MainActivity.this); + openFileUrl(uri.toString()); clearWunderbarFocus(wunderbar); handled = true; } @@ -849,7 +907,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener urlSuggestionListAdapter.setListener(new UrlSuggestionListAdapter.UrlSuggestionClickListener() { @Override public void onUrlSuggestionClicked(UrlSuggestion urlSuggestion) { - Context context = MainActivity.this; switch (urlSuggestion.getType()) { case UrlSuggestion.TYPE_CHANNEL: // open channel page @@ -861,9 +918,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener break; case UrlSuggestion.TYPE_FILE: if (urlSuggestion.getClaim() != null) { - openFileClaim(urlSuggestion.getClaim(), context); + openFileClaim(urlSuggestion.getClaim()); } else { - openFileUrl(urlSuggestion.getUri().toString(), context); + openFileUrl(urlSuggestion.getUri().toString()); } break; case UrlSuggestion.TYPE_SEARCH: @@ -1091,7 +1148,12 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener return suggestions; } - private void checkNowPlaying() { + public void checkNowPlaying() { + Fragment fragment = getCurrentFragment(); + if (fragment instanceof FileViewFragment) { + return; + } + if (nowPlayingClaim != null) { findViewById(R.id.global_now_playing_card).setVisibility(View.VISIBLE); ((TextView) findViewById(R.id.global_now_playing_title)).setText(nowPlayingClaim.getTitle()); @@ -1102,11 +1164,64 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener playerView.setPlayer(null); playerView.setPlayer(appPlayer); playerView.setUseController(false); + playerReassigned = true; getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } + public void hideGlobalNowPlaying() { + findViewById(R.id.global_now_playing_card).setVisibility(View.GONE); + } + + public void unsetFitsSystemWindows(View view) { + view.setFitsSystemWindows(false); + } + + public void enterFullScreenMode() { + hideFloatingWalletBalance(); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.hide(); + } + findViewById(R.id.global_sdk_initializing_status).setVisibility(View.GONE); + findViewById(R.id.app_bar_main_container).setFitsSystemWindows(false); + + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | + View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + + public int getStatusBarHeight() { + int height = 0; + int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + height = getResources().getDimensionPixelSize(resourceId); + } + return height; + } + + public void exitFullScreenMode() { + View decorView = getWindow().getDecorView(); + int flags = isDarkMode() ? (View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE) : + (View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE); + decorView.setSystemUiVisibility(flags); + + if (!Lbry.SDK_READY) { + findViewById(R.id.global_sdk_initializing_status).setVisibility(View.VISIBLE); + } + showFloatingWalletBalance(); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.show(); + } + } + private void initKeyStore() { try { Lbry.KEYSTORE = Utils.initKeyStore(this); @@ -1296,7 +1411,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener for (Fragment fragment : openNavFragments.values()) { if (fragment instanceof FollowingFragment) { // reload local subscriptions - ((FollowingFragment) fragment).fetchLoadedSubscriptions(); + ((FollowingFragment) fragment).fetchLoadedSubscriptions(true); } } } @@ -1353,11 +1468,81 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener return walletSyncEnabled && Lbryio.isSignedIn(); } + public void syncSet(String hash, String data) { + if (syncSetTask == null || syncSetTask.getStatus() == AsyncTask.Status.FINISHED) { + syncSetTask = new SyncSetTask(Lbryio.lastRemoteHash, hash, data, new DefaultSyncTaskHandler() { + @Override + public void onSyncSetSuccess(String hash) { + Lbryio.lastRemoteHash = hash; + WalletSync walletSync = new WalletSync(hash, data); + Lbryio.lastWalletSync = walletSync; + + if (pendingSyncSetQueue.size() > 0) { + fullSyncInProgress = true; + WalletSync nextSync = pendingSyncSetQueue.remove(0); + syncSet(nextSync.getHash(), nextSync.getData()); + } else if (queuedSyncCount > 0) { + queuedSyncCount--; + syncApplyAndSet(); + } + + fullSyncInProgress = false; + } + @Override + public void onSyncSetError(Exception error) { + // log app exceptions + if (pendingSyncSetQueue.size() > 0) { + WalletSync nextSync = pendingSyncSetQueue.remove(0); + syncSet(nextSync.getHash(), nextSync.getData()); + } else if (queuedSyncCount > 0) { + queuedSyncCount--; + syncApplyAndSet(); + } + + fullSyncInProgress = false; + } + }); + syncSetTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + WalletSync pending = new WalletSync(hash, data); + pendingSyncSetQueue.add(pending); + } + } + + public void syncApplyAndSet() { + fullSyncInProgress = true; + String password = Utils.getSecureValue(SECURE_VALUE_KEY_SAVED_PASSWORD, this, Lbry.KEYSTORE); + SyncApplyTask fetchTask = new SyncApplyTask(true, password, new DefaultSyncTaskHandler() { + @Override + public void onSyncApplySuccess(String hash, String data) { + if (!hash.equalsIgnoreCase(Lbryio.lastRemoteHash)) { + syncSet(hash, data); + } else { + fullSyncInProgress = false; + queuedSyncCount = 0; + } + } + @Override + public void onSyncApplyError(Exception error) { + fullSyncInProgress = false; + if (queuedSyncCount > 0) { + queuedSyncCount--; + syncApplyAndSet(); + } + } + }); + fetchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + public void syncWalletAndLoadPreferences() { if (!userSyncEnabled()) { return; } + if (fullSyncInProgress) { + queuedSyncCount++; + } + fullSyncInProgress = true; String password = Utils.getSecureValue(SECURE_VALUE_KEY_SAVED_PASSWORD, this, Lbry.KEYSTORE); SyncGetTask task = new SyncGetTask(password, true, null, new DefaultSyncTaskHandler() { @Override @@ -1376,13 +1561,21 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener public void onSyncGetError(Exception error) { // pass Log.e(TAG, String.format("sync get failed: %s", error != null ? error.getMessage() : "no error message"), error); + + fullSyncInProgress = false; + if (queuedSyncCount > 0) { + queuedSyncCount--; + syncApplyAndSet(); + } } @Override public void onSyncApplySuccess(String hash, String data) { if (!hash.equalsIgnoreCase(Lbryio.lastRemoteHash)) { - SyncSetTask setTask = new SyncSetTask(Lbryio.lastRemoteHash, hash, data, null); - setTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + syncSet(hash, data); + } else { + fullSyncInProgress = false; + queuedSyncCount = 0; } loadSharedUserState(); @@ -1392,6 +1585,11 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener public void onSyncApplyError(Exception error) { // pass Log.e(TAG, String.format("sync apply failed: %s", error != null ? error.getMessage() : "no error message"), error); + fullSyncInProgress = false; + if (queuedSyncCount > 0) { + queuedSyncCount--; + syncApplyAndSet(); + } } }); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -1458,70 +1656,43 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } } } - - private void registerUserActionsReceiver() { - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(ACTION_NOW_PLAYING_CLAIM_UPDATED); - intentFilter.addAction(ACTION_NOW_PLAYING_CLAIM_CLEARED); - userActionsReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (ACTION_NOW_PLAYING_CLAIM_UPDATED.equals(action)) { - handleNowPlayingClaimUpdated(); - } else if (ACTION_NOW_PLAYING_CLAIM_CLEARED.equals(action)) { - handleNowPlayingClaimCleared(); - } - } - - private void handleNowPlayingClaimUpdated() { - if (nowPlayingClaim != null) { - ((TextView) findViewById(R.id.global_now_playing_title)).setText(nowPlayingClaim.getTitle()); - ((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(nowPlayingClaim.getPublisherTitle()); - } - } - - private void handleNowPlayingClaimCleared() { - findViewById(R.id.global_now_playing_card).setVisibility(View.GONE); - ((TextView) findViewById(R.id.global_now_playing_title)).setText(null); - ((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(null); - if (MainActivity.appPlayer != null) { - MainActivity.appPlayer.setPlayWhenReady(false); - } - } - }; - registerReceiver(userActionsReceiver, intentFilter); - } - public void showMessage(int stringResourceId) { Snackbar.make(findViewById(R.id.content_main), stringResourceId, Snackbar.LENGTH_LONG).show(); } public void showMessage(String message) { Snackbar.make(findViewById(R.id.content_main), message, Snackbar.LENGTH_LONG).show(); } + public void showError(String message) { + Snackbar.make(findViewById(R.id.content_main), message, Snackbar.LENGTH_LONG). + setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show(); + } @Override public void onBackPressed() { + + if (findViewById(R.id.url_suggestions_container).getVisibility() == View.VISIBLE) { + clearWunderbarFocus(findViewById(R.id.wunderbar)); + return; + } + if (backPressInterceptor != null && backPressInterceptor.onBackPressed()) { + return; + } + DrawerLayout drawer = findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { boolean handled = false; - if (findViewById(R.id.url_suggestions_container).getVisibility() == View.VISIBLE) { - clearWunderbarFocus(findViewById(R.id.wunderbar)); + ChannelFormFragment channelFormFragment = null; + for (Fragment fragment : openNavFragments.values()) { + if (fragment instanceof ChannelFormFragment) { + channelFormFragment = ((ChannelFormFragment) fragment); + break; + } + } + if (channelFormFragment != null && channelFormFragment.isSaveInProgress()) { handled = true; - } else { - ChannelFormFragment channelFormFragment = null; - for (Fragment fragment : openNavFragments.values()) { - if (fragment instanceof ChannelFormFragment) { - channelFormFragment = ((ChannelFormFragment) fragment); - break; - } - } - if (channelFormFragment != null && channelFormFragment.isSaveInProgress()) { - handled = true; - return; - } + return; } if (!handled) { @@ -1563,24 +1734,16 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_STORAGE_PERMISSION: - ChannelFormFragment channelFormFragment = null; - //PublishFormFragment publishFormFragment = null; - for (Fragment fragment : openNavFragments.values()) { - if (fragment instanceof ChannelFormFragment) { - channelFormFragment = ((ChannelFormFragment) fragment); - break; - } - } - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - if (channelFormFragment != null) { - channelFormFragment.onStoragePermissionGranted(); + for (StoragePermissionListener listener : storagePermissionListeners) { + listener.onStoragePermissionGranted(); } } else { - if (channelFormFragment != null) { - channelFormFragment.onStoragePermissionRefused(); + for (StoragePermissionListener listener : storagePermissionListeners) { + listener.onStoragePermissionRefused(); } } + startingStoragePermissionRequest = false; break; } @@ -1631,9 +1794,18 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } } + private void applyNavbarSigninPadding() { + int statusBarHeight = getStatusBarHeight(); + + View signInButton = findViewById(R.id.sign_in_button_container); + View signedInEmailContainer = findViewById(R.id.signed_in_email_container); + signInButton.setPadding(0, statusBarHeight, 0, 0); + signedInEmailContainer.setPadding(0, statusBarHeight, 0, 0); + } + private void showSignedInUser() { if (Lbryio.isSignedIn()) { - findViewById(R.id.sign_in_button).setVisibility(View.GONE); + findViewById(R.id.sign_in_button_container).setVisibility(View.GONE); findViewById(R.id.signed_in_email_container).setVisibility(View.VISIBLE); ((TextView) findViewById(R.id.signed_in_email)).setText(Lbryio.getSignedInEmail()); findViewById(R.id.sign_in_header_divider).setBackgroundColor(getResources().getColor(R.color.lightDivider)); @@ -1891,7 +2063,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener if (uri.isChannel()) { openChannelUrl(uri.toString()); } else { - openFileUrl(uri.toString(), this); + openFileUrl(uri.toString()); } } catch (LbryUriException ex) { // pass @@ -1936,6 +2108,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener }, 1000); return; } + if (startingStoragePermissionRequest) { + return; + } enterPIPMode(); } @@ -1946,8 +2121,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPlayer != null && - FileViewActivity.instance == null && - !startingFileViewActivity && !startingFilePickerActivity && !startingSignInFlowActivity) { enteringPIPMode = true; @@ -2024,7 +2197,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener private void unregisterReceivers() { Helper.unregisterReceiver(requestsReceiver, this); Helper.unregisterReceiver(serviceActionsReceiver, this); - Helper.unregisterReceiver(userActionsReceiver, this); } private Notification buildServiceNotification() { @@ -2097,14 +2269,22 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener return flatMenu; } - public static void setNowPlayingClaim(Claim claim, Context context) { + public void setNowPlayingClaim(Claim claim) { nowPlayingClaim = claim; - context.sendBroadcast(new Intent(ACTION_NOW_PLAYING_CLAIM_UPDATED)); + if (claim != null) { + ((TextView) findViewById(R.id.global_now_playing_title)).setText(nowPlayingClaim.getTitle()); + ((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(nowPlayingClaim.getPublisherTitle()); + } } - public static void clearNowPlayingClaim(Context context) { + public void clearNowPlayingClaim() { nowPlayingClaim = null; - context.sendBroadcast(new Intent(ACTION_NOW_PLAYING_CLAIM_CLEARED)); + findViewById(R.id.global_now_playing_card).setVisibility(View.GONE); + ((TextView) findViewById(R.id.global_now_playing_title)).setText(null); + ((TextView) findViewById(R.id.global_now_playing_channel_title)).setText(null); + if (appPlayer != null) { + appPlayer.setPlayWhenReady(false); + } } private static class CheckSdkReadyTask extends AsyncTask { @@ -2225,7 +2405,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } protected void onStop() { - if (!MainActivity.startingFileViewActivity && appPlayer != null && inPictureInPictureMode) { + if (appPlayer != null && inPictureInPictureMode) { appPlayer.setPlayWhenReady(false); } super.onStop(); @@ -2253,13 +2433,17 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener openFragment(fragmentClass, allowNavigateBack, navItemId, null); } - private static String buildNavFragmentKey(Class fragmentClass, int navItemId) { + private static String buildNavFragmentKey(Class fragmentClass, int navItemId, Map params) { + if (params != null && params.containsKey("url")) { + return String.format("%s-%d-%s", fragmentClass.getName(), navItemId, params.get("url").toString()); + } + return String.format("%s-%d", fragmentClass.getName(), navItemId); } public void openFragment(Class fragmentClass, boolean allowNavigateBack, int navItemId, Map params) { try { - String key = buildNavFragmentKey(fragmentClass, navItemId); + String key = buildNavFragmentKey(fragmentClass, navItemId, params); Fragment fragment = openNavFragments.containsKey(key) ? openNavFragments.get(key) : (Fragment) fragmentClass.newInstance(); if (fragment instanceof BaseFragment) { ((BaseFragment) fragment).setParams(params); @@ -2327,6 +2511,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; ActivityCompat.requestPermissions((Activity) context, new String[] { permission }, requestCode); } } @@ -2335,4 +2520,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener public static boolean hasPermission(String permission, Context context) { return (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED); } + + public interface BackPressInterceptor { + boolean onBackPressed(); + } } diff --git a/app/src/main/java/io/lbry/browser/adapter/ChannelFilterListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/ChannelFilterListAdapter.java index f4bc6fdf..a4b0873d 100644 --- a/app/src/main/java/io/lbry/browser/adapter/ChannelFilterListAdapter.java +++ b/app/src/main/java/io/lbry/browser/adapter/ChannelFilterListAdapter.java @@ -101,7 +101,7 @@ public class ChannelFilterListAdapter extends RecyclerView.Adapter 0 ? items.get(items.size() - 1) : null; + } + public void addFeaturedItem(Claim claim) { items.add(0, claim); notifyDataSetChanged(); diff --git a/app/src/main/java/io/lbry/browser/adapter/SuggestedChannelGridAdapter.java b/app/src/main/java/io/lbry/browser/adapter/SuggestedChannelGridAdapter.java index 09a99ee5..ff152d3f 100644 --- a/app/src/main/java/io/lbry/browser/adapter/SuggestedChannelGridAdapter.java +++ b/app/src/main/java/io/lbry/browser/adapter/SuggestedChannelGridAdapter.java @@ -56,6 +56,11 @@ public class SuggestedChannelGridAdapter extends RecyclerView.Adapter getSelectedItems() { return this.selectedItems; } diff --git a/app/src/main/java/io/lbry/browser/dialog/DiscoverDialogFragment.java b/app/src/main/java/io/lbry/browser/dialog/DiscoverDialogFragment.java index d3d62f38..927ebda1 100644 --- a/app/src/main/java/io/lbry/browser/dialog/DiscoverDialogFragment.java +++ b/app/src/main/java/io/lbry/browser/dialog/DiscoverDialogFragment.java @@ -84,10 +84,16 @@ public class DiscoverDialogFragment extends BottomSheetDialogFragment { dialogActionsListener.onResume(); } } - @Override public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); + super.onDismiss(dialog); + if (dialogActionsListener != null) { + dialogActionsListener.onCancel(); + } + } + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); if (dialogActionsListener != null) { dialogActionsListener.onCancel(); } diff --git a/app/src/main/java/io/lbry/browser/dialog/RepostClaimDialogFragment.java b/app/src/main/java/io/lbry/browser/dialog/RepostClaimDialogFragment.java index caa02c4d..2443fa9c 100644 --- a/app/src/main/java/io/lbry/browser/dialog/RepostClaimDialogFragment.java +++ b/app/src/main/java/io/lbry/browser/dialog/RepostClaimDialogFragment.java @@ -24,7 +24,6 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.InlineChannelSpinnerAdapter; @@ -147,16 +146,16 @@ public class RepostClaimDialogFragment extends BottomSheetDialogFragment impleme public void onResume() { super.onResume(); Context context = getContext(); - if (context instanceof FileViewActivity) { - ((FileViewActivity) context).addWalletBalanceListener(this); + if (context instanceof MainActivity) { + ((MainActivity) context).addWalletBalanceListener(this); } fetchChannels(); } public void onPause() { Context context = getContext(); - if (context instanceof FileViewActivity) { - ((FileViewActivity) context).removeWalletBalanceListener(this); + if (context instanceof MainActivity) { + ((MainActivity) context).removeWalletBalanceListener(this); } inputDeposit.clearFocus(); super.onPause(); @@ -178,8 +177,8 @@ public class RepostClaimDialogFragment extends BottomSheetDialogFragment impleme public void onError(Exception error) { // could not fetch channels Context context = getContext(); - if (context instanceof FileViewActivity) { - ((FileViewActivity) context).showError(error.getMessage()); + if (context instanceof MainActivity) { + ((MainActivity) context).showError(error.getMessage()); } dismiss(); } diff --git a/app/src/main/java/io/lbry/browser/dialog/SendTipDialogFragment.java b/app/src/main/java/io/lbry/browser/dialog/SendTipDialogFragment.java index 6d9151a8..6be2d917 100644 --- a/app/src/main/java/io/lbry/browser/dialog/SendTipDialogFragment.java +++ b/app/src/main/java/io/lbry/browser/dialog/SendTipDialogFragment.java @@ -23,7 +23,6 @@ import com.google.android.material.textfield.TextInputEditText; import java.math.BigDecimal; import java.text.DecimalFormat; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.listener.WalletBalanceListener; @@ -164,15 +163,15 @@ public class SendTipDialogFragment extends BottomSheetDialogFragment implements public void onResume() { super.onResume(); Context context = getContext(); - if (context instanceof FileViewActivity) { - ((FileViewActivity) context).addWalletBalanceListener(this); + if (context instanceof MainActivity) { + ((MainActivity) context).addWalletBalanceListener(this); } } public void onPause() { Context context = getContext(); - if (context instanceof FileViewActivity) { - ((FileViewActivity) context).removeWalletBalanceListener(this); + if (context instanceof MainActivity) { + ((MainActivity) context).removeWalletBalanceListener(this); } super.onPause(); } diff --git a/app/src/main/java/io/lbry/browser/listener/StoragePermissionListener.java b/app/src/main/java/io/lbry/browser/listener/StoragePermissionListener.java new file mode 100644 index 00000000..44bcd3dc --- /dev/null +++ b/app/src/main/java/io/lbry/browser/listener/StoragePermissionListener.java @@ -0,0 +1,6 @@ +package io.lbry.browser.listener; + +public interface StoragePermissionListener { + void onStoragePermissionGranted(); + void onStoragePermissionRefused(); +} diff --git a/app/src/main/java/io/lbry/browser/model/Claim.java b/app/src/main/java/io/lbry/browser/model/Claim.java index 1df6f71c..9f33b7b3 100644 --- a/app/src/main/java/io/lbry/browser/model/Claim.java +++ b/app/src/main/java/io/lbry/browser/model/Claim.java @@ -118,10 +118,10 @@ public class Claim { if (fee != null) { double amount = Helper.parseDouble(fee.getAmount(), 0); if ("usd".equalsIgnoreCase(fee.getCurrency())) { - return new BigDecimal(String.valueOf(amount / usdRate)).multiply(new BigDecimal(100000000)); // deweys + return new BigDecimal(String.valueOf(amount / usdRate)); } - return new BigDecimal(String.valueOf(amount)); + return new BigDecimal(String.valueOf(amount)).divide(new BigDecimal(100000000)); // deweys } return new BigDecimal(0); diff --git a/app/src/main/java/io/lbry/browser/model/WalletSync.java b/app/src/main/java/io/lbry/browser/model/WalletSync.java index c9ab5fab..05857ff0 100644 --- a/app/src/main/java/io/lbry/browser/model/WalletSync.java +++ b/app/src/main/java/io/lbry/browser/model/WalletSync.java @@ -8,9 +8,13 @@ public class WalletSync { private String data; private boolean changed; - public WalletSync(String hash, String data, boolean changed) { + public WalletSync(String hash, String data) { this.hash = hash; this.data = data; + } + + public WalletSync(String hash, String data, boolean changed) { + this(hash, data); this.changed = changed; } } diff --git a/app/src/main/java/io/lbry/browser/tasks/SetSdkSettingTask.java b/app/src/main/java/io/lbry/browser/tasks/SetSdkSettingTask.java new file mode 100644 index 00000000..42dafdc7 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/SetSdkSettingTask.java @@ -0,0 +1,45 @@ +package io.lbry.browser.tasks; + +import android.os.AsyncTask; + +import java.util.HashMap; +import java.util.Map; + +import io.lbry.browser.exceptions.ApiCallException; +import io.lbry.browser.utils.Lbry; + +public class SetSdkSettingTask extends AsyncTask { + private String key; + private String value; + private GenericTaskHandler handler; + private Exception error; + public SetSdkSettingTask(String key, String value, GenericTaskHandler handler) { + this.key = key; + this.value = value; + this.handler = handler; + } + + @Override + protected Boolean doInBackground(Void... params) { + try { + Map options = new HashMap<>(); + options.put("key", key); + options.put("value", value); + Lbry.genericApiCall("setting_set", options); + return true; + } catch (ApiCallException ex) { + error = ex; + return false; + } + } + + protected void onPostExecute(Boolean result) { + if (handler != null) { + if (result) { + handler.onSuccess(); + } else { + handler.onError(error); + } + } + } +} diff --git a/app/src/main/java/io/lbry/browser/tasks/wallet/SyncSetTask.java b/app/src/main/java/io/lbry/browser/tasks/wallet/SyncSetTask.java index 311879d4..1f5c888f 100644 --- a/app/src/main/java/io/lbry/browser/tasks/wallet/SyncSetTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/wallet/SyncSetTask.java @@ -45,7 +45,7 @@ public class SyncSetTask extends AsyncTask { if (handler != null) { if (!Helper.isNullOrEmpty(hash)) { handler.onSyncSetSuccess(hash); - } else if (error != null) { + } else { handler.onSyncSetError(error); } } diff --git a/app/src/main/java/io/lbry/browser/ui/BaseFragment.java b/app/src/main/java/io/lbry/browser/ui/BaseFragment.java index 79893ada..bc3afeb1 100644 --- a/app/src/main/java/io/lbry/browser/ui/BaseFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/BaseFragment.java @@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment; import java.util.Map; import io.lbry.browser.MainActivity; +import io.lbry.browser.ui.following.FileViewFragment; import lombok.Getter; import lombok.Setter; @@ -19,7 +20,15 @@ public class BaseFragment extends Fragment { super.onResume(); Context context = getContext(); if (context instanceof MainActivity) { - ((MainActivity) context).setSelectedMenuItemForFragment(this); + MainActivity activity = (MainActivity) context; + activity.setSelectedMenuItemForFragment(this); + + if (this instanceof FileViewFragment) { + activity.hideGlobalNowPlaying(); + } else { + activity.checkNowPlaying(); + } } } + } diff --git a/app/src/main/java/io/lbry/browser/ui/allcontent/AllContentFragment.java b/app/src/main/java/io/lbry/browser/ui/allcontent/AllContentFragment.java index db11452e..9493381d 100644 --- a/app/src/main/java/io/lbry/browser/ui/allcontent/AllContentFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/allcontent/AllContentFragment.java @@ -26,7 +26,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.ClaimListAdapter; @@ -213,6 +212,7 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi singleTagView = true; tags = Arrays.asList(tagName); titleView.setText(Helper.capitalize(tagName)); + Helper.setViewVisibility(customizeLink, View.GONE); } else { singleTagView = false; // default to followed Tags scope if any tags are followed @@ -224,8 +224,8 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi titleView.setText(getString(R.string.all_content)); } - forPrefix.setVisibility(singleTagView ? View.GONE : View.VISIBLE); - scopeLink.setVisibility(singleTagView ? View.GONE : View.VISIBLE); + Helper.setViewVisibility(forPrefix, singleTagView ? View.GONE : View.VISIBLE); + Helper.setViewVisibility(scopeLink, singleTagView ? View.GONE : View.VISIBLE); if (reload) { fetchClaimSearchContent(true); @@ -451,22 +451,15 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi contentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() { @Override public void onClaimClicked(Claim claim) { - String claimId = claim.getClaimId(); - String url = !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl(); - - if (claim.getName().startsWith("@")) { - // channel claim - Context context = getContext(); - if (context instanceof MainActivity) { - ((MainActivity) context).openChannelClaim(claim); + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + if (claim.getName().startsWith("@")) { + // channel claim + activity.openChannelClaim(claim); + } else { + activity.openFileClaim(claim); } - } else { - Intent intent = new Intent(getContext(), FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", claimId); - intent.putExtra("url", url); - MainActivity.startingFileViewActivity = true; - startActivity(intent); } } }); diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java index 4cd7d997..e00d673b 100644 --- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelContentFragment.java @@ -24,7 +24,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.ClaimListAdapter; @@ -263,21 +262,15 @@ public class ChannelContentFragment extends Fragment implements DownloadActionLi contentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() { @Override public void onClaimClicked(Claim claim) { - String claimId = claim.getClaimId(); - String url = !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl(); - if (claim.getName().startsWith("@")) { - // channel claim - Context context = getContext(); - if (context instanceof MainActivity) { - ((MainActivity) context).openChannelClaim(claim); + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + if (claim.getName().startsWith("@")) { + // channel claim + activity.openChannelClaim(claim); + } else { + activity.openFileClaim(claim); } - } else { - Intent intent = new Intent(getContext(), FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", claimId); - intent.putExtra("url", url); - MainActivity.startingFileViewActivity = true; - startActivity(intent); } } }); diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFormFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFormFragment.java index 926143d9..43fa49b8 100644 --- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFormFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFormFragment.java @@ -37,6 +37,7 @@ import io.lbry.browser.BuildConfig; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.TagListAdapter; +import io.lbry.browser.listener.StoragePermissionListener; import io.lbry.browser.listener.WalletBalanceListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.NavMenuItem; @@ -54,7 +55,8 @@ import io.lbry.browser.utils.LbryAnalytics; import io.lbry.browser.utils.LbryUri; import lombok.Getter; -public class ChannelFormFragment extends BaseFragment implements WalletBalanceListener, TagListAdapter.TagClickListener { +public class ChannelFormFragment extends BaseFragment implements + StoragePermissionListener, TagListAdapter.TagClickListener, WalletBalanceListener { private static final int SUGGESTED_LIMIT = 8; @@ -490,6 +492,7 @@ public class ChannelFormFragment extends BaseFragment implements WalletBalanceLi Context context = getContext(); if (context instanceof MainActivity) { MainActivity activity = (MainActivity) getContext(); + activity.removeStoragePermissionListener(this); activity.removeWalletBalanceListener(this); activity.restoreToggle(); activity.showFloatingWalletBalance(); @@ -509,6 +512,7 @@ public class ChannelFormFragment extends BaseFragment implements WalletBalanceLi if (context instanceof MainActivity) { MainActivity activity = (MainActivity) context; LbryAnalytics.setCurrentScreen(activity, "Channel Form", "ChannelForm"); + activity.addStoragePermissionListener(this); if (editMode) { ActionBar actionBar = activity.getSupportActionBar(); if (actionBar != null) { diff --git a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java index 75d2a41b..e52eda27 100644 --- a/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/channel/ChannelFragment.java @@ -288,14 +288,15 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen updateRequired = true; } } - if (!updateRequired && params.containsKey("url")) { + if (params.containsKey("url")) { String newUrl = params.get("url").toString(); - if (!newUrl.equalsIgnoreCase(url) || claim == null) { + if (claim == null || !newUrl.equalsIgnoreCase(url)) { this.claim = null; this.url = newUrl; updateRequired = true; } } + if (updateRequired) { resetSubCount(); if (!Helper.isNullOrEmpty(url)) { diff --git a/app/src/main/java/io/lbry/browser/ui/editorschoice/EditorsChoiceFragment.java b/app/src/main/java/io/lbry/browser/ui/editorschoice/EditorsChoiceFragment.java index bcf338a9..221db707 100644 --- a/app/src/main/java/io/lbry/browser/ui/editorschoice/EditorsChoiceFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/editorschoice/EditorsChoiceFragment.java @@ -22,7 +22,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.EditorsChoiceItemAdapter; @@ -116,12 +115,10 @@ public class EditorsChoiceFragment extends BaseFragment { @Override public void onEditorsChoiceItemClicked(EditorsChoiceItem item) { String url = item.getPermanentUrl(); - - Intent intent = new Intent(getContext(), FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("url", url); - MainActivity.startingFileViewActivity = true; - startActivity(intent); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).openFileUrl(url); + } } }); } else { diff --git a/app/src/main/java/io/lbry/browser/FileViewActivity.java b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java similarity index 54% rename from app/src/main/java/io/lbry/browser/FileViewActivity.java rename to app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java index 29c708dd..0caf70cd 100644 --- a/app/src/main/java/io/lbry/browser/FileViewActivity.java +++ b/app/src/main/java/io/lbry/browser/ui/following/FileViewFragment.java @@ -1,23 +1,19 @@ -package io.lbry.browser; +package io.lbry.browser.ui.following; +import android.Manifest; import android.annotation.SuppressLint; -import android.app.ActivityManager; -import android.app.PictureInPictureParams; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; -import android.content.res.Configuration; import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; -import android.os.Handler; import android.text.format.DateUtils; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -30,8 +26,8 @@ import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import androidx.core.widget.NestedScrollView; @@ -44,14 +40,16 @@ import com.github.chrisbanes.photoview.PhotoView; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.ext.cast.CastPlayer; -import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener; +import com.google.android.exoplayer2.database.ExoDatabaseProvider; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.ui.PlayerControlView; import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory; +import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; +import com.google.android.exoplayer2.upstream.cache.SimpleCache; import com.google.android.exoplayer2.util.Util; import com.google.android.flexbox.FlexboxLayoutManager; import com.google.android.material.button.MaterialButton; @@ -70,16 +68,21 @@ import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import io.lbry.browser.MainActivity; +import io.lbry.browser.R; import io.lbry.browser.adapter.ClaimListAdapter; import io.lbry.browser.adapter.TagListAdapter; import io.lbry.browser.dialog.RepostClaimDialogFragment; import io.lbry.browser.dialog.SendTipDialogFragment; import io.lbry.browser.exceptions.LbryUriException; +import io.lbry.browser.listener.DownloadActionListener; +import io.lbry.browser.listener.SdkStatusListener; +import io.lbry.browser.listener.StoragePermissionListener; import io.lbry.browser.listener.WalletBalanceListener; import io.lbry.browser.model.Claim; import io.lbry.browser.model.ClaimCacheKey; @@ -89,21 +92,22 @@ import io.lbry.browser.model.Tag; import io.lbry.browser.model.UrlSuggestion; import io.lbry.browser.model.lbryinc.Reward; import io.lbry.browser.model.lbryinc.Subscription; +import io.lbry.browser.tasks.GenericTaskHandler; +import io.lbry.browser.tasks.LighthouseSearchTask; import io.lbry.browser.tasks.ReadTextFileTask; +import io.lbry.browser.tasks.SetSdkSettingTask; import io.lbry.browser.tasks.claim.ClaimListResultHandler; import io.lbry.browser.tasks.claim.ClaimSearchTask; +import io.lbry.browser.tasks.claim.ResolveTask; import io.lbry.browser.tasks.file.DeleteFileTask; import io.lbry.browser.tasks.file.FileListTask; -import io.lbry.browser.tasks.GenericTaskHandler; import io.lbry.browser.tasks.file.GetFileTask; -import io.lbry.browser.tasks.LighthouseSearchTask; -import io.lbry.browser.tasks.claim.ResolveTask; import io.lbry.browser.tasks.lbryinc.ChannelSubscribeTask; import io.lbry.browser.tasks.lbryinc.ClaimRewardTask; import io.lbry.browser.tasks.lbryinc.FetchStatCountTask; import io.lbry.browser.tasks.lbryinc.LogFileViewTask; +import io.lbry.browser.ui.BaseFragment; import io.lbry.browser.ui.controls.SolidIconView; -import io.lbry.browser.ui.following.FollowingFragment; import io.lbry.browser.utils.Helper; import io.lbry.browser.utils.Lbry; import io.lbry.browser.utils.LbryAnalytics; @@ -111,23 +115,18 @@ import io.lbry.browser.utils.LbryUri; import io.lbry.browser.utils.Lbryio; import io.lbry.lbrysdk.DownloadManager; import io.lbry.lbrysdk.LbrynetService; +import io.lbry.lbrysdk.Utils; -public class FileViewActivity extends AppCompatActivity { - - public static FileViewActivity instance = null; +public class FileViewFragment extends BaseFragment implements + MainActivity.BackPressInterceptor, DownloadActionListener, SdkStatusListener, StoragePermissionListener { private static final int RELATED_CONTENT_SIZE = 16; - private static boolean startingShareActivity; - private PlayerControlView castControlView; private Player currentPlayer; - private boolean backStackLost; private boolean loadingNewClaim; - private boolean stopServiceReceived; + private boolean startDownloadPending; + private boolean fileGetPending; private boolean downloadInProgress; private boolean downloadRequested; - private boolean walletBalanceInitialized; - private boolean inPictureInPictureMode; - private boolean hasLoadedFirstBalance; private boolean loadFilePending; private boolean resolving; private boolean initialFileLoadDone; @@ -145,62 +144,28 @@ public class FileViewActivity extends AppCompatActivity { private long startTimeMillis; private GetFileTask getFileTask; - private List walletBalanceListeners; - private BroadcastReceiver downloadEventReceiver; + private View layoutLoadingState; + private View layoutNothingAtLocation; + private View layoutDisplayArea; + private View layoutResolving; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_file_view, container, false); - String claimId = null; - String url = null; - Intent intent = getIntent(); - if (intent != null) { - claimId = intent.getStringExtra("claimId"); - url = intent.getStringExtra("url"); - } - if (Helper.isNullOrEmpty(url)) { - // This activity should not be opened without a url set - finish(); - return; - } + layoutLoadingState = root.findViewById(R.id.file_view_loading_state); + layoutNothingAtLocation = root.findViewById(R.id.container_nothing_at_location); + layoutResolving = root.findViewById(R.id.file_view_loading_container); + layoutDisplayArea = root.findViewById(R.id.file_view_claim_display_area); - instance = this; - ClaimCacheKey key = new ClaimCacheKey(); - key.setClaimId(claimId); - key.setUrl(url); // use the same url for the key so that we can match the key for any value that's the same - if (Lbry.claimCache.containsKey(key)) { - claim = Lbry.claimCache.get(key); - Helper.saveViewHistory(url, claim); - checkAndResetNowPlayingClaim(); - if (claim.getFile() == null) { - loadFile(); - } - } - - setContentView(R.layout.activity_file_view); - checkIsFileComplete(); - - currentUrl = url; - logUrlEvent(url); - Helper.saveUrlHistory(url, claim != null ? claim.getTitle() : null, UrlSuggestion.TYPE_FILE); - if (claim == null) { - MainActivity.clearNowPlayingClaim(this); - resolveUrl(url); - } - - walletBalanceListeners = new ArrayList<>(); - registerDownloadEventReceiver(); - registerSdkReceiver(); + initUi(root); fileViewPlayerListener = new Player.EventListener() { @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { if (playbackState == Player.STATE_READY) { - if (totalDuration == 0) { - elapsedDuration = MainActivity.appPlayer.getCurrentPosition(); - totalDuration = MainActivity.appPlayer.getDuration(); - } + elapsedDuration = MainActivity.appPlayer.getCurrentPosition(); + totalDuration = MainActivity.appPlayer.getDuration() < 0 ? 0 : MainActivity.appPlayer.getDuration(); if (!playbackStarted) { logPlay(currentUrl, startTimeMillis); playbackStarted = true; @@ -221,25 +186,145 @@ public class FileViewActivity extends AppCompatActivity { } }; - castControlView = findViewById(R.id.file_view_cast_control_view); - initUi(); - onWalletBalanceUpdated(); - renderClaim(); + return root; } - public void addWalletBalanceListener(WalletBalanceListener listener) { - if (!walletBalanceListeners.contains(listener)) { - walletBalanceListeners.add(listener); + public void onStart() { + super.onStart(); + Context context = getContext(); + + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + activity.setBackPressInterceptor(this); + activity.addDownloadActionListener(this); + if (!MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) { + activity.addStoragePermissionListener(this); + } } } - public void removeWalletBalanceListener(WalletBalanceListener listener) { - walletBalanceListeners.remove(listener); + private void checkParams() { + boolean updateRequired = false; + Context context = getContext(); + Map params = getParams(); + Claim newClaim = null; + String newUrl = null; + if (params != null) { + if (params.containsKey("claim")) { + newClaim = (Claim) params.get("claim"); + if (newClaim != null && !newClaim.equals(this.claim)) { + updateRequired = true; + } + } + if (params.containsKey("url")) { + newUrl = params.get("url").toString(); + if (claim == null || !newUrl.equalsIgnoreCase(currentUrl)) { + updateRequired = true; + } + } + } else if (currentUrl != null) { + updateRequired = true; + } else if (context instanceof MainActivity) { + ((MainActivity) context).onBackPressed(); + } + + if (updateRequired) { + if (context instanceof MainActivity) { + ((MainActivity) context).clearNowPlayingClaim(); + } + if (MainActivity.appPlayer != null) { + MainActivity.appPlayer.setPlayWhenReady(false); + } + + resetViewCount(); + checkNewClaimAndUrl(newClaim, newUrl); + + if (newClaim != null) { + claim = newClaim; + } + if (!Helper.isNullOrEmpty(newUrl)) { + // check if the claim is already cached + currentUrl = newUrl; + ClaimCacheKey key = new ClaimCacheKey(); + key.setUrl(currentUrl); + onNewClaim(currentUrl); + if (Lbry.claimCache.containsKey(key)) { + claim = Lbry.claimCache.get(key); + } else { + resolveUrl(currentUrl); + } + } else if (claim == null) { + // nothing at this location + renderNothingAtLocation(); + } + } + + if (!Helper.isNullOrEmpty(currentUrl)) { + Helper.saveUrlHistory(currentUrl, claim != null ? claim.getTitle() : null, UrlSuggestion.TYPE_FILE); + } + + if (claim != null) { + Helper.saveViewHistory(currentUrl, claim); + renderClaim(); + } + + checkIsFileComplete(); } - private void initWebView() { - WebView webView = findViewById(R.id.file_view_webview); - webView.setWebViewClient(new LbryWebViewClient(this)); + private void renderNothingAtLocation() { + layoutLoadingState.setVisibility(View.VISIBLE); + layoutNothingAtLocation.setVisibility(View.VISIBLE); + layoutResolving.setVisibility(View.GONE); + layoutDisplayArea.setVisibility(View.INVISIBLE); + } + + private void checkNewClaimAndUrl(Claim newClaim, String newUrl) { + boolean shouldResetNowPlaying = false; + if (newClaim != null && + MainActivity.nowPlayingClaim != null && + !MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(newClaim.getClaimId())) { + shouldResetNowPlaying = true; + } + if (!shouldResetNowPlaying && + newUrl != null && + MainActivity.nowPlayingClaim != null && + !newUrl.equalsIgnoreCase(MainActivity.nowPlayingClaim.getShortUrl()) && + !newUrl.equalsIgnoreCase(MainActivity.nowPlayingClaim.getPermanentUrl())) { + shouldResetNowPlaying = true; + } + + if (shouldResetNowPlaying) { + if (MainActivity.appPlayer != null) { + MainActivity.appPlayer.setPlayWhenReady(false); + } + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).clearNowPlayingClaim(); + resetPlayer(); + } + } + } + + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (savedInstanceState != null) { + currentUrl = savedInstanceState.getString("url"); + } + } + + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + super.onSaveInstanceState(savedInstanceState); + if (savedInstanceState != null) { + savedInstanceState.putString("url", currentUrl); + } + } + + private void initWebView(View view) { + WebView webView = view.findViewById(R.id.file_view_webview); + webView.setWebViewClient(new LbryWebViewClient(getContext())); WebSettings webSettings = webView.getSettings(); webSettings.setAllowFileAccess(true); webSettings.setJavaScriptEnabled(true); @@ -252,48 +337,11 @@ public class FileViewActivity extends AppCompatActivity { } private void checkAndResetNowPlayingClaim() { - if (MainActivity.nowPlayingClaim != null && + if (MainActivity.nowPlayingClaim != null && claim != null && !MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId())) { - MainActivity.clearNowPlayingClaim(this); - } - } - - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - MainActivity.startingFileViewActivity = false; - if (intent != null) { - String newClaimId = intent.getStringExtra("claimId"); - String newUrl = intent.getStringExtra("url"); - - String oldClaimId = claim != null ? claim.getClaimId() : null; - if (!Helper.isNullOrEmpty(newClaimId)) { - if (newClaimId.equalsIgnoreCase(oldClaimId)) { - // it's the same claim, so we do nothing - if (MainActivity.appPlayer != null) { - PlayerView view = findViewById(R.id.file_view_exoplayer_view); - view.setPlayer(null); - view.setPlayer(MainActivity.appPlayer); - } - - return; - } - - onNewClaim(newUrl); - ClaimCacheKey key = new ClaimCacheKey(); - key.setClaimId(newClaimId); - if (!Helper.isNullOrEmpty(newUrl) && newUrl.contains("#")) { - key.setUrl(newUrl); - } - loadClaimForCacheKey(key, newUrl); - } else if (!Helper.isNullOrEmpty(newUrl)) { - if (currentUrl != null && currentUrl.equalsIgnoreCase(newUrl)) { - return; - } - - onNewClaim(newUrl); - ClaimCacheKey key = new ClaimCacheKey(); - key.setUrl(newUrl); - loadClaimForCacheKey(key, newUrl); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).clearNowPlayingClaim(); } } } @@ -301,13 +349,18 @@ public class FileViewActivity extends AppCompatActivity { private void onNewClaim(String url) { loadingNewClaim = true; initialFileLoadDone = false; + playbackStarted = false; currentUrl = url; logUrlEvent(url); resetViewCount(); - + View root = getView(); + if (root != null) { + ((RecyclerView) root.findViewById(R.id.file_view_related_content_list)).setAdapter(null); + } if (MainActivity.appPlayer != null) { MainActivity.appPlayer.setPlayWhenReady(false); } + resetPlayer(); } private void loadClaimForCacheKey(ClaimCacheKey key, String url) { @@ -325,69 +378,18 @@ public class FileViewActivity extends AppCompatActivity { renderClaim(); } else { Helper.saveUrlHistory(url, null, UrlSuggestion.TYPE_FILE); - findViewById(R.id.file_view_claim_display_area).setVisibility(View.INVISIBLE); - MainActivity.clearNowPlayingClaim(this); + getView().findViewById(R.id.file_view_claim_display_area).setVisibility(View.INVISIBLE); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).clearNowPlayingClaim(); + } resolveUrl(url); } } - private void registerSdkReceiver() { - IntentFilter filter = new IntentFilter(); - filter.addAction(LbrynetService.ACTION_STOP_SERVICE); - filter.addAction(MainActivity.ACTION_SDK_READY); - filter.addAction(MainActivity.ACTION_WALLET_BALANCE_UPDATED); - sdkReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (LbrynetService.ACTION_STOP_SERVICE.equalsIgnoreCase(action)) { - stopServiceReceived = true; - finish(); - } else if (MainActivity.ACTION_SDK_READY.equalsIgnoreCase(action)) { - if (loadFilePending) { - loadFile(); - } - - initFloatingWalletBalance(); - } else if (MainActivity.ACTION_WALLET_BALANCE_UPDATED.equalsIgnoreCase(action)) { - onWalletBalanceUpdated(); - } - } - }; - registerReceiver(sdkReceiver, filter); - } - - private void initFloatingWalletBalance() { - if (walletBalanceInitialized) { - return; - } - findViewById(R.id.floating_balance_container).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - sendBroadcast(new Intent(MainActivity.ACTION_OPEN_WALLET_PAGE)); - bringMainTaskToFront(); - finish(); - } - }); - walletBalanceInitialized = true; - } - - private void onWalletBalanceUpdated() { - if (Lbry.SDK_READY) { - if (!hasLoadedFirstBalance) { - findViewById(R.id.floating_balance_loading).setVisibility(View.GONE); - findViewById(R.id.floating_balance_value).setVisibility(View.VISIBLE); - hasLoadedFirstBalance = true; - } - - ((TextView) findViewById(R.id.floating_balance_value)).setText( - Helper.shortCurrencyFormat(Lbry.walletBalance.getAvailable().doubleValue())); - - for (WalletBalanceListener listener : walletBalanceListeners) { - if (listener != null) { - listener.onWalletBalanceUpdated(Lbry.walletBalance); - } - } + public void onSdkReady() { + if (loadFilePending) { + loadFile(); } } @@ -451,22 +453,95 @@ public class FileViewActivity extends AppCompatActivity { } } - protected void onResume() { - super.onResume(); - MainActivity.mainActive = false; - MainActivity.startingFileViewActivity = false; + public void openClaimUrl(String url) { + resetViewCount(); + currentUrl = url; + + ClaimCacheKey key = new ClaimCacheKey(); + key.setUrl(currentUrl); + Claim oldClaim = claim; + claim = null; + if (Lbry.claimCache.containsKey(key)) { + claim = Lbry.claimCache.get(key); + if (oldClaim != null && oldClaim.getClaimId().equalsIgnoreCase(claim.getClaimId())) { + // same claim + return; + } + } else { + resolveUrl(currentUrl); + } + + resetMedia(); + onNewClaim(currentUrl); + Helper.setWunderbarValue(currentUrl, getContext()); + + if (claim != null) { + Helper.saveViewHistory(url, claim); + renderClaim(); + } + } + + public void resetMedia() { + View root = getView(); + if (root != null) { + PlayerView view = root.findViewById(R.id.file_view_exoplayer_view); + view.setShutterBackgroundColor(Color.BLACK); + root.findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE); + } + if (MainActivity.appPlayer != null) { + MainActivity.appPlayer.stop(); + } + resetPlayer(); + } + + public void onResume() { + super.onResume(); + checkParams(); + + Context context = getContext(); + Helper.setWunderbarValue(currentUrl, context); + if (MainActivity.appPlayer != null) { + if (MainActivity.playerReassigned) { + setPlayerForPlayerView(); + MainActivity.playerReassigned = false; + } + loadAndScheduleDurations(); + } - loadAndScheduleDurations(); if (Lbry.SDK_READY) { - initFloatingWalletBalance(); + if (context instanceof MainActivity) { + ((MainActivity) context).addSdkStatusListener(this); + } + } else { + onSdkReady(); + } + } + + public void onStop() { + super.onStop(); + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + activity.removeDownloadActionListener(this); + activity.removeSdkStatusListener(this); + activity.removeStoragePermissionListener(this); + } + } + + private void setPlayerForPlayerView() { + View root = getView(); + if (root != null) { + PlayerView view = root.findViewById(R.id.file_view_exoplayer_view); + view.setPlayer(MainActivity.appPlayer); } } private void resolveUrl(String url) { resolving = true; - findViewById(R.id.file_view_claim_display_area).setVisibility(View.INVISIBLE); - View loadingView = findViewById(R.id.file_view_loading_container); - ResolveTask task = new ResolveTask(url, Lbry.LBRY_TV_CONNECTION_STRING, loadingView, new ClaimListResultHandler() { + Helper.setViewVisibility(layoutDisplayArea, View.INVISIBLE); + Helper.setViewVisibility(layoutLoadingState, View.VISIBLE); + Helper.setViewVisibility(layoutNothingAtLocation, View.GONE); + ResolveTask task = new ResolveTask(url, Lbry.LBRY_TV_CONNECTION_STRING, layoutResolving, new ClaimListResultHandler() { @Override public void onSuccess(List claims) { if (claims.size() > 0 && !Helper.isNullOrEmpty(claims.get(0).getClaimId())) { @@ -477,12 +552,10 @@ public class FileViewActivity extends AppCompatActivity { Lbry.addClaimToCache(claim); if (claim.getName().startsWith("@")) { // this is a reposted channel, so finish this activity and launch the channel url - Intent intent = new Intent(MainActivity.ACTION_OPEN_CHANNEL_URL); - intent.putExtra("url", !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()); - sendBroadcast(intent); - - bringMainTaskToFront(); - finish(); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).openChannelUrl(!Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()); + } return; } } else { @@ -499,6 +572,7 @@ public class FileViewActivity extends AppCompatActivity { renderClaim(); } else { // render nothing at location + renderNothingAtLocation(); } } @@ -510,14 +584,14 @@ public class FileViewActivity extends AppCompatActivity { task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - private void initUi() { - initWebView(); + private void initUi(View root) { + initWebView(root); - findViewById(R.id.file_view_title_area).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_title_area).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - ImageView descIndicator = findViewById(R.id.file_view_desc_toggle_arrow); - View descriptionArea = findViewById(R.id.file_view_description_area); + ImageView descIndicator = root.findViewById(R.id.file_view_desc_toggle_arrow); + View descriptionArea = root.findViewById(R.id.file_view_description_area); if (descriptionArea.getVisibility() != View.VISIBLE) { descriptionArea.setVisibility(View.VISIBLE); descIndicator.setImageResource(R.drawable.ic_arrow_dropup); @@ -528,7 +602,7 @@ public class FileViewActivity extends AppCompatActivity { } }); - findViewById(R.id.file_view_action_share).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_share).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (claim != null) { @@ -540,7 +614,7 @@ public class FileViewActivity extends AppCompatActivity { shareIntent.setType("text/plain"); shareIntent.putExtra(Intent.EXTRA_TEXT, shareUrl); - startingShareActivity = true; + MainActivity.startingShareActivity = true; Intent shareUrlIntent = Intent.createChooser(shareIntent, getString(R.string.share_lbry_content)); shareUrlIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(shareUrlIntent); @@ -551,11 +625,11 @@ public class FileViewActivity extends AppCompatActivity { } }); - findViewById(R.id.file_view_action_tip).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_tip).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!Lbry.SDK_READY) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); return; } @@ -569,19 +643,22 @@ public class FileViewActivity extends AppCompatActivity { String message = getResources().getQuantityString( R.plurals.you_sent_a_tip, sentAmount == 1.0 ? 1 : 2, new DecimalFormat("#,###.##").format(sentAmount)); - Snackbar.make(findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG).show(); } }); - dialog.show(getSupportFragmentManager(), SendTipDialogFragment.TAG); + Context context = getContext(); + if (context instanceof MainActivity) { + dialog.show(((MainActivity) context).getSupportFragmentManager(), SendTipDialogFragment.TAG); + } } } }); - findViewById(R.id.file_view_action_repost).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_repost).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!Lbry.SDK_READY) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); return; } @@ -591,23 +668,26 @@ public class FileViewActivity extends AppCompatActivity { dialog.setListener(new RepostClaimDialogFragment.RepostClaimListener() { @Override public void onClaimReposted(Claim claim) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), R.string.content_successfully_reposted, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.content_successfully_reposted, Snackbar.LENGTH_LONG).show(); } }); - dialog.show(getSupportFragmentManager(), RepostClaimDialogFragment.TAG); + Context context = getContext(); + if (context instanceof MainActivity) { + dialog.show(((MainActivity) context).getSupportFragmentManager(), RepostClaimDialogFragment.TAG); + } } } }); - findViewById(R.id.file_view_action_delete).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_delete).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!Lbry.SDK_READY) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); return; } - AlertDialog.Builder builder = new AlertDialog.Builder(FileViewActivity.this). + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()). setTitle(R.string.delete_file). setMessage(R.string.confirm_delete_file_message) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @@ -620,11 +700,11 @@ public class FileViewActivity extends AppCompatActivity { } }); - findViewById(R.id.file_view_action_download).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_download).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!Lbry.SDK_READY) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); + Snackbar.make(root.findViewById(R.id.file_view_claim_display_area), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); return; } @@ -636,25 +716,18 @@ public class FileViewActivity extends AppCompatActivity { Intent intent = new Intent(LbrynetService.ACTION_DELETE_DOWNLOAD); intent.putExtra("uri", claim.getPermanentUrl()); intent.putExtra("nativeDelete", true); - sendBroadcast(intent); - } else { - downloadInProgress = true; - Helper.setViewVisibility(findViewById(R.id.file_view_download_progress), View.VISIBLE); - ((ImageView) findViewById(R.id.file_view_action_download_icon)).setImageResource(R.drawable.ic_stop); - - if (!claim.isFree()) { - downloadRequested = true; - onMainActionButtonClicked(); - } else { - // download the file - fileGet(true); + Context context = getContext(); + if (context != null) { + context.sendBroadcast(intent); } + } else { + checkStoragePermissionAndStartDownload(); } } } }); - findViewById(R.id.file_view_action_report).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_action_report).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (claim != null) { @@ -664,14 +737,14 @@ public class FileViewActivity extends AppCompatActivity { } }); - findViewById(R.id.player_toggle_cast).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.player_toggle_cast).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { toggleCast(); } }); - findViewById(R.id.player_toggle_fullscreen).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.player_toggle_fullscreen).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // check full screen mode @@ -683,21 +756,21 @@ public class FileViewActivity extends AppCompatActivity { } }); - findViewById(R.id.file_view_publisher_name).setOnClickListener(new View.OnClickListener() { + root.findViewById(R.id.file_view_publisher_name).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (claim != null && claim.getSigningChannel() != null) { Claim publisher = claim.getSigningChannel(); - Intent intent = new Intent(MainActivity.ACTION_OPEN_CHANNEL_URL); - intent.putExtra("url", !Helper.isNullOrEmpty(publisher.getShortUrl()) ? publisher.getShortUrl() : publisher.getPermanentUrl()); - sendBroadcast(intent); - bringMainTaskToFront(); - finish(); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).openChannelUrl( + !Helper.isNullOrEmpty(publisher.getShortUrl()) ? publisher.getShortUrl() : publisher.getPermanentUrl()); + } } } }); - View buttonFollowUnfollow = findViewById(R.id.file_view_icon_follow_unfollow); + View buttonFollowUnfollow = root.findViewById(R.id.file_view_icon_follow_unfollow); buttonFollowUnfollow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -706,7 +779,8 @@ public class FileViewActivity extends AppCompatActivity { boolean isFollowing = Lbryio.isFollowing(publisher); Subscription subscription = Subscription.fromClaim(publisher); buttonFollowUnfollow.setEnabled(false); - new ChannelSubscribeTask(FileViewActivity.this, publisher.getClaimId(), subscription, isFollowing, new ChannelSubscribeTask.ChannelSubscribeHandler() { + Context context = getContext(); + new ChannelSubscribeTask(context, publisher.getClaimId(), subscription, isFollowing, new ChannelSubscribeTask.ChannelSubscribeHandler() { @Override public void onSuccess() { if (isFollowing) { @@ -721,7 +795,9 @@ public class FileViewActivity extends AppCompatActivity { FollowingFragment.resetClaimSearchContent = true; // Save shared user state - sendBroadcast(new Intent(MainActivity.ACTION_SAVE_SHARED_USER_STATE)); + if (context != null) { + context.sendBroadcast(new Intent(MainActivity.ACTION_SAVE_SHARED_USER_STATE)); + } } @Override @@ -733,15 +809,103 @@ public class FileViewActivity extends AppCompatActivity { } }); - RecyclerView relatedContentList = findViewById(R.id.file_view_related_content_list); + RecyclerView relatedContentList = root.findViewById(R.id.file_view_related_content_list); relatedContentList.setNestedScrollingEnabled(false); - LinearLayoutManager llm = new LinearLayoutManager(this); + LinearLayoutManager llm = new LinearLayoutManager(getContext()); relatedContentList.setLayoutManager(llm); } + private void checkStoragePermissionAndStartDownload() { + Context context = getContext(); + if (MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) { + startDownload(); + } else { + startDownloadPending = true; + MainActivity.requestPermission( + Manifest.permission.WRITE_EXTERNAL_STORAGE, + MainActivity.REQUEST_STORAGE_PERMISSION, + getString(R.string.storage_permission_rationale_download), + context, + true); + } + } + + private void checkStoragePermissionAndFileGet() { + Context context = getContext(); + if (MainActivity.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, context)) { + fileGetPending = true; + MainActivity.requestPermission( + Manifest.permission.WRITE_EXTERNAL_STORAGE, + MainActivity.REQUEST_STORAGE_PERMISSION, + getString(R.string.storage_permission_rationale_download), + context, + true); + } + } + + public void onStoragePermissionGranted() { + Context context = getContext(); + SetSdkSettingTask task = null; + if (startDownloadPending) { + startDownloadPending = false; + task = new SetSdkSettingTask("download_dir", Utils.getConfiguredDownloadDirectory(context), new GenericTaskHandler() { + @Override + public void beforeStart() { } + @Override + public void onSuccess() { startDownload(); } + @Override + public void onError(Exception error) { + // start the download anyway. Only that it will be saved in the app private folder: /sdcard/Android/io.lbry.browser/Download + startDownload(); + } + }); + } else if (fileGetPending) { + fileGetPending = false; + task = new SetSdkSettingTask("download_dir", Utils.getConfiguredDownloadDirectory(context), new GenericTaskHandler() { + @Override + public void beforeStart() { } + @Override + public void onSuccess() { fileGet(true); } + @Override + public void onError(Exception error) { + // start the file get anyway. Only that it will be saved in the app private folder: /sdcard/Android/io.lbry.browser/Download + fileGet(true); + } + }); + } + if (task != null) { + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + public void onStoragePermissionRefused() { + fileGetPending = false; + startDownloadPending = false; + onDownloadAborted(); + Snackbar.make(getView(), R.string.storage_permission_rationale_download, Snackbar.LENGTH_LONG). + setBackgroundTint(Color.RED).setTextColor(Color.WHITE).show(); + } + + public void startDownload() { + downloadInProgress = true; + + View root = getView(); + if (root != null) { + Helper.setViewVisibility(root.findViewById(R.id.file_view_download_progress), View.VISIBLE); + ((ImageView) root.findViewById(R.id.file_view_action_download_icon)).setImageResource(R.drawable.ic_stop); + } + + if (!claim.isFree()) { + downloadRequested = true; + onMainActionButtonClicked(); + } else { + // download the file + fileGet(true); + } + } + private void deleteClaimFile() { if (claim != null) { - View actionDelete = findViewById(R.id.file_view_action_delete); + View actionDelete = getView().findViewById(R.id.file_view_action_delete); DeleteFileTask task = new DeleteFileTask(claim.getClaimId(), new GenericTaskHandler() { @Override public void beforeStart() { @@ -751,8 +915,8 @@ public class FileViewActivity extends AppCompatActivity { @Override public void onSuccess() { actionDelete.setVisibility(View.GONE); - findViewById(R.id.file_view_action_download).setVisibility(View.VISIBLE); - findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); + getView().findViewById(R.id.file_view_action_download).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); actionDelete.setEnabled(true); restoreMainActionButton(); } @@ -772,61 +936,68 @@ public class FileViewActivity extends AppCompatActivity { return; } + if (claim.isPlayable() && MainActivity.appPlayer != null) { + MainActivity.appPlayer.setPlayWhenReady(true); + } + + Helper.setViewVisibility(layoutLoadingState, View.GONE); + Helper.setViewVisibility(layoutNothingAtLocation, View.GONE); + loadViewCount(); checkIsFollowing(); - ((NestedScrollView) findViewById(R.id.file_view_scroll_view)).scrollTo(0, 0); - findViewById(R.id.file_view_claim_display_area).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_scroll_view).scrollTo(0, 0); + Helper.setViewVisibility(layoutDisplayArea, View.VISIBLE); - ImageView descIndicator = findViewById(R.id.file_view_desc_toggle_arrow); + ImageView descIndicator = getView().findViewById(R.id.file_view_desc_toggle_arrow); descIndicator.setImageResource(R.drawable.ic_arrow_dropdown); - findViewById(R.id.file_view_description_area).setVisibility(View.GONE); - ((TextView) findViewById(R.id.file_view_title)).setText(claim.getTitle()); - ((TextView) findViewById(R.id.file_view_description)).setText(claim.getDescription()); - ((TextView) findViewById(R.id.file_view_publisher_name)).setText( + 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()); - RecyclerView descTagsList = findViewById(R.id.file_view_tag_list); - FlexboxLayoutManager flm = new FlexboxLayoutManager(this); + Context context = getContext(); + RecyclerView descTagsList = getView().findViewById(R.id.file_view_tag_list); + FlexboxLayoutManager flm = new FlexboxLayoutManager(context); descTagsList.setLayoutManager(flm); List tags = claim.getTagObjects(); - TagListAdapter tagListAdapter = new TagListAdapter(tags, this); + 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) { - Intent intent = new Intent(MainActivity.ACTION_OPEN_ALL_CONTENT_TAG); - intent.putExtra("tag", tag.getName()); - sendBroadcast(intent); - bringMainTaskToFront(); - finish(); + Context ctx = getContext(); + if (ctx instanceof MainActivity) { + ((MainActivity) ctx).openAllContentFragmentWithTag(tag.getName()); + } } } }); descTagsList.setAdapter(tagListAdapter); - findViewById(R.id.file_view_tag_area).setVisibility(tags.size() > 0 ? View.VISIBLE : View.GONE); + getView().findViewById(R.id.file_view_tag_area).setVisibility(tags.size() > 0 ? View.VISIBLE : View.GONE); - findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE); - findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); - findViewById(R.id.file_view_media_meta_container).setVisibility(View.VISIBLE); + 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 = findViewById(R.id.file_view_thumbnail); - Glide.with(getApplicationContext()).load(claim.getThumbnailUrl()).centerCrop().into(thumbnailView); + 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 } - findViewById(R.id.file_view_main_action_button).setOnClickListener(new View.OnClickListener() { + getView().findViewById(R.id.file_view_main_action_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onMainActionButtonClicked(); } }); - findViewById(R.id.file_view_media_meta_container).setOnClickListener(new View.OnClickListener() { + getView().findViewById(R.id.file_view_media_meta_container).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onMainActionButtonClicked(); @@ -836,20 +1007,20 @@ public class FileViewActivity extends AppCompatActivity { if (metadata instanceof Claim.StreamMetadata) { Claim.StreamMetadata streamMetadata = (Claim.StreamMetadata) metadata; long publishTime = streamMetadata.getReleaseTime() > 0 ? streamMetadata.getReleaseTime() * 1000 : claim.getTimestamp() * 1000; - ((TextView) findViewById(R.id.file_view_publish_time)).setText(DateUtils.getRelativeTimeSpanString( + ((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) { - findViewById(R.id.file_view_fee_container).setVisibility(View.VISIBLE); - ((TextView) findViewById(R.id.file_view_fee)).setText( - Helper.shortCurrencyFormat(claim.getActualCost(Lbryio.LBCUSDRate).divide(new BigDecimal(100000000)).doubleValue())); + 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())); } } - findViewById(R.id.file_view_icon_follow_unfollow).setVisibility(claim.getSigningChannel() != null ? View.VISIBLE : View.GONE); + getView().findViewById(R.id.file_view_icon_follow_unfollow).setVisibility(claim.getSigningChannel() != null ? View.VISIBLE : View.GONE); - MaterialButton mainActionButton = findViewById(R.id.file_view_main_action_button); + MaterialButton mainActionButton = getView().findViewById(R.id.file_view_main_action_button); if (claim.isPlayable()) { mainActionButton.setText(R.string.play); } else if (claim.isViewable()) { @@ -859,43 +1030,61 @@ public class FileViewActivity extends AppCompatActivity { } if (claim.isFree()) { - if (claim.isPlayable() || (claim.isViewable() && Lbry.SDK_READY)) { + 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(); } } - loadRelatedContent(); + RecyclerView relatedContentList = getView().findViewById(R.id.file_view_related_content_list); + if (relatedContentList == null || relatedContentList.getAdapter() == null || relatedContentList.getAdapter().getItemCount() == 0) { + loadRelatedContent(); + } } private void showUnsupportedView() { - findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE); - findViewById(R.id.file_view_unsupported_container).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_exoplayer_container).setVisibility(View.GONE); + getView().findViewById(R.id.file_view_unsupported_container).setVisibility(View.VISIBLE); String fileNameString = ""; if (claim.getFile() != null) { LbryFile lbryFile = claim.getFile(); File file = new File(lbryFile.getDownloadPath()); fileNameString = String.format("\"%s\" ", file.getName()); } - ((TextView) findViewById(R.id.file_view_unsupported_text)).setText(getString(R.string.unsupported_content_desc, fileNameString)); + ((TextView) getView().findViewById(R.id.file_view_unsupported_text)).setText(getString(R.string.unsupported_content_desc, fileNameString)); } private void showExoplayerView() { - findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); - findViewById(R.id.file_view_exoplayer_container).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_unsupported_container).setVisibility(View.GONE); + getView().findViewById(R.id.file_view_exoplayer_container).setVisibility(View.VISIBLE); } private void playMedia() { boolean newPlayerCreated = false; - if (MainActivity.appPlayer == null) { - MainActivity.appPlayer = new SimpleExoPlayer.Builder(this).build(); - MainActivity.castPlayer = new CastPlayer(MainActivity.castContext); + Context context = getContext(); + if (MainActivity.appPlayer == null) { + MainActivity.appPlayer = new SimpleExoPlayer.Builder(context).build(); + MainActivity.playerCache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 256), new ExoDatabaseProvider(context)); newPlayerCreated = true; } - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - PlayerView view = findViewById(R.id.file_view_exoplayer_view); + PlayerView view = getView().findViewById(R.id.file_view_exoplayer_view); + view.setShutterBackgroundColor(Color.TRANSPARENT); view.setPlayer(MainActivity.appPlayer); + view.setUseController(true); + if (context instanceof MainActivity) { + ((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + if (MainActivity.nowPlayingClaim != null && MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(claim.getClaimId()) && !newPlayerCreated) { @@ -903,33 +1092,22 @@ public class FileViewActivity extends AppCompatActivity { return; } - resetPlayer(); showBuffering(); + if (fileViewPlayerListener != null) { + MainActivity.appPlayer.addListener(fileViewPlayerListener); + } + if (context instanceof MainActivity) { + ((MainActivity) context).setNowPlayingClaim(claim); + } - MainActivity.appPlayer.addListener(fileViewPlayerListener); - MainActivity.castPlayer.addListener(fileViewPlayerListener); - MainActivity.castPlayer.setSessionAvailabilityListener(new SessionAvailabilityListener() { - @Override - public void onCastSessionAvailable() { - setCurrentPlayer(MainActivity.castPlayer); - } - - @Override - public void onCastSessionUnavailable() { - setCurrentPlayer(MainActivity.appPlayer); - } - }); - - castControlView.setPlayer(MainActivity.castPlayer); - MainActivity.setNowPlayingClaim(claim, FileViewActivity.this); - String userAgent = Util.getUserAgent(this, getString(R.string.app_name)); - + MainActivity.appPlayer.setPlayWhenReady(true); + String userAgent = Util.getUserAgent(context, getString(R.string.app_name)); String mediaSourceUrl = getStreamingUrl(); MediaSource mediaSource = new ProgressiveMediaSource.Factory( - new DefaultDataSourceFactory(this, userAgent), + new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)), new DefaultExtractorsFactory() ).createMediaSource(Uri.parse(mediaSourceUrl)); - MainActivity.appPlayer.setPlayWhenReady(true); + MainActivity.appPlayer.prepare(mediaSource, true, true); } @@ -942,10 +1120,10 @@ public class FileViewActivity extends AppCompatActivity { if (currentPlayer == MainActivity.appPlayer) { //localPlayerView.setVisibility(View.VISIBLE); castControlView.hide(); - ((ImageView) findViewById(R.id.player_image_cast_toggle)).setImageResource(R.drawable.ic_cast); + ((ImageView) getView().findViewById(R.id.player_image_cast_toggle)).setImageResource(R.drawable.ic_cast); } else /* currentPlayer == castPlayer */ { castControlView.show(); - ((ImageView) findViewById(R.id.player_image_cast_toggle)).setImageResource(R.drawable.ic_cast_connected); + ((ImageView) getView().findViewById(R.id.player_image_cast_toggle)).setImageResource(R.drawable.ic_cast_connected); } // Player state management. @@ -975,7 +1153,7 @@ public class FileViewActivity extends AppCompatActivity { } private void resetViewCount() { - TextView textViewCount = findViewById(R.id.file_view_view_count); + TextView textViewCount = getView().findViewById(R.id.file_view_view_count); Helper.setViewText(textViewCount, null); Helper.setViewVisibility(textViewCount, View.GONE); } @@ -988,7 +1166,7 @@ public class FileViewActivity extends AppCompatActivity { public void onSuccess(int count) { try { String displayText = getResources().getQuantityString(R.plurals.view_count, count, NumberFormat.getInstance().format(count)); - TextView textViewCount = findViewById(R.id.file_view_view_count); + TextView textViewCount = getView().findViewById(R.id.file_view_view_count); Helper.setViewText(textViewCount, displayText); Helper.setViewVisibility(textViewCount, View.VISIBLE); } catch (IllegalStateException ex) { @@ -1014,8 +1192,8 @@ public class FileViewActivity extends AppCompatActivity { // not free (and the user does not own the claim yet), perform a purchase confirmPurchaseUrl(); } else { - findViewById(R.id.file_view_main_action_button).setVisibility(View.INVISIBLE); - findViewById(R.id.file_view_main_action_loading).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_main_action_button).setVisibility(View.INVISIBLE); + getView().findViewById(R.id.file_view_main_action_loading).setVisibility(View.VISIBLE); handleMainActionForClaim(); } } else { @@ -1028,7 +1206,7 @@ public class FileViewActivity extends AppCompatActivity { 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); - AlertDialog.Builder builder = new AlertDialog.Builder(this). + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()). setTitle(R.string.confirm_purchase). setMessage(message) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @@ -1042,8 +1220,8 @@ public class FileViewActivity extends AppCompatActivity { bundle.putString("currency", fee.getCurrency()); LbryAnalytics.logEvent(LbryAnalytics.EVENT_PURCHASE_URI, bundle); - findViewById(R.id.file_view_main_action_button).setVisibility(View.INVISIBLE); - findViewById(R.id.file_view_main_action_loading).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_main_action_button).setVisibility(View.INVISIBLE); + getView().findViewById(R.id.file_view_main_action_loading).setVisibility(View.VISIBLE); handleMainActionForClaim(); } }).setNegativeButton(R.string.no, null); @@ -1051,14 +1229,48 @@ public class FileViewActivity extends AppCompatActivity { } } + private void tryOpenFileOrFileGet() { + if (claim != null) { + String claimId = claim.getClaimId(); + FileListTask task = new FileListTask(claimId, null, new FileListTask.FileListResultHandler() { + @Override + public void onSuccess(List files, boolean hasReachedEnd) { + if (files.size() > 0) { + claim.setFile(files.get(0)); + checkIsFileComplete(); + } else { + checkStoragePermissionAndFileGet(); + } + initialFileLoadDone = true; + checkInitialFileLoadDone(); + } + + @Override + public void onError(Exception error) { + initialFileLoadDone = true; + checkInitialFileLoadDone(); + checkStoragePermissionAndFileGet(); + } + }); + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + private void handleMainActionForClaim() { if (Lbry.SDK_READY) { // Check if the file already exists for the claim if (claim.getFile() != null) { playOrViewMedia(); } else { - fileGet(downloadRequested || !claim.isPlayable()); - downloadRequested = false; + // check if the file exists from file list + boolean saveFile = downloadRequested || !claim.isPlayable(); + if (!saveFile) { + startTimeMillis = System.currentTimeMillis(); + fileGet(false); + return; + } else { + tryOpenFileOrFileGet(); + } } } else { if (claim.isPlayable()) { @@ -1066,7 +1278,7 @@ public class FileViewActivity extends AppCompatActivity { showExoplayerView(); playMedia(); } else { - Snackbar.make(findViewById(R.id.file_view_global_layout), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); + Snackbar.make(getView().findViewById(R.id.file_view_global_layout), R.string.sdk_initializing_functionality, Snackbar.LENGTH_LONG).show(); } } } @@ -1102,7 +1314,10 @@ public class FileViewActivity extends AppCompatActivity { String outpoint = String.format("%s:%d", claim.getTxid(), claim.getNout()); Intent intent = new Intent(LbrynetService.ACTION_QUEUE_DOWNLOAD); intent.putExtra("outpoint", outpoint); - sendBroadcast(intent); + Context context = getContext(); + if (context != null) { + context.sendBroadcast(intent); + } } else { // streaming playOrViewMedia(); @@ -1112,11 +1327,15 @@ public class FileViewActivity extends AppCompatActivity { @Override public void onError(Exception error, boolean saveFile) { - showError(getString(R.string.unable_to_view_url, currentUrl)); - if (saveFile) { - onDownloadAborted(); + try { + showError(getString(R.string.unable_to_view_url, currentUrl)); + if (saveFile) { + onDownloadAborted(); + } + restoreMainActionButton(); + } catch (IllegalStateException ex) { + // pass } - restoreMainActionButton(); } }); getFileTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -1146,16 +1365,16 @@ public class FileViewActivity extends AppCompatActivity { } else if (fileUri != null) { if (mediaType.startsWith("image")) { // display the image - View container = findViewById(R.id.file_view_imageviewer_container); - PhotoView photoView = findViewById(R.id.file_view_imageviewer); + View container = getView().findViewById(R.id.file_view_imageviewer_container); + PhotoView photoView = getView().findViewById(R.id.file_view_imageviewer); - Glide.with(getApplicationContext()).load(fileUri).centerInside().into(photoView); + Glide.with(getContext().getApplicationContext()).load(fileUri).centerInside().into(photoView); hideFloatingWalletBalance(); container.setVisibility(View.VISIBLE); } else if (mediaType.startsWith("text")) { // show web view (and parse markdown too) - View container = findViewById(R.id.file_view_webview_container); - WebView webView = findViewById(R.id.file_view_webview); + View container = getView().findViewById(R.id.file_view_webview_container); + WebView webView = getView().findViewById(R.id.file_view_webview); if (Arrays.asList("text/markdown", "text/md").contains(mediaType.toLowerCase())) { loadMarkdownFromFile(claimFile.getDownloadPath()); } else { @@ -1179,7 +1398,7 @@ public class FileViewActivity extends AppCompatActivity { @Override public void onSuccess(String text) { String html = buildMarkdownHtml(text); - WebView webView = findViewById(R.id.file_view_webview); + WebView webView = getView().findViewById(R.id.file_view_webview); webView.loadData(html, "text/html", "utf-8"); } @@ -1203,16 +1422,6 @@ public class FileViewActivity extends AppCompatActivity { " \n" + " \n" + " \n" + @@ -1226,7 +1435,7 @@ public class FileViewActivity extends AppCompatActivity { } public void showError(String message) { - Snackbar.make(findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG). + Snackbar.make(getView().findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG). setTextColor(Color.WHITE). setBackgroundTint(Color.RED). show(); @@ -1234,13 +1443,12 @@ public class FileViewActivity extends AppCompatActivity { private void loadRelatedContent() { // reset the list view - ((RecyclerView) findViewById(R.id.file_view_related_content_list)).setAdapter(null); - String title = claim.getTitle(); String claimId = claim.getClaimId(); - ProgressBar relatedLoading = findViewById(R.id.file_view_related_content_progress); + ProgressBar relatedLoading = getView().findViewById(R.id.file_view_related_content_progress); - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + Context context = getContext(); + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false); LighthouseSearchTask relatedTask = new LighthouseSearchTask( title, RELATED_CONTENT_SIZE, 0, canShowMatureContent, claimId, relatedLoading, new ClaimSearchTask.ClaimSearchResultHandler() { @@ -1253,33 +1461,29 @@ public class FileViewActivity extends AppCompatActivity { } } - relatedContentAdapter = new ClaimListAdapter(filteredClaims, FileViewActivity.this); + relatedContentAdapter = new ClaimListAdapter(filteredClaims, context); relatedContentAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() { @Override public void onClaimClicked(Claim claim) { - if (claim.getName().startsWith("@")) { - // opening a channel - Intent intent = new Intent(MainActivity.ACTION_OPEN_CHANNEL_URL); - intent.putExtra("url", claim.getPermanentUrl()); - sendBroadcast(intent); - bringMainTaskToFront(); - finish(); - } else { - Intent intent = new Intent(FileViewActivity.this, FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", claim.getClaimId()); - intent.putExtra("url", !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl()); - MainActivity.startingFileViewActivity = true; - startActivity(intent); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + if (claim.getName().startsWith("@")) { + activity.openChannelUrl(claim.getPermanentUrl()); + } else { + openClaimUrl(claim.getPermanentUrl()); + } } } }); - RecyclerView relatedContentList = findViewById(R.id.file_view_related_content_list); - relatedContentList.setAdapter(relatedContentAdapter); - relatedContentAdapter.notifyDataSetChanged(); + View view = getView(); + if (view != null) { + RecyclerView relatedContentList = view.findViewById(R.id.file_view_related_content_list); + relatedContentList.setAdapter(relatedContentAdapter); + relatedContentAdapter.notifyDataSetChanged(); - Helper.setViewVisibility(findViewById(R.id.file_view_no_related_content), relatedContentAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE); + Helper.setViewVisibility(view.findViewById(R.id.file_view_no_related_content), relatedContentAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE); + } } @Override @@ -1290,149 +1494,84 @@ public class FileViewActivity extends AppCompatActivity { relatedTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - public void onBackPressed() { + public boolean onBackPressed() { if (isInFullscreenMode()) { disableFullScreenMode(); - return; + return true; } if (isImageViewerVisible()) { - findViewById(R.id.file_view_imageviewer_container).setVisibility(View.GONE); + getView().findViewById(R.id.file_view_imageviewer_container).setVisibility(View.GONE); restoreMainActionButton(); showFloatingWalletBalance(); - return; + return true; } if (isWebViewVisible()) { - findViewById(R.id.file_view_webview_container).setVisibility(View.GONE); + getView().findViewById(R.id.file_view_webview_container).setVisibility(View.GONE); restoreMainActionButton(); showFloatingWalletBalance(); - return; + return true; } - bringMainTaskToFront(); - } - - private void startMainActivity() { - MainActivity.mainActive = true; - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); - finish(); + return false; } private boolean isImageViewerVisible() { - return findViewById(R.id.file_view_imageviewer_container).getVisibility() == View.VISIBLE; + View view = getView(); + return view != null && view.findViewById(R.id.file_view_imageviewer_container).getVisibility() == View.VISIBLE; } private boolean isWebViewVisible() { - return findViewById(R.id.file_view_webview_container).getVisibility() == View.VISIBLE; - } - - protected void onUserLeaveHint() { - if (stopServiceReceived || claim == null || !claim.isPlayable() || !playbackStarted) { - return; - } - - if (startingShareActivity) { - // share activity triggered this, so reset the flag at this point - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - startingShareActivity = false; - } - }, 1000); - return; - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !MainActivity.mainActive) { - PictureInPictureParams params = new PictureInPictureParams.Builder().build(); - enterPictureInPictureMode(params); - } - } - - protected void onStop() { - if (inPictureInPictureMode && MainActivity.appPlayer != null) { - MainActivity.appPlayer.setPlayWhenReady(false); - } - super.onStop(); - } - - - protected void onDestroy() { - Helper.unregisterReceiver(downloadEventReceiver, this); - Helper.unregisterReceiver(sdkReceiver, this); - if (MainActivity.appPlayer != null && fileViewPlayerListener != null) { - MainActivity.appPlayer.removeListener(fileViewPlayerListener); - } - instance = null; - - if (stopServiceReceived) { - MainActivity.stopExoplayer(); - } - - super.onDestroy(); - } - - private void renderPictureInPictureMode() { - findViewById(R.id.file_view_scroll_view).setVisibility(View.GONE); - findViewById(R.id.floating_balance_main_container).setVisibility(View.GONE); - } - private void renderFullMode() { - findViewById(R.id.file_view_scroll_view).setVisibility(View.VISIBLE); - if (!isInFullscreenMode()) { - findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE); - } - } - - @Override - public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) { - inPictureInPictureMode = isInPictureInPictureMode; - if (isInPictureInPictureMode) { - renderPictureInPictureMode(); - } else { - backStackLost = true; - renderFullMode(); - } + View view = getView(); + return view != null && view.findViewById(R.id.file_view_webview_container).getVisibility() == View.VISIBLE; } @SuppressLint("SourceLockedOrientationActivity") private void enableFullScreenMode() { - findViewById(R.id.floating_balance_main_container).setVisibility(View.INVISIBLE); + Context context = getContext(); + if (context instanceof MainActivity) { + ConstraintLayout globalLayout = getView().findViewById(R.id.file_view_global_layout); + View exoplayerContainer = getView().findViewById(R.id.file_view_exoplayer_container); + ((ViewGroup) exoplayerContainer.getParent()).removeView(exoplayerContainer); + globalLayout.addView(exoplayerContainer); - View decorView = getWindow().getDecorView(); - decorView.setSystemUiVisibility( - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | - View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + ((ImageView) getView().findViewById(R.id.player_image_full_screen_toggle)).setImageResource(R.drawable.ic_fullscreen_exit); - ConstraintLayout globalLayout = findViewById(R.id.file_view_global_layout); - View exoplayerContainer = findViewById(R.id.file_view_exoplayer_container); - ((ViewGroup) exoplayerContainer.getParent()).removeView(exoplayerContainer); - globalLayout.addView(exoplayerContainer); + MainActivity activity = (MainActivity) context; + activity.enterFullScreenMode(); - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - ((ImageView) findViewById(R.id.player_image_full_screen_toggle)).setImageResource(R.drawable.ic_fullscreen_exit); + int statusBarHeight = activity.getStatusBarHeight(); + exoplayerContainer.setPadding(0, 0, 0, statusBarHeight); + + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } } private void disableFullScreenMode() { - RelativeLayout mediaContainer = findViewById(R.id.file_view_media_container); - View exoplayerContainer = findViewById(R.id.file_view_exoplayer_container); - ((ViewGroup) exoplayerContainer.getParent()).removeView(exoplayerContainer); - mediaContainer.addView(exoplayerContainer); + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; - View decorView = getWindow().getDecorView(); - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE); - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); + RelativeLayout mediaContainer = getView().findViewById(R.id.file_view_media_container); + View exoplayerContainer = getView().findViewById(R.id.file_view_exoplayer_container); + ((ViewGroup) exoplayerContainer.getParent()).removeView(exoplayerContainer); + mediaContainer.addView(exoplayerContainer); - ((ImageView) findViewById(R.id.player_image_full_screen_toggle)).setImageResource(R.drawable.ic_fullscreen); - findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE); + ((ImageView) getView().findViewById(R.id.player_image_full_screen_toggle)).setImageResource(R.drawable.ic_fullscreen); + exoplayerContainer.setPadding(0, 0, 0, 0); + + activity.exitFullScreenMode(); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } } private boolean isInFullscreenMode() { - View exoplayerContainer = findViewById(R.id.file_view_exoplayer_container); - return exoplayerContainer.getParent() instanceof ConstraintLayout; + View view = getView(); + if (view != null) { + View exoplayerContainer = view.findViewById(R.id.file_view_exoplayer_container); + return exoplayerContainer.getParent() instanceof ConstraintLayout; + } + return false; } private void scheduleElapsedPlayback() { @@ -1441,15 +1580,18 @@ public class FileViewActivity extends AppCompatActivity { elapsedPlaybackScheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (MainActivity.appPlayer != null) { - elapsedDuration = MainActivity.appPlayer.getCurrentPosition(); - renderElapsedDuration(); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).runOnUiThread(new Runnable() { + @Override + public void run() { + if (MainActivity.appPlayer != null) { + elapsedDuration = MainActivity.appPlayer.getCurrentPosition(); + renderElapsedDuration(); + } } - } - }); + }); + } } }, 0, 500, TimeUnit.MILLISECONDS); elapsedPlaybackScheduled = true; @@ -1471,31 +1613,44 @@ public class FileViewActivity extends AppCompatActivity { playbackStarted = false; startTimeMillis = 0; - MainActivity.appPlayer.removeListener(fileViewPlayerListener); + if (MainActivity.appPlayer != null) { + MainActivity.appPlayer.removeListener(fileViewPlayerListener); + } } private void showBuffering() { - findViewById(R.id.player_buffering_progress).setVisibility(View.VISIBLE); + View view = getView(); + if (view != null) { + view.findViewById(R.id.player_buffering_progress).setVisibility(View.VISIBLE); + } } private void hideBuffering() { - findViewById(R.id.player_buffering_progress).setVisibility(View.INVISIBLE); + View view = getView(); + if (view != null) { + view.findViewById(R.id.player_buffering_progress).setVisibility(View.INVISIBLE); + } } private void renderElapsedDuration() { - Helper.setViewText(findViewById(R.id.player_duration_elapsed), Helper.formatDuration(Double.valueOf(elapsedDuration / 1000.0).longValue())); + View view = getView(); + if (view != null) { + Helper.setViewText(view.findViewById(R.id.player_duration_elapsed), Helper.formatDuration(Double.valueOf(elapsedDuration / 1000.0).longValue())); + } } private void renderTotalDuration() { - Helper.setViewText(findViewById(R.id.player_duration_total), Helper.formatDuration(Double.valueOf(totalDuration / 1000.0).longValue())); + View view = getView(); + if (view != null) { + Helper.setViewText(view.findViewById(R.id.player_duration_total), Helper.formatDuration(Double.valueOf(totalDuration / 1000.0).longValue())); + } } private void loadAndScheduleDurations() { - if (MainActivity.appPlayer != null) { - if (totalDuration == 0) { - elapsedDuration = MainActivity.appPlayer.getCurrentPosition(); - totalDuration = MainActivity.appPlayer.getDuration(); - } + if (MainActivity.appPlayer != null && playbackStarted) { + elapsedDuration = MainActivity.appPlayer.getCurrentPosition() < 0 ? 0 : MainActivity.appPlayer.getCurrentPosition(); + totalDuration = MainActivity.appPlayer.getDuration() < 0 ? 0 : MainActivity.appPlayer.getDuration(); + renderElapsedDuration(); renderTotalDuration(); scheduleElapsedPlayback(); @@ -1535,18 +1690,23 @@ public class FileViewActivity extends AppCompatActivity { private void checkIsFollowing() { if (claim != null && claim.getSigningChannel() != null) { boolean isFollowing = Lbryio.isFollowing(claim.getSigningChannel()); - SolidIconView iconFollowUnfollow = findViewById(R.id.file_view_icon_follow_unfollow); - if (iconFollowUnfollow != null) { - iconFollowUnfollow.setText(isFollowing ? R.string.fa_heart_broken : R.string.fa_heart); - iconFollowUnfollow.setTextColor(ContextCompat.getColor(this, isFollowing ? R.color.foreground : R.color.red)); + Context context = getContext(); + View root = getView(); + if (context != null && root != null) { + SolidIconView iconFollowUnfollow = root.findViewById(R.id.file_view_icon_follow_unfollow); + if (iconFollowUnfollow != null) { + iconFollowUnfollow.setText(isFollowing ? R.string.fa_heart_broken : R.string.fa_heart); + iconFollowUnfollow.setTextColor(ContextCompat.getColor(context, isFollowing ? R.color.foreground : R.color.red)); + } } } } private void claimEligibleRewards() { // attempt to claim eligible rewards after viewing or playing a file (fail silently) - ClaimRewardTask firstStreamTask = new ClaimRewardTask(Reward.TYPE_FIRST_STREAM, null, null, this, eligibleRewardHandler); - ClaimRewardTask dailyViewTask = new ClaimRewardTask(Reward.TYPE_DAILY_VIEW, null, null, this, eligibleRewardHandler); + Context context = getContext(); + ClaimRewardTask firstStreamTask = new ClaimRewardTask(Reward.TYPE_FIRST_STREAM, null, null, context, eligibleRewardHandler); + ClaimRewardTask dailyViewTask = new ClaimRewardTask(Reward.TYPE_DAILY_VIEW, null, null, context, eligibleRewardHandler); firstStreamTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); dailyViewTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -1560,7 +1720,7 @@ public class FileViewActivity extends AppCompatActivity { amountClaimed == 1 ? 1 : 2, new DecimalFormat(Helper.LBC_CURRENCY_FORMAT_PATTERN).format(amountClaimed)); } - Snackbar.make(findViewById(R.id.file_view_global_layout), message, Snackbar.LENGTH_LONG).show(); + Snackbar.make(getView().findViewById(R.id.file_view_global_layout), message, Snackbar.LENGTH_LONG).show(); } @Override @@ -1569,83 +1729,30 @@ public class FileViewActivity extends AppCompatActivity { } }; - private void registerDownloadEventReceiver() { - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_EVENT); - downloadEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String downloadAction = intent.getStringExtra("action"); - String uri = intent.getStringExtra("uri"); - String outpoint = intent.getStringExtra("outpoint"); - String fileInfoJson = intent.getStringExtra("file_info"); - double progress = intent.getDoubleExtra("progress", 0); - if (claim == null || uri == null || outpoint == null || (fileInfoJson == null && !"abort".equals(downloadAction))) { - return; - } - onRelatedDownloadAction(downloadAction, uri, outpoint, fileInfoJson, progress); - if (claim != null && !claim.getPermanentUrl().equalsIgnoreCase(uri)) { - return; - } - if ("abort".equals(downloadAction)) { - // handle download aborted - onDownloadAborted(); - return; - } - - ImageView downloadIconView = findViewById(R.id.file_view_action_download_icon); - ProgressBar downloadProgressView = findViewById(R.id.file_view_download_progress); - - try { - JSONObject fileInfo = new JSONObject(fileInfoJson); - LbryFile claimFile = LbryFile.fromJSONObject(fileInfo); - claim.setFile(claimFile); - - if (DownloadManager.ACTION_START.equals(downloadAction)) { - downloadInProgress = true; - Helper.setViewVisibility(downloadProgressView, View.VISIBLE); - downloadProgressView.setProgress(0); - downloadIconView.setImageResource(R.drawable.ic_stop); - } else if (DownloadManager.ACTION_UPDATE.equals(downloadAction)) { - // handle download updated - downloadInProgress = true; - Helper.setViewVisibility(downloadProgressView, View.VISIBLE); - downloadProgressView.setProgress(Double.valueOf(progress).intValue()); - downloadIconView.setImageResource(R.drawable.ic_stop); - } - else if (DownloadManager.ACTION_COMPLETE.equals(downloadAction)) { - downloadInProgress = false; - downloadProgressView.setProgress(100); - Helper.setViewVisibility(downloadProgressView, View.GONE); - playOrViewMedia(); - } - checkIsFileComplete(); - } catch (JSONException ex) { - // invalid file info for download - } - } - }; - registerReceiver(downloadEventReceiver, intentFilter); - } - private void checkIsFileComplete() { if (claim == null) { return; } if (claim.getFile() != null && claim.getFile().isCompleted()) { - Helper.setViewVisibility(findViewById(R.id.file_view_action_delete), View.VISIBLE); - Helper.setViewVisibility(findViewById(R.id.file_view_action_download), View.GONE); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_delete), View.VISIBLE); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_download), View.GONE); } else { - Helper.setViewVisibility(findViewById(R.id.file_view_action_delete), View.GONE); - Helper.setViewVisibility(findViewById(R.id.file_view_action_download), View.VISIBLE); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_delete), View.GONE); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_action_download), View.VISIBLE); } } private void hideFloatingWalletBalance() { - findViewById(R.id.floating_balance_main_container).setVisibility(View.GONE); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).hideFloatingWalletBalance(); + } } private void showFloatingWalletBalance() { - findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE); + Context context = getContext(); + if (context instanceof MainActivity) { + ((MainActivity) context).showFloatingWalletBalance(); + } } private void toggleCast() { @@ -1667,17 +1774,65 @@ public class FileViewActivity extends AppCompatActivity { if (claim != null) { claim.setFile(null); } - ((ImageView) findViewById(R.id.file_view_action_download_icon)).setImageResource(R.drawable.ic_download); - Helper.setViewVisibility(findViewById(R.id.file_view_download_progress), View.GONE); - Helper.setViewVisibility(findViewById(R.id.file_view_unsupported_container), View.GONE); + ((ImageView) getView().findViewById(R.id.file_view_action_download_icon)).setImageResource(R.drawable.ic_download); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_download_progress), View.GONE); + Helper.setViewVisibility(getView().findViewById(R.id.file_view_unsupported_container), View.GONE); checkIsFileComplete(); restoreMainActionButton(); } private void restoreMainActionButton() { - findViewById(R.id.file_view_main_action_loading).setVisibility(View.INVISIBLE); - findViewById(R.id.file_view_main_action_button).setVisibility(View.VISIBLE); + getView().findViewById(R.id.file_view_main_action_loading).setVisibility(View.INVISIBLE); + getView().findViewById(R.id.file_view_main_action_button).setVisibility(View.VISIBLE); + } + + @Override + public void onDownloadAction(String downloadAction, String uri, String outpoint, String fileInfoJson, double progress) { + if (uri == null || outpoint == null || (fileInfoJson == null && !"abort".equals(downloadAction))) { + return; + } + onRelatedDownloadAction(downloadAction, uri, outpoint, fileInfoJson, progress); + if (claim == null || claim != null && !claim.getPermanentUrl().equalsIgnoreCase(uri)) { + return; + } + if ("abort".equals(downloadAction)) { + onDownloadAborted(); + return; + } + + View root = getView(); + if (root != null) { + ImageView downloadIconView = root.findViewById(R.id.file_view_action_download_icon); + ProgressBar downloadProgressView = root.findViewById(R.id.file_view_download_progress); + + try { + JSONObject fileInfo = new JSONObject(fileInfoJson); + LbryFile claimFile = LbryFile.fromJSONObject(fileInfo); + claim.setFile(claimFile); + + if (DownloadManager.ACTION_START.equals(downloadAction)) { + downloadInProgress = true; + Helper.setViewVisibility(downloadProgressView, View.VISIBLE); + downloadProgressView.setProgress(0); + downloadIconView.setImageResource(R.drawable.ic_stop); + } else if (DownloadManager.ACTION_UPDATE.equals(downloadAction)) { + // handle download updated + downloadInProgress = true; + Helper.setViewVisibility(downloadProgressView, View.VISIBLE); + downloadProgressView.setProgress(Double.valueOf(progress).intValue()); + downloadIconView.setImageResource(R.drawable.ic_stop); + } else if (DownloadManager.ACTION_COMPLETE.equals(downloadAction)) { + downloadInProgress = false; + downloadProgressView.setProgress(100); + Helper.setViewVisibility(downloadProgressView, View.GONE); + playOrViewMedia(); + } + checkIsFileComplete(); + } catch (JSONException ex) { + // invalid file info for download + } + } } private static class LbryWebViewClient extends WebViewClient { @@ -1715,22 +1870,4 @@ public class FileViewActivity extends AppCompatActivity { // invalid file info for download } } - - private void bringMainTaskToFront() { - if (backStackLost) { - ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - final List appTasks = activityManager.getAppTasks(); - for (ActivityManager.AppTask task : appTasks) { - final Intent baseIntent = task.getTaskInfo().baseIntent; - final Set categories = baseIntent.getCategories(); - if (categories != null && categories.contains(Intent.CATEGORY_LAUNCHER)) { - task.moveToFront(); - finish(); - return; - } - } - } - - startMainActivity(); - } } diff --git a/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java b/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java index 67e74430..089ca60b 100644 --- a/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/following/FollowingFragment.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import io.lbry.browser.FileViewActivity; import io.lbry.browser.MainActivity; import io.lbry.browser.R; import io.lbry.browser.adapter.ChannelFilterListAdapter; @@ -90,6 +89,7 @@ public class FollowingFragment extends BaseFragment implements private boolean contentClaimSearchLoading = false; private boolean suggestedClaimSearchLoading = false; private View noContentView; + private boolean subscriptionsShown; private List queuedContentPages = new ArrayList<>(); private List queuedSuggestedPages = new ArrayList<>(); @@ -249,8 +249,8 @@ public class FollowingFragment extends BaseFragment implements @Override public void onClick(View view) { buildChannelIdsAndUrls(); + currentSuggestedPage = 1; discoverDialog = DiscoverDialogFragment.newInstance(); - excludeChannelIdsForDiscover = channelIds != null ? new ArrayList<>(channelIds) : null; discoverDialog.setAdapter(suggestedChannelAdapter); discoverDialog.setDialogActionsListener(new DiscoverDialogFragment.DiscoverDialogListener() { @Override @@ -265,6 +265,9 @@ public class FollowingFragment extends BaseFragment implements public void onCancel() { discoverDialog = null; excludeChannelIdsForDiscover = null; + if (suggestedChannelAdapter != null) { + suggestedChannelAdapter.clearItems(); + } } @Override public void onResume() { @@ -353,7 +356,7 @@ public class FollowingFragment extends BaseFragment implements } if (Lbryio.subscriptions != null && Lbryio.subscriptions.size() > 0) { - fetchLoadedSubscriptions(); + fetchLoadedSubscriptions(true); } else { fetchSubscriptions(); } @@ -366,7 +369,7 @@ public class FollowingFragment extends BaseFragment implements PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this); super.onPause(); } - public void fetchLoadedSubscriptions() { + public void fetchLoadedSubscriptions(boolean showSubscribed) { subscriptionsList = new ArrayList<>(Lbryio.subscriptions); buildChannelIdsAndUrls(); if (Lbryio.cacheResolvedSubscriptions.size() > 0) { @@ -377,7 +380,9 @@ public class FollowingFragment extends BaseFragment implements fetchClaimSearchContent(resetClaimSearchContent); resetClaimSearchContent = false; - showSubscribedContent(); + if (showSubscribed && subscriptionsList.size() > 0) { + showSubscribedContent(); + } } public void loadFollowing() { @@ -458,6 +463,7 @@ public class FollowingFragment extends BaseFragment implements } private void showSubscribedContent() { + subscriptionsShown = true; Helper.setViewText(titleView, R.string.channels_you_follow); Helper.setViewVisibility(horizontalChannelList, View.VISIBLE); @@ -484,6 +490,8 @@ public class FollowingFragment extends BaseFragment implements } } } + + excludeChannelIdsForDiscover = channelIds != null ? new ArrayList<>(channelIds) : null; } private void fetchAndResolveChannelList() { @@ -579,22 +587,15 @@ public class FollowingFragment extends BaseFragment implements contentListAdapter.setListener(new ClaimListAdapter.ClaimListItemListener() { @Override public void onClaimClicked(Claim claim) { - String claimId = claim.getClaimId(); - String url = !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl(); - - if (claim.getName().startsWith("@")) { - // channel claim - Context context = getContext(); - if (context instanceof MainActivity) { - ((MainActivity) context).openChannelClaim(claim); + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + if (claim.getName().startsWith("@")) { + // channel claim + activity.openChannelClaim(claim); + } else { + activity.openFileClaim(claim); } - } else { - Intent intent = new Intent(getContext(), FileViewActivity.class); - //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra("claimId", claimId); - intent.putExtra("url", url); - MainActivity.startingFileViewActivity = true; - startActivity(intent); } } }); @@ -718,12 +719,11 @@ public class FollowingFragment extends BaseFragment implements ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, false, new ChannelSubscribeTask.ChannelSubscribeHandler() { @Override public void onSuccess() { - if (discoverDialog != null) { - Lbryio.addSubscription(subscription); - Lbryio.addCachedResolvedSubscription(claim); - resetClaimSearchContent = true; - fetchLoadedSubscriptions(); - } + Lbryio.addSubscription(subscription); + Lbryio.addCachedResolvedSubscription(claim); + resetClaimSearchContent = true; + fetchLoadedSubscriptions(subscriptionsShown); + saveSharedUserState(); } @@ -740,12 +740,11 @@ public class FollowingFragment extends BaseFragment implements ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, true, new ChannelSubscribeTask.ChannelSubscribeHandler() { @Override public void onSuccess() { - if (discoverDialog != null) { - Lbryio.removeSubscription(subscription); - Lbryio.removeCachedResolvedSubscription(claim); - resetClaimSearchContent = true; - fetchLoadedSubscriptions(); - } + Lbryio.removeSubscription(subscription); + Lbryio.removeCachedResolvedSubscription(claim); + resetClaimSearchContent = true; + fetchLoadedSubscriptions(subscriptionsShown); + saveSharedUserState(); } diff --git a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java index ec1d11b2..0bf8eb71 100644 --- a/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/library/LibraryFragment.java @@ -58,6 +58,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe private int currentPage; private Date lastDate; private boolean listReachedEnd; + private boolean contentListLoading; private CardView cardStats; private TextView linkStats; @@ -114,6 +115,32 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe showHistory(); } }); + contentList.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (contentListLoading) { + return; + } + + LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager(); + if (lm != null) { + int visibleItemCount = lm.getChildCount(); + int totalItemCount = lm.getItemCount(); + int pastVisibleItems = lm.findFirstVisibleItemPosition(); + if (pastVisibleItems + visibleItemCount >= totalItemCount) { + if (!listReachedEnd) { + // load more + if (currentFilter == FILTER_DOWNLOADS) { + currentPage++; + fetchDownloads(); + } else if (currentFilter == FILTER_HISTORY) { + fetchHistory(); + } + } + } + } + } + }); // stats linkStats = root.findViewById(R.id.library_show_stats); @@ -203,6 +230,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe contentListAdapter.clearItems(); contentListAdapter.setCanEnterSelectionMode(true); } + listReachedEnd = false; checkStatsLink(); layoutSdkInitializing.setVisibility(Lbry.SDK_READY ? View.GONE : View.VISIBLE); @@ -220,6 +248,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe contentListAdapter.clearItems(); contentListAdapter.setCanEnterSelectionMode(false); } + listReachedEnd = false; cardStats.setVisibility(View.GONE); checkStatsLink(); @@ -241,7 +270,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe if (claim.getName().startsWith("@")) { activity.openChannelUrl(claim.getPermanentUrl()); } else { - MainActivity.openFileUrl(claim.getPermanentUrl(), context); + activity.openFileUrl(claim.getPermanentUrl()); } } } @@ -249,6 +278,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe } private void fetchDownloads() { + contentListLoading = true; Helper.setViewVisibility(linkStats, View.GONE); Helper.setViewVisibility(layoutListEmpty, View.GONE); FileListTask task = new FileListTask(currentPage, PAGE_SIZE, true, listLoading, new FileListTask.FileListResultHandler() { @@ -269,6 +299,7 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe } contentList.setAdapter(contentListAdapter); checkListEmpty(); + contentListLoading = false; } @Override @@ -276,12 +307,14 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe // pass checkStatsLink(); checkListEmpty(); + contentListLoading = false; } }); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private void fetchHistory() { + contentListLoading = true; Helper.setViewVisibility(layoutListEmpty, View.GONE); DatabaseHelper dbHelper = DatabaseHelper.getInstance(); if (dbHelper != null) { @@ -289,6 +322,10 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe @Override public void onSuccess(List history, boolean hasReachedEnd) { listReachedEnd = hasReachedEnd; + if (history.size() > 0) { + lastDate = history.get(history.size() - 1).getTimestamp(); + } + List claims = Helper.claimsFromViewHistory(history); if (contentListAdapter == null) { initContentListAdapter(claims); @@ -297,11 +334,13 @@ public class LibraryFragment extends BaseFragment implements DownloadActionListe } contentList.setAdapter(contentListAdapter); checkListEmpty(); + contentListLoading = false; } }); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { checkListEmpty(); + contentListLoading = false; } } diff --git a/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java b/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java index bcc43bfa..bfbfe297 100644 --- a/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/search/SearchFragment.java @@ -265,7 +265,7 @@ public class SearchFragment extends BaseFragment implements ((MainActivity) getContext()).openChannelUrl(claim.getPermanentUrl()); } else { // not a channel - MainActivity.openFileClaim(claim, getContext()); + ((MainActivity) getContext()).openFileClaim(claim); } } diff --git a/app/src/main/java/io/lbry/browser/ui/wallet/TransactionHistoryFragment.java b/app/src/main/java/io/lbry/browser/ui/wallet/TransactionHistoryFragment.java index 4076ddbb..68b3d34b 100644 --- a/app/src/main/java/io/lbry/browser/ui/wallet/TransactionHistoryFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/wallet/TransactionHistoryFragment.java @@ -161,7 +161,7 @@ public class TransactionHistoryFragment extends BaseFragment implements Transact if (uri.isChannel()) { activity.openChannelUrl(uri.toString()); } else { - MainActivity.openFileUrl(uri.toString(), context); + activity.openFileUrl(uri.toString()); } } } diff --git a/app/src/main/java/io/lbry/browser/utils/Helper.java b/app/src/main/java/io/lbry/browser/utils/Helper.java index 31d61220..0a7140e2 100644 --- a/app/src/main/java/io/lbry/browser/utils/Helper.java +++ b/app/src/main/java/io/lbry/browser/utils/Helper.java @@ -285,21 +285,22 @@ public final class Helper { } public static String shortCurrencyFormat(double value) { + DecimalFormat format = new DecimalFormat("#,###.#"); if (value > 1000000000.00) { - return String.format("%.1fB", value / 1000000000.0); + return String.format("%sB", format.format(value / 1000000000.0)); } if (value > 1000000.0) { - return String.format("%.1fM", value / 1000000.0); + return String.format("%sM",format.format( value / 1000000.0)); } if (value > 1000.0) { - return String.format("%.1fK", value / 1000.0); + return String.format("%sK", format.format(value / 1000.0)); } if (value == 0) { return "0"; } - return new DecimalFormat("###.##").format(value); + return format.format(value); } public static String getValue(CharSequence cs) { diff --git a/app/src/main/java/io/lbry/browser/utils/Lbry.java b/app/src/main/java/io/lbry/browser/utils/Lbry.java index 63bab37f..14ae413f 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbry.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbry.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.security.KeyStore; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -26,6 +27,9 @@ import io.lbry.browser.model.Tag; import io.lbry.browser.model.Transaction; import io.lbry.browser.model.WalletBalance; import io.lbry.lbrysdk.Utils; +import kotlin.Pair; +import okhttp3.CacheControl; +import okhttp3.Headers; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; @@ -161,7 +165,7 @@ public final class Lbry { if (value instanceof Double) { jsonParams.put(param.getKey(), (double) value); } else { - jsonParams.put(param.getKey(), value); + jsonParams.put(param.getKey(), value == null ? JSONObject.NULL : value); } } } catch (JSONException ex) { @@ -313,10 +317,10 @@ public final class Lbry { if (!Helper.isNullOrEmpty(claimId)) { params.put("claim_id", claimId); } - /*if (downloads) { - params.put("file_name", null); + if (downloads) { + params.put("download_path", null); params.put("comparison", "ne"); - }*/ + } if (page > 0) { params.put("page", page); } diff --git a/app/src/main/res/layout/activity_file_view.xml b/app/src/main/res/layout/activity_file_view.xml deleted file mode 100644 index 6afd90ef..00000000 --- a/app/src/main/res/layout/activity_file_view.xml +++ /dev/null @@ -1,646 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 85f39dd0..800b76a1 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,6 @@ android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" - android:fitsSystemWindows="true" tools:openDrawer="start"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_editors_choice.xml b/app/src/main/res/layout/list_item_editors_choice.xml index bb75af89..c616dea1 100644 --- a/app/src/main/res/layout/list_item_editors_choice.xml +++ b/app/src/main/res/layout/list_item_editors_choice.xml @@ -53,10 +53,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" - android:layout_centerVertical="true" + android:lineHeight="14dp" android:fontFamily="@font/inter" android:ellipsize="end" - android:maxLines="6" + android:maxLines="8" android:textFontWeight="300" android:textSize="12sp" /> diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml index d33feba5..c30ccbf5 100644 --- a/app/src/main/res/layout/nav_header_main.xml +++ b/app/src/main/res/layout/nav_header_main.xml @@ -2,32 +2,38 @@ - + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + - + + + There\'s nothing at this location. Publish something here This content cannot be accessed at this time. Please try again later. - 00:00 + 0:00 The file at "%1$s" does not exist. Confirm Purchase Delete file @@ -305,6 +305,7 @@ \@ Deposit This LBC remains yours. It is a deposit to reserve the name and can be undone at any time. + LBRY requires access to download content to your device. LBRY requires access to load images from your device storage. Select thumbnail Select cover image