Finish Following and All Content views. Add customize your tags view.
This commit is contained in:
parent
59584c1be7
commit
1d1c761d3f
41 changed files with 1761 additions and 169 deletions
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
@ -18,6 +19,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.widget.NestedScrollView;
|
import androidx.core.widget.NestedScrollView;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -292,11 +294,13 @@ public class FileViewActivity extends AppCompatActivity {
|
||||||
TagListAdapter tagListAdapter = new TagListAdapter(tags, this);
|
TagListAdapter tagListAdapter = new TagListAdapter(tags, this);
|
||||||
tagListAdapter.setClickListener(new TagListAdapter.TagClickListener() {
|
tagListAdapter.setClickListener(new TagListAdapter.TagClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTagClicked(Tag tag) {
|
public void onTagClicked(Tag tag, int customizeMode) {
|
||||||
Intent intent = new Intent(MainActivity.ACTION_OPEN_ALL_CONTENT_TAG);
|
if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_NONE) {
|
||||||
intent.putExtra("tag", tag.getName());
|
Intent intent = new Intent(MainActivity.ACTION_OPEN_ALL_CONTENT_TAG);
|
||||||
sendBroadcast(intent);
|
intent.putExtra("tag", tag.getName());
|
||||||
moveTaskToBack(true);
|
sendBroadcast(intent);
|
||||||
|
moveTaskToBack(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
descTagsList.setAdapter(tagListAdapter);
|
descTagsList.setAdapter(tagListAdapter);
|
||||||
|
@ -378,7 +382,11 @@ public class FileViewActivity extends AppCompatActivity {
|
||||||
String title = claim.getTitle();
|
String title = claim.getTitle();
|
||||||
String claimId = claim.getClaimId();
|
String claimId = claim.getClaimId();
|
||||||
ProgressBar relatedLoading = findViewById(R.id.file_view_related_content_progress);
|
ProgressBar relatedLoading = findViewById(R.id.file_view_related_content_progress);
|
||||||
LighthouseSearchTask relatedTask = new LighthouseSearchTask(title, RELATED_CONTENT_SIZE, 0, false, claimId, relatedLoading, new ClaimSearchTask.ClaimSearchResultHandler() {
|
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
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() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
|
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
|
||||||
List<Claim> filteredClaims = new ArrayList<>();
|
List<Claim> filteredClaims = new ArrayList<>();
|
||||||
|
|
|
@ -12,6 +12,7 @@ import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -20,7 +21,6 @@ import android.os.Handler;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
@ -63,6 +63,7 @@ import java.io.InputStreamReader;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -73,12 +74,13 @@ import java.util.concurrent.TimeUnit;
|
||||||
import io.lbry.browser.adapter.NavigationMenuAdapter;
|
import io.lbry.browser.adapter.NavigationMenuAdapter;
|
||||||
import io.lbry.browser.adapter.UrlSuggestionListAdapter;
|
import io.lbry.browser.adapter.UrlSuggestionListAdapter;
|
||||||
import io.lbry.browser.data.DatabaseHelper;
|
import io.lbry.browser.data.DatabaseHelper;
|
||||||
import io.lbry.browser.exceptions.ApiCallException;
|
import io.lbry.browser.exceptions.LbryUriException;
|
||||||
import io.lbry.browser.listener.SdkStatusListener;
|
import io.lbry.browser.listener.SdkStatusListener;
|
||||||
import io.lbry.browser.listener.WalletBalanceListener;
|
import io.lbry.browser.listener.WalletBalanceListener;
|
||||||
import io.lbry.browser.model.Claim;
|
import io.lbry.browser.model.Claim;
|
||||||
import io.lbry.browser.model.ClaimCacheKey;
|
import io.lbry.browser.model.ClaimCacheKey;
|
||||||
import io.lbry.browser.model.NavMenuItem;
|
import io.lbry.browser.model.NavMenuItem;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
import io.lbry.browser.model.UrlSuggestion;
|
import io.lbry.browser.model.UrlSuggestion;
|
||||||
import io.lbry.browser.model.WalletBalance;
|
import io.lbry.browser.model.WalletBalance;
|
||||||
import io.lbry.browser.model.WalletSync;
|
import io.lbry.browser.model.WalletSync;
|
||||||
|
@ -87,7 +89,6 @@ import io.lbry.browser.tasks.LighthouseAutoCompleteTask;
|
||||||
import io.lbry.browser.tasks.ResolveTask;
|
import io.lbry.browser.tasks.ResolveTask;
|
||||||
import io.lbry.browser.tasks.wallet.DefaultSyncTaskHandler;
|
import io.lbry.browser.tasks.wallet.DefaultSyncTaskHandler;
|
||||||
import io.lbry.browser.tasks.wallet.SyncGetTask;
|
import io.lbry.browser.tasks.wallet.SyncGetTask;
|
||||||
import io.lbry.browser.tasks.wallet.SyncTaskHandler;
|
|
||||||
import io.lbry.browser.tasks.wallet.WalletBalanceTask;
|
import io.lbry.browser.tasks.wallet.WalletBalanceTask;
|
||||||
import io.lbry.browser.ui.BaseFragment;
|
import io.lbry.browser.ui.BaseFragment;
|
||||||
import io.lbry.browser.ui.channel.ChannelFragment;
|
import io.lbry.browser.ui.channel.ChannelFragment;
|
||||||
|
@ -103,6 +104,7 @@ import io.lbry.browser.utils.Lbryio;
|
||||||
import io.lbry.lbrysdk.LbrynetService;
|
import io.lbry.lbrysdk.LbrynetService;
|
||||||
import io.lbry.lbrysdk.ServiceHelper;
|
import io.lbry.lbrysdk.ServiceHelper;
|
||||||
import io.lbry.lbrysdk.Utils;
|
import io.lbry.lbrysdk.Utils;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements SdkStatusListener {
|
public class MainActivity extends AppCompatActivity implements SdkStatusListener {
|
||||||
|
@ -141,6 +143,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
|
|
||||||
// preference keys
|
// preference keys
|
||||||
public static final String PREFERENCE_KEY_DARK_MODE = "io.lbry.browser.preference.userinterface.DarkMode";
|
public static final String PREFERENCE_KEY_DARK_MODE = "io.lbry.browser.preference.userinterface.DarkMode";
|
||||||
|
public static final String PREFERENCE_KEY_SHOW_MATURE_CONTENT = "io.lbry.browser.preference.userinterface.ShowMatureContent";
|
||||||
public static final String PREFERENCE_KEY_NOTIFICATION_URL_SUGGESTIONS = "io.lbry.browser.preference.userinterface.UrlSuggestions";
|
public static final String PREFERENCE_KEY_NOTIFICATION_URL_SUGGESTIONS = "io.lbry.browser.preference.userinterface.UrlSuggestions";
|
||||||
public static final String PREFERENCE_KEY_NOTIFICATION_SUBSCRIPTIONS = "io.lbry.browser.preference.notifications.Subscriptions";
|
public static final String PREFERENCE_KEY_NOTIFICATION_SUBSCRIPTIONS = "io.lbry.browser.preference.notifications.Subscriptions";
|
||||||
public static final String PREFERENCE_KEY_NOTIFICATION_REWARDS = "io.lbry.browser.preference.notifications.Rewards";
|
public static final String PREFERENCE_KEY_NOTIFICATION_REWARDS = "io.lbry.browser.preference.notifications.Rewards";
|
||||||
|
@ -164,6 +167,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
|
|
||||||
private NavigationMenuAdapter navMenuAdapter;
|
private NavigationMenuAdapter navMenuAdapter;
|
||||||
private UrlSuggestionListAdapter urlSuggestionListAdapter;
|
private UrlSuggestionListAdapter urlSuggestionListAdapter;
|
||||||
|
private List<UrlSuggestion> recentHistory;
|
||||||
|
|
||||||
// broadcast receivers
|
// broadcast receivers
|
||||||
private BroadcastReceiver serviceActionsReceiver;
|
private BroadcastReceiver serviceActionsReceiver;
|
||||||
|
@ -526,10 +530,18 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
private void toggleUrlSuggestions(boolean visible) {
|
private void toggleUrlSuggestions(boolean visible) {
|
||||||
View container = findViewById(R.id.url_suggestions_container);
|
View container = findViewById(R.id.url_suggestions_container);
|
||||||
View closeIcon = findViewById(R.id.wunderbar_close);
|
View closeIcon = findViewById(R.id.wunderbar_close);
|
||||||
|
EditText wunderbar = findViewById(R.id.wunderbar);
|
||||||
|
wunderbar.setPadding(0, 0, visible ? getScaledValue(36) : 0, 0);
|
||||||
|
|
||||||
container.setVisibility(visible ? View.VISIBLE : View.GONE);
|
container.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
closeIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
|
closeIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getScaledValue(int value) {
|
||||||
|
float scale = getResources().getDisplayMetrics().density;
|
||||||
|
return (int) (value * scale + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
private void setupUriBar() {
|
private void setupUriBar() {
|
||||||
findViewById(R.id.wunderbar_close).setOnClickListener(new View.OnClickListener() {
|
findViewById(R.id.wunderbar_close).setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -543,6 +555,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
@Override
|
@Override
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
public void onFocusChange(View view, boolean hasFocus) {
|
||||||
toggleUrlSuggestions(hasFocus);
|
toggleUrlSuggestions(hasFocus);
|
||||||
|
if (hasFocus && Helper.isNullOrEmpty(Helper.getValue(((EditText) view).getText()))) {
|
||||||
|
displayUrlSuggestionsForNoInput();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -572,6 +587,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
switch (urlSuggestion.getType()) {
|
switch (urlSuggestion.getType()) {
|
||||||
case UrlSuggestion.TYPE_CHANNEL:
|
case UrlSuggestion.TYPE_CHANNEL:
|
||||||
// open channel page
|
// open channel page
|
||||||
|
openChannelUrl(urlSuggestion.getUri().toString());
|
||||||
break;
|
break;
|
||||||
case UrlSuggestion.TYPE_FILE:
|
case UrlSuggestion.TYPE_FILE:
|
||||||
Context context = MainActivity.this;
|
Context context = MainActivity.this;
|
||||||
|
@ -586,6 +602,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
break;
|
break;
|
||||||
case UrlSuggestion.TYPE_TAG:
|
case UrlSuggestion.TYPE_TAG:
|
||||||
// open tag page
|
// open tag page
|
||||||
|
openAllContentFragmentWithTag(urlSuggestion.getText());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
findViewById(R.id.wunderbar).clearFocus();
|
findViewById(R.id.wunderbar).clearFocus();
|
||||||
|
@ -618,24 +635,26 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
ResolveTask task = new ResolveTask(urls, Lbry.LBRY_TV_CONNECTION_STRING, null, new ResolveTask.ResolveResultHandler() {
|
ResolveTask task = new ResolveTask(urls, Lbry.LBRY_TV_CONNECTION_STRING, null, new ResolveTask.ResolveResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Claim> claims) {
|
public void onSuccess(List<Claim> claims) {
|
||||||
for (int i = 0; i < claims.size(); i++) {
|
if (findViewById(R.id.url_suggestions_container).getVisibility() == View.VISIBLE) {
|
||||||
// build a simple url from the claim for matching
|
for (int i = 0; i < claims.size(); i++) {
|
||||||
Claim claim = claims.get(i);
|
// build a simple url from the claim for matching
|
||||||
if (Helper.isNullOrEmpty(claim.getName())) {
|
Claim claim = claims.get(i);
|
||||||
continue;
|
if (Helper.isNullOrEmpty(claim.getName())) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
LbryUri simpleUrl = new LbryUri();
|
LbryUri simpleUrl = new LbryUri();
|
||||||
if (claim.getName().startsWith("@")) {
|
if (claim.getName().startsWith("@")) {
|
||||||
// channel
|
// channel
|
||||||
simpleUrl.setChannelName(claim.getName());
|
simpleUrl.setChannelName(claim.getName());
|
||||||
} else {
|
} else {
|
||||||
simpleUrl.setStreamName(claim.getName());
|
simpleUrl.setStreamName(claim.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
urlSuggestionListAdapter.setClaimForUrl(simpleUrl, claim);
|
urlSuggestionListAdapter.setClaimForUrl(simpleUrl, claim);
|
||||||
|
}
|
||||||
|
urlSuggestionListAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
urlSuggestionListAdapter.notifyDataSetChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -646,10 +665,19 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void displayUrlSuggestionsForNoInput() {
|
||||||
|
urlSuggestionListAdapter.clear();
|
||||||
|
List<UrlSuggestion> blankSuggestions = buildDefaultSuggestionsForBlankUrl();
|
||||||
|
urlSuggestionListAdapter.addUrlSuggestions(blankSuggestions);
|
||||||
|
List<String> urls = urlSuggestionListAdapter.getItemUrls();
|
||||||
|
resolveUrlSuggestions(urls);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleUriInputChanged(String text) {
|
private void handleUriInputChanged(String text) {
|
||||||
// build the default suggestions
|
// build the default suggestions
|
||||||
urlSuggestionListAdapter.clear();
|
urlSuggestionListAdapter.clear();
|
||||||
if (Helper.isNullOrEmpty(text)) {
|
if (Helper.isNullOrEmpty(text) || text.trim().equals("@")) {
|
||||||
|
displayUrlSuggestionsForNoInput();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,10 +687,12 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
LighthouseAutoCompleteTask task = new LighthouseAutoCompleteTask(text, null, new LighthouseAutoCompleteTask.AutoCompleteResultHandler() {
|
LighthouseAutoCompleteTask task = new LighthouseAutoCompleteTask(text, null, new LighthouseAutoCompleteTask.AutoCompleteResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<UrlSuggestion> suggestions) {
|
public void onSuccess(List<UrlSuggestion> suggestions) {
|
||||||
urlSuggestionListAdapter.addUrlSuggestions(suggestions);
|
String wunderBarText = Helper.getValue(((EditText) findViewById(R.id.wunderbar)).getText());
|
||||||
|
if (wunderBarText.equalsIgnoreCase(text)) {
|
||||||
List<String> urls = urlSuggestionListAdapter.getItemUrls();
|
urlSuggestionListAdapter.addUrlSuggestions(suggestions);
|
||||||
resolveUrlSuggestions(urls);
|
List<String> urls = urlSuggestionListAdapter.getItemUrls();
|
||||||
|
resolveUrlSuggestions(urls);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -673,12 +703,37 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
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")));
|
||||||
|
for (UrlSuggestion suggestion : suggestions) {
|
||||||
|
suggestion.setUseTextAsDescription(true);
|
||||||
|
}
|
||||||
|
} catch (LbryUriException ex) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
private List<UrlSuggestion> buildDefaultSuggestions(String text) {
|
private List<UrlSuggestion> buildDefaultSuggestions(String text) {
|
||||||
List<UrlSuggestion> suggestions = new ArrayList<UrlSuggestion>();
|
List<UrlSuggestion> suggestions = new ArrayList<UrlSuggestion>();
|
||||||
|
|
||||||
// First item is always search
|
// First item is always search
|
||||||
UrlSuggestion searchSuggestion = new UrlSuggestion(UrlSuggestion.TYPE_SEARCH, text);
|
if (!text.startsWith(LbryUri.PROTO_DEFAULT)) {
|
||||||
suggestions.add(searchSuggestion);
|
UrlSuggestion searchSuggestion = new UrlSuggestion(UrlSuggestion.TYPE_SEARCH, text);
|
||||||
|
suggestions.add(searchSuggestion);
|
||||||
|
}
|
||||||
|
|
||||||
if (!text.matches(LbryUri.REGEX_INVALID_URI)) {
|
if (!text.matches(LbryUri.REGEX_INVALID_URI)) {
|
||||||
boolean isChannel = text.startsWith("@");
|
boolean isChannel = text.startsWith("@");
|
||||||
|
@ -990,6 +1045,12 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SQLiteDatabase db = dbHelper.getReadableDatabase();
|
||||||
|
List<Tag> fetchedTags = DatabaseHelper.getTags(db);
|
||||||
|
Lbry.knownTags = Helper.mergeKnownTags(fetchedTags);
|
||||||
|
Collections.sort(Lbry.knownTags, new Tag());
|
||||||
|
Lbry.followedTags = Helper.filterFollowedTags(Lbry.knownTags);
|
||||||
|
|
||||||
// load the exchange rate
|
// load the exchange rate
|
||||||
if (Lbryio.LBCUSDRate == 0) {
|
if (Lbryio.LBCUSDRate == 0) {
|
||||||
Lbryio.loadExchangeRate();
|
Lbryio.loadExchangeRate();
|
||||||
|
@ -1175,7 +1236,6 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
findContentGroup.setItems(Arrays.asList(
|
findContentGroup.setItems(Arrays.asList(
|
||||||
new NavMenuItem(NavMenuItem.ID_ITEM_FOLLOWING, R.string.fa_heart, R.string.following, "Following", context),
|
new NavMenuItem(NavMenuItem.ID_ITEM_FOLLOWING, R.string.fa_heart, R.string.following, "Following", context),
|
||||||
new NavMenuItem(NavMenuItem.ID_ITEM_EDITORS_CHOICE, R.string.fa_star, R.string.editors_choice, "EditorsChoice", context),
|
new NavMenuItem(NavMenuItem.ID_ITEM_EDITORS_CHOICE, R.string.fa_star, R.string.editors_choice, "EditorsChoice", context),
|
||||||
new NavMenuItem(NavMenuItem.ID_ITEM_YOUR_TAGS, R.string.fa_hashtag, R.string.your_tags, "YourTags", context),
|
|
||||||
new NavMenuItem(NavMenuItem.ID_ITEM_ALL_CONTENT, R.string.fa_globe_americas, R.string.all_content, "AllContent", context)
|
new NavMenuItem(NavMenuItem.ID_ITEM_ALL_CONTENT, R.string.fa_globe_americas, R.string.all_content, "AllContent", context)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -1421,4 +1481,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
||||||
});
|
});
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadTags() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -13,23 +14,35 @@ import java.util.List;
|
||||||
|
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
import io.lbry.browser.model.Tag;
|
import io.lbry.browser.model.Tag;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
public class TagListAdapter extends RecyclerView.Adapter<TagListAdapter.ViewHolder> {
|
public class TagListAdapter extends RecyclerView.Adapter<TagListAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public static final int CUSTOMIZE_MODE_NONE = 0;
|
||||||
|
public static final int CUSTOMIZE_MODE_ADD = 1;
|
||||||
|
public static final int CUSTOMIZE_MODE_REMOVE = 2;
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private List<Tag> items;
|
private List<Tag> items;
|
||||||
@Setter
|
@Setter
|
||||||
private TagClickListener clickListener;
|
private TagClickListener clickListener;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private int customizeMode;
|
||||||
|
|
||||||
public TagListAdapter(List<Tag> tags, Context context) {
|
public TagListAdapter(List<Tag> tags, Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.items = new ArrayList<>(tags);
|
this.items = new ArrayList<>(tags);
|
||||||
|
this.customizeMode = CUSTOMIZE_MODE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
protected ImageView iconView;
|
||||||
protected TextView nameView;
|
protected TextView nameView;
|
||||||
public ViewHolder(View v) {
|
public ViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
|
iconView = v.findViewById(R.id.tag_action);
|
||||||
nameView = v.findViewById(R.id.tag_name);
|
nameView = v.findViewById(R.id.tag_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +51,21 @@ public class TagListAdapter extends RecyclerView.Adapter<TagListAdapter.ViewHold
|
||||||
return items != null ? items.size() : 0;
|
return items != null ? items.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTag(Tag tag) {
|
||||||
|
if (!items.contains(tag)) {
|
||||||
|
items.add(tag);
|
||||||
|
}
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return new ArrayList<>(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTags(List<Tag> tags) {
|
||||||
|
items = new ArrayList<>(tags);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public void addTags(List<Tag> tags) {
|
public void addTags(List<Tag> tags) {
|
||||||
for (Tag tag : tags) {
|
for (Tag tag : tags) {
|
||||||
if (!items.contains(tag)) {
|
if (!items.contains(tag)) {
|
||||||
|
@ -46,6 +74,10 @@ public class TagListAdapter extends RecyclerView.Adapter<TagListAdapter.ViewHold
|
||||||
}
|
}
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
public void removeTag(Tag tag) {
|
||||||
|
items.remove(tag);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagListAdapter.ViewHolder onCreateViewHolder(ViewGroup root, int viewType) {
|
public TagListAdapter.ViewHolder onCreateViewHolder(ViewGroup root, int viewType) {
|
||||||
|
@ -57,18 +89,20 @@ public class TagListAdapter extends RecyclerView.Adapter<TagListAdapter.ViewHold
|
||||||
public void onBindViewHolder(TagListAdapter.ViewHolder vh, int position) {
|
public void onBindViewHolder(TagListAdapter.ViewHolder vh, int position) {
|
||||||
Tag tag = items.get(position);
|
Tag tag = items.get(position);
|
||||||
vh.nameView.setText(tag.getName().toLowerCase());
|
vh.nameView.setText(tag.getName().toLowerCase());
|
||||||
|
vh.iconView.setVisibility(customizeMode == CUSTOMIZE_MODE_NONE ? View.GONE : View.VISIBLE);
|
||||||
|
vh.iconView.setImageResource(customizeMode == CUSTOMIZE_MODE_REMOVE ? R.drawable.ic_close : R.drawable.ic_add);
|
||||||
vh.itemView.setBackgroundResource(tag.isMature() ? R.drawable.bg_tag_mature : R.drawable.bg_tag);
|
vh.itemView.setBackgroundResource(tag.isMature() ? R.drawable.bg_tag_mature : R.drawable.bg_tag);
|
||||||
vh.itemView.setOnClickListener(new View.OnClickListener() {
|
vh.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (clickListener != null) {
|
if (clickListener != null) {
|
||||||
clickListener.onTagClicked(tag);
|
clickListener.onTagClicked(tag, customizeMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface TagClickListener {
|
public interface TagClickListener {
|
||||||
void onTagClicked(Tag tag);
|
void onTagClicked(Tag tag, int customizeMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
|
import io.lbry.browser.exceptions.LbryUriException;
|
||||||
import io.lbry.browser.model.Claim;
|
import io.lbry.browser.model.Claim;
|
||||||
import io.lbry.browser.model.UrlSuggestion;
|
import io.lbry.browser.model.UrlSuggestion;
|
||||||
import io.lbry.browser.ui.controls.SolidIconView;
|
import io.lbry.browser.ui.controls.SolidIconView;
|
||||||
|
@ -52,8 +53,15 @@ public class UrlSuggestionListAdapter extends RecyclerView.Adapter<UrlSuggestion
|
||||||
public void setClaimForUrl(LbryUri url, Claim claim) {
|
public void setClaimForUrl(LbryUri url, Claim claim) {
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
LbryUri thisUrl = items.get(i).getUri();
|
LbryUri thisUrl = items.get(i).getUri();
|
||||||
if (thisUrl != null && thisUrl.equals(url)) {
|
try {
|
||||||
items.get(i).setClaim(claim);
|
if (thisUrl != null) {
|
||||||
|
LbryUri vanity = LbryUri.parse(thisUrl.toVanityString());
|
||||||
|
if (thisUrl.equals(url) || vanity.equals(url)) {
|
||||||
|
items.get(i).setClaim(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (LbryUriException ex) {
|
||||||
|
// pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +96,7 @@ public class UrlSuggestionListAdapter extends RecyclerView.Adapter<UrlSuggestion
|
||||||
iconStringId = R.string.fa_at;
|
iconStringId = R.string.fa_at;
|
||||||
fullTitle = item.getTitle();
|
fullTitle = item.getTitle();
|
||||||
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
||||||
String.format(context.getString(R.string.view_channel_url_desc), item.getText());
|
(item.isUseTextAsDescription() ? item.getText() : String.format(context.getString(R.string.view_channel_url_desc), item.getText()));
|
||||||
break;
|
break;
|
||||||
case UrlSuggestion.TYPE_TAG:
|
case UrlSuggestion.TYPE_TAG:
|
||||||
iconStringId = R.string.fa_hashtag;
|
iconStringId = R.string.fa_hashtag;
|
||||||
|
@ -105,7 +113,7 @@ public class UrlSuggestionListAdapter extends RecyclerView.Adapter<UrlSuggestion
|
||||||
iconStringId = R.string.fa_file;
|
iconStringId = R.string.fa_file;
|
||||||
fullTitle = item.getTitle();
|
fullTitle = item.getTitle();
|
||||||
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
desc = item.getClaim() != null ? item.getClaim().getTitle() :
|
||||||
String.format(context.getString(R.string.view_file_url_desc), item.getText());
|
(item.isUseTextAsDescription() ? item.getText() : String.format(context.getString(R.string.view_file_url_desc), item.getText()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,17 @@ import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.lbry.browser.exceptions.LbryUriException;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
|
import io.lbry.browser.model.UrlSuggestion;
|
||||||
import io.lbry.browser.model.lbryinc.Subscription;
|
import io.lbry.browser.model.lbryinc.Subscription;
|
||||||
import io.lbry.browser.utils.Helper;
|
import io.lbry.browser.utils.Helper;
|
||||||
|
import io.lbry.browser.utils.LbryUri;
|
||||||
|
|
||||||
public class DatabaseHelper extends SQLiteOpenHelper {
|
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||||
public static final int DATABASE_VERSION = 1;
|
public static final int DATABASE_VERSION = 1;
|
||||||
|
@ -18,18 +24,34 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
||||||
private static final String[] SQL_CREATE_TABLES = {
|
private static final String[] SQL_CREATE_TABLES = {
|
||||||
// local subscription store
|
// local subscription store
|
||||||
"CREATE TABLE subscriptions (url TEXT PRIMARY KEY NOT NULL, channel_name TEXT NOT NULL)",
|
"CREATE TABLE subscriptions (url TEXT PRIMARY KEY NOT NULL, channel_name TEXT NOT NULL)",
|
||||||
|
// url entry / suggestion history
|
||||||
// local claim cache store for quick load / refresh
|
"CREATE TABLE history (id INTEGER PRIMARY KEY NOT NULL, value TEXT NOT NULL, url TEXT, type INTEGER NOT NULL, timestamp TEXT NOT NULL)",
|
||||||
|
// tags (known and followed)
|
||||||
|
"CREATE TABLE tags (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, is_followed INTEGER NOT NULL)"
|
||||||
|
// local claim cache store for quick load / refresh (or offline mode)?
|
||||||
|
|
||||||
};
|
};
|
||||||
private static final String[] SQL_CREATE_INDEXES = {
|
private static final String[] SQL_CREATE_INDEXES = {
|
||||||
"CREATE UNIQUE INDEX idx_subscription_url ON subscriptions (url)"
|
"CREATE UNIQUE INDEX idx_subscription_url ON subscriptions (url)",
|
||||||
|
"CREATE UNIQUE INDEX idx_history_value ON history (value)",
|
||||||
|
"CREATE UNIQUE INDEX idx_history_url ON history (url)",
|
||||||
|
"CREATE UNIQUE INDEX idx_tag_name ON tags (name)"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String SQL_INSERT_SUBSCRIPTION = "REPLACE INTO subscriptions (channel_name, url) VALUES (?, ?)";
|
private static final String SQL_INSERT_SUBSCRIPTION = "REPLACE INTO subscriptions (channel_name, url) VALUES (?, ?)";
|
||||||
private static final String SQL_DELETE_SUBSCRIPTION = "DELETE FROM subscriptions WHERE url = ?";
|
private static final String SQL_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_GET_SUBSCRIPTIONS = "SELECT channel_name, url FROM subscriptions";
|
||||||
|
|
||||||
|
private static final String SQL_INSERT_HISTORY = "REPLACE INTO history (value, url, type, timestamp) VALUES (?, ?, ?)";
|
||||||
|
private static final String SQL_CLEAR_HISTORY = "DELETE FROM history";
|
||||||
|
private static final String SQL_CLEAR_HISTORY_BEFORE_TIME = "DELETE FROM history WHERE timestamp < ?";
|
||||||
|
private static final String SQL_GET_RECENT_HISTORY = "SELECT value, url, type FROM history ORDER BY timestamp DESC LIMIT 10";
|
||||||
|
|
||||||
|
private static final String SQL_INSERT_TAG = "REPLACE INTO tags (name, is_followed) VALUES (?, ?)";
|
||||||
|
private static final String SQL_SET_TAG_FOLLOWED = "UPDATE tags SET is_followed = ? WHERE name = ?";
|
||||||
|
private static final String SQL_GET_KNOWN_TAGS = "SELECT name FROM tags";
|
||||||
|
private static final String SQL_GET_FOLLOWED_TAGS = "SELECT name FROM tags WHERE is_followed = 1";
|
||||||
|
|
||||||
public DatabaseHelper(Context context) {
|
public DatabaseHelper(Context context) {
|
||||||
super(context, String.format("%s/%s", context.getFilesDir().getAbsolutePath(), DATABASE_NAME), null, DATABASE_VERSION);
|
super(context, String.format("%s/%s", context.getFilesDir().getAbsolutePath(), DATABASE_NAME), null, DATABASE_VERSION);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +70,64 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void createOrUpdateHistoryItem(String text, String url, int type, SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_INSERT_HISTORY, new Object[] {
|
||||||
|
text, url, type, new SimpleDateFormat(Helper.ISO_DATE_FORMAT_PATTERN).format(new Date())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public static void clearHistory(SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_CLEAR_HISTORY);
|
||||||
|
}
|
||||||
|
public static void clearHistoryBefore(Date date, SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_CLEAR_HISTORY_BEFORE_TIME, new Object[] { new SimpleDateFormat(Helper.ISO_DATE_FORMAT_PATTERN).format(new Date()) });
|
||||||
|
}
|
||||||
|
// History items are essentially url suggestions
|
||||||
|
public static List<UrlSuggestion> getRecentHistory(SQLiteDatabase db) {
|
||||||
|
List<UrlSuggestion> suggestions = new ArrayList<>();
|
||||||
|
Cursor cursor = null;
|
||||||
|
try {
|
||||||
|
cursor = db.rawQuery(SQL_GET_RECENT_HISTORY, null);
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
UrlSuggestion suggestion = new UrlSuggestion();
|
||||||
|
suggestion.setText(cursor.getString(0));
|
||||||
|
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
|
||||||
|
}
|
||||||
|
suggestions.add(suggestion);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Helper.closeCursor(cursor);
|
||||||
|
}
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void createOrUpdateTag(Tag tag, SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_INSERT_TAG, new Object[] { tag.getLowercaseName(), tag.isFollowed() ? 1 : 0 });
|
||||||
|
}
|
||||||
|
public static void setTagFollowed(boolean followed, String name, SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_SET_TAG_FOLLOWED, new Object[] { followed ? 1 : 0, name });
|
||||||
|
}
|
||||||
|
public static List<Tag> getTags(SQLiteDatabase db) {
|
||||||
|
List<Tag> tags = new ArrayList<>();
|
||||||
|
Cursor cursor = null;
|
||||||
|
try {
|
||||||
|
cursor = db.rawQuery(SQL_GET_KNOWN_TAGS, null);
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
Tag tag = new Tag();
|
||||||
|
tag.setName(cursor.getString(0));
|
||||||
|
tag.setFollowed(cursor.getInt(1) == 1);
|
||||||
|
tags.add(tag);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Helper.closeCursor(cursor);
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
public static void createOrUpdateSubscription(Subscription subscription, SQLiteDatabase db) {
|
public static void createOrUpdateSubscription(Subscription subscription, SQLiteDatabase db) {
|
||||||
db.execSQL(SQL_INSERT_SUBSCRIPTION, new Object[] { subscription.getChannelName(), subscription.getUrl() });
|
db.execSQL(SQL_INSERT_SUBSCRIPTION, new Object[] { subscription.getChannelName(), subscription.getUrl() });
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package io.lbry.browser.dialog;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
|
|
||||||
|
import io.lbry.browser.R;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class ContentScopeDialogFragment extends BottomSheetDialogFragment {
|
||||||
|
public static final String TAG = "ContentScopeDialog";
|
||||||
|
public static final int ITEM_EVERYONE = 1;
|
||||||
|
public static final int ITEM_TAGS = 2;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private ContentScopeListener contentScopeListener;
|
||||||
|
private int currentScopeItem;
|
||||||
|
|
||||||
|
public static ContentScopeDialogFragment newInstance() {
|
||||||
|
return new ContentScopeDialogFragment();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_content_scope, container,false);
|
||||||
|
|
||||||
|
ContentScopeItemClickListener clickListener = new ContentScopeItemClickListener(this, contentScopeListener);
|
||||||
|
view.findViewById(R.id.content_scope_everyone_item).setOnClickListener(clickListener);
|
||||||
|
view.findViewById(R.id.content_scope_tags_item).setOnClickListener(clickListener);
|
||||||
|
checkSelectedScopeItem(currentScopeItem, view);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void checkSelectedScopeItem(int scope, View parent) {
|
||||||
|
int checkViewId = -1;
|
||||||
|
switch (scope) {
|
||||||
|
case ITEM_EVERYONE: checkViewId = R.id.content_scope_everyone_item_selected; break;
|
||||||
|
case ITEM_TAGS: checkViewId = R.id.content_scope_tags_item_selected; break;
|
||||||
|
}
|
||||||
|
if (parent != null && checkViewId > -1) {
|
||||||
|
parent.findViewById(checkViewId).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentScopeItem(int scopeItem) {
|
||||||
|
this.currentScopeItem = scopeItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ContentScopeItemClickListener implements View.OnClickListener {
|
||||||
|
|
||||||
|
private final int[] checkViewIds = {
|
||||||
|
R.id.content_scope_everyone_item_selected, R.id.content_scope_tags_item_selected
|
||||||
|
};
|
||||||
|
private BottomSheetDialogFragment dialog;
|
||||||
|
private ContentScopeListener listener;
|
||||||
|
|
||||||
|
public ContentScopeItemClickListener(BottomSheetDialogFragment dialog, ContentScopeListener listener) {
|
||||||
|
this.dialog = dialog;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View view) {
|
||||||
|
int scopeItem = -1;
|
||||||
|
|
||||||
|
if (dialog != null) {
|
||||||
|
View dialogView = dialog.getView();
|
||||||
|
if (dialogView != null) {
|
||||||
|
for (int id : checkViewIds) {
|
||||||
|
dialogView.findViewById(id).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.content_scope_everyone_item: scopeItem = ITEM_EVERYONE; break;
|
||||||
|
case R.id.content_scope_tags_item: scopeItem = ITEM_TAGS; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSelectedScopeItem(scopeItem, view);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onContentScopeItemSelected(scopeItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ContentScopeListener {
|
||||||
|
void onContentScopeItemSelected(int scopeItem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
package io.lbry.browser.dialog;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.flexbox.FlexboxLayoutManager;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
|
import com.google.android.material.button.MaterialButton;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import io.lbry.browser.R;
|
||||||
|
import io.lbry.browser.adapter.TagListAdapter;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class CustomizeTagsDialogFragment extends BottomSheetDialogFragment {
|
||||||
|
public static final String TAG = "CustomizeTagsDialog";
|
||||||
|
private static final int SUGGESTED_LIMIT = 8;
|
||||||
|
private String currentFilter;
|
||||||
|
|
||||||
|
private RecyclerView followedTagsList;
|
||||||
|
private RecyclerView suggestedTagsList;
|
||||||
|
private TagListAdapter followedTagsAdapter;
|
||||||
|
private TagListAdapter suggestedTagsAdapter;
|
||||||
|
private View noTagsView;
|
||||||
|
private View noResultsView;
|
||||||
|
@Setter
|
||||||
|
private TagListener listener;
|
||||||
|
|
||||||
|
private void checkNoTags() {
|
||||||
|
Helper.setViewVisibility(noTagsView, followedTagsAdapter == null || followedTagsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
private void checkNoResults() {
|
||||||
|
Helper.setViewVisibility(noResultsView, suggestedTagsAdapter == null || suggestedTagsAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
public void addTag(Tag tag) {
|
||||||
|
if (followedTagsAdapter.getTags().contains(tag)) {
|
||||||
|
Snackbar.make(getView(), getString(R.string.tag_already_followed, tag.getName()), Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.setFollowed(true);
|
||||||
|
followedTagsAdapter.addTag(tag);
|
||||||
|
if (suggestedTagsAdapter != null) {
|
||||||
|
suggestedTagsAdapter.removeTag(tag);
|
||||||
|
}
|
||||||
|
updateKnownTags(currentFilter, SUGGESTED_LIMIT, false);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onTagAdded(tag);
|
||||||
|
}
|
||||||
|
checkNoTags();
|
||||||
|
checkNoResults();
|
||||||
|
}
|
||||||
|
public void removeTag(Tag tag) {
|
||||||
|
tag.setFollowed(false);
|
||||||
|
followedTagsAdapter.removeTag(tag);
|
||||||
|
updateKnownTags(currentFilter, SUGGESTED_LIMIT, false);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onTagRemoved(tag);
|
||||||
|
}
|
||||||
|
checkNoTags();
|
||||||
|
checkNoResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilter(String filter) {
|
||||||
|
currentFilter = filter;
|
||||||
|
updateKnownTags(currentFilter, SUGGESTED_LIMIT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomizeTagsDialogFragment newInstance() {
|
||||||
|
return new CustomizeTagsDialogFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_customize_tags, container, false);
|
||||||
|
|
||||||
|
noResultsView = view.findViewById(R.id.customize_no_tag_results);
|
||||||
|
noTagsView = view.findViewById(R.id.customize_no_followed_tags);
|
||||||
|
|
||||||
|
followedTagsAdapter = new TagListAdapter(Lbry.followedTags, getContext());
|
||||||
|
followedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_REMOVE);
|
||||||
|
followedTagsAdapter.setClickListener(customizeTagClickListener);
|
||||||
|
suggestedTagsAdapter = new TagListAdapter(new ArrayList<>(), getContext());
|
||||||
|
suggestedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
|
||||||
|
suggestedTagsAdapter.setClickListener(customizeTagClickListener);
|
||||||
|
|
||||||
|
FlexboxLayoutManager flm1 = new FlexboxLayoutManager(getContext());
|
||||||
|
followedTagsList = view.findViewById(R.id.customize_tags_followed_list);
|
||||||
|
followedTagsList.setLayoutManager(flm1);
|
||||||
|
followedTagsList.setAdapter(followedTagsAdapter);
|
||||||
|
|
||||||
|
FlexboxLayoutManager flm2 = new FlexboxLayoutManager(getContext());
|
||||||
|
suggestedTagsList = view.findViewById(R.id.customize_tags_suggested_list);
|
||||||
|
suggestedTagsList.setLayoutManager(flm2);
|
||||||
|
suggestedTagsList.setAdapter(suggestedTagsAdapter);
|
||||||
|
|
||||||
|
TextInputEditText filterInput = view.findViewById(R.id.customize_tag_filter_input);
|
||||||
|
filterInput.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
|
String value = Helper.getValue(charSequence);
|
||||||
|
setFilter(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
MaterialButton doneButton = view.findViewById(R.id.customize_done_button);
|
||||||
|
doneButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
checkNoTags();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TagListAdapter.TagClickListener customizeTagClickListener = new TagListAdapter.TagClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onTagClicked(Tag tag, int customizeMode) {
|
||||||
|
if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_ADD) {
|
||||||
|
addTag(tag);
|
||||||
|
} else if (customizeMode == TagListAdapter.CUSTOMIZE_MODE_REMOVE) {
|
||||||
|
removeTag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
updateKnownTags(null, SUGGESTED_LIMIT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateKnownTags(String filter, int limit, boolean clearPrevious) {
|
||||||
|
(new AsyncTask<Void, Void, List<Tag>>() {
|
||||||
|
protected List<Tag> doInBackground(Void... params) {
|
||||||
|
List<Tag> tags = new ArrayList<>();
|
||||||
|
if (Helper.isNullOrEmpty(filter)) {
|
||||||
|
Random random = new Random();
|
||||||
|
if (suggestedTagsAdapter != null && !clearPrevious) {
|
||||||
|
tags = new ArrayList<>(suggestedTagsAdapter.getTags());
|
||||||
|
}
|
||||||
|
while (tags.size() < limit) {
|
||||||
|
Tag randomTag = Lbry.knownTags.get(random.nextInt(Lbry.knownTags.size()));
|
||||||
|
if (!Lbry.followedTags.contains(randomTag) && (followedTagsAdapter == null || !followedTagsAdapter.getTags().contains(randomTag))) {
|
||||||
|
tags.add(randomTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Tag filterTag = new Tag(filter);
|
||||||
|
if (followedTagsAdapter == null || !followedTagsAdapter.getTags().contains(filterTag)) {
|
||||||
|
tags.add(new Tag(filter));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Lbry.knownTags.size() && tags.size() < SUGGESTED_LIMIT - 1; i++) {
|
||||||
|
Tag knownTag = Lbry.knownTags.get(i);
|
||||||
|
if ((knownTag.getLowercaseName().startsWith(filter) || knownTag.getLowercaseName().matches(filter)) &&
|
||||||
|
(!tags.contains(knownTag) &&
|
||||||
|
!Lbry.followedTags.contains(knownTag) && (followedTagsAdapter == null || !followedTagsAdapter.getTags().contains(knownTag)))) {
|
||||||
|
tags.add(knownTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
protected void onPostExecute(List<Tag> tags) {
|
||||||
|
if (suggestedTagsAdapter == null) {
|
||||||
|
suggestedTagsAdapter = new TagListAdapter(tags, getContext());
|
||||||
|
suggestedTagsAdapter.setCustomizeMode(TagListAdapter.CUSTOMIZE_MODE_ADD);
|
||||||
|
suggestedTagsAdapter.setClickListener(customizeTagClickListener);
|
||||||
|
if (suggestedTagsList != null) {
|
||||||
|
suggestedTagsList.setAdapter(suggestedTagsAdapter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
suggestedTagsAdapter.setTags(tags);
|
||||||
|
}
|
||||||
|
checkNoResults();
|
||||||
|
}
|
||||||
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface TagListener {
|
||||||
|
void onTagAdded(Tag tag);
|
||||||
|
void onTagRemoved(Tag tag);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package io.lbry.browser.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
public class ClaimSearchCacheValue {
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private List<Claim> claims;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private long timestamp;
|
||||||
|
|
||||||
|
public ClaimSearchCacheValue(List<Claim> claims, long timestamp) {
|
||||||
|
this.claims = new ArrayList<>(claims);
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpired(long ttl) {
|
||||||
|
return System.currentTimeMillis() - timestamp > ttl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,7 @@ public class NavMenuItem {
|
||||||
// Find Content
|
// Find Content
|
||||||
public static final int ID_ITEM_FOLLOWING = 101;
|
public static final int ID_ITEM_FOLLOWING = 101;
|
||||||
public static final int ID_ITEM_EDITORS_CHOICE = 102;
|
public static final int ID_ITEM_EDITORS_CHOICE = 102;
|
||||||
public static final int ID_ITEM_YOUR_TAGS = 103;
|
public static final int ID_ITEM_ALL_CONTENT = 103;
|
||||||
public static final int ID_ITEM_ALL_CONTENT = 104;
|
|
||||||
|
|
||||||
// Your Content
|
// Your Content
|
||||||
public static final int ID_ITEM_CHANNELS = 201;
|
public static final int ID_ITEM_CHANNELS = 201;
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
package io.lbry.browser.model;
|
package io.lbry.browser.model;
|
||||||
|
|
||||||
import io.lbry.browser.utils.Helper;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import io.lbry.browser.utils.Predefined;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
public class Tag {
|
public class Tag implements Comparator<Tag> {
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private String name;
|
private String name;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean followed;
|
||||||
|
|
||||||
|
public Tag() {
|
||||||
|
|
||||||
|
}
|
||||||
public Tag(String name) {
|
public Tag(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -18,13 +26,16 @@ public class Tag {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMature() {
|
public boolean isMature() {
|
||||||
return Helper.MATURE_TAG_NAMES.contains(name.toLowerCase());
|
return Predefined.MATURE_TAGS.contains(name.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o instanceof Tag) && ((Tag) o).getName().equalsIgnoreCase(name);
|
return (o instanceof Tag) && ((Tag) o).getName().equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return name.hashCode();
|
return name.toLowerCase().hashCode();
|
||||||
|
}
|
||||||
|
public int compare(Tag a, Tag b) {
|
||||||
|
return a.getLowercaseName().compareToIgnoreCase(b.getLowercaseName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +14,35 @@ public class UrlSuggestion {
|
||||||
private String text;
|
private String text;
|
||||||
private LbryUri uri;
|
private LbryUri uri;
|
||||||
private Claim claim; // associated claim if resolved
|
private Claim claim; // associated claim if resolved
|
||||||
|
private boolean titleTextOnly;
|
||||||
|
private boolean useTextAsDescription;
|
||||||
|
|
||||||
|
public UrlSuggestion() {
|
||||||
|
|
||||||
|
}
|
||||||
public UrlSuggestion(int type, String text) {
|
public UrlSuggestion(int type, String text) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
public UrlSuggestion(int type, String text, LbryUri uri) {
|
||||||
|
this(type, text);
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
public UrlSuggestion(int type, String text, LbryUri uri, boolean titleTextOnly) {
|
||||||
|
this(type, text, uri);
|
||||||
|
this.titleTextOnly = titleTextOnly;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
switch (type) {
|
if (!titleTextOnly) {
|
||||||
case TYPE_CHANNEL:
|
switch (type) {
|
||||||
return String.format("%s - %s", text.startsWith("@") ? text.substring(1) : text, uri.toString());
|
case TYPE_CHANNEL:
|
||||||
case TYPE_FILE:
|
return String.format("%s - %s", text.startsWith("@") ? text.substring(1) : text, uri.toVanityString());
|
||||||
return String.format("%s - %s", text, uri.toString());
|
case TYPE_FILE:
|
||||||
case TYPE_TAG:
|
return String.format("%s - %s", text, uri.toVanityString());
|
||||||
return String.format("%s - #%s", text, text);
|
case TYPE_TAG:
|
||||||
|
return String.format("%s - #%s", text, text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
|
59
app/src/main/java/io/lbry/browser/tasks/LoadTagsTask.java
Normal file
59
app/src/main/java/io/lbry/browser/tasks/LoadTagsTask.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package io.lbry.browser.tasks;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteException;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.lbry.browser.MainActivity;
|
||||||
|
import io.lbry.browser.data.DatabaseHelper;
|
||||||
|
import io.lbry.browser.exceptions.LbryRequestException;
|
||||||
|
import io.lbry.browser.exceptions.LbryResponseException;
|
||||||
|
import io.lbry.browser.model.Claim;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
|
import io.lbry.browser.utils.Helper;
|
||||||
|
|
||||||
|
public class LoadTagsTask extends AsyncTask<Void, Void, List<Tag>> {
|
||||||
|
private Context context;
|
||||||
|
private LoadTagsHandler handler;
|
||||||
|
private Exception error;
|
||||||
|
|
||||||
|
public LoadTagsTask(Context context, LoadTagsHandler handler) {
|
||||||
|
this.context = context;
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
protected List<Tag> doInBackground(Void... params) {
|
||||||
|
List<Tag> tags = null;
|
||||||
|
SQLiteDatabase db = null;
|
||||||
|
try {
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
db = ((MainActivity) context).getDbHelper().getReadableDatabase();
|
||||||
|
if (db != null) {
|
||||||
|
tags = DatabaseHelper.getTags(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLiteException ex) {
|
||||||
|
error = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
protected void onPostExecute(List<Tag> tags) {
|
||||||
|
if (handler != null) {
|
||||||
|
if (tags != null) {
|
||||||
|
handler.onSuccess(tags);
|
||||||
|
} else {
|
||||||
|
handler.onError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface LoadTagsHandler {
|
||||||
|
void onSuccess(List<Tag> tags);
|
||||||
|
void onError(Exception error);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package io.lbry.browser.ui.allcontent;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -10,9 +11,12 @@ import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -23,19 +27,24 @@ import io.lbry.browser.MainActivity;
|
||||||
import io.lbry.browser.R;
|
import io.lbry.browser.R;
|
||||||
import io.lbry.browser.adapter.ClaimListAdapter;
|
import io.lbry.browser.adapter.ClaimListAdapter;
|
||||||
import io.lbry.browser.dialog.ContentFromDialogFragment;
|
import io.lbry.browser.dialog.ContentFromDialogFragment;
|
||||||
|
import io.lbry.browser.dialog.ContentScopeDialogFragment;
|
||||||
import io.lbry.browser.dialog.ContentSortDialogFragment;
|
import io.lbry.browser.dialog.ContentSortDialogFragment;
|
||||||
|
import io.lbry.browser.dialog.CustomizeTagsDialogFragment;
|
||||||
import io.lbry.browser.model.Claim;
|
import io.lbry.browser.model.Claim;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
import io.lbry.browser.tasks.ClaimSearchTask;
|
import io.lbry.browser.tasks.ClaimSearchTask;
|
||||||
import io.lbry.browser.ui.BaseFragment;
|
import io.lbry.browser.ui.BaseFragment;
|
||||||
import io.lbry.browser.utils.Helper;
|
import io.lbry.browser.utils.Helper;
|
||||||
import io.lbry.browser.utils.Lbry;
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.Predefined;
|
||||||
|
|
||||||
// TODO: Similar code to FollowingFragment and Channel page fragment. Probably make common operations (sorting/filtering) into a control
|
// TODO: Similar code to FollowingFragment and Channel page fragment. Probably make common operations (sorting/filtering) into a control
|
||||||
public class AllContentFragment extends BaseFragment {
|
public class AllContentFragment extends BaseFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
private boolean singleTagView;
|
private boolean singleTagView;
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
private View layoutFilterContainer;
|
private View layoutFilterContainer;
|
||||||
|
private View customizeLink;
|
||||||
private View sortLink;
|
private View sortLink;
|
||||||
private View contentFromLink;
|
private View contentFromLink;
|
||||||
private View scopeLink;
|
private View scopeLink;
|
||||||
|
@ -46,13 +55,14 @@ public class AllContentFragment extends BaseFragment {
|
||||||
private RecyclerView contentList;
|
private RecyclerView contentList;
|
||||||
private int currentSortBy;
|
private int currentSortBy;
|
||||||
private int currentContentFrom;
|
private int currentContentFrom;
|
||||||
private int currentScope;
|
private int currentContentScope;
|
||||||
private String contentReleaseTime;
|
private String contentReleaseTime;
|
||||||
private List<String> contentSortOrder;
|
private List<String> contentSortOrder;
|
||||||
private View fromPrefix;
|
private View fromPrefix;
|
||||||
private View forPrefix;
|
private View forPrefix;
|
||||||
private View contentLoading;
|
private View contentLoading;
|
||||||
private View bigContentLoading;
|
private View bigContentLoading;
|
||||||
|
private View noContentView;
|
||||||
private ClaimListAdapter contentListAdapter;
|
private ClaimListAdapter contentListAdapter;
|
||||||
private boolean contentClaimSearchLoading;
|
private boolean contentClaimSearchLoading;
|
||||||
private boolean contentHasReachedEnd;
|
private boolean contentHasReachedEnd;
|
||||||
|
@ -72,6 +82,7 @@ public class AllContentFragment extends BaseFragment {
|
||||||
sortLink = root.findViewById(R.id.all_content_sort_link);
|
sortLink = root.findViewById(R.id.all_content_sort_link);
|
||||||
contentFromLink = root.findViewById(R.id.all_content_time_link);
|
contentFromLink = root.findViewById(R.id.all_content_time_link);
|
||||||
scopeLink = root.findViewById(R.id.all_content_scope_link);
|
scopeLink = root.findViewById(R.id.all_content_scope_link);
|
||||||
|
customizeLink = root.findViewById(R.id.all_content_customize_link);
|
||||||
fromPrefix = root.findViewById(R.id.all_content_from_prefix);
|
fromPrefix = root.findViewById(R.id.all_content_from_prefix);
|
||||||
forPrefix = root.findViewById(R.id.all_content_for_prefix);
|
forPrefix = root.findViewById(R.id.all_content_for_prefix);
|
||||||
|
|
||||||
|
@ -81,6 +92,7 @@ public class AllContentFragment extends BaseFragment {
|
||||||
|
|
||||||
bigContentLoading = root.findViewById(R.id.all_content_main_progress);
|
bigContentLoading = root.findViewById(R.id.all_content_main_progress);
|
||||||
contentLoading = root.findViewById(R.id.all_content_load_progress);
|
contentLoading = root.findViewById(R.id.all_content_load_progress);
|
||||||
|
noContentView = root.findViewById(R.id.all_content_no_claim_search_content);
|
||||||
|
|
||||||
contentList = root.findViewById(R.id.all_content_list);
|
contentList = root.findViewById(R.id.all_content_list);
|
||||||
LinearLayoutManager llm = new LinearLayoutManager(getContext());
|
LinearLayoutManager llm = new LinearLayoutManager(getContext());
|
||||||
|
@ -127,6 +139,25 @@ public class AllContentFragment extends BaseFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
scopeLink.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
ContentScopeDialogFragment dialog = ContentScopeDialogFragment.newInstance();
|
||||||
|
dialog.setCurrentScopeItem(currentContentScope);
|
||||||
|
dialog.setContentScopeListener(new ContentScopeDialogFragment.ContentScopeListener() {
|
||||||
|
@Override
|
||||||
|
public void onContentScopeItemSelected(int scopeItem) {
|
||||||
|
onContentScopeChanged(scopeItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
MainActivity activity = (MainActivity) context;
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), ContentScopeDialogFragment.TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
contentFromLink.setOnClickListener(new View.OnClickListener() {
|
contentFromLink.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
@ -145,6 +176,12 @@ public class AllContentFragment extends BaseFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
customizeLink.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
showCustomizeTagsDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
checkParams(false);
|
checkParams(false);
|
||||||
|
|
||||||
|
@ -188,6 +225,51 @@ public class AllContentFragment extends BaseFragment {
|
||||||
fetchClaimSearchContent(true);
|
fetchClaimSearchContent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onContentScopeChanged(int contentScope) {
|
||||||
|
currentContentScope = contentScope;
|
||||||
|
|
||||||
|
// rebuild options and search
|
||||||
|
updateContentScopeLinkText();
|
||||||
|
boolean isTagScope = currentContentScope == ContentScopeDialogFragment.ITEM_TAGS;
|
||||||
|
if (isTagScope) {
|
||||||
|
tags = Helper.getTagsForTagObjects(Lbry.followedTags);
|
||||||
|
// Update tags list with the user's followed tags
|
||||||
|
if (tags == null || tags.size() == 0) {
|
||||||
|
Snackbar.make(getView(), R.string.customize_tags_hint, Snackbar.LENGTH_LONG).setAction(R.string.customize, new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
// show customize
|
||||||
|
showCustomizeTagsDialog();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Helper.setViewVisibility(customizeLink, isTagScope ? View.VISIBLE : View.GONE);
|
||||||
|
fetchClaimSearchContent(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showCustomizeTagsDialog() {
|
||||||
|
CustomizeTagsDialogFragment dialog = CustomizeTagsDialogFragment.newInstance();
|
||||||
|
dialog.setListener(new CustomizeTagsDialogFragment.TagListener() {
|
||||||
|
@Override
|
||||||
|
public void onTagAdded(Tag tag) {
|
||||||
|
// heavy-lifting
|
||||||
|
// save to local, save to wallet and then sync
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTagRemoved(Tag tag) {
|
||||||
|
// heavy-lifting
|
||||||
|
// save to local, save to wallet and then sync
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Context context = getContext();
|
||||||
|
if (context instanceof MainActivity) {
|
||||||
|
MainActivity activity = (MainActivity) context;
|
||||||
|
dialog.show(activity.getSupportFragmentManager(), CustomizeTagsDialogFragment.TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onSortByChanged(int sortBy) {
|
private void onSortByChanged(int sortBy) {
|
||||||
currentSortBy = sortBy;
|
currentSortBy = sortBy;
|
||||||
|
|
||||||
|
@ -214,6 +296,16 @@ public class AllContentFragment extends BaseFragment {
|
||||||
Helper.setViewText(sortLinkText, stringResourceId);
|
Helper.setViewText(sortLinkText, stringResourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateContentScopeLinkText() {
|
||||||
|
int stringResourceId = -1;
|
||||||
|
switch (currentContentScope) {
|
||||||
|
case ContentScopeDialogFragment.ITEM_EVERYONE: default: stringResourceId = R.string.everyone; break;
|
||||||
|
case ContentScopeDialogFragment.ITEM_TAGS: stringResourceId = R.string.tags; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.setViewText(scopeLinkText, stringResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateContentFromLinkText() {
|
private void updateContentFromLinkText() {
|
||||||
int stringResourceId = -1;
|
int stringResourceId = -1;
|
||||||
switch (currentContentFrom) {
|
switch (currentContentFrom) {
|
||||||
|
@ -229,14 +321,26 @@ public class AllContentFragment extends BaseFragment {
|
||||||
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||||
|
updateContentFromLinkText();
|
||||||
|
updateContentScopeLinkText();
|
||||||
|
updateSortByLinkText();
|
||||||
fetchClaimSearchContent();
|
fetchClaimSearchContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onPause() {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Object> buildContentOptions() {
|
private Map<String, Object> buildContentOptions() {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||||
|
|
||||||
return Lbry.buildClaimSearchOptions(
|
return Lbry.buildClaimSearchOptions(
|
||||||
Claim.TYPE_STREAM,
|
Claim.TYPE_STREAM,
|
||||||
tags != null ? tags : null,
|
(currentContentScope == ContentScopeDialogFragment.ITEM_EVERYONE) ? null : tags,
|
||||||
null, // TODO: Check mature
|
canShowMatureContent ? null : new ArrayList<>(Predefined.MATURE_TAGS),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
getContentSortOrder(),
|
getContentSortOrder(),
|
||||||
|
@ -267,6 +371,7 @@ public class AllContentFragment extends BaseFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
contentClaimSearchLoading = true;
|
contentClaimSearchLoading = true;
|
||||||
|
Helper.setViewVisibility(noContentView, View.GONE);
|
||||||
Map<String, Object> claimSearchOptions = buildContentOptions();
|
Map<String, Object> claimSearchOptions = buildContentOptions();
|
||||||
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -303,13 +408,26 @@ public class AllContentFragment extends BaseFragment {
|
||||||
|
|
||||||
contentHasReachedEnd = hasReachedEnd;
|
contentHasReachedEnd = hasReachedEnd;
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception error) {
|
public void onError(Exception error) {
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkNoContent() {
|
||||||
|
boolean noContent = contentListAdapter == null || contentListAdapter.getItemCount() == 0;
|
||||||
|
Helper.setViewVisibility(noContentView, noContent ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
|
||||||
|
if (key.equalsIgnoreCase(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT)) {
|
||||||
|
fetchClaimSearchContent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.lbry.browser.ui.channel;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -11,9 +12,11 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -28,9 +31,10 @@ import io.lbry.browser.model.Claim;
|
||||||
import io.lbry.browser.tasks.ClaimSearchTask;
|
import io.lbry.browser.tasks.ClaimSearchTask;
|
||||||
import io.lbry.browser.utils.Helper;
|
import io.lbry.browser.utils.Helper;
|
||||||
import io.lbry.browser.utils.Lbry;
|
import io.lbry.browser.utils.Lbry;
|
||||||
|
import io.lbry.browser.utils.Predefined;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
public class ChannelContentFragment extends Fragment {
|
public class ChannelContentFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private String channelId;
|
private String channelId;
|
||||||
|
@ -45,6 +49,7 @@ public class ChannelContentFragment extends Fragment {
|
||||||
private List<String> contentSortOrder;
|
private List<String> contentSortOrder;
|
||||||
private View contentLoading;
|
private View contentLoading;
|
||||||
private View bigContentLoading;
|
private View bigContentLoading;
|
||||||
|
private View noContentView;
|
||||||
private ClaimListAdapter contentListAdapter;
|
private ClaimListAdapter contentListAdapter;
|
||||||
private boolean contentClaimSearchLoading;
|
private boolean contentClaimSearchLoading;
|
||||||
private boolean contentHasReachedEnd;
|
private boolean contentHasReachedEnd;
|
||||||
|
@ -66,6 +71,7 @@ public class ChannelContentFragment extends Fragment {
|
||||||
|
|
||||||
bigContentLoading = root.findViewById(R.id.channel_content_main_progress);
|
bigContentLoading = root.findViewById(R.id.channel_content_main_progress);
|
||||||
contentLoading = root.findViewById(R.id.channel_content_load_progress);
|
contentLoading = root.findViewById(R.id.channel_content_load_progress);
|
||||||
|
noContentView = root.findViewById(R.id.channel_content_no_claim_search_content);
|
||||||
|
|
||||||
contentList = root.findViewById(R.id.channel_content_list);
|
contentList = root.findViewById(R.id.channel_content_list);
|
||||||
LinearLayoutManager llm = new LinearLayoutManager(getContext());
|
LinearLayoutManager llm = new LinearLayoutManager(getContext());
|
||||||
|
@ -183,18 +189,23 @@ public class ChannelContentFragment extends Fragment {
|
||||||
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||||
fetchClaimSearchContent();
|
fetchClaimSearchContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void onPause() {
|
||||||
fetchClaimSearchContent(true);
|
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||||
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> buildContentOptions() {
|
private Map<String, Object> buildContentOptions() {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||||
|
|
||||||
return Lbry.buildClaimSearchOptions(
|
return Lbry.buildClaimSearchOptions(
|
||||||
Claim.TYPE_STREAM,
|
Claim.TYPE_STREAM,
|
||||||
null,
|
null,
|
||||||
null, // TODO: Check mature
|
canShowMatureContent ? null : new ArrayList<>(Predefined.MATURE_TAGS),
|
||||||
Arrays.asList(channelId),
|
Arrays.asList(channelId),
|
||||||
null,
|
null,
|
||||||
getContentSortOrder(),
|
getContentSortOrder(),
|
||||||
|
@ -225,6 +236,7 @@ public class ChannelContentFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
contentClaimSearchLoading = true;
|
contentClaimSearchLoading = true;
|
||||||
|
Helper.setViewVisibility(noContentView, View.GONE);
|
||||||
Map<String, Object> claimSearchOptions = buildContentOptions();
|
Map<String, Object> claimSearchOptions = buildContentOptions();
|
||||||
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -261,13 +273,26 @@ public class ChannelContentFragment extends Fragment {
|
||||||
|
|
||||||
contentHasReachedEnd = hasReachedEnd;
|
contentHasReachedEnd = hasReachedEnd;
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception error) {
|
public void onError(Exception error) {
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkNoContent() {
|
||||||
|
boolean noContent = contentListAdapter == null || contentListAdapter.getItemCount() == 0;
|
||||||
|
Helper.setViewVisibility(noContentView, noContent ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
|
||||||
|
if (key.equalsIgnoreCase(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT)) {
|
||||||
|
fetchClaimSearchContent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,6 @@ public class ChannelFragment extends BaseFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateRequired) {
|
if (updateRequired) {
|
||||||
resetFragments();
|
|
||||||
if (!Helper.isNullOrEmpty(url)) {
|
if (!Helper.isNullOrEmpty(url)) {
|
||||||
resolveUrl();
|
resolveUrl();
|
||||||
} else if (claim == null) {
|
} else if (claim == null) {
|
||||||
|
@ -179,25 +178,6 @@ public class ChannelFragment extends BaseFragment {
|
||||||
}).attach();
|
}).attach();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetFragments() {
|
|
||||||
try {
|
|
||||||
Context context = getContext();
|
|
||||||
if (context instanceof MainActivity) {
|
|
||||||
MainActivity activity = (MainActivity) getContext();
|
|
||||||
FragmentManager manager = activity.getSupportFragmentManager();
|
|
||||||
FragmentTransaction tx = manager.beginTransaction();
|
|
||||||
for (Fragment fragment : manager.getFragments()) {
|
|
||||||
if (fragment.getClass().equals(ChannelAboutFragment.class) || fragment.getClass().equals(ChannelContentFragment.class)) {
|
|
||||||
tx.remove(fragment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.commitAllowingStateLoss();
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ChannelPagerAdapter extends FragmentStateAdapter {
|
private static class ChannelPagerAdapter extends FragmentStateAdapter {
|
||||||
private Claim channelClaim;
|
private Claim channelClaim;
|
||||||
public ChannelPagerAdapter(Claim channelClaim, FragmentActivity activity) {
|
public ChannelPagerAdapter(Claim channelClaim, FragmentActivity activity) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.lbry.browser.ui.following;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -11,6 +12,8 @@ import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -45,8 +48,11 @@ import io.lbry.browser.utils.Helper;
|
||||||
import io.lbry.browser.utils.Lbry;
|
import io.lbry.browser.utils.Lbry;
|
||||||
import io.lbry.browser.utils.LbryUri;
|
import io.lbry.browser.utils.LbryUri;
|
||||||
import io.lbry.browser.utils.Lbryio;
|
import io.lbry.browser.utils.Lbryio;
|
||||||
|
import io.lbry.browser.utils.Predefined;
|
||||||
|
|
||||||
public class FollowingFragment extends BaseFragment implements FetchSubscriptionsTask.FetchSubscriptionsHandler, ChannelItemSelectionListener {
|
public class FollowingFragment extends BaseFragment implements
|
||||||
|
FetchSubscriptionsTask.FetchSubscriptionsHandler,
|
||||||
|
ChannelItemSelectionListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
private static final int SUGGESTED_PAGE_SIZE = 45;
|
private static final int SUGGESTED_PAGE_SIZE = 45;
|
||||||
private static final int MIN_SUGGESTED_SUBSCRIBE_COUNT = 5;
|
private static final int MIN_SUGGESTED_SUBSCRIBE_COUNT = 5;
|
||||||
|
@ -74,6 +80,7 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
private List<String> contentSortOrder;
|
private List<String> contentSortOrder;
|
||||||
private boolean contentClaimSearchLoading = false;
|
private boolean contentClaimSearchLoading = false;
|
||||||
private boolean suggestedClaimSearchLoading = false;
|
private boolean suggestedClaimSearchLoading = false;
|
||||||
|
private View noContentView;
|
||||||
|
|
||||||
private List<Integer> queuedContentPages = new ArrayList<>();
|
private List<Integer> queuedContentPages = new ArrayList<>();
|
||||||
private List<Integer> queuedSuggestedPages = new ArrayList<>();
|
private List<Integer> queuedSuggestedPages = new ArrayList<>();
|
||||||
|
@ -122,6 +129,7 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
contentLoading = root.findViewById(R.id.following_content_progress);
|
contentLoading = root.findViewById(R.id.following_content_progress);
|
||||||
channelListLoading = root.findViewById(R.id.following_channel_load_progress);
|
channelListLoading = root.findViewById(R.id.following_channel_load_progress);
|
||||||
discoverLink = root.findViewById(R.id.following_discover_link);
|
discoverLink = root.findViewById(R.id.following_discover_link);
|
||||||
|
noContentView = root.findViewById(R.id.following_no_claim_search_content);
|
||||||
|
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
GridLayoutManager glm = new GridLayoutManager(context, 3);
|
GridLayoutManager glm = new GridLayoutManager(context, 3);
|
||||||
|
@ -318,6 +326,7 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
// check if subscriptions exist
|
// check if subscriptions exist
|
||||||
if (suggestedChannelAdapter != null) {
|
if (suggestedChannelAdapter != null) {
|
||||||
|
@ -338,6 +347,10 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
fetchSubscriptions();
|
fetchSubscriptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void onPause() {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
public void loadFollowing() {
|
public void loadFollowing() {
|
||||||
// wrapper to just re-fetch subscriptions (upon user sign in, for example)
|
// wrapper to just re-fetch subscriptions (upon user sign in, for example)
|
||||||
|
@ -350,10 +363,13 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> buildSuggestedOptions() {
|
private Map<String, Object> buildSuggestedOptions() {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||||
|
|
||||||
return Lbry.buildClaimSearchOptions(
|
return Lbry.buildClaimSearchOptions(
|
||||||
Claim.TYPE_CHANNEL,
|
Claim.TYPE_CHANNEL,
|
||||||
null,
|
null,
|
||||||
null,
|
canShowMatureContent ? null : new ArrayList<>(Predefined.MATURE_TAGS),
|
||||||
null,
|
null,
|
||||||
excludeChannelIdsForDiscover,
|
excludeChannelIdsForDiscover,
|
||||||
Arrays.asList(Claim.ORDER_BY_EFFECTIVE_AMOUNT),
|
Arrays.asList(Claim.ORDER_BY_EFFECTIVE_AMOUNT),
|
||||||
|
@ -363,10 +379,13 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> buildContentOptions() {
|
private Map<String, Object> buildContentOptions() {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||||
|
|
||||||
return Lbry.buildClaimSearchOptions(
|
return Lbry.buildClaimSearchOptions(
|
||||||
Claim.TYPE_STREAM,
|
Claim.TYPE_STREAM,
|
||||||
null,
|
null,
|
||||||
null,
|
canShowMatureContent ? null : new ArrayList<>(Predefined.MATURE_TAGS),
|
||||||
getChannelIds(),
|
getChannelIds(),
|
||||||
null,
|
null,
|
||||||
getContentSortOrder(),
|
getContentSortOrder(),
|
||||||
|
@ -514,6 +533,7 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
}
|
}
|
||||||
|
|
||||||
contentClaimSearchLoading = true;
|
contentClaimSearchLoading = true;
|
||||||
|
Helper.setViewVisibility(noContentView, View.GONE);
|
||||||
Map<String, Object> claimSearchOptions = buildContentOptions();
|
Map<String, Object> claimSearchOptions = buildContentOptions();
|
||||||
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
contentClaimSearchTask = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, getLoadingView(), new ClaimSearchTask.ClaimSearchResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -551,11 +571,13 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
|
|
||||||
contentHasReachedEnd = hasReachedEnd;
|
contentHasReachedEnd = hasReachedEnd;
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception error) {
|
public void onError(Exception error) {
|
||||||
contentClaimSearchLoading = false;
|
contentClaimSearchLoading = false;
|
||||||
|
checkNoContent(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
contentClaimSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
@ -571,10 +593,16 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchSuggestedChannels() {
|
private void fetchSuggestedChannels() {
|
||||||
|
if (suggestedClaimSearchLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
suggestedClaimSearchLoading = true;
|
suggestedClaimSearchLoading = true;
|
||||||
if (discoverDialog != null) {
|
if (discoverDialog != null) {
|
||||||
discoverDialog.setLoading(true);
|
discoverDialog.setLoading(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Helper.setViewVisibility(noContentView, View.GONE);
|
||||||
suggestedChannelClaimSearchTask = new ClaimSearchTask(
|
suggestedChannelClaimSearchTask = new ClaimSearchTask(
|
||||||
buildSuggestedOptions(),
|
buildSuggestedOptions(),
|
||||||
Lbry.LBRY_TV_CONNECTION_STRING,
|
Lbry.LBRY_TV_CONNECTION_STRING,
|
||||||
|
@ -600,6 +628,10 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
} else {
|
} else {
|
||||||
suggestedChannelAdapter.addClaims(claims);
|
suggestedChannelAdapter.addClaims(claims);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (discoverDialog == null || !discoverDialog.isVisible()) {
|
||||||
|
checkNoContent(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -608,6 +640,9 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
if (discoverDialog != null) {
|
if (discoverDialog != null) {
|
||||||
discoverDialog.setLoading(false);
|
discoverDialog.setLoading(false);
|
||||||
}
|
}
|
||||||
|
if (discoverDialog == null || !discoverDialog.isVisible()) {
|
||||||
|
checkNoContent(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -645,13 +680,21 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
subscription.setUrl(claim.getPermanentUrl());
|
subscription.setUrl(claim.getPermanentUrl());
|
||||||
String channelClaimId = claim.getClaimId();
|
String channelClaimId = claim.getClaimId();
|
||||||
|
|
||||||
ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, false, null);
|
ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, false, new ChannelSubscribeTask.ChannelSubscribeHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
if (discoverDialog != null) {
|
||||||
|
fetchSubscriptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
updateSuggestedDoneButtonText();
|
updateSuggestedDoneButtonText();
|
||||||
|
|
||||||
if (discoverDialog != null) {
|
|
||||||
fetchSubscriptions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void onChannelItemDeselected(Claim claim) {
|
public void onChannelItemDeselected(Claim claim) {
|
||||||
// unsubscribe
|
// unsubscribe
|
||||||
|
@ -660,15 +703,35 @@ public class FollowingFragment extends BaseFragment implements FetchSubscription
|
||||||
subscription.setUrl(claim.getPermanentUrl());
|
subscription.setUrl(claim.getPermanentUrl());
|
||||||
String channelClaimId = claim.getClaimId();
|
String channelClaimId = claim.getClaimId();
|
||||||
|
|
||||||
ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, true, null);
|
ChannelSubscribeTask task = new ChannelSubscribeTask(getContext(), channelClaimId, subscription, true, new ChannelSubscribeTask.ChannelSubscribeHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
if (discoverDialog != null) {
|
||||||
|
fetchSubscriptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
updateSuggestedDoneButtonText();
|
updateSuggestedDoneButtonText();
|
||||||
|
|
||||||
if (discoverDialog != null) {
|
|
||||||
fetchSubscriptions();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void onChannelSelectionCleared() {
|
public void onChannelSelectionCleared() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkNoContent(boolean suggested) {
|
||||||
|
RecyclerView.Adapter adpater = suggested ? suggestedChannelAdapter : contentListAdapter;
|
||||||
|
boolean noContent = adpater == null || adpater.getItemCount() == 0;
|
||||||
|
Helper.setViewVisibility(noContentView, noContent ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
|
||||||
|
if (key.equalsIgnoreCase(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT)) {
|
||||||
|
fetchClaimSearchContent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.lbry.browser.ui.search;
|
package io.lbry.browser.ui.search;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -10,6 +11,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -29,7 +31,8 @@ import io.lbry.browser.utils.Lbry;
|
||||||
import io.lbry.browser.utils.LbryUri;
|
import io.lbry.browser.utils.LbryUri;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
public class SearchFragment extends BaseFragment implements ClaimListAdapter.ClaimListItemListener {
|
public class SearchFragment extends BaseFragment implements
|
||||||
|
ClaimListAdapter.ClaimListItemListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private ClaimListAdapter resultListAdapter;
|
private ClaimListAdapter resultListAdapter;
|
||||||
private static final int PAGE_SIZE = 25;
|
private static final int PAGE_SIZE = 25;
|
||||||
|
|
||||||
|
@ -84,18 +87,20 @@ public class SearchFragment extends BaseFragment implements ClaimListAdapter.Cla
|
||||||
|
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
if (resultListAdapter == null || resultListAdapter.getItemCount() == 0) {
|
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
|
||||||
// new search
|
if (!Helper.isNullOrEmpty(currentQuery)) {
|
||||||
if (!Helper.isNullOrEmpty(currentQuery)) {
|
search(currentQuery, currentFrom);
|
||||||
search(currentQuery, currentFrom);
|
} else {
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Helper.isNullOrEmpty(currentQuery)) {
|
|
||||||
noQueryView.setVisibility(View.VISIBLE);
|
noQueryView.setVisibility(View.VISIBLE);
|
||||||
noResultsView.setVisibility(View.GONE);
|
noResultsView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onPause() {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkQuery(String query) {
|
private boolean checkQuery(String query) {
|
||||||
if (!Helper.isNullOrEmpty(query) && !query.equalsIgnoreCase(currentQuery)) {
|
if (!Helper.isNullOrEmpty(query) && !query.equalsIgnoreCase(currentQuery)) {
|
||||||
// new query, reset values
|
// new query, reset values
|
||||||
|
@ -176,7 +181,10 @@ public class SearchFragment extends BaseFragment implements ClaimListAdapter.Cla
|
||||||
}
|
}
|
||||||
|
|
||||||
searchLoading = true;
|
searchLoading = true;
|
||||||
LighthouseSearchTask task = new LighthouseSearchTask(currentQuery, PAGE_SIZE, currentFrom, false, null, loadingView, new ClaimSearchTask.ClaimSearchResultHandler() {
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
boolean canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||||
|
LighthouseSearchTask task = new LighthouseSearchTask(
|
||||||
|
currentQuery, PAGE_SIZE, currentFrom, canShowMatureContent, null, loadingView, new ClaimSearchTask.ClaimSearchResultHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
|
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
|
||||||
contentHasReachedEnd = hasReachedEnd;
|
contentHasReachedEnd = hasReachedEnd;
|
||||||
|
@ -227,4 +235,10 @@ public class SearchFragment extends BaseFragment implements ClaimListAdapter.Cla
|
||||||
MainActivity.openFileClaim(claim, getContext());
|
MainActivity.openFileClaim(claim, getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
|
||||||
|
if (key.equalsIgnoreCase(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT)) {
|
||||||
|
search(currentQuery, currentFrom);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,15 @@ import java.util.Random;
|
||||||
import io.lbry.browser.dialog.ContentFromDialogFragment;
|
import io.lbry.browser.dialog.ContentFromDialogFragment;
|
||||||
import io.lbry.browser.dialog.ContentSortDialogFragment;
|
import io.lbry.browser.dialog.ContentSortDialogFragment;
|
||||||
import io.lbry.browser.model.Claim;
|
import io.lbry.browser.model.Claim;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
|
|
||||||
public final class Helper {
|
public final class Helper {
|
||||||
public static final String METHOD_GET = "GET";
|
public static final String METHOD_GET = "GET";
|
||||||
public static final String METHOD_POST = "POST";
|
public static final String METHOD_POST = "POST";
|
||||||
|
public static final String ISO_DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";
|
||||||
public static final MediaType FORM_MEDIA_TYPE = MediaType.parse("application/x-www-form-urlencoded");
|
public static final MediaType FORM_MEDIA_TYPE = MediaType.parse("application/x-www-form-urlencoded");
|
||||||
public static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
public static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
|
||||||
public static final List<String> MATURE_TAG_NAMES = Arrays.asList("mature", "nsfw", "porn", "xxx");
|
|
||||||
public static final int CONTENT_PAGE_SIZE = 25;
|
public static final int CONTENT_PAGE_SIZE = 25;
|
||||||
|
|
||||||
public static boolean isNull(String value) {
|
public static boolean isNull(String value) {
|
||||||
|
@ -283,4 +284,43 @@ public final class Helper {
|
||||||
((ColorDrawable) bg).setColor(isPlaceholder ? ContextCompat.getColor(context, android.R.color.transparent) : color);
|
((ColorDrawable) bg).setColor(isPlaceholder ? ContextCompat.getColor(context, android.R.color.transparent) : color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Tag> getTagObjectsForTags(List<String> tags) {
|
||||||
|
List<Tag> tagObjects = new ArrayList<>(tags.size());
|
||||||
|
for (String tag : tags) {
|
||||||
|
tagObjects.add(new Tag(tag));
|
||||||
|
}
|
||||||
|
return tagObjects;
|
||||||
|
}
|
||||||
|
public static List<String> getTagsForTagObjects(List<Tag> tagObjects) {
|
||||||
|
List<String> tags = new ArrayList<>(tagObjects.size());
|
||||||
|
for (Tag tagObject : tagObjects) {
|
||||||
|
tags.add(tagObject.getLowercaseName());
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
public static List<Tag> mergeKnownTags(List<Tag> fetchedTags) {
|
||||||
|
List<Tag> allKnownTags = getTagObjectsForTags(Predefined.DEFAULT_KNOWN_TAGS);
|
||||||
|
List<Integer> followIndexes = new ArrayList<>();
|
||||||
|
for (Tag tag : fetchedTags) {
|
||||||
|
if (!allKnownTags.contains(tag)) {
|
||||||
|
allKnownTags.add(tag);
|
||||||
|
} else if (tag.isFollowed()) {
|
||||||
|
followIndexes.add(allKnownTags.indexOf(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int index : followIndexes) {
|
||||||
|
allKnownTags.get(index).setFollowed(true);
|
||||||
|
}
|
||||||
|
return allKnownTags;
|
||||||
|
}
|
||||||
|
public static List<Tag> filterFollowedTags(List<Tag> tags) {
|
||||||
|
List<Tag> followedTags = new ArrayList<>();
|
||||||
|
for (Tag tag : followedTags) {
|
||||||
|
if (tag.isFollowed()) {
|
||||||
|
followedTags.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return followedTags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,9 @@ import io.lbry.browser.exceptions.LbryRequestException;
|
||||||
import io.lbry.browser.exceptions.LbryResponseException;
|
import io.lbry.browser.exceptions.LbryResponseException;
|
||||||
import io.lbry.browser.model.Claim;
|
import io.lbry.browser.model.Claim;
|
||||||
import io.lbry.browser.model.ClaimCacheKey;
|
import io.lbry.browser.model.ClaimCacheKey;
|
||||||
|
import io.lbry.browser.model.ClaimSearchCacheValue;
|
||||||
import io.lbry.browser.model.File;
|
import io.lbry.browser.model.File;
|
||||||
|
import io.lbry.browser.model.Tag;
|
||||||
import io.lbry.browser.model.Transaction;
|
import io.lbry.browser.model.Transaction;
|
||||||
import io.lbry.browser.model.WalletBalance;
|
import io.lbry.browser.model.WalletBalance;
|
||||||
import io.lbry.browser.model.lbryinc.User;
|
import io.lbry.browser.model.lbryinc.User;
|
||||||
|
@ -39,13 +41,16 @@ import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
public final class Lbry {
|
public final class Lbry {
|
||||||
public static final String TAG = "Lbry";
|
|
||||||
public static LinkedHashMap<ClaimCacheKey, Claim> claimCache = new LinkedHashMap<>();
|
public static LinkedHashMap<ClaimCacheKey, Claim> claimCache = new LinkedHashMap<>();
|
||||||
public static LinkedHashMap<Map<String, Object>, List<Claim>> claimSearchCache = new LinkedHashMap<>();
|
public static LinkedHashMap<Map<String, Object>, ClaimSearchCacheValue> claimSearchCache = new LinkedHashMap<>();
|
||||||
public static WalletBalance walletBalance = new WalletBalance();
|
public static WalletBalance walletBalance = new WalletBalance();
|
||||||
|
public static List<Tag> knownTags = new ArrayList<>();
|
||||||
|
public static List<Tag> followedTags = new ArrayList<>();
|
||||||
|
|
||||||
|
public static final int TTL_CLAIM_SEARCH_VALUE = 120000; // 2-minute TTL for cache
|
||||||
public static final String SDK_CONNECTION_STRING = "http://127.0.0.1:5279";
|
public static final String SDK_CONNECTION_STRING = "http://127.0.0.1:5279";
|
||||||
public static final String LBRY_TV_CONNECTION_STRING = "https://api.lbry.tv/api/v1/proxy";
|
public static final String LBRY_TV_CONNECTION_STRING = "https://api.lbry.tv/api/v1/proxy";
|
||||||
|
public static final String TAG = "Lbry";
|
||||||
|
|
||||||
// Values to obtain from LBRY SDK status
|
// Values to obtain from LBRY SDK status
|
||||||
public static boolean IS_STATUS_PARSED = false; // Check if the status has been parsed at least once
|
public static boolean IS_STATUS_PARSED = false; // Check if the status has been parsed at least once
|
||||||
|
@ -360,7 +365,10 @@ public final class Lbry {
|
||||||
|
|
||||||
public static List<Claim> claimSearch(Map<String, Object> options, String connectionString) throws ApiCallException {
|
public static List<Claim> claimSearch(Map<String, Object> options, String connectionString) throws ApiCallException {
|
||||||
if (claimSearchCache.containsKey(options)) {
|
if (claimSearchCache.containsKey(options)) {
|
||||||
return claimSearchCache.get(options);
|
ClaimSearchCacheValue value = claimSearchCache.get(options);
|
||||||
|
if (!value.isExpired(TTL_CLAIM_SEARCH_VALUE)) {
|
||||||
|
return claimSearchCache.get(options).getClaims();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Claim> claims = new ArrayList<>();
|
List<Claim> claims = new ArrayList<>();
|
||||||
|
@ -377,7 +385,7 @@ public final class Lbry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
claimSearchCache.put(options, claims);
|
claimSearchCache.put(options, new ClaimSearchCacheValue(claims, System.currentTimeMillis()));
|
||||||
} catch (LbryRequestException | LbryResponseException | JSONException ex) {
|
} catch (LbryRequestException | LbryResponseException | JSONException ex) {
|
||||||
throw new ApiCallException("Could not execute resolve call", ex);
|
throw new ApiCallException("Could not execute resolve call", ex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,10 @@ public class LbryUri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (components.size() == 0) {
|
||||||
|
throw new LbryUriException("Regular expression error occurred while trying to parse the value");
|
||||||
|
}
|
||||||
|
|
||||||
// components[0] = proto
|
// components[0] = proto
|
||||||
// components[1] = streamNameOrChannelName
|
// components[1] = streamNameOrChannelName
|
||||||
// components[2] = primaryModSeparator
|
// components[2] = primaryModSeparator
|
||||||
|
@ -141,7 +145,7 @@ public class LbryUri {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String build(boolean includeProto, String protoDefault) {
|
public String build(boolean includeProto, String protoDefault, boolean vanity) {
|
||||||
String formattedChannelName = null;
|
String formattedChannelName = null;
|
||||||
if (channelName != null) {
|
if (channelName != null) {
|
||||||
formattedChannelName = channelName.startsWith("@") ? channelName : String.format("@%s", channelName);
|
formattedChannelName = channelName.startsWith("@") ? channelName : String.format("@%s", channelName);
|
||||||
|
@ -162,6 +166,15 @@ public class LbryUri {
|
||||||
primaryClaimId = !Helper.isNullOrEmpty(formattedChannelName) ? channelClaimId : streamClaimId;
|
primaryClaimId = !Helper.isNullOrEmpty(formattedChannelName) ? channelClaimId : streamClaimId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (includeProto) {
|
||||||
|
sb.append(protoDefault);
|
||||||
|
}
|
||||||
|
sb.append(primaryClaimName);
|
||||||
|
if (vanity) {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
String secondaryClaimName = null;
|
String secondaryClaimName = null;
|
||||||
if (Helper.isNullOrEmpty(claimName) && !Helper.isNullOrEmpty(contentName)) {
|
if (Helper.isNullOrEmpty(claimName) && !Helper.isNullOrEmpty(contentName)) {
|
||||||
secondaryClaimName = contentName;
|
secondaryClaimName = contentName;
|
||||||
|
@ -171,11 +184,6 @@ public class LbryUri {
|
||||||
}
|
}
|
||||||
String secondaryClaimId = !Helper.isNullOrEmpty(secondaryClaimName) ? streamClaimId : null;
|
String secondaryClaimId = !Helper.isNullOrEmpty(secondaryClaimName) ? streamClaimId : null;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (includeProto) {
|
|
||||||
sb.append(protoDefault);
|
|
||||||
}
|
|
||||||
sb.append(primaryClaimName);
|
|
||||||
if (!Helper.isNullOrEmpty(primaryClaimId)) {
|
if (!Helper.isNullOrEmpty(primaryClaimId)) {
|
||||||
sb.append('#').append(primaryClaimId);
|
sb.append('#').append(primaryClaimId);
|
||||||
}
|
}
|
||||||
|
@ -205,8 +213,11 @@ public class LbryUri {
|
||||||
return parse(url).toString();
|
return parse(url).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toVanityString() {
|
||||||
|
return build(true, PROTO_DEFAULT, true);
|
||||||
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return build(true, PROTO_DEFAULT);
|
return build(true, PROTO_DEFAULT, false);
|
||||||
}
|
}
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return toString().hashCode();
|
return toString().hashCode();
|
||||||
|
|
492
app/src/main/java/io/lbry/browser/utils/Predefined.java
Normal file
492
app/src/main/java/io/lbry/browser/utils/Predefined.java
Normal file
|
@ -0,0 +1,492 @@
|
||||||
|
package io.lbry.browser.utils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class Predefined {
|
||||||
|
public static final List<String> DEFAULT_KNOWN_TAGS = Arrays.asList(
|
||||||
|
"free speech",
|
||||||
|
"censorship",
|
||||||
|
"gaming",
|
||||||
|
"pop culture",
|
||||||
|
"entertainment",
|
||||||
|
"technology",
|
||||||
|
"music",
|
||||||
|
"funny",
|
||||||
|
"education",
|
||||||
|
"learning",
|
||||||
|
"news",
|
||||||
|
"gameplay",
|
||||||
|
"nature",
|
||||||
|
"beliefs",
|
||||||
|
"comedy",
|
||||||
|
"games",
|
||||||
|
"film & animation",
|
||||||
|
"whothinks",
|
||||||
|
"game",
|
||||||
|
"weapons",
|
||||||
|
"blockchain",
|
||||||
|
"video game",
|
||||||
|
"sports",
|
||||||
|
"walkthrough",
|
||||||
|
"art",
|
||||||
|
"pc",
|
||||||
|
"minecraft",
|
||||||
|
"playthrough",
|
||||||
|
"economics",
|
||||||
|
"automotive",
|
||||||
|
"play",
|
||||||
|
"tutorial",
|
||||||
|
"twitch",
|
||||||
|
"how to",
|
||||||
|
"ps4",
|
||||||
|
"bitcoin",
|
||||||
|
"fortnite",
|
||||||
|
"commentary",
|
||||||
|
"lets play",
|
||||||
|
"fun",
|
||||||
|
"politics",
|
||||||
|
"travel",
|
||||||
|
"food",
|
||||||
|
"science",
|
||||||
|
"xbox",
|
||||||
|
"liberal",
|
||||||
|
"democrat",
|
||||||
|
"progressive",
|
||||||
|
"survival",
|
||||||
|
"non-profits",
|
||||||
|
"activism",
|
||||||
|
"cryptocurrency",
|
||||||
|
"playstation",
|
||||||
|
"nintendo",
|
||||||
|
"government",
|
||||||
|
"steam",
|
||||||
|
"podcast",
|
||||||
|
"gamer",
|
||||||
|
"horror",
|
||||||
|
"conservative",
|
||||||
|
"reaction",
|
||||||
|
"trailer",
|
||||||
|
"love",
|
||||||
|
"cnn",
|
||||||
|
"republican",
|
||||||
|
"political",
|
||||||
|
"hangoutsonair",
|
||||||
|
"hoa",
|
||||||
|
"msnbc",
|
||||||
|
"cbs",
|
||||||
|
"anime",
|
||||||
|
"donald trump",
|
||||||
|
"fiction",
|
||||||
|
"fox news",
|
||||||
|
"crypto",
|
||||||
|
"ethereum",
|
||||||
|
"call of duty",
|
||||||
|
"android",
|
||||||
|
"multiplayer",
|
||||||
|
"epic",
|
||||||
|
"rpg",
|
||||||
|
"adventure",
|
||||||
|
"secular talk",
|
||||||
|
"btc",
|
||||||
|
"atheist",
|
||||||
|
"atheism",
|
||||||
|
"video games",
|
||||||
|
"ps3",
|
||||||
|
"cod",
|
||||||
|
"online",
|
||||||
|
"agnostic",
|
||||||
|
"movie",
|
||||||
|
"fps",
|
||||||
|
"lets",
|
||||||
|
"mod",
|
||||||
|
"world",
|
||||||
|
"reviews",
|
||||||
|
"sharefactory",
|
||||||
|
"space",
|
||||||
|
"pokemon",
|
||||||
|
"stream",
|
||||||
|
"hilarious",
|
||||||
|
"lol",
|
||||||
|
"sony",
|
||||||
|
"god",
|
||||||
|
"dance",
|
||||||
|
"pvp",
|
||||||
|
"tech",
|
||||||
|
"strategy",
|
||||||
|
"zombies",
|
||||||
|
"fail",
|
||||||
|
"film",
|
||||||
|
"xbox360",
|
||||||
|
"animation",
|
||||||
|
"unboxing",
|
||||||
|
"money",
|
||||||
|
"wwe",
|
||||||
|
"mods",
|
||||||
|
"indie",
|
||||||
|
"pubg",
|
||||||
|
"ios",
|
||||||
|
"history",
|
||||||
|
"rap",
|
||||||
|
"mobile",
|
||||||
|
"trump",
|
||||||
|
"hack",
|
||||||
|
"flat earth",
|
||||||
|
"trap",
|
||||||
|
"humor",
|
||||||
|
"vlogging",
|
||||||
|
"fox",
|
||||||
|
"news radio",
|
||||||
|
"facebook",
|
||||||
|
"edm",
|
||||||
|
"fitness",
|
||||||
|
"vaping",
|
||||||
|
"hip hop",
|
||||||
|
"secular",
|
||||||
|
"jesus",
|
||||||
|
"song",
|
||||||
|
"vape",
|
||||||
|
"guitar",
|
||||||
|
"remix",
|
||||||
|
"mining",
|
||||||
|
"daily",
|
||||||
|
"diy",
|
||||||
|
"pets",
|
||||||
|
"videogame",
|
||||||
|
"death",
|
||||||
|
"funny moments",
|
||||||
|
"religion",
|
||||||
|
"media",
|
||||||
|
"viral",
|
||||||
|
"war",
|
||||||
|
"nbc",
|
||||||
|
"freedom",
|
||||||
|
"gold",
|
||||||
|
"family",
|
||||||
|
"meme",
|
||||||
|
"zombie",
|
||||||
|
"photography",
|
||||||
|
"chill",
|
||||||
|
"sniper",
|
||||||
|
"computer",
|
||||||
|
"iphone",
|
||||||
|
"dragon",
|
||||||
|
"bible",
|
||||||
|
"pro",
|
||||||
|
"overwatch",
|
||||||
|
"litecoin",
|
||||||
|
"gta",
|
||||||
|
"house",
|
||||||
|
"fire",
|
||||||
|
"bass",
|
||||||
|
"truth",
|
||||||
|
"crash",
|
||||||
|
"mario",
|
||||||
|
"league of legends",
|
||||||
|
"wii",
|
||||||
|
"mmorpg",
|
||||||
|
"health",
|
||||||
|
"marvel",
|
||||||
|
"racing",
|
||||||
|
"apple",
|
||||||
|
"instrumental",
|
||||||
|
"earth",
|
||||||
|
"destiny",
|
||||||
|
"satire",
|
||||||
|
"race",
|
||||||
|
"training",
|
||||||
|
"electronic",
|
||||||
|
"boss",
|
||||||
|
"roblox",
|
||||||
|
"family friendly",
|
||||||
|
"california",
|
||||||
|
"react",
|
||||||
|
"christian",
|
||||||
|
"mmo",
|
||||||
|
"twitter",
|
||||||
|
"help",
|
||||||
|
"star",
|
||||||
|
"cars",
|
||||||
|
"random",
|
||||||
|
"top 10",
|
||||||
|
"ninja",
|
||||||
|
"guns",
|
||||||
|
"linux",
|
||||||
|
"lessons",
|
||||||
|
"vegan",
|
||||||
|
"future",
|
||||||
|
"dota 2",
|
||||||
|
"studio",
|
||||||
|
"star wars",
|
||||||
|
"shooting",
|
||||||
|
"nasa",
|
||||||
|
"rock",
|
||||||
|
"league",
|
||||||
|
"subscribe",
|
||||||
|
"water",
|
||||||
|
"gta v",
|
||||||
|
"car",
|
||||||
|
"samsung",
|
||||||
|
"music video",
|
||||||
|
"skyrim",
|
||||||
|
"dog",
|
||||||
|
"comics",
|
||||||
|
"shooter game",
|
||||||
|
"bo3",
|
||||||
|
"halloween",
|
||||||
|
"liberty",
|
||||||
|
"eth",
|
||||||
|
"conspiracy",
|
||||||
|
"knife",
|
||||||
|
"fashion",
|
||||||
|
"stories",
|
||||||
|
"vapor",
|
||||||
|
"nvidia",
|
||||||
|
"cute",
|
||||||
|
"beat",
|
||||||
|
"nintendo switch",
|
||||||
|
"fantasy",
|
||||||
|
"christmas",
|
||||||
|
"world of warcraft",
|
||||||
|
"industry",
|
||||||
|
"cartoon",
|
||||||
|
"garden",
|
||||||
|
"animals",
|
||||||
|
"windows",
|
||||||
|
"happy",
|
||||||
|
"magic",
|
||||||
|
"memes",
|
||||||
|
"design",
|
||||||
|
"tactical",
|
||||||
|
"fallout 4",
|
||||||
|
"puzzle",
|
||||||
|
"parody",
|
||||||
|
"rv",
|
||||||
|
"beats",
|
||||||
|
"building",
|
||||||
|
"disney",
|
||||||
|
"drone",
|
||||||
|
"ps2",
|
||||||
|
"beach",
|
||||||
|
"metal",
|
||||||
|
"christianity",
|
||||||
|
"business",
|
||||||
|
"mix",
|
||||||
|
"bo2",
|
||||||
|
"cover",
|
||||||
|
"senate",
|
||||||
|
"4k",
|
||||||
|
"united states",
|
||||||
|
"final",
|
||||||
|
"hero",
|
||||||
|
"playing",
|
||||||
|
"dlc",
|
||||||
|
"ubisoft",
|
||||||
|
"halo",
|
||||||
|
"pc gaming",
|
||||||
|
"raw",
|
||||||
|
"investing",
|
||||||
|
"online learning",
|
||||||
|
"software",
|
||||||
|
"ark",
|
||||||
|
"mojang",
|
||||||
|
"console",
|
||||||
|
"battle royale",
|
||||||
|
"canon",
|
||||||
|
"microsoft",
|
||||||
|
"camping",
|
||||||
|
"ufo",
|
||||||
|
"progressive talk",
|
||||||
|
"switch",
|
||||||
|
"fpv",
|
||||||
|
"arcade",
|
||||||
|
"school",
|
||||||
|
"driving",
|
||||||
|
"bodybuilding",
|
||||||
|
"drama",
|
||||||
|
"retro",
|
||||||
|
"science fiction",
|
||||||
|
"eggs",
|
||||||
|
"australia",
|
||||||
|
"modded",
|
||||||
|
"rainbow",
|
||||||
|
"gamers",
|
||||||
|
"resident evil",
|
||||||
|
"drawing",
|
||||||
|
"brasil",
|
||||||
|
"england",
|
||||||
|
"hillary clinton",
|
||||||
|
"singing",
|
||||||
|
"final fantasy",
|
||||||
|
"hiphop",
|
||||||
|
"video blog",
|
||||||
|
"mature",
|
||||||
|
"quad",
|
||||||
|
"noob",
|
||||||
|
"simulation",
|
||||||
|
"illuminati",
|
||||||
|
"poetry",
|
||||||
|
"dayz",
|
||||||
|
"manga",
|
||||||
|
"howto",
|
||||||
|
"insane",
|
||||||
|
"press",
|
||||||
|
"special",
|
||||||
|
"church",
|
||||||
|
"ico",
|
||||||
|
"weird",
|
||||||
|
"libertarian",
|
||||||
|
"crafting",
|
||||||
|
"level",
|
||||||
|
"comic",
|
||||||
|
"sandbox",
|
||||||
|
"daily vlog",
|
||||||
|
"outdoor",
|
||||||
|
"black ops",
|
||||||
|
"sound",
|
||||||
|
"christ",
|
||||||
|
"duty",
|
||||||
|
"juvenile fiction",
|
||||||
|
"pc game",
|
||||||
|
"how-to",
|
||||||
|
"ww2",
|
||||||
|
"creepy",
|
||||||
|
"artist",
|
||||||
|
"galaxy",
|
||||||
|
"destiny 2",
|
||||||
|
"new music",
|
||||||
|
"quest",
|
||||||
|
"lee",
|
||||||
|
"pacman",
|
||||||
|
"super smash bros",
|
||||||
|
"day",
|
||||||
|
"survival horror",
|
||||||
|
"patreon",
|
||||||
|
"bitcoin price",
|
||||||
|
"trending",
|
||||||
|
"open world",
|
||||||
|
"wii u",
|
||||||
|
"dope",
|
||||||
|
"reaper",
|
||||||
|
"sniping",
|
||||||
|
"dubstep",
|
||||||
|
"truck",
|
||||||
|
"planet",
|
||||||
|
"dc",
|
||||||
|
"amazon",
|
||||||
|
"spirituality",
|
||||||
|
"universe",
|
||||||
|
"video game culture",
|
||||||
|
"community",
|
||||||
|
"cat",
|
||||||
|
"aliens",
|
||||||
|
"tourism",
|
||||||
|
"altcoins",
|
||||||
|
"style",
|
||||||
|
"travel trailer",
|
||||||
|
"rda",
|
||||||
|
"gun",
|
||||||
|
"secret",
|
||||||
|
"far cry 5",
|
||||||
|
"auto",
|
||||||
|
"culture",
|
||||||
|
"dj",
|
||||||
|
"mw2",
|
||||||
|
"lord",
|
||||||
|
"full time rving",
|
||||||
|
"role-playing game",
|
||||||
|
"prank",
|
||||||
|
"grand theft auto",
|
||||||
|
"master",
|
||||||
|
"wrestling",
|
||||||
|
"sci-fi",
|
||||||
|
"workout",
|
||||||
|
"ghost",
|
||||||
|
"fake news",
|
||||||
|
"silly",
|
||||||
|
"season",
|
||||||
|
"bo4",
|
||||||
|
"trading",
|
||||||
|
"extreme",
|
||||||
|
"economy",
|
||||||
|
"combat",
|
||||||
|
"plays",
|
||||||
|
"muslim",
|
||||||
|
"pubg mobile",
|
||||||
|
"clips",
|
||||||
|
"bo1",
|
||||||
|
"paypal",
|
||||||
|
"sims",
|
||||||
|
"exploration",
|
||||||
|
"light",
|
||||||
|
"ripple",
|
||||||
|
"paranormal",
|
||||||
|
"football",
|
||||||
|
"capcom",
|
||||||
|
"rta",
|
||||||
|
"discord",
|
||||||
|
"batman",
|
||||||
|
"player",
|
||||||
|
"server",
|
||||||
|
"anarchy",
|
||||||
|
"military",
|
||||||
|
"playlist",
|
||||||
|
"cosplay",
|
||||||
|
"rv park",
|
||||||
|
"rant",
|
||||||
|
"edit",
|
||||||
|
"germany",
|
||||||
|
"reading",
|
||||||
|
"chris",
|
||||||
|
"flash",
|
||||||
|
"loot",
|
||||||
|
"bitcoin gratis",
|
||||||
|
"game reviews",
|
||||||
|
"movies",
|
||||||
|
"stupid",
|
||||||
|
"latest news",
|
||||||
|
"squad gameplay",
|
||||||
|
"guru",
|
||||||
|
"timelapse",
|
||||||
|
"black ops 3",
|
||||||
|
"holiday",
|
||||||
|
"soul",
|
||||||
|
"motivation",
|
||||||
|
"mw3",
|
||||||
|
"vacation",
|
||||||
|
"sega",
|
||||||
|
"19th century",
|
||||||
|
"pop",
|
||||||
|
"sims 4",
|
||||||
|
"post",
|
||||||
|
"smok",
|
||||||
|
"island",
|
||||||
|
"scotland",
|
||||||
|
"paladins",
|
||||||
|
"warrior",
|
||||||
|
"creepypasta",
|
||||||
|
"role-playing",
|
||||||
|
"solar",
|
||||||
|
"vr",
|
||||||
|
"animal",
|
||||||
|
"peace",
|
||||||
|
"consciousness",
|
||||||
|
"dota",
|
||||||
|
"audio",
|
||||||
|
"mass effect",
|
||||||
|
"humour",
|
||||||
|
"first look",
|
||||||
|
"videogames",
|
||||||
|
"future bass",
|
||||||
|
"freestyle",
|
||||||
|
"hardcore",
|
||||||
|
"portugal",
|
||||||
|
"dantdm",
|
||||||
|
"teaser",
|
||||||
|
"lbry",
|
||||||
|
"coronavirus",
|
||||||
|
"covidcuts",
|
||||||
|
"covid-19"
|
||||||
|
);
|
||||||
|
public static final List<String> MATURE_TAGS = Arrays.asList("mature", "nsfw", "porn", "xxx");
|
||||||
|
}
|
11
app/src/main/res/drawable-anydpi/ic_add.xml
Normal file
11
app/src/main/res/drawable-anydpi/ic_add.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="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
</vector>
|
BIN
app/src/main/res/drawable-hdpi/ic_add.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 B |
BIN
app/src/main/res/drawable-mdpi/ic_add.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 B |
BIN
app/src/main/res/drawable-xhdpi/ic_add.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_add.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 164 B |
|
@ -148,7 +148,8 @@
|
||||||
android:layout_marginRight="24dp"
|
android:layout_marginRight="24dp"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:textFontWeight="300" />
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/file_view_publish_time"
|
android:id="@+id/file_view_publish_time"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginRight="36dp"
|
|
||||||
android:hint="@string/uri_placeholder"
|
android:hint="@string/uri_placeholder"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textFontWeight="300"
|
android:textFontWeight="300"
|
||||||
|
|
94
app/src/main/res/layout/dialog_content_scope.xml
Normal file
94
app/src/main/res/layout/dialog_content_scope.xml
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/filter_for"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0.5dp"
|
||||||
|
android:background="@color/divider"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/content_scope_everyone_item"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp">
|
||||||
|
<io.lbry.browser.ui.controls.SolidIconView
|
||||||
|
android:id="@+id/content_scope_everyone_item_icon"
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:text="@string/fa_globe_americas" />
|
||||||
|
<TextView
|
||||||
|
android:layout_toRightOf="@+id/content_scope_everyone_item_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/everyone"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/content_scope_everyone_item_selected"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_check"
|
||||||
|
android:tint="@color/lbryGreen"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/content_scope_tags_item"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp">
|
||||||
|
<io.lbry.browser.ui.controls.SolidIconView
|
||||||
|
android:id="@+id/content_scope_tags_item_icon"
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:text="@string/fa_hashtag" />
|
||||||
|
<TextView
|
||||||
|
android:layout_toRightOf="@+id/content_scope_tags_item_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/tags_you_follow"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/content_scope_tags_item_selected"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_check"
|
||||||
|
android:tint="@color/lbryGreen"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
106
app/src/main/res/layout/dialog_customize_tags.xml
Normal file
106
app/src/main/res/layout/dialog_customize_tags.xml
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<TextView
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/customize_your_tags"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0.5dp"
|
||||||
|
android:background="@color/divider"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/customize_tags_followed_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/customize_no_followed_tags"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_followed_tags"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0.5dp"
|
||||||
|
android:background="@color/divider"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/customize_tags_suggested_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/customize_no_tag_results"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_tag_results"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/customize_tag_filter_input"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/search_for_more_tags"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/customize_done_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/done" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -180,6 +180,17 @@
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/all_content_no_claim_search_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_claim_search_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/all_content_list"
|
android:id="@+id/all_content_list"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
|
@ -98,6 +98,17 @@
|
||||||
android:layout_alignParentRight="true" />
|
android:layout_alignParentRight="true" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/channel_content_no_claim_search_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_claim_search_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/channel_content_list"
|
android:id="@+id/channel_content_list"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -159,6 +158,17 @@
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/following_no_claim_search_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:fontFamily="@font/inter"
|
||||||
|
android:text="@string/no_claim_search_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textFontWeight="300"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/following_suggested_grid"
|
android:id="@+id/following_suggested_grid"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
|
android:textAllCaps="true"
|
||||||
android:textSize="48sp"
|
android:textSize="48sp"
|
||||||
android:textColor="@color/white" />
|
android:textColor="@color/white" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="6dp"
|
||||||
android:layout_marginRight="4dp"
|
android:layout_marginRight="6dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
android:paddingTop="4dp"
|
android:paddingTop="4dp"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
android:paddingLeft="12dp"
|
android:paddingLeft="8dp"
|
||||||
android:paddingRight="12dp"
|
android:paddingRight="12dp"
|
||||||
android:foreground="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/tag_action"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:tint="@color/darkForeground" />
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tag_name"
|
android:id="@+id/tag_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/inter"
|
android:fontFamily="@font/inter"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:textFontWeight="300" />
|
android:textFontWeight="300" />
|
||||||
</RelativeLayout>
|
</LinearLayout>
|
|
@ -1,20 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:showIn="navigation_view">
|
|
||||||
|
|
||||||
<group android:checkableBehavior="single">
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_home"
|
|
||||||
android:icon="@drawable/ic_menu_camera"
|
|
||||||
android:title="@string/menu_home" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_gallery"
|
|
||||||
android:icon="@drawable/ic_menu_gallery"
|
|
||||||
android:title="@string/menu_gallery" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_slideshow"
|
|
||||||
android:icon="@drawable/ic_menu_slideshow"
|
|
||||||
android:title="@string/menu_slideshow" />
|
|
||||||
</group>
|
|
||||||
</menu>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_settings"
|
|
||||||
android:orderInCategory="100"
|
|
||||||
android:title="@string/action_settings"
|
|
||||||
app:showAsAction="never" />
|
|
||||||
</menu>
|
|
|
@ -13,6 +13,7 @@
|
||||||
<color name="selectedNavItem">#0E0E0E</color>
|
<color name="selectedNavItem">#0E0E0E</color>
|
||||||
<color name="channelCoverBackground">#CC000000</color>
|
<color name="channelCoverBackground">#CC000000</color>
|
||||||
|
|
||||||
|
<color name="darkForeground">#EEEEEE</color>
|
||||||
<color name="foreground">#999999</color>
|
<color name="foreground">#999999</color>
|
||||||
<color name="mediaContainerBackground">#333333</color>
|
<color name="mediaContainerBackground">#333333</color>
|
||||||
<color name="borderTextArea">#5F5F5F</color>
|
<color name="borderTextArea">#5F5F5F</color>
|
||||||
|
@ -21,8 +22,8 @@
|
||||||
<color name="brighterLbryGreen">#40B887</color>
|
<color name="brighterLbryGreen">#40B887</color>
|
||||||
<color name="lbryGreen">#2F9176</color>
|
<color name="lbryGreen">#2F9176</color>
|
||||||
<color name="nextLbryGreen">#38D9A9</color>
|
<color name="nextLbryGreen">#38D9A9</color>
|
||||||
<color name="tagGreen">#E3F6F1</color>
|
<color name="tagGreen">#329A7E</color>
|
||||||
<color name="tagGrape">#77F255DA</color>
|
<color name="tagGrape">#77D510B8</color>
|
||||||
|
|
||||||
<color name="divider">#454545</color>
|
<color name="divider">#454545</color>
|
||||||
<color name="lightDivider">#0A0A0A</color>
|
<color name="lightDivider">#0A0A0A</color>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<color name="selectedNavItem">#F1F1F1</color>
|
<color name="selectedNavItem">#F1F1F1</color>
|
||||||
<color name="channelCoverBackground">#CC000000</color>
|
<color name="channelCoverBackground">#CC000000</color>
|
||||||
|
|
||||||
|
<color name="darkForeground">#222222</color>
|
||||||
<color name="foreground">#333333</color>
|
<color name="foreground">#333333</color>
|
||||||
<color name="mediaContainerBackground">#333333</color>
|
<color name="mediaContainerBackground">#333333</color>
|
||||||
<color name="borderTextArea">#777777</color>
|
<color name="borderTextArea">#777777</color>
|
||||||
|
|
|
@ -2,21 +2,11 @@
|
||||||
<string name="app_name">LBRY</string>
|
<string name="app_name">LBRY</string>
|
||||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||||
<string name="nav_header_desc">Navigation header</string>
|
|
||||||
<string name="action_settings">Settings</string>
|
|
||||||
|
|
||||||
<string name="menu_home">Home</string>
|
|
||||||
<string name="menu_gallery">Gallery</string>
|
|
||||||
<string name="menu_slideshow">Slideshow</string>
|
|
||||||
|
|
||||||
<string name="home_second">Home Second</string>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Nav menu -->
|
<!-- Nav menu -->
|
||||||
<string name="find_content">Find Content</string>
|
<string name="find_content">Find Content</string>
|
||||||
<string name="your_content">Your Content</string>
|
<string name="your_content">Your Content</string>
|
||||||
<string name="wallet">Wallet</string>
|
<string name="wallet">Wallet</string>
|
||||||
|
|
||||||
<string name="following">Following</string>
|
<string name="following">Following</string>
|
||||||
<string name="editors_choice">Editor\'s Choice</string>
|
<string name="editors_choice">Editor\'s Choice</string>
|
||||||
<string name="your_tags">Your Tags</string>
|
<string name="your_tags">Your Tags</string>
|
||||||
|
@ -29,9 +19,9 @@
|
||||||
<string name="invites">Invites</string>
|
<string name="invites">Invites</string>
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
|
|
||||||
<string name="sign_in">Sign In</string>
|
<string name="sign_in">Sign In</string>
|
||||||
<string name="startup_failed">App startup failed. Please check your data connection and try again. If this problem persists, please email hello@lbry.com</string>
|
<string name="startup_failed">App startup failed. Please check your data connection and try again. If this problem persists, please email hello@lbry.com</string>
|
||||||
|
<string name="no_claim_search_content">No content to display at this time. Please refine your selection or check back later.</string>
|
||||||
|
|
||||||
<!-- Welcome Page -->
|
<!-- Welcome Page -->
|
||||||
<string name="welcome_to_lbry">Welcome to LBRY.</string>
|
<string name="welcome_to_lbry">Welcome to LBRY.</string>
|
||||||
|
@ -59,7 +49,6 @@
|
||||||
|
|
||||||
<!-- File view -->
|
<!-- File view -->
|
||||||
<string name="tags">Tags</string>
|
<string name="tags">Tags</string>
|
||||||
|
|
||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
<string name="repost">Repost</string>
|
<string name="repost">Repost</string>
|
||||||
<string name="tip">Tip</string>
|
<string name="tip">Tip</string>
|
||||||
|
@ -79,10 +68,11 @@
|
||||||
<string name="website">Website</string>
|
<string name="website">Website</string>
|
||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="user_interface">User interface</string>
|
<string name="user_interface">Content & User interface</string>
|
||||||
<string name="other">Other</string>
|
<string name="other">Other</string>
|
||||||
<string name="enable_dark_mode">Enable dark theme</string>
|
<string name="enable_dark_mode">Enable dark theme</string>
|
||||||
<string name="show_url_suggestions">Show URL suggestsions</string>
|
<string name="show_mature_content">Show mature content</string>
|
||||||
|
<string name="show_url_suggestions">Show URL suggestions</string>
|
||||||
<string name="notifications">Notifications</string>
|
<string name="notifications">Notifications</string>
|
||||||
<string name="subscriptions">Subscriptions</string>
|
<string name="subscriptions">Subscriptions</string>
|
||||||
<string name="content_interests">Content Interests</string>
|
<string name="content_interests">Content Interests</string>
|
||||||
|
@ -172,6 +162,7 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<!-- Dialogs -->
|
<!-- Dialogs -->
|
||||||
|
<string name="customize_your_tags">Customize your tags</string>
|
||||||
<string name="sort_content_by">Sort content by</string>
|
<string name="sort_content_by">Sort content by</string>
|
||||||
<string name="content_from">Content from</string>
|
<string name="content_from">Content from</string>
|
||||||
<string name="trending_content">Trending content</string>
|
<string name="trending_content">Trending content</string>
|
||||||
|
@ -187,9 +178,16 @@
|
||||||
<string name="all_time">All time</string>
|
<string name="all_time">All time</string>
|
||||||
<string name="from">from</string>
|
<string name="from">from</string>
|
||||||
<string name="for_text">for</string>
|
<string name="for_text">for</string>
|
||||||
|
<string name="filter_for">Filter for</string>
|
||||||
<string name="everyone">Everyone</string>
|
<string name="everyone">Everyone</string>
|
||||||
|
<string name="tags_you_follow">Tags you follow</string>
|
||||||
<string name="customize">Customize</string>
|
<string name="customize">Customize</string>
|
||||||
<string name="not_yet_implemented">The selected view is not yet available.</string>
|
<string name="not_yet_implemented">The selected view is not yet available.</string>
|
||||||
|
<string name="customize_tags_hint">It looks like you have not followed any tags yet.</string>
|
||||||
|
<string name="search_for_more_tags">Search for more tags</string>
|
||||||
|
<string name="no_followed_tags">You have not followed any tags yet. Get started by adding tags that you are interested in!</string>
|
||||||
|
<string name="no_tag_results">We could not find new tags that you\'re not following.</string>
|
||||||
|
<string name="tag_already_followed">The \'%1$s\' tag has already been added.</string>
|
||||||
|
|
||||||
<!-- Verification -->
|
<!-- Verification -->
|
||||||
<string name="provide_email_address">Please provide an email address.</string>
|
<string name="provide_email_address">Please provide an email address.</string>
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
app:key="io.lbry.browser.preference.userinterface.DarkMode"
|
app:key="io.lbry.browser.preference.userinterface.DarkMode"
|
||||||
app:title="@string/enable_dark_mode"
|
app:title="@string/enable_dark_mode"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
app:key="io.lbry.browser.preference.userinterface.ShowMatureContent"
|
||||||
|
app:title="@string/show_mature_content"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="io.lbry.browser.preference.userinterface.UrlSuggestions"
|
app:key="io.lbry.browser.preference.userinterface.UrlSuggestions"
|
||||||
app:title="@string/show_url_suggestions"
|
app:title="@string/show_url_suggestions"
|
||||||
|
@ -23,14 +27,17 @@
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="io.lbry.browser.preference.notifications.Subscriptions"
|
app:key="io.lbry.browser.preference.notifications.Subscriptions"
|
||||||
app:title="@string/subscriptions"
|
app:title="@string/subscriptions"
|
||||||
|
app:defaultValue="true"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="io.lbry.browser.preference.notifications.Rewards"
|
app:key="io.lbry.browser.preference.notifications.Rewards"
|
||||||
app:title="@string/rewards"
|
app:title="@string/rewards"
|
||||||
|
app:defaultValue="true"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="io.lbry.browser.preference.notifications.ContentInterests"
|
app:key="io.lbry.browser.preference.notifications.ContentInterests"
|
||||||
app:title="@string/content_interests"
|
app:title="@string/content_interests"
|
||||||
|
app:defaultValue="true"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue