diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4bb39341..ea66be0f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,6 +20,9 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
+
+
@@ -39,7 +42,7 @@
android:supportsPictureInPicture="true"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTask"
- android:windowSoftInputMode="adjustPan">
+ android:windowSoftInputMode="adjustResize">
diff --git a/app/src/main/java/io/lbry/browser/FileViewActivity.java b/app/src/main/java/io/lbry/browser/FileViewActivity.java
index 5f7654cd..83a90954 100644
--- a/app/src/main/java/io/lbry/browser/FileViewActivity.java
+++ b/app/src/main/java/io/lbry/browser/FileViewActivity.java
@@ -1,7 +1,6 @@
package io.lbry.browser;
import android.annotation.SuppressLint;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
@@ -34,7 +33,6 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.core.app.NavUtils;
import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
import androidx.preference.PreferenceManager;
@@ -43,11 +41,15 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
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.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.util.Util;
@@ -84,6 +86,7 @@ import io.lbry.browser.model.ClaimCacheKey;
import io.lbry.browser.model.Fee;
import io.lbry.browser.model.LbryFile;
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.ReadTextFileTask;
@@ -115,6 +118,8 @@ public class FileViewActivity extends AppCompatActivity {
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;
@@ -163,11 +168,8 @@ public class FileViewActivity extends AppCompatActivity {
instance = this;
ClaimCacheKey key = new ClaimCacheKey();
key.setClaimId(claimId);
- if (url.contains("#")) {
- key.setPermanentUrl(url); // use the same url for the key so that we can match the key for any value that's the same
- key.setCanonicalUrl(url);
- key.setShortUrl(url);
- }
+ 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);
checkAndResetNowPlayingClaim();
@@ -181,6 +183,7 @@ public class FileViewActivity extends AppCompatActivity {
currentUrl = url;
logUrlEvent(url);
+ Helper.saveUrlHistory(url, claim != null ? claim.getTitle() : null, UrlSuggestion.TYPE_FILE);
if (claim == null) {
MainActivity.clearNowPlayingClaim(this);
resolveUrl(url);
@@ -218,6 +221,7 @@ public class FileViewActivity extends AppCompatActivity {
}
};
+ castControlView = findViewById(R.id.file_view_cast_control_view);
initUi();
onWalletBalanceUpdated();
renderClaim();
@@ -278,9 +282,7 @@ public class FileViewActivity extends AppCompatActivity {
ClaimCacheKey key = new ClaimCacheKey();
key.setClaimId(newClaimId);
if (!Helper.isNullOrEmpty(newUrl) && newUrl.contains("#")) {
- key.setPermanentUrl(newUrl);
- key.setCanonicalUrl(newUrl);
- key.setShortUrl(newUrl);
+ key.setUrl(newUrl);
}
loadClaimForCacheKey(key, newUrl);
} else if (!Helper.isNullOrEmpty(newUrl)) {
@@ -290,9 +292,7 @@ public class FileViewActivity extends AppCompatActivity {
onNewClaim(newUrl);
ClaimCacheKey key = new ClaimCacheKey();
- key.setPermanentUrl(newUrl);
- key.setCanonicalUrl(newUrl);
- key.setShortUrl(newUrl);
+ key.setUrl(newUrl);
loadClaimForCacheKey(key, newUrl);
}
}
@@ -313,6 +313,7 @@ public class FileViewActivity extends AppCompatActivity {
private void loadClaimForCacheKey(ClaimCacheKey key, String url) {
if (Lbry.claimCache.containsKey(key)) {
claim = Lbry.claimCache.get(key);
+ Helper.saveUrlHistory(url, claim.getTitle(), UrlSuggestion.TYPE_FILE);
checkAndResetNowPlayingClaim();
if (claim.getFile() == null) {
loadFile();
@@ -322,6 +323,7 @@ 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);
resolveUrl(url);
@@ -452,6 +454,8 @@ public class FileViewActivity extends AppCompatActivity {
super.onResume();
MainActivity.mainActive = false;
MainActivity.startingFileViewActivity = false;
+
+ loadAndScheduleDurations();
if (Lbry.SDK_READY) {
initFloatingWalletBalance();
}
@@ -468,12 +472,25 @@ public class FileViewActivity extends AppCompatActivity {
claim = claims.get(0);
if (Claim.TYPE_REPOST.equalsIgnoreCase(claim.getValueType())) {
claim = claim.getRepostedClaim();
-
// cache the reposted claim too for subsequent loads
- ClaimCacheKey key = ClaimCacheKey.fromClaim(claim);
- Lbry.claimCache.put(key, claim);
+ 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();
+ return;
+ }
+ } else {
+ Lbry.addClaimToCache(claim);
}
+ Helper.saveUrlHistory(url, claim.getTitle(), UrlSuggestion.TYPE_FILE);
+
+ // also save view history
checkAndResetNowPlayingClaim();
loadFile();
renderClaim();
@@ -644,7 +661,14 @@ public class FileViewActivity extends AppCompatActivity {
}
});
- findViewById(R.id.player_toggle_full_screen).setOnClickListener(new View.OnClickListener() {
+ 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() {
@Override
public void onClick(View view) {
// check full screen mode
@@ -664,7 +688,6 @@ public class FileViewActivity extends AppCompatActivity {
Intent intent = new Intent(MainActivity.ACTION_OPEN_CHANNEL_URL);
intent.putExtra("url", !Helper.isNullOrEmpty(publisher.getShortUrl()) ? publisher.getShortUrl() : publisher.getPermanentUrl());
sendBroadcast(intent);
-
bringMainTaskToFront();
finish();
}
@@ -862,12 +885,12 @@ public class FileViewActivity extends AppCompatActivity {
boolean newPlayerCreated = false;
if (MainActivity.appPlayer == null) {
MainActivity.appPlayer = new SimpleExoPlayer.Builder(this).build();
+ MainActivity.castPlayer = new CastPlayer(MainActivity.castContext);
newPlayerCreated = true;
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
-
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
PlayerView view = findViewById(R.id.file_view_exoplayer_view);
view.setPlayer(MainActivity.appPlayer);
if (MainActivity.nowPlayingClaim != null &&
@@ -881,6 +904,20 @@ public class FileViewActivity extends AppCompatActivity {
showBuffering();
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));
@@ -893,6 +930,47 @@ public class FileViewActivity extends AppCompatActivity {
MainActivity.appPlayer.prepare(mediaSource, true, true);
}
+ private void setCurrentPlayer(Player currentPlayer) {
+ if (this.currentPlayer == currentPlayer) {
+ return;
+ }
+
+ // View management.
+ if (currentPlayer == MainActivity.appPlayer) {
+ //localPlayerView.setVisibility(View.VISIBLE);
+ castControlView.hide();
+ ((ImageView) 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);
+ }
+
+ // Player state management.
+ long playbackPositionMs = C.TIME_UNSET;
+ int windowIndex = C.INDEX_UNSET;
+ boolean playWhenReady = false;
+
+ Player previousPlayer = this.currentPlayer;
+ if (previousPlayer != null) {
+ // Save state from the previous player.
+ int playbackState = previousPlayer.getPlaybackState();
+ if (playbackState != Player.STATE_ENDED) {
+ playbackPositionMs = previousPlayer.getCurrentPosition();
+ playWhenReady = previousPlayer.getPlayWhenReady();
+ }
+ previousPlayer.stop(true);
+ }
+
+ this.currentPlayer = currentPlayer;
+
+ // Media queue management.
+ /*if (currentPlayer == exoPlayer) {
+ exoPlayer.prepare(concatenatingMediaSource);
+ }*/
+ currentPlayer.seekTo(playbackPositionMs);
+ currentPlayer.setPlayWhenReady(true);
+ }
+
private void resetViewCount() {
TextView textViewCount = findViewById(R.id.file_view_view_count);
Helper.setViewText(textViewCount, null);
@@ -1179,7 +1257,7 @@ public class FileViewActivity extends AppCompatActivity {
if (claim.getName().startsWith("@")) {
// opening a channel
Intent intent = new Intent(MainActivity.ACTION_OPEN_CHANNEL_URL);
- intent.putExtra("url", !Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl());
+ intent.putExtra("url", claim.getPermanentUrl());
sendBroadcast(intent);
bringMainTaskToFront();
finish();
@@ -1409,6 +1487,18 @@ public class FileViewActivity extends AppCompatActivity {
Helper.setViewText(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();
+ }
+ renderElapsedDuration();
+ renderTotalDuration();
+ scheduleElapsedPlayback();
+ }
+ }
+
private void logPlay(String url, long startTimeMillis) {
long timeToStartMillis = startTimeMillis > 0 ? System.currentTimeMillis() - startTimeMillis : 0;
@@ -1554,6 +1644,19 @@ public class FileViewActivity extends AppCompatActivity {
findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE);
}
+ private void toggleCast() {
+ if (!MainActivity.castPlayer.isCastSessionAvailable()) {
+ showError(getString(R.string.no_cast_session_available));
+ return;
+ }
+
+ if (currentPlayer == MainActivity.appPlayer) {
+ setCurrentPlayer(MainActivity.castPlayer);
+ } else {
+ setCurrentPlayer(MainActivity.appPlayer);
+ }
+ }
+
private void onDownloadAborted() {
downloadInProgress = false;
@@ -1598,6 +1701,7 @@ public class FileViewActivity extends AppCompatActivity {
final Set categories = baseIntent.getCategories();
if (categories != null && categories.contains(Intent.CATEGORY_LAUNCHER)) {
task.moveToFront();
+ finish();
return;
}
}
diff --git a/app/src/main/java/io/lbry/browser/MainActivity.java b/app/src/main/java/io/lbry/browser/MainActivity.java
index 793bf2a5..b9775219 100644
--- a/app/src/main/java/io/lbry/browser/MainActivity.java
+++ b/app/src/main/java/io/lbry/browser/MainActivity.java
@@ -36,7 +36,9 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.ext.cast.CastPlayer;
import com.google.android.exoplayer2.ui.PlayerView;
+import com.google.android.gms.cast.framework.CastContext;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.snackbar.Snackbar;
@@ -105,6 +107,7 @@ import io.lbry.browser.tasks.lbryinc.FetchRewardsTask;
import io.lbry.browser.tasks.LighthouseAutoCompleteTask;
import io.lbry.browser.tasks.MergeSubscriptionsTask;
import io.lbry.browser.tasks.claim.ResolveTask;
+import io.lbry.browser.tasks.localdata.FetchRecentUrlHistoryTask;
import io.lbry.browser.tasks.wallet.DefaultSyncTaskHandler;
import io.lbry.browser.tasks.wallet.LoadSharedUserStateTask;
import io.lbry.browser.tasks.wallet.SaveSharedUserStateTask;
@@ -140,6 +143,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private Map specialRouteFragmentClassMap;
private boolean inPictureInPictureMode;
public static SimpleExoPlayer appPlayer;
+ public static CastContext castContext;
+ public static CastPlayer castPlayer;
public static Claim nowPlayingClaim;
public static boolean startingFilePickerActivity = false;
public static boolean startingShareActivity = false;
@@ -225,7 +230,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private NavigationMenuAdapter navMenuAdapter;
private UrlSuggestionListAdapter urlSuggestionListAdapter;
- private List recentHistory;
+ private List recentUrlHistory;
private boolean hasLoadedFirstBalance;
// broadcast receivers
@@ -295,7 +300,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
initKeyStore();
loadAuthToken();
- dbHelper = new DatabaseHelper(this);
if (!isDarkMode()) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
@@ -315,6 +319,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
});
super.onCreate(savedInstanceState);
+ castContext = CastContext.getSharedInstance(this);
+ dbHelper = new DatabaseHelper(this);
checkNotificationOpenIntent(getIntent());
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
@@ -542,9 +548,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private Claim getCachedClaimForUrl(String url) {
ClaimCacheKey key = new ClaimCacheKey();
- key.setCanonicalUrl(url);
- key.setPermanentUrl(url);
- key.setShortUrl(url);
+ key.setUrl(url);
return Lbry.claimCache.containsKey(key) ? Lbry.claimCache.get(key) : null;
}
@@ -881,19 +885,25 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
for (int i = 0; i < claims.size(); i++) {
// build a simple url from the claim for matching
Claim claim = claims.get(i);
+ Claim actualClaim = claim;
+ boolean isRepost = false;
+ if (Claim.TYPE_REPOST.equalsIgnoreCase(claim.getValueType())) {
+ actualClaim = claim.getRepostedClaim();
+ isRepost = true;
+ }
if (Helper.isNullOrEmpty(claim.getName())) {
continue;
}
LbryUri simpleUrl = new LbryUri();
- if (claim.getName().startsWith("@")) {
+ if (actualClaim.getName().startsWith("@") && !isRepost) {
// channel
- simpleUrl.setChannelName(claim.getName());
+ simpleUrl.setChannelName(actualClaim.getName());
} else {
simpleUrl.setStreamName(claim.getName());
}
- urlSuggestionListAdapter.setClaimForUrl(simpleUrl, claim);
+ urlSuggestionListAdapter.setClaimForUrl(simpleUrl, actualClaim);
}
urlSuggestionListAdapter.notifyDataSetChanged();
}
@@ -909,10 +919,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
private void displayUrlSuggestionsForNoInput() {
urlSuggestionListAdapter.clear();
- List blankSuggestions = buildDefaultSuggestionsForBlankUrl();
- urlSuggestionListAdapter.addUrlSuggestions(blankSuggestions);
- List urls = urlSuggestionListAdapter.getItemUrls();
- resolveUrlSuggestions(urls);
+ loadDefaultSuggestionsForBlankUrl();
}
private void handleUriInputChanged(String text) {
@@ -948,25 +955,48 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- private List buildDefaultSuggestionsForBlankUrl() {
- List suggestions = new ArrayList<>();
- if (recentHistory != null && recentHistory.size() > 0) {
- // show recent history if avaiable
- suggestions = new ArrayList<>(recentHistory);
- } else {
- try {
- suggestions.add(new UrlSuggestion(
- UrlSuggestion.TYPE_FILE, "What is LBRY?", LbryUri.parse("lbry://what#19b9c243bea0c45175e6a6027911abbad53e983e")));
- suggestions.add(new UrlSuggestion(
- UrlSuggestion.TYPE_CHANNEL, "LBRYCast", LbryUri.parse("lbry://@lbrycast#4c29f8b013adea4d5cca1861fb2161d5089613ea")));
- suggestions.add(new UrlSuggestion(
- UrlSuggestion.TYPE_CHANNEL, "The LBRY Channel", LbryUri.parse("lbry://@lbry#3fda836a92faaceedfe398225fb9b2ee2ed1f01a")));
+ private void loadDefaultSuggestionsForBlankUrl() {
+ if (recentUrlHistory != null && recentUrlHistory.size() > 0) {
+ urlSuggestionListAdapter.addUrlSuggestions(recentUrlHistory);
+ }
+
+ FetchRecentUrlHistoryTask task = new FetchRecentUrlHistoryTask(DatabaseHelper.getInstance(), new FetchRecentUrlHistoryTask.FetchRecentUrlHistoryHandler() {
+ @Override
+ public void onSuccess(List recentHistory) {
+ List suggestions = new ArrayList<>(recentHistory);
+ List lbrySuggestions = buildLbryUrlSuggestions();
+ if (suggestions.size() < 10) {
+ for (int i = suggestions.size(), j = 0; i < 10 && j < lbrySuggestions.size(); i++, j++) {
+ suggestions.add(lbrySuggestions.get(j));
+ }
+ } else if (suggestions.size() == 0) {
+ suggestions.addAll(lbrySuggestions);
+ }
+
for (UrlSuggestion suggestion : suggestions) {
suggestion.setUseTextAsDescription(true);
}
- } catch (LbryUriException ex) {
- // pass
+
+ recentUrlHistory = new ArrayList<>(suggestions);
+ urlSuggestionListAdapter.clear();
+ urlSuggestionListAdapter.addUrlSuggestions(recentUrlHistory);
+ List urls = urlSuggestionListAdapter.getItemUrls();
+ resolveUrlSuggestions(urls);
}
+ });
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private List buildLbryUrlSuggestions() {
+ List suggestions = new ArrayList<>();
+ suggestions.add(new UrlSuggestion(
+ UrlSuggestion.TYPE_FILE, "What is LBRY?", LbryUri.tryParse("lbry://what#19b9c243bea0c45175e6a6027911abbad53e983e")));
+ suggestions.add(new UrlSuggestion(
+ UrlSuggestion.TYPE_CHANNEL, "LBRYCast", LbryUri.tryParse("lbry://@lbrycast#4c29f8b013adea4d5cca1861fb2161d5089613ea")));
+ suggestions.add(new UrlSuggestion(
+ UrlSuggestion.TYPE_CHANNEL, "The LBRY Channel", LbryUri.tryParse("lbry://@lbry#3fda836a92faaceedfe398225fb9b2ee2ed1f01a")));
+ for (UrlSuggestion suggestion : suggestions) {
+ suggestion.setUseTextAsDescription(true);
}
return suggestions;
}
@@ -975,7 +1005,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
List suggestions = new ArrayList();
if (LbryUri.PROTO_DEFAULT.equalsIgnoreCase(text)) {
- return buildDefaultSuggestionsForBlankUrl();
+ loadDefaultSuggestionsForBlankUrl();
+ return recentUrlHistory != null ? recentUrlHistory : new ArrayList<>();
}
// First item is always search
diff --git a/app/src/main/java/io/lbry/browser/adapter/UrlSuggestionListAdapter.java b/app/src/main/java/io/lbry/browser/adapter/UrlSuggestionListAdapter.java
index 1ebf542e..cc2a09ea 100644
--- a/app/src/main/java/io/lbry/browser/adapter/UrlSuggestionListAdapter.java
+++ b/app/src/main/java/io/lbry/browser/adapter/UrlSuggestionListAdapter.java
@@ -16,6 +16,7 @@ import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.UrlSuggestion;
import io.lbry.browser.ui.controls.SolidIconView;
+import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.LbryUri;
import lombok.Setter;
@@ -96,7 +97,7 @@ public class UrlSuggestionListAdapter extends RecyclerView.Adapter> {
}
protected List doInBackground(Void... params) {
try {
- return Lbry.claimSearch(options, connectionString);
+ return Helper.filterInvalidReposts(Lbry.claimSearch(options, connectionString));
} catch (ApiCallException ex) {
error = ex;
return null;
diff --git a/app/src/main/java/io/lbry/browser/tasks/claim/ResolveTask.java b/app/src/main/java/io/lbry/browser/tasks/claim/ResolveTask.java
index 5cab8c93..120c36b7 100644
--- a/app/src/main/java/io/lbry/browser/tasks/claim/ResolveTask.java
+++ b/app/src/main/java/io/lbry/browser/tasks/claim/ResolveTask.java
@@ -34,7 +34,7 @@ public class ResolveTask extends AsyncTask> {
}
protected List doInBackground(Void... params) {
try {
- return Lbry.resolve(urls, connectionString);
+ return Helper.filterInvalidReposts(Lbry.resolve(urls, connectionString));
} catch (ApiCallException ex) {
error = ex;
return null;
diff --git a/app/src/main/java/io/lbry/browser/tasks/localdata/FetchRecentUrlHistoryTask.java b/app/src/main/java/io/lbry/browser/tasks/localdata/FetchRecentUrlHistoryTask.java
new file mode 100644
index 00000000..852e87ae
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/tasks/localdata/FetchRecentUrlHistoryTask.java
@@ -0,0 +1,37 @@
+package io.lbry.browser.tasks.localdata;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.os.AsyncTask;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.lbry.browser.data.DatabaseHelper;
+import io.lbry.browser.model.UrlSuggestion;
+
+public class FetchRecentUrlHistoryTask extends AsyncTask> {
+ private DatabaseHelper dbHelper;
+ private FetchRecentUrlHistoryHandler handler;
+ public FetchRecentUrlHistoryTask(DatabaseHelper dbHelper, FetchRecentUrlHistoryHandler handler) {
+ this.dbHelper = dbHelper;
+ this.handler = handler;
+ }
+ protected List doInBackground(Void... params) {
+ try {
+ SQLiteDatabase db = dbHelper.getReadableDatabase();
+ return DatabaseHelper.getRecentHistory(db);
+ } catch (SQLiteException ex) {
+ return new ArrayList<>();
+ }
+ }
+ protected void onPostExecute(List recentHistory) {
+ if (handler != null) {
+ handler.onSuccess(recentHistory);
+ }
+ }
+
+ public interface FetchRecentUrlHistoryHandler {
+ void onSuccess(List recentHistory);
+ }
+}
diff --git a/app/src/main/java/io/lbry/browser/tasks/localdata/CreateUrlHistoryTask.java b/app/src/main/java/io/lbry/browser/tasks/localdata/SaveUrlHistoryTask.java
similarity index 64%
rename from app/src/main/java/io/lbry/browser/tasks/localdata/CreateUrlHistoryTask.java
rename to app/src/main/java/io/lbry/browser/tasks/localdata/SaveUrlHistoryTask.java
index f74683eb..a5778984 100644
--- a/app/src/main/java/io/lbry/browser/tasks/localdata/CreateUrlHistoryTask.java
+++ b/app/src/main/java/io/lbry/browser/tasks/localdata/SaveUrlHistoryTask.java
@@ -9,21 +9,21 @@ import io.lbry.browser.data.DatabaseHelper;
import io.lbry.browser.model.UrlSuggestion;
import io.lbry.browser.tasks.GenericTaskHandler;
-public class CreateUrlHistoryTask extends AsyncTask {
- private Context context;
+public class SaveUrlHistoryTask extends AsyncTask {
+ private DatabaseHelper dbHelper;
private UrlSuggestion suggestion;
- private GenericTaskHandler handler;
+ private SaveUrlHistoryHandler handler;
private Exception error;
- public CreateUrlHistoryTask(UrlSuggestion suggestion, Context context, GenericTaskHandler handler) {
+ public SaveUrlHistoryTask(UrlSuggestion suggestion, DatabaseHelper dbHelper, SaveUrlHistoryHandler handler) {
this.suggestion = suggestion;
- this.context = context;
+ this.dbHelper = dbHelper;
this.handler = handler;
}
protected Boolean doInBackground(Void... params) {
try {
- SQLiteDatabase db = ((MainActivity) context).getDbHelper().getWritableDatabase();
+ SQLiteDatabase db = dbHelper.getWritableDatabase();
DatabaseHelper.createOrUpdateUrlHistoryItem(suggestion.getText(), suggestion.getUri().toString(), suggestion.getType(), db);
} catch (Exception ex) {
error = ex;
@@ -35,10 +35,15 @@ public class CreateUrlHistoryTask extends AsyncTask {
protected void onPostExecute(Boolean result) {
if (handler != null) {
if (result) {
- handler.onSuccess();
+ handler.onSuccess(suggestion);
} else {
handler.onError(error);
}
}
}
+
+ public interface SaveUrlHistoryHandler {
+ void onSuccess(UrlSuggestion item);
+ void onError(Exception error);
+ }
}
diff --git a/app/src/main/java/io/lbry/browser/tasks/localdata/SaveViewHistoryTask.java b/app/src/main/java/io/lbry/browser/tasks/localdata/SaveViewHistoryTask.java
new file mode 100644
index 00000000..097d5a13
--- /dev/null
+++ b/app/src/main/java/io/lbry/browser/tasks/localdata/SaveViewHistoryTask.java
@@ -0,0 +1,4 @@
+package io.lbry.browser.tasks.localdata;
+
+public class SaveViewHistoryTask {
+}
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 d08d2539..75d2a41b 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
@@ -31,10 +31,13 @@ import java.util.Map;
import io.lbry.browser.MainActivity;
import io.lbry.browser.R;
+import io.lbry.browser.data.DatabaseHelper;
import io.lbry.browser.dialog.SendTipDialogFragment;
import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.listener.FetchChannelsListener;
import io.lbry.browser.model.Claim;
+import io.lbry.browser.model.ClaimCacheKey;
+import io.lbry.browser.model.UrlSuggestion;
import io.lbry.browser.model.lbryinc.Subscription;
import io.lbry.browser.tasks.lbryinc.ChannelSubscribeTask;
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
@@ -296,13 +299,24 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
if (updateRequired) {
resetSubCount();
if (!Helper.isNullOrEmpty(url)) {
- resolveUrl();
+ // check if the claim is already cached
+ ClaimCacheKey key = new ClaimCacheKey();
+ key.setUrl(url);
+ if (Lbry.claimCache.containsKey(key)) {
+ claim = Lbry.claimCache.get(key);
+ } else {
+ resolveUrl();
+ }
} else if (claim == null) {
// nothing at this location
renderNothingAtLocation();
}
}
+ if (!Helper.isNullOrEmpty(url)) {
+ Helper.saveUrlHistory(url, claim != null ? claim.getTitle() : null, UrlSuggestion.TYPE_CHANNEL);
+ }
+
if (claim != null) {
renderClaim();
}
@@ -315,6 +329,10 @@ public class ChannelFragment extends BaseFragment implements FetchChannelsListen
public void onSuccess(List claims) {
if (claims.size() > 0 && !Helper.isNullOrEmpty(claims.get(0).getClaimId())) {
claim = claims.get(0);
+ if (!Helper.isNullOrEmpty(url)) {
+ Helper.saveUrlHistory(url, claim.getTitle(), UrlSuggestion.TYPE_CHANNEL);
+ }
+
renderClaim();
checkOwnChannel();
} else {
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 feeb6545..0b148416 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
@@ -141,7 +141,7 @@ public class SearchFragment extends BaseFragment implements
private void resolveFeaturedItem(String vanityUrl) {
final ClaimCacheKey key = new ClaimCacheKey();
- key.setVanityUrl(vanityUrl);
+ key.setUrl(vanityUrl);
if (Lbry.claimCache.containsKey(key)) {
Claim cachedClaim = Lbry.claimCache.get(key);
updateFeaturedItemFromResolvedClaim(cachedClaim);
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 18673b39..4a7165d1 100644
--- a/app/src/main/java/io/lbry/browser/utils/Helper.java
+++ b/app/src/main/java/io/lbry/browser/utils/Helper.java
@@ -12,6 +12,7 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
@@ -40,10 +41,13 @@ import java.util.Map;
import java.util.Random;
import io.lbry.browser.MainActivity;
+import io.lbry.browser.data.DatabaseHelper;
import io.lbry.browser.dialog.ContentFromDialogFragment;
import io.lbry.browser.dialog.ContentSortDialogFragment;
import io.lbry.browser.model.Claim;
import io.lbry.browser.model.Tag;
+import io.lbry.browser.model.UrlSuggestion;
+import io.lbry.browser.tasks.localdata.SaveUrlHistoryTask;
import okhttp3.MediaType;
public final class Helper {
@@ -555,4 +559,26 @@ public final class Helper {
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(HtmlCompat.fromHtml(textView.getText().toString(), HtmlCompat.FROM_HTML_MODE_LEGACY));
}
+
+ public static List filterInvalidReposts(List claims) {
+ List filtered = new ArrayList<>();
+ for (Claim claim : claims) {
+ if (Claim.TYPE_REPOST.equalsIgnoreCase(claim.getValueType()) && claim.getRepostedClaim() == null) {
+ continue;
+ }
+ filtered.add(claim);
+ }
+ return filtered;
+ }
+
+ public static void saveUrlHistory(String url, String title, int type) {
+ DatabaseHelper dbHelper = DatabaseHelper.getInstance();
+ if (dbHelper != null) {
+ UrlSuggestion suggestion = new UrlSuggestion();
+ suggestion.setUri(LbryUri.tryParse(url));
+ suggestion.setType(type);
+ suggestion.setText(Helper.isNull(title) ? "" : title);
+ new SaveUrlHistoryTask(suggestion, dbHelper, null).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
}
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 3b793d6d..0982ff1d 100644
--- a/app/src/main/java/io/lbry/browser/utils/Lbry.java
+++ b/app/src/main/java/io/lbry/browser/utils/Lbry.java
@@ -250,9 +250,7 @@ public final class Lbry {
Claim claim = Claim.fromJSONObject(result.getJSONObject(keys.next()));
claims.add(claim);
- // TODO: Add/remove/prune entries claim cache management
- ClaimCacheKey key = ClaimCacheKey.fromClaim(claim);
- claimCache.put(key, claim);
+ addClaimToCache(claim);
}
}
} catch (LbryRequestException | LbryResponseException | JSONException ex) {
@@ -396,8 +394,7 @@ public final class Lbry {
Claim claim = Claim.fromJSONObject(items.getJSONObject(i));
claims.add(claim);
- ClaimCacheKey key = ClaimCacheKey.fromClaim(claim);
- claimCache.put(key, claim);
+ addClaimToCache(claim);
}
}
@@ -452,4 +449,15 @@ public final class Lbry {
}
}
}
+
+ public static void addClaimToCache(Claim claim) {
+ ClaimCacheKey fullKey = ClaimCacheKey.fromClaim(claim);
+ ClaimCacheKey shortUrlKey = ClaimCacheKey.fromClaimShortUrl(claim);
+ ClaimCacheKey permanentUrlKey = ClaimCacheKey.fromClaimPermanentUrl(claim);
+ claimCache.put(fullKey, claim);
+ claimCache.put(permanentUrlKey, claim);
+ if (!Helper.isNullOrEmpty(shortUrlKey.getUrl())) {
+ claimCache.put(shortUrlKey, claim);
+ }
+ }
}
diff --git a/app/src/main/res/drawable-anydpi/ic_cast.xml b/app/src/main/res/drawable-anydpi/ic_cast.xml
new file mode 100644
index 00000000..da0e952f
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_cast.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_cast_connected.xml b/app/src/main/res/drawable-anydpi/ic_cast_connected.xml
new file mode 100644
index 00000000..491bf6c8
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_cast_connected.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_cast.png b/app/src/main/res/drawable-hdpi/ic_cast.png
new file mode 100644
index 00000000..5449b8f5
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_cast.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_cast_connected.png b/app/src/main/res/drawable-hdpi/ic_cast_connected.png
new file mode 100644
index 00000000..55bddaad
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_cast_connected.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_cast.png b/app/src/main/res/drawable-mdpi/ic_cast.png
new file mode 100644
index 00000000..60bb5f50
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_cast.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_cast_connected.png b/app/src/main/res/drawable-mdpi/ic_cast_connected.png
new file mode 100644
index 00000000..b4b72ba3
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_cast_connected.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_cast.png b/app/src/main/res/drawable-xhdpi/ic_cast.png
new file mode 100644
index 00000000..fdde81a4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_cast.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_cast_connected.png b/app/src/main/res/drawable-xhdpi/ic_cast_connected.png
new file mode 100644
index 00000000..bcc195dc
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_cast_connected.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_cast.png b/app/src/main/res/drawable-xxhdpi/ic_cast.png
new file mode 100644
index 00000000..62fc53f7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_cast.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_cast_connected.png b/app/src/main/res/drawable-xxhdpi/ic_cast_connected.png
new file mode 100644
index 00000000..a28df6de
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_cast_connected.png differ
diff --git a/app/src/main/res/layout/activity_file_view.xml b/app/src/main/res/layout/activity_file_view.xml
index 61767607..6afd90ef 100644
--- a/app/src/main/res/layout/activity_file_view.xml
+++ b/app/src/main/res/layout/activity_file_view.xml
@@ -162,9 +162,15 @@
android:layout_height="wrap_content" />
-
+
+
-
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index 7a78d484..b147284d 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -20,9 +20,9 @@
android:id="@+id/url_suggestions_container"
android:background="@color/pageBackground"
android:elevation="6dp"
+ android:visibility="gone"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone">
+ android:layout_height="match_parent">
+
+
+
+
Delete file
Are you sure you want to remove this file from your device?
Failed to load %1$s. Please try again later.
+ There is no cast session available at this time.
- %1$s view
- %1$s views