Merge branch 'master' of https://github.com/lbryio/lbry-android
# Conflicts: # app/src/main/java/io/lbry/browser/MainActivity.java
This commit is contained in:
commit
f5c1068052
17 changed files with 966 additions and 642 deletions
|
@ -14,14 +14,15 @@ android {
|
|||
applicationId "io.lbry.browser"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1602
|
||||
versionName "0.16.2"
|
||||
versionCode 1604
|
||||
versionName "0.16.4"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
exclude 'lib/x86_64/darwin/libscrypt.dylib'
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
|
|
|
@ -65,6 +65,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
@ -113,6 +114,8 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
||||
import io.lbry.browser.adapter.NavigationMenuAdapter;
|
||||
import io.lbry.browser.adapter.NotificationListAdapter;
|
||||
import io.lbry.browser.adapter.UrlSuggestionListAdapter;
|
||||
|
@ -171,9 +174,10 @@ import io.lbry.browser.ui.other.AboutFragment;
|
|||
import io.lbry.browser.ui.publish.PublishFormFragment;
|
||||
import io.lbry.browser.ui.publish.PublishFragment;
|
||||
import io.lbry.browser.ui.publish.PublishesFragment;
|
||||
import io.lbry.browser.ui.findcontent.SearchFragment;
|
||||
import io.lbry.browser.ui.other.SettingsFragment;
|
||||
import io.lbry.browser.ui.findcontent.AllContentFragment;
|
||||
import io.lbry.browser.ui.findcontent.SearchFragment;
|
||||
import io.lbry.browser.ui.findcontent.ShuffleFragment;
|
||||
import io.lbry.browser.ui.other.SettingsFragment;
|
||||
import io.lbry.browser.ui.wallet.InvitesFragment;
|
||||
import io.lbry.browser.ui.wallet.RewardsFragment;
|
||||
import io.lbry.browser.ui.wallet.WalletFragment;
|
||||
|
@ -191,11 +195,14 @@ import lombok.Setter;
|
|||
import lombok.SneakyThrows;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements SdkStatusListener {
|
||||
public class MainActivity extends AppCompatActivity implements SdkStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final String CHANNEL_ID_PLAYBACK = "io.lbry.browser.LBRY_PLAYBACK_CHANNEL";
|
||||
private static final int PLAYBACK_NOTIFICATION_ID = 3;
|
||||
private static final String SPECIAL_URL_PREFIX = "lbry://?";
|
||||
private static final int REMOTE_NOTIFICATION_REFRESH_TTL = 300000; // 5 minutes
|
||||
|
||||
public static final int SOURCE_NOW_PLAYING_FILE = 1;
|
||||
public static final int SOURCE_NOW_PLAYING_SHUFFLE = 2;
|
||||
public static MainActivity instance;
|
||||
|
||||
private boolean shuttingDown;
|
||||
|
@ -214,6 +221,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
public static boolean playerReassigned;
|
||||
public CastContext castContext;
|
||||
public static CastPlayer castPlayer;
|
||||
public static int nowPlayingSource;
|
||||
public static Claim nowPlayingClaim;
|
||||
public static String nowPlayingClaimUrl;
|
||||
public static boolean startingFilePickerActivity = false;
|
||||
|
@ -242,6 +250,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
fragmentClassNavIdMap.put(FollowingFragment.class, NavMenuItem.ID_ITEM_FOLLOWING);
|
||||
fragmentClassNavIdMap.put(EditorsChoiceFragment.class, NavMenuItem.ID_ITEM_EDITORS_CHOICE);
|
||||
fragmentClassNavIdMap.put(AllContentFragment.class, NavMenuItem.ID_ITEM_ALL_CONTENT);
|
||||
fragmentClassNavIdMap.put(ShuffleFragment.class, NavMenuItem.ID_ITEM_SHUFFLE);
|
||||
|
||||
fragmentClassNavIdMap.put(PublishFragment.class, NavMenuItem.ID_ITEM_NEW_PUBLISH);
|
||||
fragmentClassNavIdMap.put(ChannelManagerFragment.class, NavMenuItem.ID_ITEM_CHANNELS);
|
||||
|
@ -292,6 +301,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
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_SHOW_URL_SUGGESTIONS = "io.lbry.browser.preference.userinterface.UrlSuggestions";
|
||||
public static final String PREFERENCE_KEY_MINI_PLAYER_BOTTOM_MARGIN = "io.lbry.browser.preference.userinterface.MiniPlayerBottomMargin";
|
||||
public static final String PREFERENCE_KEY_NOTIFICATION_COMMENTS = "io.lbry.browser.preference.notifications.Comments";
|
||||
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";
|
||||
|
@ -372,6 +382,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
private static final int STARTUP_STAGE_NEW_INSTALL_DONE = 5;
|
||||
private static final int STARTUP_STAGE_SUBSCRIPTIONS_LOADED = 6;
|
||||
private static final int STARTUP_STAGE_SUBSCRIPTIONS_RESOLVED = 7;
|
||||
private static final int DEFAULT_MINI_PLAYER_MARGIN = 4;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -401,6 +412,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
updateMiniPlayerMargins();
|
||||
|
||||
playerNotificationManager = new PlayerNotificationManager(
|
||||
this, LbrynetService.NOTIFICATION_CHANNEL_ID, PLAYBACK_NOTIFICATION_ID, new PlayerNotificationDescriptionAdapter());
|
||||
|
||||
|
@ -522,7 +535,11 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
public void onClick(View view) {
|
||||
if (nowPlayingClaim != null && !Helper.isNullOrEmpty(nowPlayingClaimUrl)) {
|
||||
hideNotifications();
|
||||
openFileUrl(nowPlayingClaimUrl);
|
||||
if (nowPlayingSource == SOURCE_NOW_PLAYING_SHUFFLE) {
|
||||
openFragment(ShuffleFragment.class, true, NavMenuItem.ID_ITEM_SHUFFLE);
|
||||
} else {
|
||||
openFileUrl(nowPlayingClaimUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -559,6 +576,17 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
});
|
||||
}
|
||||
|
||||
private void updateMiniPlayerMargins() {
|
||||
// mini-player bottom margin setting
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
int miniPlayerBottomMargin = Helper.parseInt(
|
||||
sp.getString(PREFERENCE_KEY_MINI_PLAYER_BOTTOM_MARGIN, String.valueOf(DEFAULT_MINI_PLAYER_MARGIN)), DEFAULT_MINI_PLAYER_MARGIN);
|
||||
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) findViewById(R.id.global_now_playing_card).getLayoutParams();
|
||||
int scaledMiniPlayerMargin = getScaledValue(DEFAULT_MINI_PLAYER_MARGIN);
|
||||
int scaledMiniPlayerBottomMargin = getScaledValue(miniPlayerBottomMargin);
|
||||
lp.setMargins(scaledMiniPlayerMargin, 0, scaledMiniPlayerMargin, scaledMiniPlayerBottomMargin);
|
||||
}
|
||||
|
||||
public boolean isDarkMode() {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
return sp.getBoolean(PREFERENCE_KEY_DARK_MODE, false);
|
||||
|
@ -589,6 +617,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
specialRouteFragmentClassMap.put("settings", SettingsFragment.class);
|
||||
specialRouteFragmentClassMap.put("subscription", FollowingFragment.class);
|
||||
specialRouteFragmentClassMap.put("subscriptions", FollowingFragment.class);
|
||||
specialRouteFragmentClassMap.put("surf", ShuffleFragment.class);
|
||||
specialRouteFragmentClassMap.put("wallet", WalletFragment.class);
|
||||
specialRouteFragmentClassMap.put("discover", FollowingFragment.class);
|
||||
}
|
||||
|
@ -744,6 +773,9 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
case NavMenuItem.ID_ITEM_ALL_CONTENT:
|
||||
openFragment(AllContentFragment.class, true, NavMenuItem.ID_ITEM_ALL_CONTENT);
|
||||
break;
|
||||
case NavMenuItem.ID_ITEM_SHUFFLE:
|
||||
openFragment(ShuffleFragment.class, true, NavMenuItem.ID_ITEM_SHUFFLE);
|
||||
break;
|
||||
|
||||
case NavMenuItem.ID_ITEM_NEW_PUBLISH:
|
||||
openFragment(PublishFragment.class, true, NavMenuItem.ID_ITEM_NEW_PUBLISH);
|
||||
|
@ -958,7 +990,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
fragment instanceof LibraryFragment ||
|
||||
fragment instanceof SearchFragment;
|
||||
findViewById(R.id.floating_balance_main_container).setVisibility(!canShowFloatingBalance || inFullscreenMode ? View.INVISIBLE : View.VISIBLE);
|
||||
if (!(fragment instanceof FileViewFragment) && !inFullscreenMode) {
|
||||
if (!(fragment instanceof FileViewFragment) && !(fragment instanceof ShuffleFragment) && !inFullscreenMode) {
|
||||
findViewById(R.id.global_now_playing_card).setVisibility(View.VISIBLE);
|
||||
}
|
||||
/*if (!Lbry.SDK_READY && !inFullscreenMode) {
|
||||
|
@ -1075,6 +1107,13 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
|
||||
@Override
|
||||
public void onError(Exception ex) { }
|
||||
|
||||
protected void onSetSSLParameters(SSLParameters sslParameters) {
|
||||
// don't call setEndpointIdentificationAlgorithm for API level < 24
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
|
||||
}
|
||||
}
|
||||
};
|
||||
webSocketClient.connect();
|
||||
}
|
||||
|
@ -1083,7 +1122,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
checkWebSocketClient();
|
||||
updateMiniPlayerMargins();
|
||||
enteringPIPMode = false;
|
||||
|
||||
applyNavbarSigninPadding();
|
||||
|
@ -1133,6 +1175,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
if (!enteringPIPMode && !inPictureInPictureMode && appPlayer != null && !isBackgroundPlaybackEnabled()) {
|
||||
appPlayer.setPlayWhenReady(false);
|
||||
}
|
||||
|
@ -1745,6 +1788,13 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (PREFERENCE_KEY_MINI_PLAYER_BOTTOM_MARGIN.equalsIgnoreCase(key)) {
|
||||
updateMiniPlayerMargins();
|
||||
}
|
||||
}
|
||||
|
||||
private class PlayerNotificationDescriptionAdapter implements PlayerNotificationManager.MediaDescriptionAdapter {
|
||||
|
||||
@Override
|
||||
|
@ -2907,7 +2957,8 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
findContentGroup.setItems(Arrays.asList(
|
||||
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_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),
|
||||
new NavMenuItem(NavMenuItem.ID_ITEM_SHUFFLE, R.string.fa_random, R.string.shuffle, "Shuffle",context)
|
||||
));
|
||||
|
||||
yourContentGroup.setItems(Arrays.asList(
|
||||
|
|
|
@ -20,6 +20,7 @@ public class NavMenuItem {
|
|||
public static final int ID_ITEM_FOLLOWING = 101;
|
||||
public static final int ID_ITEM_EDITORS_CHOICE = 102;
|
||||
public static final int ID_ITEM_ALL_CONTENT = 103;
|
||||
public static final int ID_ITEM_SHUFFLE = 104;
|
||||
|
||||
// Your Content
|
||||
public static final int ID_ITEM_CHANNELS = 201;
|
||||
|
|
|
@ -51,8 +51,8 @@ public class CommentListTask extends AsyncTask<Void, Void, List<Comment>> {
|
|||
options.put("skip_validation", true);
|
||||
options.put("visible", true);
|
||||
|
||||
|
||||
JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_COMMENT_LIST, options);
|
||||
android.util.Log.d("LbryMain", result.toString(2));
|
||||
JSONArray items = result.getJSONArray("items");
|
||||
|
||||
List<Comment> children = new ArrayList<>();
|
||||
|
@ -78,6 +78,7 @@ public class CommentListTask extends AsyncTask<Void, Void, List<Comment>> {
|
|||
}
|
||||
} catch (Exception ex) {
|
||||
error = ex;
|
||||
android.util.Log.d("LbryMain", ex.toString(), ex);
|
||||
}
|
||||
return comments;
|
||||
}
|
||||
|
|
|
@ -227,6 +227,8 @@ public class ChannelContentFragment extends Fragment implements DownloadActionLi
|
|||
null,
|
||||
getContentSortOrder(),
|
||||
contentReleaseTime,
|
||||
0,
|
||||
0,
|
||||
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
|
||||
Helper.CONTENT_PAGE_SIZE);
|
||||
}
|
||||
|
|
|
@ -414,6 +414,8 @@ public class AllContentFragment extends BaseFragment implements DownloadActionLi
|
|||
null,
|
||||
getContentSortOrder(),
|
||||
contentReleaseTime,
|
||||
0,
|
||||
0,
|
||||
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
|
||||
Helper.CONTENT_PAGE_SIZE);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Outline;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
|
@ -37,7 +36,6 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.AppCompatSpinner;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
@ -167,7 +165,7 @@ public class FileViewFragment extends BaseFragment implements
|
|||
WalletBalanceListener {
|
||||
private static final int RELATED_CONTENT_SIZE = 16;
|
||||
private static final String DEFAULT_PLAYBACK_SPEED = "1x";
|
||||
private static final String CDN_PREFIX = "https://cdn.lbryplayer.xyz";
|
||||
public static final String CDN_PREFIX = "https://cdn.lbryplayer.xyz";
|
||||
|
||||
private PlayerControlView castControlView;
|
||||
private Player currentPlayer;
|
||||
|
@ -609,7 +607,7 @@ public class FileViewFragment extends BaseFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
if (!Helper.isNullOrEmpty(lbryFile.getStreamingUrl()) && !Lbryio.isSignedIn()) {
|
||||
if (!Helper.isNullOrEmpty(lbryFile.getStreamingUrl()) && (!claim.isFree() || !Lbryio.isSignedIn())) {
|
||||
return lbryFile.getStreamingUrl();
|
||||
}
|
||||
}
|
||||
|
@ -741,6 +739,13 @@ public class FileViewFragment extends BaseFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if (MainActivity.appPlayer != null) {
|
||||
MainActivity.nowPlayingSource = MainActivity.SOURCE_NOW_PLAYING_FILE;
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
Context context = getContext();
|
||||
|
@ -1874,7 +1879,7 @@ public class FileViewFragment extends BaseFragment implements
|
|||
}
|
||||
|
||||
private void handleMainActionForClaim() {
|
||||
if (claim.isPlayable() && Lbryio.isSignedIn()) {
|
||||
if (claim.isPlayable() && claim.isFree() && Lbryio.isSignedIn()) {
|
||||
// always use lbry.tv streaming when signed in and playabble
|
||||
startTimeMillis = System.currentTimeMillis();
|
||||
showExoplayerView();
|
||||
|
@ -2781,7 +2786,7 @@ public class FileViewFragment extends BaseFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
private static class StreamLoadErrorPolicy extends DefaultLoadErrorHandlingPolicy {
|
||||
public static class StreamLoadErrorPolicy extends DefaultLoadErrorHandlingPolicy {
|
||||
@Override
|
||||
public long getRetryDelayMsFor(int dataType, long loadDurationMs, IOException exception, int errorCount) {
|
||||
return exception instanceof ParserException
|
||||
|
|
|
@ -434,6 +434,8 @@ public class FollowingFragment extends BaseFragment implements
|
|||
null,
|
||||
getContentSortOrder(),
|
||||
contentReleaseTime,
|
||||
0,
|
||||
0,
|
||||
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
|
||||
Helper.CONTENT_PAGE_SIZE);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,748 @@
|
|||
package io.lbry.browser.ui.findcontent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
|
||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.lbry.browser.MainActivity;
|
||||
import io.lbry.browser.R;
|
||||
import io.lbry.browser.exceptions.LbryUriException;
|
||||
import io.lbry.browser.model.Claim;
|
||||
import io.lbry.browser.model.lbryinc.Reward;
|
||||
import io.lbry.browser.tasks.BufferEventTask;
|
||||
import io.lbry.browser.tasks.GenericTaskHandler;
|
||||
import io.lbry.browser.tasks.claim.ClaimSearchResultHandler;
|
||||
import io.lbry.browser.tasks.claim.ClaimSearchTask;
|
||||
import io.lbry.browser.tasks.lbryinc.ClaimRewardTask;
|
||||
import io.lbry.browser.tasks.lbryinc.LogFileViewTask;
|
||||
import io.lbry.browser.ui.BaseFragment;
|
||||
import io.lbry.browser.utils.Helper;
|
||||
import io.lbry.browser.utils.Lbry;
|
||||
import io.lbry.browser.utils.LbryAnalytics;
|
||||
import io.lbry.browser.utils.LbryUri;
|
||||
import io.lbry.browser.utils.Lbryio;
|
||||
import io.lbry.browser.utils.Predefined;
|
||||
|
||||
public class ShuffleFragment extends BaseFragment {
|
||||
|
||||
private static final int PAGE_SIZE = 50;
|
||||
|
||||
private int currentClaimSearchPage;
|
||||
private int playlistIndex;
|
||||
private Claim current;
|
||||
private List<Claim> playlist;
|
||||
|
||||
private long sessionStart;
|
||||
private ProgressBar surfModeLoading;
|
||||
private TextView textTitle;
|
||||
private TextView textPublisher;
|
||||
private Player player;
|
||||
private long elapsedDuration = 0;
|
||||
private long totalDuration = 0;
|
||||
private boolean elapsedPlaybackScheduled;
|
||||
private ScheduledExecutorService elapsedPlaybackScheduler;
|
||||
private boolean playbackStarted;
|
||||
private long startTimeMillis;
|
||||
private boolean isPlaying;
|
||||
private boolean newPlayerCreated;
|
||||
private String currentUrl;
|
||||
private Player.EventListener playerListener;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_shuffle, container, false);
|
||||
|
||||
surfModeLoading = root.findViewById(R.id.shuffle_loading);
|
||||
textTitle = root.findViewById(R.id.shuffle_content_title);
|
||||
textPublisher = root.findViewById(R.id.shuffle_content_publisher);
|
||||
playerListener = new Player.EventListener() {
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playbackState == Player.STATE_READY) {
|
||||
elapsedDuration = MainActivity.appPlayer.getCurrentPosition();
|
||||
totalDuration = MainActivity.appPlayer.getDuration() < 0 ? 0 : MainActivity.appPlayer.getDuration();
|
||||
if (!playbackStarted) {
|
||||
logPlay(currentUrl, startTimeMillis);
|
||||
playbackStarted = true;
|
||||
isPlaying = true;
|
||||
}
|
||||
|
||||
renderTotalDuration();
|
||||
scheduleElapsedPlayback();
|
||||
hideBuffering();
|
||||
} else if (playbackState == Player.STATE_BUFFERING) {
|
||||
Context ctx = getContext();
|
||||
boolean sendBufferingEvents = true;
|
||||
|
||||
if (ctx != null) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(ctx);
|
||||
sendBufferingEvents = sp.getBoolean(MainActivity.PREFERENCE_KEY_SEND_BUFFERING_EVENTS, true);
|
||||
}
|
||||
|
||||
if (MainActivity.appPlayer != null && MainActivity.appPlayer.getCurrentPosition() > 0 && sendBufferingEvents) {
|
||||
// we only want to log a buffer event after the media has already started playing
|
||||
String mediaSourceUrl = getStreamingUrl();
|
||||
long duration = MainActivity.appPlayer.getDuration();
|
||||
long position = MainActivity.appPlayer.getCurrentPosition();
|
||||
// TODO: Determine a hash for the userId
|
||||
String userIdHash = Helper.SHA256(Lbryio.currentUser != null ? String.valueOf(Lbryio.currentUser.getId()) : "0");
|
||||
if (mediaSourceUrl.startsWith(FileViewFragment.CDN_PREFIX)) {
|
||||
BufferEventTask bufferEvent = new BufferEventTask(current.getPermanentUrl(), duration, position, 1, userIdHash);
|
||||
bufferEvent.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
showBuffering();
|
||||
} else if (playbackState == Player.STATE_ENDED) {
|
||||
playNextClaim();
|
||||
} else {
|
||||
hideBuffering();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Context context = getContext();
|
||||
PlayerView playerView = root.findViewById(R.id.shuffle_exoplayer_view);
|
||||
playerView.setOnTouchListener(new SwipeListener(playerView, context) {
|
||||
@Override
|
||||
public void onSwipeLeft() { playNextClaim(); }
|
||||
@Override
|
||||
public void onSwipeRight() { playPreviousClaim(); }
|
||||
});
|
||||
|
||||
root.findViewById(R.id.shuffle_share_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (current != null) {
|
||||
try {
|
||||
String shareUrl = LbryUri.parse(
|
||||
!Helper.isNullOrEmpty(current.getCanonicalUrl()) ? current.getCanonicalUrl() :
|
||||
(!Helper.isNullOrEmpty(current.getShortUrl()) ? current.getShortUrl() : current.getPermanentUrl())).toTvString();
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, shareUrl);
|
||||
|
||||
MainActivity.startingShareActivity = true;
|
||||
Intent shareUrlIntent = Intent.createChooser(shareIntent, getString(R.string.share_lbry_content));
|
||||
shareUrlIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(shareUrlIntent);
|
||||
} catch (LbryUriException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
root.setOnTouchListener(new SwipeListener(root, context) {
|
||||
@Override
|
||||
public void onSwipeLeft() { playNextClaim(); }
|
||||
@Override
|
||||
public void onSwipeRight() { playPreviousClaim(); }
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private String getStreamingUrl() {
|
||||
return current != null ? String.format("https://cdn.lbryplayer.xyz/content/claims/%s/%s/stream", current.getName(), current.getClaimId()) : "";
|
||||
}
|
||||
|
||||
private Map<String, Object> buildContentOptions() {
|
||||
Context context = getContext();
|
||||
boolean canShowMatureContent = false;
|
||||
if (context != null) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
canShowMatureContent = sp.getBoolean(MainActivity.PREFERENCE_KEY_SHOW_MATURE_CONTENT, false);
|
||||
}
|
||||
|
||||
return Lbry.buildClaimSearchOptions(
|
||||
Claim.TYPE_STREAM,
|
||||
canShowMatureContent ? null : new ArrayList<>(Predefined.MATURE_TAGS),
|
||||
null/*contentChannelIds*/,
|
||||
Arrays.asList(Claim.ORDER_BY_TRENDING_GROUP),
|
||||
121, // 2 minutes or less
|
||||
1,
|
||||
currentClaimSearchPage == 0 ? 1 : currentClaimSearchPage,
|
||||
PAGE_SIZE);
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
MainActivity activity = (MainActivity) getContext();
|
||||
if (activity != null) {
|
||||
activity.hideFloatingWalletBalance();
|
||||
}
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
sessionStart = System.currentTimeMillis();
|
||||
MainActivity activity = (MainActivity) getContext();
|
||||
if (activity != null) {
|
||||
LbryAnalytics.setCurrentScreen(activity, "Shuffle", "Shuffle");
|
||||
}
|
||||
if (MainActivity.appPlayer != null && MainActivity.nowPlayingSource != MainActivity.SOURCE_NOW_PLAYING_SHUFFLE) {
|
||||
MainActivity.appPlayer.setPlayWhenReady(false);
|
||||
}
|
||||
|
||||
if (playlist == null) {
|
||||
loadContent();
|
||||
} else {
|
||||
if (current != null) {
|
||||
playbackCurrentClaim();
|
||||
} else {
|
||||
startPlaylist();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if (MainActivity.appPlayer != null && MainActivity.appPlayer.isPlaying()) {
|
||||
MainActivity.nowPlayingSource = MainActivity.SOURCE_NOW_PLAYING_SHUFFLE;
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
long sessionDuration = System.currentTimeMillis() - sessionStart;
|
||||
if (sessionStart > 0 && sessionDuration > 0) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong("duration_ms", sessionDuration);
|
||||
bundle.putInt("duration", Double.valueOf(Math.ceil(sessionDuration / 1000.0)).intValue());
|
||||
LbryAnalytics.logEvent(LbryAnalytics.EVENT_SHUFFLE_SESSION, bundle);
|
||||
}
|
||||
sessionStart = 0;
|
||||
|
||||
MainActivity activity = (MainActivity) getContext();
|
||||
if (activity != null) {
|
||||
activity.hideFloatingWalletBalance();
|
||||
|
||||
}
|
||||
|
||||
super.onStop();
|
||||
|
||||
}
|
||||
|
||||
private void loadContent() {
|
||||
if (playlist == null || playlist.size() == 0) {
|
||||
Helper.setViewVisibility(surfModeLoading, View.VISIBLE);
|
||||
}
|
||||
|
||||
Map<String, Object> claimSearchOptions = buildContentOptions();
|
||||
ClaimSearchTask task = new ClaimSearchTask(claimSearchOptions, Lbry.LBRY_TV_CONNECTION_STRING, null, new ClaimSearchResultHandler() {
|
||||
@Override
|
||||
public void onSuccess(List<Claim> claims, boolean hasReachedEnd) {
|
||||
if (playlist == null) {
|
||||
playlist = new ArrayList<>(claims);
|
||||
startPlaylist();
|
||||
} else {
|
||||
for (Claim claim : claims) {
|
||||
if (!playlist.contains(claim)) {
|
||||
playlist.add(claim);
|
||||
}
|
||||
}
|
||||
}
|
||||
Helper.setViewVisibility(surfModeLoading, View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception error) {
|
||||
Helper.setViewVisibility(surfModeLoading, View.GONE);
|
||||
}
|
||||
});
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void startPlaylist() {
|
||||
if (playlist == null || playlist.size() == 0) {
|
||||
return;
|
||||
}
|
||||
playlistIndex = 0;
|
||||
current = playlist.get(playlistIndex);
|
||||
checkCurrentClaimIsVideo(false);
|
||||
playbackCurrentClaim();
|
||||
}
|
||||
|
||||
private void checkCurrentClaimIsVideo(boolean previous) {
|
||||
while (current == null || current.getMediaType() == null || !current.getMediaType().startsWith("video")) {
|
||||
// only play videos
|
||||
if (previous) {
|
||||
playlistIndex--;
|
||||
} else {
|
||||
playlistIndex++;
|
||||
}
|
||||
current = playlist.get(playlistIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void playPreviousClaim() {
|
||||
if (playlist == null || playlist.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (playlistIndex > 0) {
|
||||
playlistIndex--;
|
||||
}
|
||||
current = playlist.get(playlistIndex);
|
||||
checkCurrentClaimIsVideo(true);
|
||||
playbackCurrentClaim();
|
||||
}
|
||||
private void playNextClaim() {
|
||||
if (playlist == null || playlist.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (playlistIndex < playlist.size() - 1) {
|
||||
playlistIndex++;
|
||||
}
|
||||
if (playlist.size() - playlistIndex < 10) {
|
||||
currentClaimSearchPage++;
|
||||
loadContent();
|
||||
}
|
||||
current = playlist.get(playlistIndex);
|
||||
checkCurrentClaimIsVideo(false);
|
||||
playbackCurrentClaim();
|
||||
}
|
||||
|
||||
private void playbackCurrentClaim() {
|
||||
resetPlayer();
|
||||
String publisherText = !Helper.isNullOrEmpty(current.getPublisherTitle()) ?
|
||||
String.format("%s (%s)", current.getPublisherTitle(), current.getPublisherName()) :
|
||||
!Helper.isNullOrEmpty(current.getPublisherName()) ? current.getPublisherName() : getString(R.string.anonymous);
|
||||
|
||||
textTitle.setText(current.getTitle());
|
||||
textPublisher.setText(publisherText);
|
||||
|
||||
Context context = getContext();
|
||||
if (MainActivity.appPlayer == null && context != null) {
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(C.USAGE_MEDIA)
|
||||
.setContentType(C.CONTENT_TYPE_MOVIE)
|
||||
.build();
|
||||
|
||||
MainActivity.appPlayer = new SimpleExoPlayer.Builder(context).build();
|
||||
MainActivity.appPlayer.setAudioAttributes(audioAttributes, true);
|
||||
MainActivity.playerCache =
|
||||
new SimpleCache(context.getCacheDir(),
|
||||
new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 256), new ExoDatabaseProvider(context));
|
||||
if (context instanceof MainActivity) {
|
||||
MainActivity activity = (MainActivity) context;
|
||||
activity.initMediaSession();
|
||||
activity.initPlaybackNotification();
|
||||
}
|
||||
if (playerListener != null) {
|
||||
MainActivity.appPlayer.addListener(playerListener);
|
||||
}
|
||||
|
||||
newPlayerCreated = true;
|
||||
}
|
||||
|
||||
if (context instanceof MainActivity) {
|
||||
MainActivity activity = (MainActivity) context;
|
||||
activity.initPlaybackNotification();
|
||||
}
|
||||
|
||||
View root = getView();
|
||||
if (root != null) {
|
||||
PlayerView view = root.findViewById(R.id.shuffle_exoplayer_view);
|
||||
view.setShutterBackgroundColor(Color.TRANSPARENT);
|
||||
view.setPlayer(MainActivity.appPlayer);
|
||||
view.setUseController(true);
|
||||
if (context instanceof MainActivity) {
|
||||
((MainActivity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
if (MainActivity.nowPlayingClaim != null &&
|
||||
MainActivity.nowPlayingClaim.getClaimId().equalsIgnoreCase(current.getClaimId()) &&
|
||||
!newPlayerCreated) {
|
||||
// if the claim is already playing, we don't need to reload the media source
|
||||
return;
|
||||
}
|
||||
|
||||
if (MainActivity.appPlayer != null) {
|
||||
showBuffering();
|
||||
if (context instanceof MainActivity) {
|
||||
((MainActivity) context).setNowPlayingClaim(current, current.getPermanentUrl());
|
||||
}
|
||||
|
||||
MainActivity.appPlayer.setPlayWhenReady(true);
|
||||
String userAgent = Util.getUserAgent(context, getString(R.string.app_name));
|
||||
String mediaSourceUrl = getStreamingUrl();
|
||||
MediaSource mediaSource = new ProgressiveMediaSource.Factory(
|
||||
new CacheDataSourceFactory(MainActivity.playerCache, new DefaultDataSourceFactory(context, userAgent)),
|
||||
new DefaultExtractorsFactory()
|
||||
).setLoadErrorHandlingPolicy(new FileViewFragment.StreamLoadErrorPolicy()).createMediaSource(Uri.parse(mediaSourceUrl));
|
||||
|
||||
MainActivity.appPlayer.prepare(mediaSource, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetPlayer() {
|
||||
elapsedDuration = 0;
|
||||
totalDuration = 0;
|
||||
renderElapsedDuration();
|
||||
renderTotalDuration();
|
||||
|
||||
elapsedPlaybackScheduled = false;
|
||||
if (elapsedPlaybackScheduler != null) {
|
||||
elapsedPlaybackScheduler.shutdownNow();
|
||||
elapsedPlaybackScheduler = null;
|
||||
}
|
||||
|
||||
playbackStarted = false;
|
||||
startTimeMillis = 0;
|
||||
|
||||
/*
|
||||
if (MainActivity.appPlayer != null) {
|
||||
MainActivity.appPlayer.stop(true);
|
||||
MainActivity.appPlayer.removeListener(fileViewPlayerListener);
|
||||
PlaybackParameters params = new PlaybackParameters(1.0f);
|
||||
MainActivity.appPlayer.setPlaybackParameters(params);
|
||||
}*/
|
||||
}
|
||||
|
||||
private void logPlay(String url, long startTimeMillis) {
|
||||
long timeToStartMillis = startTimeMillis > 0 ? System.currentTimeMillis() - startTimeMillis : 0;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("uri", url);
|
||||
bundle.putLong("time_to_start_ms", timeToStartMillis);
|
||||
bundle.putLong("time_to_start_seconds", Double.valueOf(timeToStartMillis / 1000.0).longValue());
|
||||
LbryAnalytics.logEvent(LbryAnalytics.EVENT_PLAY, bundle);
|
||||
|
||||
logFileView(current.getPermanentUrl(), timeToStartMillis);
|
||||
}
|
||||
|
||||
private void logFileView(String url, long timeToStart) {
|
||||
if (current != null) {
|
||||
LogFileViewTask task = new LogFileViewTask(url, current, timeToStart, new GenericTaskHandler() {
|
||||
@Override
|
||||
public void beforeStart() { }
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
claimEligibleRewards();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception error) { }
|
||||
});
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
private void showBuffering() {
|
||||
View root = getView();
|
||||
if (root != null) {
|
||||
root.findViewById(R.id.player_buffering_progress).setVisibility(View.VISIBLE);
|
||||
|
||||
PlayerView playerView = root.findViewById(R.id.shuffle_exoplayer_view);
|
||||
playerView.findViewById(R.id.player_skip_back_10).setVisibility(View.INVISIBLE);
|
||||
playerView.findViewById(R.id.player_skip_forward_10).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideBuffering() {
|
||||
View root = getView();
|
||||
if (root != null) {
|
||||
root.findViewById(R.id.player_buffering_progress).setVisibility(View.INVISIBLE);
|
||||
|
||||
PlayerView playerView = root.findViewById(R.id.shuffle_exoplayer_view);
|
||||
playerView.findViewById(R.id.player_skip_back_10).setVisibility(View.VISIBLE);
|
||||
playerView.findViewById(R.id.player_skip_forward_10).setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderElapsedDuration() {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Helper.setViewText(view.findViewById(R.id.player_duration_elapsed), Helper.formatDuration(Double.valueOf(elapsedDuration / 1000.0).longValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private void renderTotalDuration() {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Helper.setViewText(view.findViewById(R.id.player_duration_total), Helper.formatDuration(Double.valueOf(totalDuration / 1000.0).longValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAndScheduleDurations() {
|
||||
if (MainActivity.appPlayer != null && playbackStarted) {
|
||||
elapsedDuration = MainActivity.appPlayer.getCurrentPosition() < 0 ? 0 : MainActivity.appPlayer.getCurrentPosition();
|
||||
totalDuration = MainActivity.appPlayer.getDuration() < 0 ? 0 : MainActivity.appPlayer.getDuration();
|
||||
|
||||
renderElapsedDuration();
|
||||
renderTotalDuration();
|
||||
scheduleElapsedPlayback();
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleElapsedPlayback() {
|
||||
if (!elapsedPlaybackScheduled) {
|
||||
elapsedPlaybackScheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
elapsedPlaybackScheduler.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Context context = getContext();
|
||||
if (context instanceof MainActivity) {
|
||||
((MainActivity) context).runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (MainActivity.appPlayer != null) {
|
||||
elapsedDuration = MainActivity.appPlayer.getCurrentPosition();
|
||||
int elapsedSeconds = Double.valueOf(elapsedDuration / 1000.0).intValue();
|
||||
renderElapsedDuration();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
||||
elapsedPlaybackScheduled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this call to MainActivity?
|
||||
private void claimEligibleRewards() {
|
||||
// attempt to claim eligible rewards after viewing or playing a file (fail silently)
|
||||
Context context = getContext();
|
||||
ClaimRewardTask firstStreamTask = new ClaimRewardTask(Reward.TYPE_FIRST_STREAM, null, null, context, eligibleRewardHandler);
|
||||
ClaimRewardTask dailyViewTask = new ClaimRewardTask(Reward.TYPE_DAILY_VIEW, null, null, context, eligibleRewardHandler);
|
||||
firstStreamTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
dailyViewTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private ClaimRewardTask.ClaimRewardHandler eligibleRewardHandler = new ClaimRewardTask.ClaimRewardHandler() {
|
||||
@Override
|
||||
public void onSuccess(double amountClaimed, String message) {
|
||||
if (Helper.isNullOrEmpty(message)) {
|
||||
message = getResources().getQuantityString(
|
||||
R.plurals.claim_reward_message,
|
||||
amountClaimed == 1 ? 1 : 2,
|
||||
new DecimalFormat(Helper.LBC_CURRENCY_FORMAT_PATTERN).format(amountClaimed));
|
||||
}
|
||||
Context context = getContext();
|
||||
if (context instanceof MainActivity) {
|
||||
((MainActivity) context).showMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception error) {
|
||||
// pass
|
||||
}
|
||||
};
|
||||
|
||||
private static class SwipeListener implements View.OnTouchListener {
|
||||
private final GestureDetector gestureDetector;
|
||||
private final View control;
|
||||
public SwipeListener(View control, Context context) {
|
||||
this.control = control;
|
||||
gestureDetector = new GestureDetector(context, new SwipeGestureListener());
|
||||
}
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
return gestureDetector.onTouchEvent(motionEvent);
|
||||
}
|
||||
|
||||
public void onSwipeLeft() { }
|
||||
public void onSwipeRight() { }
|
||||
public void onSwipeTop() { }
|
||||
public void onSwipeBottom() { }
|
||||
|
||||
private final class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
private static final int SWIPE_THRESHOLD = 100;
|
||||
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent e) {
|
||||
if (control instanceof PlayerView) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
boolean result = false;
|
||||
try {
|
||||
float diffY = e2.getY() - e1.getY();
|
||||
float diffX = e2.getX() - e1.getX();
|
||||
if (Math.abs(diffX) > Math.abs(diffY)) {
|
||||
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
|
||||
if (diffX > 0) {
|
||||
onSwipeRight();
|
||||
} else {
|
||||
onSwipeLeft();
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
|
||||
if (diffY > 0) {
|
||||
onSwipeBottom();
|
||||
} else {
|
||||
onSwipeTop();
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// pass
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldHideGlobalPlayer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final List<String> contentChannelIds = Arrays.asList(
|
||||
"3fec094c5937e9eb4e8f5e71e4ca430e8a993d03",
|
||||
"6184648aab0431c4c95c649072d1f9ff08b9bb7c",
|
||||
"b5d31cde873073718c033076656a27471e392afc",
|
||||
"7317cdf6f62be93b22295062e191f6ba59a5db26",
|
||||
"1cdb5d0bdcb484907d0a2fea4efdfe0153838642",
|
||||
"b516294f541a18ce00b71a60b2c82ad2f87ff78d",
|
||||
"91e42cc450075f2c4c245bac7617bf903f16b4ce",
|
||||
"b6e207c5f8c58e7c8362cd05a1501bf2f5b694f2",
|
||||
"25f384bd95e218f6ac37fcaca99ed40f36760d8c",
|
||||
"f33657a2fcbab2dc3ce555d5d6728f8758af7bc7",
|
||||
"294f5c164da5ac9735658b2d58d8fee6745dfc45",
|
||||
"119a2e8c0b50f78d3861636d37c3b44ba8e689b5",
|
||||
"7b23cca3f49059f005e812be03931c81272eaac4",
|
||||
"fb0efeaa3788d1292bb49a94d77622503fe08129",
|
||||
"797a528c49b6535560f7fd8222b121b0223287c8",
|
||||
"bc490776f367b8afccf0ea7349d657431ba1ded6",
|
||||
"48c7ea8bc2c4adba09bf21a29689e3b8c2967522",
|
||||
"bf7490f905904e79de5c90e472bb9e6f26e634a0",
|
||||
"df961194a798cc76306b9290701130c592530fb6",
|
||||
"cf0be9078d76951e2e228df68b5b0bbf71313aaa",
|
||||
"d746ac8d782f94d12d176c7a591f5bf8365bef3d",
|
||||
"1f30267438257020f08abf452746a48e53a71ad5",
|
||||
"4ad942982e43326c7700b1b6443049b3cfd82161",
|
||||
"1cdb5d0bdcb484907d0a2fea4efdfe0153838642",
|
||||
"6616707e1109aaa1c11b9f399f914d0cfb4f5303",
|
||||
"4ee7cfaf1fc50a6df858ed0b99c278d633bccca9",
|
||||
"b7d02b4a0036114732c072269adb891dc5e34ca4",
|
||||
"9c51c1a119137cd17ed5ae09daa80c1cab6ac01d",
|
||||
"5f2a5c14b971a6f5eed0a67dc7af3a3fe5c0b6a4",
|
||||
"0e2b5b4cf59e859860000ff123dc12a317ad416b",
|
||||
"3fe68ad3da93065e35c37b14fbeef88b4b7785ed",
|
||||
"fd7ffcbafb74412a8812df4720feaf11fe70fe12",
|
||||
"b4c30fe36b79870a79c55e1e909adb5ad23f323f",
|
||||
"92c0f2f3239f1f61496997bd2cdc197ec51bd423",
|
||||
"29193e9240a71a735639c66ee954e68414f11236",
|
||||
"25f384bd95e218f6ac37fcaca99ed40f36760d8c",
|
||||
"87b13b074936b1f42a7c6758c7c2995f58c602e7",
|
||||
"8d935c6c30510e1dfc10f803a9646fa8aa128b07",
|
||||
"8f4fecfc836ea33798ee3e5cef56926fa54e2cf9",
|
||||
"9a5dfcb1a4b29c3a1598392d039744b9938b5a26",
|
||||
"c5724e280283cd985186af9a62494aae377daabd",
|
||||
"b39833be3032bbe1005f4f719f379a4621faeb13",
|
||||
"589276465a23c589801d874f484cc39f307d7ec7",
|
||||
"fb364ef587872515f545a5b4b3182b58073f230f",
|
||||
"6c0bf1fed2705d675da950a94e4af004ec975a06",
|
||||
"b924ac36b7499591f7929d9c4903de79b07b1cb9",
|
||||
"113515e893b8186595595e594ecc410bae50c026",
|
||||
"72f9815b087b6d346745e3de71a6ce5fe73a8677",
|
||||
"b0198a465290f065378f3535666bee0653d6a9bb",
|
||||
"020ebeb40642bfb4bc3d9f6d28c098afc0a47481",
|
||||
"5c15e604c4207f52c8cf58fe21e63164c230e257",
|
||||
"273a2fa759f1a9f56b078633ea2f08fc2406002a",
|
||||
"930fc43ca7bae20d4706543e97175d1872b0671f",
|
||||
"0cb2ec46f06ba85520a1c1a56706acf35d5176dd",
|
||||
"057053dfb657aaa98553e2c544b06e1a2371557e",
|
||||
"64e091964a611a48424d254a3de2b952d0d6565a",
|
||||
"50ebba2b06908f93d7963b1c6826cc0fd6104477",
|
||||
"374ff82251a384601da73f30485c3ac8d7f4176b",
|
||||
"1487afc813124abbeb0629d2172be0f01ccec3bf",
|
||||
"6a4fa1a68b92336e64006a4310cb160b07854329",
|
||||
"15f986a262fc6eff5774050c94d174c0533d505d",
|
||||
"6184648aab0431c4c95c649072d1f9ff08b9bb7c",
|
||||
"1efa9b640ad980b2ec53834d60e9cff9554979cd",
|
||||
"064d4999ea15e433e06f16f391922390acab01cb",
|
||||
"4884e30b93b3c4c123a83154516196095f9e831e",
|
||||
"2827bfc459c12d7c6d280cbacee750811291d4ba",
|
||||
"9626816275585ac3443e7cddd1272c8652c23f1d",
|
||||
"a2e1bb1fed32c6a6290b679785dd31ca5c59cb5f",
|
||||
"d9535951222dd7a1ff7f763872cb0df44f7962bf",
|
||||
"243b6f18093ff97c861d0568c7d3379606201a4b",
|
||||
"1ce5ac7bab7f2e82af02305ced3c095e320b52e5",
|
||||
"3e63119a8503a6f666b0a736c8fdeb9e79d11eb4",
|
||||
"e33372c0d8b2cdd3e12252962ee1671d66143075",
|
||||
"7364ba2ac9090e468855ce9074bb50c306196f4c",
|
||||
"d6350f9158825662b99e4b5e0442bcc94d39bc11",
|
||||
"2a294ea41312c6da8de5ebd0f18dbfb2963bb1a4",
|
||||
"44c49bbab8a3e9999f3ba9dee0186288b1d960a7",
|
||||
"2305db36455aa0d18571015b9e9bd0950262aa0f",
|
||||
"82f1d8c257d3e76b711a5cecd1e49bd3fa6a9de9",
|
||||
"faed2b028a9b5a712d5180eaa6fd2aa619f941bc",
|
||||
"39ac239b5687f7d1c2ba74cd020b3547545dfdaf",
|
||||
"5737eb22f6119f27c9afccfe73ba710afd885371",
|
||||
"5f22b6daf7204d73cf79d3ff0b46fc4fe237c7f7",
|
||||
"3583f5a570af6870504eea5a5f7afad6e1508508",
|
||||
"b0e489f986c345aef23c4a48d91cbcf5a6fdb9ac",
|
||||
"ba79c80788a9e1751e49ad401f5692d86f73a2db",
|
||||
"c54323436f50c633c870298bb374ac8e7560e6cd",
|
||||
"83725c7ee23bd4a8ca28a4fab0e313409def1dc7",
|
||||
"61c4e8636704f2f38bbe88b1f30ef0d74d6c0f49",
|
||||
"87ef9ba36019f7f3bf217cf47511645893b13f2e",
|
||||
"1bd0adfcf1c75bafc1ba3fc9b65a1a0470df6a91",
|
||||
"1be15348c51955179b7bf9aa90230a9425927ef6",
|
||||
"1f45ab3495df2c3be7d9c882bca9966305115cbb",
|
||||
"7317777e3751efa66218f6da5ef0d01dda69af48",
|
||||
"3346a4ff80b70ee7eea8a79fc79f19c43bb4464a",
|
||||
"452916a904030d2ce4ea2440fad2d0774e7296d9",
|
||||
"2675ef3adf52ebf8a44ff5da4306c293dfa6f901",
|
||||
"e2a76643735f8611a561794509c6bb2aac70eb04",
|
||||
"dc577db3caf5ff83a3b573ba92f2d447f067eee1",
|
||||
"89c4cf244099918b1d3ed413df27d4216e97b499",
|
||||
"4b2b5822c8af3074c6ef9b789a8142d0ef623402",
|
||||
"3c5794f775975669745c412b0c30f48991d9e455",
|
||||
"1df464dbb302ced815c61431a5548a273e6de8e1"
|
||||
);
|
||||
}
|
|
@ -4,9 +4,13 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.preference.EditTextPreference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
|
@ -23,6 +27,15 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
|
|||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.settings, rootKey);
|
||||
PreferenceManager manager = getPreferenceManager();
|
||||
|
||||
EditTextPreference miniPlayerBottomMarginPreference = manager.findPreference(MainActivity.PREFERENCE_KEY_MINI_PLAYER_BOTTOM_MARGIN);
|
||||
miniPlayerBottomMarginPreference.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
|
||||
@Override
|
||||
public void onBindEditText(@NonNull EditText editText) {
|
||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -375,6 +375,23 @@ public final class Lbry {
|
|||
"any_tags", "channel_ids", "order_by", "not_tags", "not_channel_ids", "urls"
|
||||
};
|
||||
|
||||
// build claim search for surf mode
|
||||
public static Map<String, Object> buildClaimSearchOptions(
|
||||
String claimType, List<String> notTags, List<String> channelIds, List<String> orderBy, long maxDuration, int limitClaimsPerChannel, int page, int pageSize) {
|
||||
return buildClaimSearchOptions(
|
||||
Collections.singletonList(claimType),
|
||||
null,
|
||||
notTags,
|
||||
channelIds,
|
||||
null,
|
||||
orderBy,
|
||||
null,
|
||||
maxDuration,
|
||||
limitClaimsPerChannel,
|
||||
page,
|
||||
pageSize);
|
||||
}
|
||||
|
||||
public static Map<String, Object> buildClaimSearchOptions(
|
||||
String claimType,
|
||||
List<String> anyTags,
|
||||
|
@ -393,6 +410,8 @@ public final class Lbry {
|
|||
notChannelIds,
|
||||
orderBy,
|
||||
releaseTime,
|
||||
0,
|
||||
0,
|
||||
page,
|
||||
pageSize);
|
||||
}
|
||||
|
@ -405,6 +424,8 @@ public final class Lbry {
|
|||
List<String> notChannelIds,
|
||||
List<String> orderBy,
|
||||
String releaseTime,
|
||||
long maxDuration,
|
||||
int limitClaimsPerChannel,
|
||||
int page,
|
||||
int pageSize) {
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
|
@ -417,6 +438,12 @@ public final class Lbry {
|
|||
if (!Helper.isNullOrEmpty(releaseTime)) {
|
||||
options.put("release_time", releaseTime);
|
||||
}
|
||||
if (maxDuration > 0) {
|
||||
options.put("duration", String.format("<%d", maxDuration));
|
||||
}
|
||||
if (limitClaimsPerChannel > 0) {
|
||||
options.put("limit_claims_per_channel", limitClaimsPerChannel);
|
||||
}
|
||||
|
||||
addClaimSearchListOption("any_tags", anyTags, options);
|
||||
addClaimSearchListOption("not_tags", notTags, options);
|
||||
|
|
|
@ -26,6 +26,7 @@ public class LbryAnalytics {
|
|||
public static final String EVENT_PUBLISH_UPDATE = "publish_update";
|
||||
public static final String EVENT_CHANNEL_CREATE = "channel_create";
|
||||
public static final String EVENT_SEARCH = "search";
|
||||
public static final String EVENT_SHUFFLE_SESSION = "shuffle_session";
|
||||
|
||||
public static void init(Context context) {
|
||||
|
||||
|
|
87
app/src/main/res/layout/fragment_shuffle.xml
Normal file
87
app/src/main/res/layout/fragment_shuffle.xml
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<RelativeLayout
|
||||
android:background="@android:color/black"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/shuffle_exoplayer_container"
|
||||
android:background="@android:color/black"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@id/shuffle_content_details">
|
||||
<com.google.android.exoplayer2.ui.PlayerView
|
||||
android:id="@+id/shuffle_exoplayer_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:controller_layout_id="@layout/exo_playback_control_view"/>
|
||||
<ProgressBar
|
||||
android:id="@+id/player_buffering_progress"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/shuffle_content_details"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_alignParentBottom="true">
|
||||
<TextView
|
||||
android:id="@+id/shuffle_content_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/inter"
|
||||
android:textColor="@color/white"
|
||||
android:textFontWeight="300"
|
||||
android:minLines="1"
|
||||
android:maxLines="3"
|
||||
android:textSize="20sp"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/shuffle_content_publisher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/inter"
|
||||
android:textColor="@color/white"
|
||||
android:textFontWeight="300"
|
||||
android:minLines="1"
|
||||
android:maxLines="1"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/shuffle_loading"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/shuffle_share_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:clickable="true"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:tint="@color/white"
|
||||
android:src="@drawable/ic_share" />
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.slideshow.SlideshowFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_slideshow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,605 +0,0 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
<string name="app_name">LBRY</string>
|
||||
<string name="navigation_drawer_open">Avaa navigointilaatikko</string>
|
||||
<string name="navigation_drawer_close">Sulje navigointilaatikko</string>
|
||||
|
||||
<!-- Nav menu -->
|
||||
<string name="find_content">Etsi sisältöä</string>
|
||||
<string name="your_content">Sinun sisältö</string>
|
||||
<string name="wallet">Lompakko</string>
|
||||
<string name="following">Seuraamassa</string>
|
||||
<string name="editors_choice">Toimittajan valinta</string>
|
||||
<string name="your_tags">Sinun Tunnisteet</string>
|
||||
<string name="all_content">Kaikki sisältö</string>
|
||||
<string name="channels">Kanavat</string>
|
||||
<string name="library">Kirjasto</string>
|
||||
<string name="publishes">Julkaisut</string>
|
||||
<string name="new_publish">Uusi julkaisu</string>
|
||||
<string name="rewards">Palkinnot</string>
|
||||
<string name="invites">Kutsut</string>
|
||||
<string name="settings">Asetukset</string>
|
||||
<string name="about">Noin</string>
|
||||
<string name="sign_in">Kirjaudu sisään</string>
|
||||
<string name="startup_failed">Sovelluksen käynnistys epäonnistui. Tarkista datayhteys ja yritä uudelleen. Jos tämä ongelma jatkuu, lähetä sähköpostia osoitteeseen hello@lbry.com</string>
|
||||
<string name="no_claim_search_content">Ei näytettävää sisältöä tällä hetkellä. Tarkenna valintaasi tai tarkista myöhemmin uudelleen.</string>
|
||||
|
||||
<!-- Welcome Page -->
|
||||
<string name="welcome_to_lbry">Tervetuloa LBRY:lle</string>
|
||||
<string name="welcome_paragraph">LBRY on yhteisön ohjaama sisältöalusta, josta voit löytää ja julkaista videoita, musiikkia, kirjoja ja paljon muuta.</string>
|
||||
<string name="welcome_tos">Jatkamalla, hyväksyn <a href=\"https://lbry.com/termsofservice\">Terms of Service</a> ja vahvistan että olen yli 13vuotias.</string>
|
||||
<string name="welcome_please_wait">Odota, kunnes saamme asiat valmiiksi ...</string>
|
||||
<string name="use_lbry">Käytä LBRY »</string>
|
||||
|
||||
<!-- URI bar -->
|
||||
<string name="uri_placeholder">Etsi videoita, musiikkia ja muuta</string>
|
||||
|
||||
<!-- Following page -->
|
||||
<string name="find_channels_to_follow">Etsi seurattavat kanavat</string>
|
||||
<string name="channels_you_follow">Kanavat joita seuraat</string>
|
||||
<string name="discover">Tutustu</string>
|
||||
<string name="lbry_works_better">LBRY toimii paremmin, jos seuraat vähintään 5 haluamaasi tekijää. Kirjaudu sisään näyttääksesi seuraamasi tekijät, jos sinulla on jo tili.</string>
|
||||
<string name="select_five_subscriptions">Valitse enintään 5 tekijää jatkaaksesi.</string>
|
||||
<string name="n_remaining">%1$djäljellä...</string>
|
||||
<string name="done">Tehty</string>
|
||||
<string name="all">Kaikki</string>
|
||||
<string name="discover_channels">Löydä uusia kanavia</string>
|
||||
|
||||
<!-- Claim lists -->
|
||||
<string name="anonymous">Anonyymi</string>
|
||||
|
||||
<!-- File view -->
|
||||
<string name="tags">Tunnisteet</string>
|
||||
<string name="share">Jaa</string>
|
||||
<string name="repost">Repost</string>
|
||||
<string name="tip">Tippi</string>
|
||||
<string name="edit">Muokkaa</string>
|
||||
<string name="delete">Poista</string>
|
||||
<string name="download">Lataa</string>
|
||||
<string name="open">Avoin</string>
|
||||
<string name="report">Ilmianna</string>
|
||||
<string name="loading_decentralized_data">Ladataan hajautettua tietoa ...</string>
|
||||
<string name="related_content">Samankaltaista sisältöä</string>
|
||||
<string name="comments">Kommentit</string>
|
||||
<string name="no_comments">Ei kommentteja näytettäväksi tällä hetkellä.</string>
|
||||
<string name="sdk_initializing_comments">Kommentit tulevat näkyviin, kun taustapalvelu on alustettu.</string>
|
||||
<string name="comment_error">Kommenttiasi ei voitu lähettää tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<string name="share_lbry_content">Jaa LBRY-sisältö</string>
|
||||
<string name="view">Näytä</string>
|
||||
<string name="play">Toista</string>
|
||||
<string name="unsupported_content">Ei tuettu sisältö</string>
|
||||
<string name="unsupported_content_desc">Valitettavasti emme pysty näyttämään tätä sisältöä sovelluksessa. Löydät tiedoston %1$s latauskansiostasi.</string>
|
||||
<string name="nothing_at_this_location">Tässä paikassa ei ole mitään.</string>
|
||||
<string name="publish_something_here">Julkaise jotain täällä</string>
|
||||
<string name="cannot_view_claim">Tätä sisältöä ei voida käyttää tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<string name="zero_duration">0:00</string>
|
||||
<string name="claim_file_not_found">Tiedostoa kohteessa \"%1$s\" ei ole.</string>
|
||||
<string name="confirm_purchase">Vahvista ostos</string>
|
||||
<string name="delete_file">Poista tiedosto</string>
|
||||
<string name="confirm_delete_file_message">Haluatko varmasti poistaa tämän tiedoston laitteestasi?</string>
|
||||
<string name="unable_to_view_url">Lataus epäonnistui %1$s.Yritä uudelleen myöhemmin.</string>
|
||||
<string name="no_cast_session_available">Tällä hetkellä ei ole saatavana suoratoistoistuntoa.</string>
|
||||
<string name="delete_content">Poistetaanko sisältö?</string>
|
||||
<string name="confirm_delete_content_message">Haluatko varmasti poistaa tämän sisällön julkaisun? Laitteistasi ei poisteta tiedostoja.</string>
|
||||
<string name="content_deleted">Sisältö poistettiin onnistuneesti lohkoketjusta.</string>
|
||||
<string name="content_failed_delete">Sisältöä ei voitu poistaa tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<string name="comment">Kommentti</string>
|
||||
<string name="comment_as">Kommentoi nimellä</string>
|
||||
<string name="please_enter_comment">Kirjoita kommentti lähettääksesi viestin.</string>
|
||||
<string name="please_select_channel">Valitse kanava, johon haluat lähettää kommenttisi.</string>
|
||||
<string name="comment_posted">Kommenttisi lähetetty onnistuneesti.</string>
|
||||
<string name="please_select_repost_channel">Valitse kanava, johon haluat lähettää uudelleen.</string>
|
||||
<string name="reply">Vastaa</string>
|
||||
<string name="replying_to">Vastaa käyttäjille %1$s</string>
|
||||
<plurals name="post_and_tip">
|
||||
<item quantity="one">Posti- ja tip-l%1$s uottotiedot?</item>
|
||||
<item quantity="other">Posti- ja tippi %1$s krediitit?</item>
|
||||
</plurals>
|
||||
<plurals name="post_for_credits">
|
||||
<item quantity="one">Lähetä %1$s krediitillä</item>
|
||||
<item quantity="other">Post for %1$scredits</item>
|
||||
</plurals>
|
||||
<plurals name="confirm_post_comment">
|
||||
<item quantity="one">Tämä lähettää kommenttisi %1$s hyvityksellä %2$s</item>
|
||||
<item quantity="other">Tämä lähettää kommenttisi %1$s hyvityksellä %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="view_count">
|
||||
<item quantity="one">%1$s Näyttökertaa</item>
|
||||
<item quantity="other">%1$s Näyttökertaa</item>
|
||||
</plurals>
|
||||
<plurals name="confirm_purchase_message">
|
||||
<item quantity="one">Tämä ostos \"%1$s\" maksaa %2$s Crediittiä</item>
|
||||
<item quantity="other">Tämä ostos \"%1$s\" maksaa %2$s Crediittiä</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Channel view -->
|
||||
<string name="no_channel_info">Täällä ei ole vielä mitään.\nTarkista myöhemmin uudelleen.</string>
|
||||
<string name="content">Sisältö</string>
|
||||
<string name="website">Nettisivu</string>
|
||||
<string name="reposted">uudelleen julkaistu</string>
|
||||
<plurals name="follower_count">
|
||||
<item quantity="one">%1$s Seuraaja</item>
|
||||
<item quantity="other">%1$s Seuraajaa</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Publish -->
|
||||
<string name="no_publishes_created">Näyttää siltä, että et ole vielä julkaissut sisältöä LBRY: lle.</string>
|
||||
<string name="record">Tallentaa</string>
|
||||
<string name="take_photo">Ota kuva</string>
|
||||
<string name="upload_file">Lähetä tiedosto</string>
|
||||
<string name="no_videos_found">Laitteestasi ei löytynyt videoita. Ota valokuva tai nauhoita video aloittaaksesi.</string>
|
||||
<string name="loading_videos">Odota, kun lataamme videoitasi ...</string>
|
||||
<string name="storage_permission_rationale_videos">LBRY vaatii pääsyn voidaksesi näyttää ja julkaista videoitasi, kuvia ja muita tiedostoja laitteeltasi.</string>
|
||||
<string name="camera_permission_rationale_record">LBRY vaatii pääsyn kameraan videoiden tallentamiseksi.</string>
|
||||
<string name="camera_permission_rationale_photo">LBRY vaatii pääsyn kameraan valokuvien ottamista varten.</string>
|
||||
<string name="edit_content">Muokkaa sisältöä</string>
|
||||
<string name="mature_tags">Kypsät tunnisteet</string>
|
||||
<string name="price">Hinta</string>
|
||||
<string name="free_publish">Sisältösi on ilmaista. Aseta hinta painamalla kytkintä.</string>
|
||||
<string name="content_address">Sisältöosoite</string>
|
||||
<string name="randomize">Satunnainen</string>
|
||||
<string name="address">Osoite</string>
|
||||
<string name="content_address_desc">Osoite, josta ihmiset voivat löytää sisältösi (esim. Lbry://myvideo)</string>
|
||||
<string name="license">Lisenssi</string>
|
||||
<string name="license_desc">Kuvaus</string>
|
||||
<string name="additional_options">Lisävaihtoehtoja</string>
|
||||
<string name="show_extra_fields">Näytä ylimääräiset kentät</string>
|
||||
<string name="hide_extra_fields">Piilota ylimääräiset kentät</string>
|
||||
<string name="no_file_found">Tiedostoa ei löytynyt julkaistavaksi.</string>
|
||||
<string name="publish_invalid_claim_type">Muokkaamiseen määritetty virheellinen vaatimus.</string>
|
||||
<string name="video_optimization">Videon optimointi</string>
|
||||
<string name="thumbnail_creation_failed">Pikkukuvaa ei voitu luoda automaattisesti sisältötiedostostasi.</string>
|
||||
<string name="video_being_optimized">Videosi on optimoitu paremman tuen tarjoamiseksi monille laitteille. Voit täyttää jäljellä olevat kentät alla, kun tämä on käynnissä.</string>
|
||||
<string name="video_optimized">Videosi optimoitiin onnistuneesti parempaan toistoon mahdollisimman monissa laitteissa. Jatka julkaisemasi sisältöä.</string>
|
||||
<string name="video_optimize_failed">Videota ei voitu optimoida. Tiedosto ladataan ilman muutoksia.</string>
|
||||
<string name="completed_video_duration">Valmistunut videon kesto: %1$s</string>
|
||||
<string name="sdk_initializing_publish">Et voi julkaista sisältöä tällä hetkellä, koska taustapalvelu on edelleen alustamassa.</string>
|
||||
<string name="publish_successful">Sisällön julkaiseminen onnistui. Voi kestää hetken, että näyttöön pääsyketju.</string>
|
||||
<string name="transcode_in_progress">Videon optimointi on käynnissä. Jos haluat peruuttaa, paina Peruuta sivun alaosassa.</string>
|
||||
<string name="optimization_in_progress">Videon optimointi on käynnissä.</string>
|
||||
<string name="cannot_capture_video">Tällä laitteella ei ole käytettävissä kamerasovellusta videoiden nauhoittamiseen.</string>
|
||||
<string name="cannot_take_photo">Tällä laitteella ei ole käytettävissä kamerasovellusta valokuvien ottamiseen.</string>
|
||||
|
||||
<string name="please_provide_title">Anna otsikko.</string>
|
||||
<string name="please_specify_address">Määritä osoite, josta ihmiset voivat löytää sisältösi.</string>
|
||||
<string name="address_invalid_characters">Sisältöosoitteesi sisältää virheellisiä merkkejä.</string>
|
||||
<string name="address_already_used">Olet jo julkaissut määritettyyn sisältöosoitteeseen. Anna uusi osoite.</string>
|
||||
<string name="no_file_selected">Ei tiedostoa valittuna. Valitse video tai ota valokuva tai valitse tiedosto ennen julkaisemista.</string>
|
||||
<string name="price_amount_not_set">Anna hinta tai kytke kytkin pois päältä, jotta sisältösi on ilmaista.</string>
|
||||
<string name="publish_no_thumbnail">Valitse ladattava pikkukuva ennen julkaisua.</string>
|
||||
<string name="publish_thumbnail_in_progress">Odota, että pikkukuva latautuu loppuun ennen julkaisua.</string>
|
||||
|
||||
<string name="language">Kieli</string>
|
||||
<string name="english">Englanti</string>
|
||||
<string name="chinese">Kiina</string>
|
||||
<string name="french">Ranska</string>
|
||||
<string name="german">Saksa</string>
|
||||
<string name="japanese">Japani</string>
|
||||
<string name="russian">Venäjä</string>
|
||||
<string name="spanish">Espanja</string>
|
||||
<string name="indonesian">Indoneesia</string>
|
||||
<string name="italian">Italia</string>
|
||||
<string name="dutch">Hollanti</string>
|
||||
<string name="turkish">Turkki</string>
|
||||
<string name="polish">Puola</string>
|
||||
<string name="malay">Malaiji</string>
|
||||
<string name="portuguese">Portugali</string>
|
||||
<string name="vietnamese">Vietnami</string>
|
||||
<string name="thai">Thaimaa</string>
|
||||
<string name="arabic">Arabi</string>
|
||||
<string name="czech">Tshekki</string>
|
||||
<string name="croatian">Kroatia</string>
|
||||
<string name="cambodian">Kambodžan</string>
|
||||
<string name="korean">Korea</string>
|
||||
<string name="norwegian">Norja</string>
|
||||
<string name="romanian">Romaania</string>
|
||||
<string name="hindi">Hindi</string>
|
||||
<string name="greek">Kreikka</string>
|
||||
<string name="catalan">Katalaani</string>
|
||||
|
||||
<string name="none">Ei mitään</string>
|
||||
<string name="public_domain">Julkinen</string>
|
||||
<string name="copyrighted">Tekijänoikeudella suojattuja ...</string>
|
||||
<string name="cca_4_0_international">Creative Commons Attribution 4.0 International</string>
|
||||
<string name="cca_sa_4_0_international">Creative Commons Attribution-ShareAlike 4.0 International</string>
|
||||
<string name="cca_nd_4_0_international">Creative Commons Attribution-NoDerivatives 4.0 International</string>
|
||||
<string name="cca_nc_4_0_international">Creative Commons Attribution-NonCommercial 4.0 International</string>
|
||||
<string name="cca_nc_sa_4_0_international">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</string>
|
||||
<string name="cca_nc_nd_4_0_international">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International</string>
|
||||
|
||||
<string-array name="publish_currencies">
|
||||
<item>LBC</item>
|
||||
<item>USD</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Publishes -->
|
||||
<string name="one_or_more_publishes_failed_abandon">Yhtä tai useampaa sisältökohdetta ei voitu poistaa tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<plurals name="confirm_delete_publishes">
|
||||
<item quantity="one">Haluatko varmasti poistaa valitut sisältökohteet?</item>
|
||||
<item quantity="other">Haluatko varmasti poistaa valitut sisältökohteet?</item>
|
||||
</plurals>
|
||||
<plurals name="publishes_deleted">
|
||||
<item quantity="one">Sisältökohteet poistettiin onnistuneesti.</item>
|
||||
<item quantity="other">Sisältökohteet poistettiin onnistuneesti.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Splash -->
|
||||
<string name="oops_something_went_wrong">Oho! Jotain meni pieleen.</string>
|
||||
<string name="installation_id_loaded">Ladattu asennustunnus.</string>
|
||||
<string name="known_tags_loaded">Ladattu paikalliset tunnetut ja seuratut tunnisteet.</string>
|
||||
<string name="exchange_rate_loaded">Ladattu LBC / USD-vaihtokurssi.</string>
|
||||
<string name="user_authenticated">Käyttäjän todennettu.</string>
|
||||
<string name="installation_registered">Asennus rekisteröity.</string>
|
||||
<string name="subscriptions_loaded">Ladatut tilaukset.</string>
|
||||
<string name="subscriptions_resolved">Ratkaistut tilaukset.</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="user_interface">Content & Käyttäjä näkymä</string>
|
||||
<string name="other">Muu</string>
|
||||
<string name="enable_background_playback">Ota taustamedian toisto käyttöön</string>
|
||||
<string name="enable_dark_mode">Ota tumma teema käyttöön</string>
|
||||
<string name="show_mature_content">Näytä kypsä sisältö</string>
|
||||
<string name="show_url_suggestions">Näytä URL-ehdotukset</string>
|
||||
<string name="notifications">Ilmoitukset</string>
|
||||
<string name="subscriptions">Tilaukset</string>
|
||||
<string name="content_interests">Sisältö kiinnostaa</string>
|
||||
|
||||
<string name="keep_sdk_in_background">Pidä LBRY-palvelu käynnissä taustalla parantaaksesi lompakkoa ja verkon suorituskykyä</string>
|
||||
<string name="participate_in_data_network">Osallistu tietoverkkoon (vaatii sovelluksen ja taustapalvelun uudelleenkäynnistyksen)</string>
|
||||
|
||||
<!-- URL suggestions -->
|
||||
<string name="search_url_title">%1$s - Etsi</string>
|
||||
<string name="tag_url_title">%1$s - Tunniste</string>
|
||||
<string name="search_url_desc">Etsi \'%1$s\'</string>
|
||||
<string name="explore_tag_url_desc">Tutustu \'%1$s\' Tunnisteeseen</string>
|
||||
<string name="view_file_url_desc">Näytä sisältöä %1$s</string>
|
||||
<string name="view_channel_url_desc">Näytä %1$s kanava</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_no_results">Ei tuloksia, joita näyttää \'%1$s\'. Kokeile toista hakutermiä.</string>
|
||||
<string name="search_no_query">Voit etsiä mitä tahansa, mukaan lukien elokuvat, musiikki, e-kirjat, ohjelmistot ja paljon muuta.</string>
|
||||
<string name="no_related_content">Ei liittyvää sisältöä näytettäväksi tällä hetkellä.</string>
|
||||
|
||||
<!-- Wallet -->
|
||||
<string name="balance">Saldo</string>
|
||||
<string name="you_currently_have">Sinulla on tällä hetkellä</string>
|
||||
<string name="convert_credits">Voit muuntaa luotosi USD: iin ja nostaa muunnetun summan vaihdon avulla. <a href=\"https://lbry.com/faq/exchanges\">Learn more</a>.</string>
|
||||
<string name="convert_credits_bittrex"><a href=\"https://bittrex.com/Account/Register?referralCode=4M1-P30-BON\">Convert Muunna hyvitykset USD: ksi Bittrexillä</a></string>
|
||||
<string name="you_also_have">Sinulla on myös</string>
|
||||
<string name="you_staked">Olet panostanut</string>
|
||||
<string name="in_tips">Lahjoituksissa</string>
|
||||
<string name="in_your_publishes">julkaisuissasi</string>
|
||||
<string name="in_your_supports">tuillasi</string>
|
||||
<string name="earn_more_tips">Ansaitse lisää vinkkejä lähettämällä hienoja videoita</string>
|
||||
<string name="sdk_initializing">Taustapalvelu alustetaan ...</string>
|
||||
<string name="sdk_still_initializing">Taustapalvelu on edelleen alustamassa. Voit tutkia ja katsella sisältöä sillä välin.</string>
|
||||
<string name="sdk_initializing_functionality">Et voi tehdä tätä nyt, koska taustapalvelu on edelleen käynnistymässä.</string>
|
||||
|
||||
<string name="backup_synced">Varmuuskopio lompakostasi synkronoidaan lbry.tv-tiedoston kanssa</string>
|
||||
<string name="backup_notsynced">Lompakkoasi ei ole tällä hetkellä synkronoitu lbry.tv: n kanssa. Olet vastuussa lompakkosi varmuuskopiosta.</string>
|
||||
<string name="synced_what_does_this_mean"><a href=\"https://lbry.com/faq/account-sync\">What Mitä se tarkoittaa?</a></string>
|
||||
<string name="backup_what_does_this_mean"><a href=\"https://lbry.com/faq/how-to-backup-wallet#android\">What Mitä se tarkoittaa?</a></string>
|
||||
|
||||
<string name="receive_credits">Saa krediittejä</string>
|
||||
<string name="use_this_address_hint">Käytä tätä lompakko-osoitetta saadaksesi toisen käyttäjän (tai itsesi) lähettämiä krediittejä.</string>
|
||||
<string name="get_new_address">Saa uusi osoite</string>
|
||||
<string name="generate_address_hint">Voit luoda uuden osoitteen milloin tahansa, ja kaikki aiemmat osoitteet toimivat edelleen. Useiden osoitteiden käyttäminen voi olla hyödyllistä seurata useista lähteistä tulevia maksuja.</string>
|
||||
|
||||
<string name="send_credits">Lähetä krediittejä</string>
|
||||
<string name="recipient_address">Vastaanottajan osoite</string>
|
||||
<string name="recipient_address_placeholder">bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs</string>
|
||||
<string name="amount">Määrä</string>
|
||||
<string name="send">Lähetä</string>
|
||||
|
||||
<string name="recent_transactions">Viimeaikaiset tapahtumat</string>
|
||||
<string name="view_all">Näytä kaikki</string>
|
||||
<string name="receive">Vastaanota</string>
|
||||
<string name="spend">Tuhlaa</string>
|
||||
<string name="publish">Julkaise</string>
|
||||
<string name="support">Tue</string>
|
||||
<string name="abandon">Hylätä</string>
|
||||
<string name="channel">Kanava</string>
|
||||
<string name="channel_update">Kanavan päivitys</string>
|
||||
<string name="publish_update">Julkaise päivitys</string>
|
||||
|
||||
<string name="wallet_sync">Synkronoi lompakko</string>
|
||||
<string name="sync_status">Synkronoinnin tila</string>
|
||||
<string name="on">Päällä</string>
|
||||
<string name="off">Kiinni</string>
|
||||
<string name="email">Sähköposti</string>
|
||||
<string name="no_connected_email">Ei yhdistettyjä sähköposteja</string>
|
||||
<string name="manual_backup"><a href=\"https://lbry.com/faq/how-to-backup-wallet#android\">Manual Manuaalinen palautus</a></string>
|
||||
<string name="sync_faq"><a href=\"https://lbry.com/faq/how-to-backup-wallet#sync\">Sync FAQ</a></string>
|
||||
<string name="zero">0</string>
|
||||
<string name="lbc">LBC</string>
|
||||
|
||||
<string name="account_recommended">Suositellut tilit</string>
|
||||
<string name="wallet_account_desc">Lbry.tv-tilin avulla voit ansaita palkintoja, varmuuskopioida lompakkosi ja pitää kaiken synkronoituna.</string>
|
||||
<string name="wallet_without_account">Ilman tiliäsi olet vastuussa lompakon ja LBRY-tietojen suojaamisesta.</string>
|
||||
<string name="skip_account">Ohita tili</string>
|
||||
<string name="sign_up">Rekisteröidy</string>
|
||||
<string name="address_copied">Osoite kopioitu</string>
|
||||
|
||||
<string name="invalid_recipient_address">Anna kelvollinen osoite, johon haluat lähettää hyvityksiä</string>
|
||||
<string name="insufficient_balance">Riittämätön tasapaino</string>
|
||||
<string name="invalid_amount">Anna oikea summa</string>
|
||||
<string name="send_credit_error">Hyvityksiäsi ei voitu lähettää tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<string name="loading_transactions">Ladataan tapahtumia ...</string>
|
||||
<string name="no_recent_transactions">Viimeisimmät näytettävät tapahtumat eivät ole.</string>
|
||||
<string name="no_transactions">Tällä hetkellä ei ole näkyviä tapahtumia.</string>
|
||||
<string name="tx_list_fee">maksu %1$s</string>
|
||||
<string name="transaction_history">Tapahtumahistoria</string>
|
||||
|
||||
<string name="unlock">Avata</string>
|
||||
<string name="unlock_tips">Avaako tippejä?</string>
|
||||
<string name="confirm_unlock_tips">Haluatko varmasti avata kaikki tippisi?</string>
|
||||
<string name="min_spend_required">Anna summa, joka on enemmän kuin 0,0001 krediittiä.</string>
|
||||
|
||||
<string name="buy_lbc">Osta LBC</string>
|
||||
<string name="hash_not_supported">Laitteesi ei tue vähimmäisvaatimuksia ostopyynnön turvaamiseksi.</string>
|
||||
<string name="receive_address_not_set">Sinulla ei ole lompakon osoitetta määritetty. Luo uusi osoite ja yritä uudelleen.</string>
|
||||
|
||||
<plurals name="you_sent_credits">
|
||||
<item quantity="one">Sinä lähetät %1$s krediittiä</item>
|
||||
<item quantity="other">Sinä lähetät %1$s krediittiä</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Dialogs -->
|
||||
<string name="customize_your_tags">Muokkaa sinun tunnisteita</string>
|
||||
<string name="sort_content_by">Lajittele sisältö</string>
|
||||
<string name="content_from">Sisältö</string>
|
||||
<string name="trending_content">Trendikäs sisältö</string>
|
||||
<string name="new_content">Uusi sisältö</string>
|
||||
<string name="top_content">Suosituin sisältö</string>
|
||||
<string name="trending">Nousussa</string>
|
||||
<string name="top">Paras</string>
|
||||
<string name="new_text">Uusi</string>
|
||||
<string name="past_24_hours">Viimeisen 24 tunnin aikana</string>
|
||||
<string name="past_week">Mennyt viikko</string>
|
||||
<string name="past_month">Viime kuukausi</string>
|
||||
<string name="past_year">Viime vuosi</string>
|
||||
<string name="all_time">Koko aikana</string>
|
||||
<string name="from">tullut</string>
|
||||
<string name="for_text">varten</string>
|
||||
<string name="filter_for">Suodata</string>
|
||||
<string name="everyone">Jokaiselle</string>
|
||||
<string name="tags_you_follow">Tunnisteet mitä sinä seuraat</string>
|
||||
<string name="customize">Muokkaa</string>
|
||||
<string name="not_yet_implemented">Valittu näkymä ei ole vielä käytettävissä.</string>
|
||||
<string name="customize_tags_hint">Näyttää siltä, että et ole vielä seurannut yhtään tunnistetta.</string>
|
||||
<string name="search_for_more_tags">Etsi lisää tunnisteita</string>
|
||||
<string name="no_followed_tags">Et ole vielä seurannut yhtään tunnistetta. Aloita lisäämällä kiinnostavia tunnisteita!</string>
|
||||
<string name="no_tag_results">Emme löytäneet uusia tunnisteita, joita et seuraa.</string>
|
||||
<string name="tag_already_added">\'%1$s\' tunniste on jo lisätty.</string>
|
||||
<string name="tag_limit_reached">Et voi lisätä enempää kuin 5 tunnistetta.</string>
|
||||
<string name="send_a_tip">Lähetä tippi</string>
|
||||
<string name="send_a_tip_to">Lähetä tippiä %1$s</string>
|
||||
<string name="support_this_content">Tue tätä sisältöä</string>
|
||||
<string name="support_info">Tämä nostaa tämän sisällön kokonaishintamäärää, mikä parantaa sen kykyä löytää edelleen aktiivisena. <a href=\"https://lbry.com/faq/tipping\">Learn more</a>.</string>
|
||||
<string name="channel_to_show_support_as">Kanava tuen näyttämiseksi nimellä</string>
|
||||
<string name="make_this_a_tip">Tee tästä Tippi</string>
|
||||
<string name="send_revocable_support">Lähetä peruutettava tuki</string>
|
||||
<string name="send_lbc_tip">Lähetä %1$s LBC tippi</string>
|
||||
<string name="send_tip_info_content">Tämä näyttää tipille %1$s, mikä parantaa sen kykyä löytää edelleen aktiivisena. <a href=\"https://lbry.com/faq/tipping\">Learn more</a>.</string>
|
||||
<string name="send_tip_info_channel">Tämä näyttää tipille %1$s, mikä parantaa sen kykyä löytää edelleen aktiivisena. <a href=\"https://lbry.com/faq/tipping\">Learn more</a>.</string>
|
||||
<string name="cancel">Peruuta</string>
|
||||
<string name="repost_title">Repost %1$s</string>
|
||||
<string name="repost_your_favorite">Lähetä suosikkisisältösi uudelleen, jotta useammat ihmiset löytävät ne!</string>
|
||||
<string name="channel_to_post_on">Kanava, johon lähettää viesti</string>
|
||||
<string name="show_advanced">Näytä edistyneet</string>
|
||||
<string name="hide_advanced">Piilota edistynyt</string>
|
||||
<string name="name">Nimi</string>
|
||||
<string name="min_deposit">0.001</string>
|
||||
<string name="content_successfully_reposted">Sisältö postitettiin onnistuneesti!</string>
|
||||
<string name="repost_name_invalid_characters">Jälleenlähetys nimi sisältää virheellisiä merkkejä.</string>
|
||||
<plurals name="you_sent_a_tip">
|
||||
<item quantity="one">Sinä lähetit %1$s LBC tippinä, Mahtavaa!</item>
|
||||
<item quantity="other">Sinä lähetit %1$s LBC tippinä, Mahtavaa!</item>
|
||||
</plurals>
|
||||
<plurals name="you_sent_a_support">
|
||||
<item quantity="one">Panosit %1$s hyvityksiä tueksi. Voit peruuttaa tuen milloin tahansa. </item>
|
||||
<item quantity="other">Panosit %1$s hyvityksiä tueksi. Voit peruuttaa tuen milloin tahansa. </item>
|
||||
</plurals>
|
||||
|
||||
<!-- Verification -->
|
||||
<string name="provide_email_address">Anna sähköpostiosoite.</string>
|
||||
<string name="email_placeholder">you@example.com</string>
|
||||
<string name="email_sent_to">Sähköposti on lähetetty osoitteeseen</string>
|
||||
<string name="please_click_link">Napsauta viestin linkkiä suorittaaksesi kirjautumisen loppuun.</string>
|
||||
<string name="resend">Uudelleen lähetä</string>
|
||||
<string name="continue_text">Jatka</string>
|
||||
<string name="provide_valid_email">Ole hyvä ja syötä toimiva sähköpostiosoite</string>
|
||||
<string name="please_follow_instructions">Noudata osoitteeseesi lähetetyn sähköpostin ohjeita jatkaaksesi.</string>
|
||||
<string name="sign_in_successful">Olet onnistuneesti kirjautunut sisään lbry.tv-sivustoon</string>
|
||||
<string name="retrieving_account_information">Haetaan tilitietoja ...</string>
|
||||
<string name="apply_wallet_data">Sovelletaan lompakotietoja ...</string>
|
||||
<string name="please_enter_your_password">Anna salasana, jolla turvasit lompakon.</string>
|
||||
<string name="please_enter_a_password">Anna salasana suojataksesi lompakon.</string>
|
||||
<string name="wallet_security_purposes">Huomaa: LBRY ei pysty uudelleen asettaa salasanaa lompakon suojausta varten.</string>
|
||||
<string name="password">Salasana</string>
|
||||
<string name="enable_sync">Ota synkronointi käyttöön</string>
|
||||
<string name="wallet_sync_op_failed">Lompakon synkronointia ei voitu suorittaa tällä hetkellä. Yritä uudelleen myöhemmin. Jos ongelma jatkuu, lähetä sähköpostia osoitteeseen hello@lbry.com</string>
|
||||
<string name="phone_number">Puhelinnumero</string>
|
||||
<string name="enter_phone_number">Ole hyvä ja anna puhelinnumerosi.</string>
|
||||
<string name="not_interested">Ei kiinnostunut</string>
|
||||
<string name="manual_reward_verification">Manuaalinen palkkion todentaminen</string>
|
||||
<string name="account_undergo_review">Tämä tili on tarkistettava ennen kuin voit osallistua palkitsemisohjelmaan. Tämä voi viedä useita minuutteja useisiin päiviin.</string>
|
||||
<string name="enjoy_free_content">Nauti ilmaisesta sisällöstä sillä välin!</string>
|
||||
<string name="verify_phone_number">Vahvista puhelinnumero</string>
|
||||
<string name="enter_phone_verify_code">Anna vahvistuskoodi, joka lähetettiin osoitteeseen %1$s</string>
|
||||
<string name="code_placeholder">0000</string>
|
||||
<string name="verify">Vahvista</string>
|
||||
<string name="please_enter_valid_phone">Ole hyvä ja näppäile voimassaoleva puhelinnumero.</string>
|
||||
<string name="please_enter_verification_code">Anna puhelinnumeroosi lähetetty vahvistuskoodi.</string>
|
||||
<string name="fetch_current_user_error">Käyttäjätiliä ei voitu noutaa tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<!-- Forms -->
|
||||
<string name="no_added_tags">Et ole vielä lisännyt tageja. Lisää tunnisteita etsinnän parantamiseksi.</string>
|
||||
<string name="form_no_tag_results">Emme löytäneet uusia tunnisteita, joita ei ole vielä lisätty.</string>
|
||||
|
||||
<!-- Channels -->
|
||||
<string name="no_channel_created">Et ole luonut kanavaa.
|
||||
Aloita nyt luomalla uusi kanava!</string>
|
||||
<string name="create_a_channel">Tee kanava</string>
|
||||
<string name="create_a_channel_item">Tee kanava...</string>
|
||||
<string name="edit_channel">Muokkaa kanavaa</string>
|
||||
<string name="delete_selection">Poistetaanko valinta?</string>
|
||||
<string name="delete_channel">Poistetaanko kanava?</string>
|
||||
<string name="confirm_delete_channel">Haluatko varmasti poistaa tämän kanavan?</string>
|
||||
<string name="channel_deleted">Kanava poistettiin onnistuneesti.</string>
|
||||
<string name="channel_failed_delete">Kanavaa ei voitu poistaa tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<string name="description">Kuvaus</string>
|
||||
<string name="yes">Kyllä</string>
|
||||
<string name="no">Ei</string>
|
||||
<string name="show_optional_fields">Näytä valinnaiset kentät</string>
|
||||
<string name="hide_optional_fields">Näytä valinnaiset kentät</string>
|
||||
<string name="save">Tallenna</string>
|
||||
<string name="channel_name">Kanavan nimi</string>
|
||||
<string name="title">Otsikko</string>
|
||||
<string name="at">\@</string>
|
||||
<string name="deposit">Tallettaa</string>
|
||||
<string name="deposit_remains_yours">Tämä LBC on sinun. Nimen varaaminen on talletus, ja sen voi peruuttaa milloin tahansa.</string>
|
||||
<string name="storage_permission_rationale_download">LBRY vaatii pääsyn sisällön lataamiseen laitteellesi.</string>
|
||||
<string name="storage_permission_rationale_images">LBRY vaatii pääsyn kuvien lataamiseen laitteen varastosta.</string>
|
||||
<string name="select_thumbnail">Valitse pikkukuva</string>
|
||||
<string name="select_cover">Valitse kannen kuva</string>
|
||||
<string name="undetermined_image_filepath">Tiedostopolkua ei voitu määrittää valitulle kuvalle. Valitse kuva eri sijainnista.</string>
|
||||
<string name="wait_for_upload">Odota, että nykyinen lataus on valmis.</string>
|
||||
<string name="image_upload_failed">Kuvan lähetyspyyntö epäonnistui. Yritä uudelleen.</string>
|
||||
<string name="uploading">Lataaminen ...</string>
|
||||
<string name="please_enter_channel_name">Anna kanavan nimi.</string>
|
||||
<string name="channel_name_invalid_characters">Kanavasi nimi sisältää virheellisiä merkkejä.</string>
|
||||
<string name="channel_name_already_created">Olet jo luonut kanavan samalla nimellä.</string>
|
||||
<string name="please_enter_valid_deposit">Anna oikea talletussumma.</string>
|
||||
<string name="deposit_more_than_balance">Talletus ei voi olla suurempi kuin saldosi.</string>
|
||||
<string name="channel_save_failed">Kanavan tallennuspyyntö epäonnistui. Yritä uudelleen.</string>
|
||||
<string name="channel_save_successful">Kanava tallennettiin onnistuneesti.</string>
|
||||
<string name="item_pending_blockchain">Vaatimus odottaa julkaisua lohkoketjussa. Voit käyttää vaatimusta tai muokata sitä hetkessä.</string>
|
||||
<string name="pending">vireillä</string>
|
||||
<string name="create">Luo</string>
|
||||
<string name="one_or_more_channels_failed_abandon">Yhtä tai useampaa sisältökohdetta ei voitu poistaa tällä hetkellä. Yritä uudelleen myöhemmin.</string>
|
||||
<plurals name="min_deposit_required">
|
||||
<item quantity="one">Vaaditaan vähintään %1$s luottojen talletus.</item>
|
||||
<item quantity="other">Vaaditaan vähintään %1$s luottojen talletus.</item>
|
||||
</plurals>
|
||||
<plurals name="confirm_delete_channels">
|
||||
<item quantity="one">Haluatko varmasti poistaa valitut kanava?</item>
|
||||
<item quantity="other">Haluatko varmasti poistaa valitut kanavat?</item>
|
||||
</plurals>
|
||||
<plurals name="channels_deleted">
|
||||
<item quantity="one">Kanava poistettiin onnistuneesti.</item>
|
||||
<item quantity="other">Kanava poistettiin onnistuneesti.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Rewards -->
|
||||
<string name="lbry_credits_allow">LBRY-crediitit antavat sinun julkaista tai ostaa sisältöä.</string>
|
||||
<string name="free_credits_worth">Voit saada ilmaisia hyvityksiä, joiden arvo on %1$s, kun olet antanut sähköpostiosoitteen.</string>
|
||||
<string name="rewards_learn_more"><a href=\"https://lbry.com/faq/earn-credits\">Learn more</a>.</string>
|
||||
<string name="get_started">Pääse alkuun</string>
|
||||
<string name="reward_code_placeholder">abc123</string>
|
||||
<string name="claim">vaatimus</string>
|
||||
<string name="please_enter_claim_code">Anna mukautettu palkituskoodi vaatiaksesi.</string>
|
||||
<string name="unclaimed">Lunastamattomat</string>
|
||||
<string name="custom_reward_title">Kustomoitu koodi</string>
|
||||
<string name="up_to">aikeissa</string>
|
||||
<string name="custom_reward_description">Oletko supermalli tai rockstar, joka sai mukautetun palkinnon? Vaadi sitä täältä.</string>
|
||||
<plurals name="claim_reward_message">
|
||||
<item quantity="one">Olet vaatinut %1$s hyvitystä palkkiona.</item>
|
||||
<item quantity="other">Olet vaatinut %1$shyvitystä palkkiona.</item>
|
||||
</plurals>
|
||||
<plurals name="available_credits">
|
||||
<item quantity="one">%1$s käytettävissä olevia krediittejä</item>
|
||||
<item quantity="other">%1$s käytettävissä olevia krediittejä</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Reward drivers -->
|
||||
<string name="publishing_requires_credits">Julkaiseminen vaatii krediittejä.</string>
|
||||
<string name="channel_creation_requires_credits">Kanavien luominen vaatii krediittejä.</string>
|
||||
<string name="earn_rewards_for_inviting">Ansaitse palkkioita ystävien kutsumisesta.</string>
|
||||
<string name="earn_some_credits_to_access">Ansaitse joitakin hyvityksiä tämän sisällön käyttämiseksi.</string>
|
||||
<string name="tap_here_to_get_some">Napauta tätä saadaksesi ilmaiseksi.</string>
|
||||
<string name="free_credits_available">Ilmaisia hyvityksiä palkkioina.</string>
|
||||
<plurals name="wallet_signed_in_free_credits">
|
||||
<item quantity="one"> %1$s Ilmaisia hyvityksiä palkkioina.</item>
|
||||
<item quantity="other">%1$s Ilmaisia hyvityksiä palkkioina.</item>
|
||||
</plurals>
|
||||
<plurals name="wallet_get_free_credits">
|
||||
<item quantity="one">Hanki %1$s ilmaisia krediittejä tilin luomisen jälkeen.</item>
|
||||
<item quantity="other">Hanki %1$s ilmaisia krediittejä tilin luomisen jälkeen.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Invites -->
|
||||
<string name="lbry_invite_program">LBRY-kutsuohjelma</string>
|
||||
<string name="earn_extra_credits_invites">Voit ansaita ylimääräisiä krediittejä jokaisesta henkilöstä, jonka kutsut käyttämään LBRY: tä.</string>
|
||||
<string name="invites_learn_more"><a href=\"https://lbry.com/faq/invites\">Learn more</a>.</string>
|
||||
<string name="invite_link">Kutsu linkki</string>
|
||||
<string name="share_this_link">Jaa tämä linkki ystävien (tai vihollisten) kanssa ja hanki krediittejä liittyessään lbry.tv.</string>
|
||||
<string name="your_invite_link">Kutsu-linkkisi</string>
|
||||
<string name="customize_invite_link">Mukauta kutsulinkki</string>
|
||||
<string name="invite_by_email">Kutsu sähköpostitse</string>
|
||||
<string name="invite_someone">Kutsu tuntemaasi henkilö sähköpostilla ja ansaitse krediittejä liittyessään lbry.tv.</string>
|
||||
<string name="invite_email_placeholder">imaginary@friend.com</string>
|
||||
<string name="invite">Kutsu</string>
|
||||
<string name="invite_history">Kutsu historia</string>
|
||||
<string name="earn_credits_for_inviting">Ansaitse pisteitä ystävän, vihollisen, frenemian tai eneystävän kutsumiseen. Jokainen tarvitsee sisältövapauden.</string>
|
||||
<string name="reward">Palkinto</string>
|
||||
<string name="claimed">noutaa</string>
|
||||
<string name="claimable">lunastettavana</string>
|
||||
<string name="unclaimable">Ei vaadittavissa</string>
|
||||
<string name="invite_link_copied">Kutsu linkki kopioitu.</string>
|
||||
<string name="invite_sent_to">Kutsu lähetetty %1$s</string>
|
||||
|
||||
<!-- Library -->
|
||||
<string name="downloads">Lataukset</string>
|
||||
<string name="purchases">ostos</string>
|
||||
<string name="history">Historia</string>
|
||||
<string name="library_no_downloads">Sinulla ei ole yhtään ladattua sisältöä tälle laitteelle.</string>
|
||||
<string name="library_no_history">Et ole katsellut mitään sisältöä tällä laitteella.</string>
|
||||
<string name="library_no_purchases">Et ole ostanut sisältöä tililtäsi.</string>
|
||||
<string name="hide">Piilota</string>
|
||||
<string name="stats">Tilastot</string>
|
||||
<string name="video">Video</string>
|
||||
<string name="audio">Ääni</string>
|
||||
<string name="images">Kuvat</string>
|
||||
<string name="mb">MB</string>
|
||||
<string name="kb">KB</string>
|
||||
<string name="gb">GB</string>
|
||||
<string name="zero_mb">0MB</string>
|
||||
<plurals name="confirm_delete_files">
|
||||
<item quantity="one">Haluatko varmasti poistaa valitut tiedostot laitteestasi?</item>
|
||||
<item quantity="other">Haluatko varmasti poistaa valitut tiedostot laitteestasi?</item>
|
||||
</plurals>
|
||||
<plurals name="files_deleted">
|
||||
<item quantity="one">Tiedostot poistettiin onnistuneesti.</item>
|
||||
<item quantity="other">Tiedostot poistettiin onnistuneesti.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about_lbry">Tietoa LBRY</string>
|
||||
<string name="content_freedom">Sisällönvapaus</string>
|
||||
<string name="about_paragraph">LBRY on ilmainen, avoin ja yhteisömäinen digitaalinen markkinapaikka. Se on hajautettu vertaisverkkosisällön jakelualusta, jonka avulla tekijät voivat ladata ja jakaa sisältöä sekä ansaita LBRY-krediittejä työstään. Käyttäjät voivat löytää laajan valikoiman videoita, musiikkia, e-kirjoja ja muuta kiinnostavaa digitaalista sisältöä.</string>
|
||||
<string name="get_social">Hanki sosiaalinen</string>
|
||||
<string name="social_paragraph">Voit olla tekemisissä LBRY-tiimin ja yhteisön jäsenten kanssa Discordissa, Facebookissa, Instagramissa, Twitterissä tai Redditissä.</string>
|
||||
<string name="app_info">Sovellustiedot</string>
|
||||
<string name="loading">Latautuu...</string>
|
||||
<string name="about_link_what_is_lbry"><a href=\"https://lbry.com/faq/what-is-lbry\">What is LBRY?</a></string>
|
||||
<string name="about_link_android_basics"><a href=\"https://lbry.com/faq/android-basics\">Android Basics</a></string>
|
||||
<string name="about_link_faq"><a href=\"https://lbry.com/faq\">FAQ</a></string>
|
||||
<string name="about_link_discord"><a href=\"https://discordapp.com/invite/Z3bERWA\">Discord</a></string>
|
||||
<string name="about_link_facebook"><a href=\"https://www.facebook.com/LBRYio\">Facebook</a></string>
|
||||
<string name="about_link_instagram"><a href=\"https://www.instagram.com/LBRYio\">Instagram</a></string>
|
||||
<string name="about_link_reddit"><a href=\"https://reddit.com/r/lbry\">Reddit</a></string>
|
||||
<string name="about_link_telegram"><a href=\"https://t.me/lbryofficial\">Telegram</a></string>
|
||||
<string name="about_link_twitter"><a href=\"https://twitter.com/LBRYio\">Twitter</a></string>
|
||||
<string name="update_mailing_preferences">Päivitä postitusasetukset</string>
|
||||
<string name="app_version">Sovellus versio</string>
|
||||
<string name="lbry_sdk">LBRY SDK</string>
|
||||
<string name="platform">Alusta</string>
|
||||
<string name="installation_id">Asennustunnus</string>
|
||||
<string name="firebase_token">Firebase-tunnus</string>
|
||||
<string name="logs">Lokit</string>
|
||||
<string name="send_log">Lähetä loki</string>
|
||||
<string name="connected_email">Yhdistetty sähköposti</string>
|
||||
<string name="unknown">Tuntematon</string>
|
||||
<string name="cannot_find_lbrynet_log">Lbrynet.log-tiedostoa ei löytynyt.</string>
|
||||
<string name="cannot_share_lbrynet_log">Lbrynet.log-tiedostoa ei voi jakaa luparajoitusten takia.</string>
|
||||
|
||||
</resources>
|
|
@ -20,6 +20,7 @@
|
|||
<string name="settings">Settings</string>
|
||||
<string name="about">About</string>
|
||||
<string name="sign_in">Sign In</string>
|
||||
<string name="shuffle">Shuffle</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>
|
||||
|
||||
|
@ -242,6 +243,7 @@
|
|||
<string name="notifications">Notifications</string>
|
||||
<string name="subscriptions">Subscriptions</string>
|
||||
<string name="content_interests">Content Interests</string>
|
||||
<string name="mini_player_bottom_spacing">Mini-player bottom spacing</string>
|
||||
|
||||
<string name="keep_sdk_in_background">Keep the LBRY service running in the background for improved wallet and network performance</string>
|
||||
<string name="participate_in_data_network">Participate in the data network (requires app and background service restart)</string>
|
||||
|
@ -637,4 +639,6 @@
|
|||
|
||||
<string name="fa_asterisk" translatable="false"></string>
|
||||
<string name="fa_comment_alt" translatable="false"></string>
|
||||
<string name="fa_broadcast_tower" translatable="false"></string>
|
||||
<string name="fa_random" translatable="false"></string>
|
||||
</resources>
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
app:title="@string/show_url_suggestions"
|
||||
app:defaultValue="true"
|
||||
app:iconSpaceReserved="false" />
|
||||
<EditTextPreference
|
||||
android:inputType="numberDecimal|numberSigned"
|
||||
app:key="io.lbry.browser.preference.userinterface.MiniPlayerBottomMargin"
|
||||
app:title="@string/mini_player_bottom_spacing"
|
||||
app:defaultValue="4"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
|
Loading…
Reference in a new issue