Native rewrite #878
|
@ -20,6 +20,9 @@
|
|||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
|
||||
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@drawable/ic_lbry" />
|
||||
|
@ -39,7 +42,7 @@
|
|||
android:supportsPictureInPicture="true"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
|
@ -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<String> categories = baseIntent.getCategories();
|
||||
if (categories != null && categories.contains(Intent.CATEGORY_LAUNCHER)) {
|
||||
task.moveToFront();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, Class> 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<UrlSuggestion> recentHistory;
|
||||
private List<UrlSuggestion> 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<UrlSuggestion> blankSuggestions = buildDefaultSuggestionsForBlankUrl();
|
||||
urlSuggestionListAdapter.addUrlSuggestions(blankSuggestions);
|
||||
List<String> 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<UrlSuggestion> buildDefaultSuggestionsForBlankUrl() {
|
||||
List<UrlSuggestion> 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<UrlSuggestion> recentHistory) {
|
||||
List<UrlSuggestion> suggestions = new ArrayList<>(recentHistory);
|
||||
List<UrlSuggestion> 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<String> urls = urlSuggestionListAdapter.getItemUrls();
|
||||
resolveUrlSuggestions(urls);
|
||||
}
|
||||
});
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private List<UrlSuggestion> buildLbryUrlSuggestions() {
|
||||
List<UrlSuggestion> 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<UrlSuggestion> suggestions = new ArrayList<UrlSuggestion>();
|
||||
|
||||
if (LbryUri.PROTO_DEFAULT.equalsIgnoreCase(text)) {
|
||||
return buildDefaultSuggestionsForBlankUrl();
|
||||
loadDefaultSuggestionsForBlankUrl();
|
||||
return recentUrlHistory != null ? recentUrlHistory : new ArrayList<>();
|
||||
}
|
||||
|
||||
// First item is always search
|
||||
|
|
|
@ -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<UrlSuggestion
|
|||
iconStringId = R.string.fa_at;
|
||||
fullTitle = item.getTitle();
|
||||
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
||||
(item.isUseTextAsDescription() ? item.getText() : String.format(context.getString(R.string.view_channel_url_desc), item.getText()));
|
||||
((item.isUseTextAsDescription() && !Helper.isNullOrEmpty(item.getText())) ? item.getText() : String.format(context.getString(R.string.view_channel_url_desc), item.getText()));
|
||||
break;
|
||||
case UrlSuggestion.TYPE_TAG:
|
||||
iconStringId = R.string.fa_hashtag;
|
||||
|
@ -113,7 +114,7 @@ public class UrlSuggestionListAdapter extends RecyclerView.Adapter<UrlSuggestion
|
|||
iconStringId = R.string.fa_file;
|
||||
fullTitle = item.getTitle();
|
||||
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
||||
(item.isUseTextAsDescription() ? item.getText() : String.format(context.getString(R.string.view_file_url_desc), item.getText()));
|
||||
((item.isUseTextAsDescription() && !Helper.isNullOrEmpty(item.getText())) ? item.getText() : String.format(context.getString(R.string.view_file_url_desc), item.getText()));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.lbry.browser.utils.LbryUri;
|
|||
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
public static final int DATABASE_VERSION = 1;
|
||||
public static final String DATABASE_NAME = "LbryApp.db";
|
||||
private static DatabaseHelper instance;
|
||||
|
||||
private static final String[] SQL_CREATE_TABLES = {
|
||||
// local subscription store
|
||||
|
@ -58,7 +59,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
private static final String SQL_DELETE_SUBSCRIPTION = "DELETE FROM subscriptions WHERE url = ?";
|
||||
private static final String SQL_GET_SUBSCRIPTIONS = "SELECT channel_name, url FROM subscriptions";
|
||||
|
||||
private static final String SQL_INSERT_URL_HISTORY = "REPLACE INTO url_history (value, url, type, timestamp) VALUES (?, ?, ?)";
|
||||
private static final String SQL_INSERT_URL_HISTORY = "REPLACE INTO url_history (value, url, type, timestamp) VALUES (?, ?, ?, ?)";
|
||||
private static final String SQL_CLEAR_URL_HISTORY = "DELETE FROM url_history";
|
||||
private static final String SQL_CLEAR_URL_HISTORY_BEFORE_TIME = "DELETE FROM url_history WHERE timestamp < ?";
|
||||
private static final String SQL_GET_RECENT_URL_HISTORY = "SELECT value, url, type FROM url_history ORDER BY timestamp DESC LIMIT 10";
|
||||
|
@ -77,6 +78,10 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, String.format("%s/%s", context.getFilesDir().getAbsolutePath(), DATABASE_NAME), null, DATABASE_VERSION);
|
||||
instance = this;
|
||||
}
|
||||
public static DatabaseHelper getInstance() {
|
||||
return instance;
|
||||
}
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
for (String sql : SQL_CREATE_TABLES) {
|
||||
|
@ -113,13 +118,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
|||
while (cursor.moveToNext()) {
|
||||
UrlSuggestion suggestion = new UrlSuggestion();
|
||||
suggestion.setText(cursor.getString(0));
|
||||
suggestion.setUri(cursor.isNull(1) ? null : LbryUri.tryParse(cursor.getString(1)));
|
||||
suggestion.setType(cursor.getInt(2));
|
||||
|
||||
try {
|
||||
suggestion.setUri(cursor.isNull(1) ? null : LbryUri.parse(cursor.getString(1)));
|
||||
} catch (LbryUriException ex) {
|
||||
// don't fail if the LbryUri is invalid
|
||||
}
|
||||
suggestion.setTitleUrlOnly(true);
|
||||
suggestions.add(suggestion);
|
||||
}
|
||||
} finally {
|
||||
|
|
|
@ -372,9 +372,10 @@ public class Claim {
|
|||
Claim signingChannel = new Claim();
|
||||
signingChannel.setClaimId(searchResultObject.getString("channel_claim_id"));
|
||||
signingChannel.setName(searchResultObject.getString("channel"));
|
||||
|
||||
claimUri.setChannelClaimId(signingChannel.getClaimId());
|
||||
claimUri.setChannelName(signingChannel.getName());
|
||||
LbryUri channelUri = new LbryUri();
|
||||
channelUri.setChannelClaimId(signingChannel.getClaimId());
|
||||
channelUri.setChannelName(signingChannel.getName());
|
||||
signingChannel.setPermanentUrl(channelUri.toString());
|
||||
|
||||
claim.setSigningChannel(signingChannel);
|
||||
}
|
||||
|
|
|
@ -5,34 +5,36 @@ import androidx.annotation.Nullable;
|
|||
import io.lbry.browser.utils.Helper;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Class to represent a key to check equality with another object
|
||||
*/
|
||||
@ToString
|
||||
public class ClaimCacheKey {
|
||||
@Getter
|
||||
@Setter
|
||||
private String claimId;
|
||||
@Getter
|
||||
@Setter
|
||||
private String canonicalUrl;
|
||||
@Getter
|
||||
@Setter
|
||||
private String permanentUrl;
|
||||
@Getter
|
||||
@Setter
|
||||
private String shortUrl;
|
||||
@Getter
|
||||
@Setter
|
||||
private String vanityUrl;
|
||||
private String url;
|
||||
|
||||
public static ClaimCacheKey fromClaimShortUrl(Claim claim) {
|
||||
ClaimCacheKey key = new ClaimCacheKey();
|
||||
key.setUrl(claim.getShortUrl());
|
||||
return key;
|
||||
}
|
||||
|
||||
public static ClaimCacheKey fromClaimPermanentUrl(Claim claim) {
|
||||
ClaimCacheKey key = new ClaimCacheKey();
|
||||
key.setUrl(claim.getPermanentUrl());
|
||||
return key;
|
||||
}
|
||||
|
||||
public static ClaimCacheKey fromClaim(Claim claim) {
|
||||
ClaimCacheKey key = new ClaimCacheKey();
|
||||
key.setClaimId(claim.getClaimId());
|
||||
key.setCanonicalUrl(claim.getCanonicalUrl());
|
||||
key.setPermanentUrl(claim.getPermanentUrl());
|
||||
key.setShortUrl(claim.getShortUrl());
|
||||
|
||||
key.setUrl(!Helper.isNullOrEmpty(claim.getShortUrl()) ? claim.getShortUrl() : claim.getPermanentUrl());
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -41,44 +43,24 @@ public class ClaimCacheKey {
|
|||
if (obj == null || !(obj instanceof ClaimCacheKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClaimCacheKey key = (ClaimCacheKey) obj;
|
||||
if (!Helper.isNullOrEmpty(claimId) && !Helper.isNullOrEmpty(key.getClaimId())) {
|
||||
return claimId.equalsIgnoreCase(key.getClaimId());
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(permanentUrl) && !Helper.isNullOrEmpty(key.getPermanentUrl())) {
|
||||
return permanentUrl.equalsIgnoreCase(key.getPermanentUrl());
|
||||
if (!Helper.isNullOrEmpty(url) && !Helper.isNullOrEmpty(key.getUrl())) {
|
||||
return url.equalsIgnoreCase(key.getUrl());
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(canonicalUrl) && !Helper.isNullOrEmpty(key.getCanonicalUrl())) {
|
||||
return canonicalUrl.equalsIgnoreCase(key.getCanonicalUrl());
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(shortUrl) && !Helper.isNullOrEmpty(key.getShortUrl())) {
|
||||
return shortUrl.equalsIgnoreCase(key.getShortUrl());
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(vanityUrl) && !Helper.isNullOrEmpty(key.getVanityUrl())) {
|
||||
return vanityUrl.equalsIgnoreCase(key.getVanityUrl());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (!Helper.isNullOrEmpty(url)) {
|
||||
return url.hashCode();
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(claimId)) {
|
||||
return claimId.hashCode();
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(permanentUrl)) {
|
||||
return permanentUrl.hashCode();
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(canonicalUrl)) {
|
||||
return canonicalUrl.hashCode();
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(shortUrl)) {
|
||||
return shortUrl.hashCode();
|
||||
}
|
||||
if (!Helper.isNullOrEmpty(vanityUrl)) {
|
||||
return vanityUrl.hashCode();
|
||||
}
|
||||
|
||||
return super.hashCode();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public class UrlSuggestion {
|
|||
private LbryUri uri;
|
||||
private Claim claim; // associated claim if resolved
|
||||
private boolean titleTextOnly;
|
||||
private boolean titleUrlOnly;
|
||||
private boolean useTextAsDescription;
|
||||
|
||||
public UrlSuggestion() {
|
||||
|
@ -34,6 +35,10 @@ public class UrlSuggestion {
|
|||
}
|
||||
|
||||
public String getTitle() {
|
||||
if (titleUrlOnly && (type == TYPE_CHANNEL || type == TYPE_FILE)) {
|
||||
return uri.toString();
|
||||
}
|
||||
|
||||
if (!titleTextOnly) {
|
||||
switch (type) {
|
||||
case TYPE_CHANNEL:
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ClaimSearchTask extends AsyncTask<Void, Void, List<Claim>> {
|
|||
}
|
||||
protected List<Claim> doInBackground(Void... params) {
|
||||
try {
|
||||
return Lbry.claimSearch(options, connectionString);
|
||||
return Helper.filterInvalidReposts(Lbry.claimSearch(options, connectionString));
|
||||
} catch (ApiCallException ex) {
|
||||
error = ex;
|
||||
return null;
|
||||
|
|
|
@ -34,7 +34,7 @@ public class ResolveTask extends AsyncTask<Void, Void, List<Claim>> {
|
|||
}
|
||||
protected List<Claim> doInBackground(Void... params) {
|
||||
try {
|
||||
return Lbry.resolve(urls, connectionString);
|
||||
return Helper.filterInvalidReposts(Lbry.resolve(urls, connectionString));
|
||||
} catch (ApiCallException ex) {
|
||||
error = ex;
|
||||
return null;
|
||||
|
|
|
@ -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<Void, Void, List<UrlSuggestion>> {
|
||||
private DatabaseHelper dbHelper;
|
||||
private FetchRecentUrlHistoryHandler handler;
|
||||
public FetchRecentUrlHistoryTask(DatabaseHelper dbHelper, FetchRecentUrlHistoryHandler handler) {
|
||||
this.dbHelper = dbHelper;
|
||||
this.handler = handler;
|
||||
}
|
||||
protected List<UrlSuggestion> doInBackground(Void... params) {
|
||||
try {
|
||||
SQLiteDatabase db = dbHelper.getReadableDatabase();
|
||||
return DatabaseHelper.getRecentHistory(db);
|
||||
} catch (SQLiteException ex) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
protected void onPostExecute(List<UrlSuggestion> recentHistory) {
|
||||
if (handler != null) {
|
||||
handler.onSuccess(recentHistory);
|
||||
}
|
||||
}
|
||||
|
||||
public interface FetchRecentUrlHistoryHandler {
|
||||
void onSuccess(List<UrlSuggestion> recentHistory);
|
||||
}
|
||||
}
|
|
@ -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<Void, Void, Boolean> {
|
||||
private Context context;
|
||||
public class SaveUrlHistoryTask extends AsyncTask<Void, Void, Boolean> {
|
||||
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<Void, Void, Boolean> {
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package io.lbry.browser.tasks.localdata;
|
||||
|
||||
public class SaveViewHistoryTask {
|
||||
}
|
|
@ -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<Claim> 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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Claim> filterInvalidReposts(List<Claim> claims) {
|
||||
List<Claim> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
app/src/main/res/drawable-anydpi/ic_cast.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z"/>
|
||||
</vector>
|
11
app/src/main/res/drawable-anydpi/ic_cast_connected.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:alpha="0.8">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM19,7L5,7v1.63c3.96,1.28 7.09,4.41 8.37,8.37L19,17L19,7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11zM21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable-hdpi/ic_cast.png
Normal file
After Width: | Height: | Size: 410 B |
BIN
app/src/main/res/drawable-hdpi/ic_cast_connected.png
Normal file
After Width: | Height: | Size: 477 B |
BIN
app/src/main/res/drawable-mdpi/ic_cast.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
app/src/main/res/drawable-mdpi/ic_cast_connected.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
app/src/main/res/drawable-xhdpi/ic_cast.png
Normal file
After Width: | Height: | Size: 497 B |
BIN
app/src/main/res/drawable-xhdpi/ic_cast_connected.png
Normal file
After Width: | Height: | Size: 563 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_cast.png
Normal file
After Width: | Height: | Size: 750 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_cast_connected.png
Normal file
After Width: | Height: | Size: 867 B |
|
@ -162,9 +162,15 @@
|
|||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.exoplayer2.ui.PlayerControlView android:id="@+id/file_view_cast_control_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:repeat_toggle_modes="all|one"
|
||||
app:show_timeout="-1"/>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/file_view_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
|
|
@ -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">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/url_suggestions"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -21,7 +21,25 @@
|
|||
style="@style/ExoMediaButton.Pause" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_toggle_full_screen"
|
||||
android:id="@+id/player_toggle_cast"
|
||||
android:clickable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:visibility="gone">
|
||||
<ImageView
|
||||
android:id="@+id/player_image_cast_toggle"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/ic_cast"
|
||||
android:tint="@color/white" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_toggle_fullscreen"
|
||||
android:clickable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:layout_width="48dp"
|
||||
|
@ -41,7 +59,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toLeftOf="@id/player_toggle_full_screen"
|
||||
android:layout_toLeftOf="@id/player_toggle_fullscreen"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="4dp">
|
||||
<TextView
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<string name="delete_file">Delete file</string>
|
||||
<string name="confirm_delete_file_message">Are you sure you want to remove this file from your device?</string>
|
||||
<string name="unable_to_view_url">Failed to load %1$s. Please try again later.</string>
|
||||
<string name="no_cast_session_available">There is no cast session available at this time.</string>
|
||||
<plurals name="view_count">
|
||||
<item quantity="one">%1$s view</item>
|
||||
<item quantity="other">%1$s views</item>
|
||||
|
|