Merge branch 'develop' into 'master'

Release 1049

See merge request sschueller/peertube!1
This commit is contained in:
Stefan Schüller 2020-09-26 18:56:58 +02:00
commit c4ff2921dd
40 changed files with 752 additions and 105 deletions

View File

@ -1,3 +1,15 @@
### Version 1.0.49 Tag: v1.0.49 (2020-09-26)
- add support of hypertext redirection in description (@freeboub)
- various crash fixes (@freeboub)
- avoid going to pip when leaving the app due to share button (@freeboub)
- Add ability to filter server list (@freeboub)
- Refactor Toast error management to split network error (@freeboub)
- keep video aspect ratio for pip (@freeboub)
- navigation bar was not restored when leaving landscape mode (@freeboub)
### Version 1.0.48 Tag: v1.0.48 (2020-09-26)
- f-droid release to fix auto deployment
### Version 1.0.47 Tag: v1.0.47 (2020-07-10) ### Version 1.0.47 Tag: v1.0.47 (2020-07-10)
* Authentication refresh * Authentication refresh

15
DEPLOYMENT.md Normal file
View File

@ -0,0 +1,15 @@
## Internal deployment notes
1. merge pull-requests on github into develop
2. Locally switch to develop
3. Pull github develop
4. Pull weblate develop
5. Add change logs (fastlane/metadata/android/en-US/changelogs/XXX.txt)
6. Push to gitlab and github
7. Merge request into master and merge
8. Add Release Tag on master branch
9. Release to play store
10. Wait for gitlab -> github sync
11. Run publishGithub

View File

@ -6,8 +6,8 @@ GEM
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.1.0) aws-eventstream (1.1.0)
aws-partitions (1.341.0) aws-partitions (1.353.0)
aws-sdk-core (3.103.0) aws-sdk-core (3.104.3)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0) aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
@ -15,8 +15,8 @@ GEM
aws-sdk-kms (1.36.0) aws-sdk-kms (1.36.0)
aws-sdk-core (~> 3, >= 3.99.0) aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.74.0) aws-sdk-s3 (1.76.0)
aws-sdk-core (~> 3, >= 3.102.1) aws-sdk-core (~> 3, >= 3.104.1)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1) aws-sigv4 (1.2.1)
@ -33,9 +33,9 @@ GEM
rake (~> 13.0) rake (~> 13.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.5) dotenv (2.7.6)
emoji_regex (3.0.0) emoji_regex (3.0.0)
excon (0.75.0) excon (0.76.0)
faraday (1.0.1) faraday (1.0.1)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6) faraday-cookie_jar (0.0.6)
@ -43,8 +43,8 @@ GEM
http-cookie (~> 1.0.0) http-cookie (~> 1.0.0)
faraday_middleware (1.0.0) faraday_middleware (1.0.0)
faraday (~> 1.0) faraday (~> 1.0)
fastimage (2.1.7) fastimage (2.2.0)
fastlane (2.151.2) fastlane (2.155.3)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0) addressable (>= 2.3, < 3.0.0)
aws-sdk-s3 (~> 1.0) aws-sdk-s3 (~> 1.0)
@ -55,9 +55,9 @@ GEM
dotenv (>= 2.1.1, < 3.0.0) dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0) emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0) excon (>= 0.71.0, < 1.0.0)
faraday (>= 0.17, < 2.0) faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6) faraday-cookie_jar (~> 0.0.6)
faraday_middleware (>= 0.13.1, < 2.0) faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0) fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0) gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0) google-api-client (>= 0.37.0, < 0.39.0)
@ -92,17 +92,17 @@ GEM
google-cloud-core (1.5.0) google-cloud-core (1.5.0)
google-cloud-env (~> 1.0) google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-cloud-env (1.3.2) google-cloud-env (1.3.3)
faraday (>= 0.17.3, < 2.0) faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1) google-cloud-errors (1.0.1)
google-cloud-storage (1.26.2) google-cloud-storage (1.27.0)
addressable (~> 2.5) addressable (~> 2.5)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-api-client (~> 0.33) google-api-client (~> 0.33)
google-cloud-core (~> 1.2) google-cloud-core (~> 1.2)
googleauth (~> 0.9) googleauth (~> 0.9)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (0.13.0) googleauth (0.13.1)
faraday (>= 0.17.3, < 2.0) faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16) memoist (~> 0.16)
@ -119,13 +119,13 @@ GEM
memoist (0.16.2) memoist (0.16.2)
mini_magick (4.10.1) mini_magick (4.10.1)
mini_mime (1.0.2) mini_mime (1.0.2)
multi_json (1.14.1) multi_json (1.15.0)
multipart-post (2.0.0) multipart-post (2.0.0)
nanaimo (0.2.6) nanaimo (0.3.0)
naturally (2.2.0) naturally (2.2.0)
os (1.1.0) os (1.1.1)
plist (3.5.0) plist (3.5.0)
public_suffix (4.0.1) public_suffix (4.0.5)
rake (13.0.1) rake (13.0.1)
representable (3.0.4) representable (3.0.4)
declarative (< 0.1.0) declarative (< 0.1.0)
@ -147,22 +147,22 @@ GEM
terminal-notifier (2.0.0) terminal-notifier (2.0.0)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.7.0) tty-cursor (0.7.1)
tty-screen (0.7.0) tty-screen (0.8.1)
tty-spinner (0.9.3) tty-spinner (0.9.3)
tty-cursor (~> 0.7) tty-cursor (~> 0.7)
uber (0.1.0) uber (0.1.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.7) unf_ext (0.0.7.7)
unicode-display_width (1.6.0) unicode-display_width (1.7.0)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.17.0) xcodeproj (1.17.1)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1) colored2 (~> 3.1)
nanaimo (~> 0.2.6) nanaimo (~> 0.3.0)
xcpretty (0.3.0) xcpretty (0.3.0)
rouge (~> 2.0.7) rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0) xcpretty-travis-formatter (1.0.0)

View File

@ -28,6 +28,13 @@ Please note this is app is in beta and is still missing a lot of features.
* Beta Test on Google Play: https://play.google.com/store/apps/details?id=net.schueller.peertube * Beta Test on Google Play: https://play.google.com/store/apps/details?id=net.schueller.peertube
* F-Droid: https://f-droid.org/packages/net.schueller.peertube/ * F-Droid: https://f-droid.org/packages/net.schueller.peertube/
## Releases
Release Tags are automatically built and deployed to the play store but not released to production right away.
To use the latest tagged release download it from github or fdroid (~1 day delay).
## Reproducible Builds
Reproducible builds currently does not work.
## Help Translate ## Help Translate
* https://hosted.weblate.org/projects/peertube/ * https://hosted.weblate.org/projects/peertube/
@ -48,11 +55,11 @@ Please note this is app is in beta and is still missing a lot of features.
* Video speed selection * Video speed selection
* Video quality selection * Video quality selection
* Server selection * Server selection
* Video overlay play and draggable video window
## Coming soon ## Coming soon
* Video Playback via WebRTC * Video Playback via WebRTC
* Video overlay play and draggable video window
* Comment videos * Comment videos
* Report Videos * Report Videos
* User / Channel Overview Page * User / Channel Overview Page
@ -66,4 +73,4 @@ Whether you have ideas, translations, design changes, code cleaning, or real hea
<noscript><a href="https://liberapay.com/sschueller/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript> <noscript><a href="https://liberapay.com/sschueller/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
Bitcoin: 1LoTXo728HzYTtyfbkaf5ewSRvu8ABTDPm Bitcoin: 1LoTXo728HzYTtyfbkaf5ewSRvu8ABTDPm

View File

@ -37,6 +37,7 @@ import net.schueller.peertube.R;
import net.schueller.peertube.adapter.ChannelAdapter; import net.schueller.peertube.adapter.ChannelAdapter;
import net.schueller.peertube.adapter.VideoAdapter; import net.schueller.peertube.adapter.VideoAdapter;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.helper.MetaDataHelper; import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.model.Account; import net.schueller.peertube.model.Account;
import net.schueller.peertube.model.Avatar; import net.schueller.peertube.model.Avatar;
@ -206,7 +207,7 @@ public class AccountActivity extends CommonActivity {
} }
} else { } else {
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, null );
} }
@ -215,7 +216,7 @@ public class AccountActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<Account> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Account> call, @NonNull Throwable t) {
Log.wtf(TAG, t.fillInStackTrace()); Log.wtf(TAG, t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, t );
} }
}); });
@ -247,8 +248,7 @@ public class AccountActivity extends CommonActivity {
} }
} else{ } else{
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, null );
} }
isLoadingVideos = false; isLoadingVideos = false;
@ -258,7 +258,7 @@ public class AccountActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace()); Log.wtf("err", t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, t );
isLoadingVideos = false; isLoadingVideos = false;
swipeRefreshLayoutVideos.setRefreshing(false); swipeRefreshLayoutVideos.setRefreshing(false);
} }
@ -281,7 +281,7 @@ public class AccountActivity extends CommonActivity {
} else { } else {
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, null );
} }
@ -290,7 +290,7 @@ public class AccountActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<ChannelList> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ChannelList> call, @NonNull Throwable t) {
Log.wtf(TAG, t.fillInStackTrace()); Log.wtf(TAG, t.fillInStackTrace());
Toast.makeText(AccountActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( AccountActivity.this, t );
} }
}); });
} }

View File

@ -31,6 +31,7 @@ import android.widget.TextView;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.model.Avatar; import net.schueller.peertube.model.Avatar;
import net.schueller.peertube.model.Me; import net.schueller.peertube.model.Me;
import net.schueller.peertube.network.GetUserService; import net.schueller.peertube.network.GetUserService;
@ -162,6 +163,7 @@ public class MeActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<Me> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Me> call, @NonNull Throwable t) {
ErrorHelper.showToastFromCommunicationError( MeActivity.this, t );
account.setVisibility(View.GONE); account.setVisibility(View.GONE);
} }
}); });

View File

@ -28,13 +28,17 @@ import retrofit2.Response;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.adapter.ServerSearchAdapter; import net.schueller.peertube.adapter.ServerSearchAdapter;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.model.ServerList; import net.schueller.peertube.model.ServerList;
import net.schueller.peertube.network.GetServerListDataService; import net.schueller.peertube.network.GetServerListDataService;
import net.schueller.peertube.network.RetrofitInstance; import net.schueller.peertube.network.RetrofitInstance;
@ -46,9 +50,13 @@ public class SearchServerActivity extends CommonActivity {
private ServerSearchAdapter serverAdapter; private ServerSearchAdapter serverAdapter;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText searchTextView;
private final static String TAG = "SearchServerActivity";
private int currentStart = 0; private int currentStart = 0;
private int count = 12; private final int count = 12;
private String lastSearchtext = "";
private TextView emptyView; private TextView emptyView;
private RecyclerView recyclerView; private RecyclerView recyclerView;
@ -77,11 +85,20 @@ public class SearchServerActivity extends CommonActivity {
} }
TextView.OnEditorActionListener onSearchTextValidated = ( textView, i, keyEvent ) -> {
if ( keyEvent != null && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER
|| i == EditorInfo.IME_ACTION_GO ) {
loadServers(currentStart, count, textView.getText().toString());
}
return false;
};
private void loadList() { private void loadList() {
recyclerView = findViewById(R.id.serverRecyclerView); recyclerView = findViewById(R.id.serverRecyclerView);
swipeRefreshLayout = findViewById(R.id.serversSwipeRefreshLayout); swipeRefreshLayout = findViewById(R.id.serversSwipeRefreshLayout);
searchTextView = findViewById(R.id.search_server_input_field );
searchTextView.setOnEditorActionListener( onSearchTextValidated );
emptyView = findViewById(R.id.empty_server_selection_view); emptyView = findViewById(R.id.empty_server_selection_view);
@ -91,7 +108,7 @@ public class SearchServerActivity extends CommonActivity {
serverAdapter = new ServerSearchAdapter(new ArrayList<>(), this); serverAdapter = new ServerSearchAdapter(new ArrayList<>(), this);
recyclerView.setAdapter(serverAdapter); recyclerView.setAdapter(serverAdapter);
loadServers(currentStart, count); loadServers(currentStart, count, searchTextView.getText().toString() );
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override @Override
@ -107,7 +124,7 @@ public class SearchServerActivity extends CommonActivity {
if (!recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)) { if (!recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)) {
if (!isLoading) { if (!isLoading) {
currentStart = currentStart + count; currentStart = currentStart + count;
loadServers(currentStart, count); loadServers(currentStart, count, searchTextView.getText().toString());
} }
} }
} }
@ -119,26 +136,29 @@ public class SearchServerActivity extends CommonActivity {
// Refresh items // Refresh items
if (!isLoading) { if (!isLoading) {
currentStart = 0; currentStart = 0;
loadServers(currentStart, count); loadServers(currentStart, count, searchTextView.getText().toString());
} }
}); });
} }
private void loadServers(int start, int count, String searchtext) {
private void loadServers(int start, int count) {
isLoading = true; isLoading = true;
GetServerListDataService service = RetrofitInstance.getRetrofitInstance( GetServerListDataService service = RetrofitInstance.getRetrofitInstance(
APIUrlHelper.getServerIndexUrl(SearchServerActivity.this) APIUrlHelper.getServerIndexUrl(SearchServerActivity.this)
).create(GetServerListDataService.class); ).create(GetServerListDataService.class);
if ( !searchtext.equals( lastSearchtext ) )
{
currentStart = 0;
lastSearchtext = searchtext;
}
Call<ServerList> call; Call<ServerList> call;
call = service.getInstancesData(start, count); call = service.getInstancesData(start, count, searchtext);
Log.d("URL Called", call.request().url() + ""); Log.d("URL Called", call.request().url() + "");
@ -171,7 +191,7 @@ public class SearchServerActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<ServerList> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<ServerList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace()); Log.wtf("err", t.fillInStackTrace());
Toast.makeText(SearchServerActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( SearchServerActivity.this, t );
isLoading = false; isLoading = false;
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
} }

View File

@ -59,6 +59,8 @@ import com.mikepenz.iconics.IconicsDrawable;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.adapter.VideoAdapter; import net.schueller.peertube.adapter.VideoAdapter;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.model.Video;
import net.schueller.peertube.model.VideoList; import net.schueller.peertube.model.VideoList;
import net.schueller.peertube.network.GetUserService; import net.schueller.peertube.network.GetUserService;
import net.schueller.peertube.network.GetVideoDataService; import net.schueller.peertube.network.GetVideoDataService;
@ -348,7 +350,10 @@ public class VideoListActivity extends CommonActivity {
} }
if (response.body() != null) { if (response.body() != null) {
videoAdapter.setData(response.body().getVideoArrayList()); ArrayList<Video> videoList = response.body().getVideoArrayList();
if (videoList != null) {
videoAdapter.setData(response.body().getVideoArrayList());
}
} }
// no results show no results message // no results show no results message
@ -368,7 +373,7 @@ public class VideoListActivity extends CommonActivity {
@Override @Override
public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<VideoList> call, @NonNull Throwable t) {
Log.wtf("err", t.fillInStackTrace()); Log.wtf("err", t.fillInStackTrace());
Toast.makeText(VideoListActivity.this, getString(R.string.api_error), Toast.LENGTH_SHORT).show(); ErrorHelper.showToastFromCommunicationError( VideoListActivity.this, t );
isLoading = false; isLoading = false;
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
} }

View File

@ -295,7 +295,11 @@ public class VideoPlayActivity extends AppCompatActivity {
videoPlayerFragment.setIsFullscreen(isLandscape); videoPlayerFragment.setIsFullscreen(isLandscape);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); if ( isLandscape ) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
} }
@Override @Override
@ -351,11 +355,17 @@ public class VideoPlayActivity extends AppCompatActivity {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment); VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById(R.id.video_player_fragment);
VideoMetaDataFragment videoMetaDataFragment = (VideoMetaDataFragment) fragmentManager.findFragmentById(R.id.video_meta_data_fragment);
String backgroundBehavior = sharedPref.getString(getString(R.string.pref_background_behavior_key), getString(R.string.pref_background_stop_key)); String backgroundBehavior = sharedPref.getString(getString(R.string.pref_background_behavior_key), getString(R.string.pref_background_stop_key));
assert videoPlayerFragment != null; assert videoPlayerFragment != null;
assert backgroundBehavior != null; assert backgroundBehavior != null;
if ( videoMetaDataFragment.isLeaveAppExpected() )
{
super.onUserLeaveHint();
return;
}
if (backgroundBehavior.equals(getString(R.string.pref_background_stop_key))) { if (backgroundBehavior.equals(getString(R.string.pref_background_stop_key))) {
Log.v(TAG, "stop the video"); Log.v(TAG, "stop the video");
@ -451,15 +461,21 @@ public class VideoPlayActivity extends AppCompatActivity {
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
public void enterPipMode() { public void enterPipMode() {
Rational rational = new Rational(239, 100); final FragmentManager fragmentManager = getSupportFragmentManager();
Log.v(TAG, rational.toString()); final VideoPlayerFragment videoPlayerFragment = (VideoPlayerFragment) fragmentManager.findFragmentById( R.id.video_player_fragment );
PictureInPictureParams mParams =
new PictureInPictureParams.Builder()
.setAspectRatio(rational)
// .setSourceRectHint(new Rect(0,500,400,600))
.build();
enterPictureInPictureMode(mParams); if ( videoPlayerFragment.getVideoAspectRatio() == 0 ) {
Log.i( TAG, "impossible to switch to pip" );
} else {
Rational rational = new Rational( (int) ( videoPlayerFragment.getVideoAspectRatio() * 100 ), 100 );
PictureInPictureParams mParams =
new PictureInPictureParams.Builder()
.setAspectRatio( rational )
// .setSourceRectHint(new Rect(0,500,400,600))
.build();
enterPictureInPictureMode( mParams );
}
} }
@Override @Override

View File

@ -39,6 +39,7 @@ import com.squareup.picasso.Picasso;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.helper.MetaDataHelper; import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.intents.Intents; import net.schueller.peertube.intents.Intents;
import net.schueller.peertube.model.Account; import net.schueller.peertube.model.Account;
@ -72,6 +73,8 @@ public class VideoMetaDataFragment extends Fragment {
private Rating videoRating; private Rating videoRating;
private ColorStateList defaultTextColor; private ColorStateList defaultTextColor;
private boolean leaveAppExpected = false;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@ -80,6 +83,18 @@ public class VideoMetaDataFragment extends Fragment {
return inflater.inflate(R.layout.fragment_video_meta, container, false); return inflater.inflate(R.layout.fragment_video_meta, container, false);
} }
@Override
public void onPause()
{
leaveAppExpected = false;
super.onPause();
}
public boolean isLeaveAppExpected()
{
return leaveAppExpected;
}
public void updateVideoMeta(Video video, VideoPlayerService mService) { public void updateVideoMeta(Video video, VideoPlayerService mService) {
Context context = getContext(); Context context = getContext();
Activity activity = getActivity(); Activity activity = getActivity();
@ -122,6 +137,7 @@ public class VideoMetaDataFragment extends Fragment {
@Override @Override
public void onFailure(Call<Rating> call, Throwable t) { public void onFailure(Call<Rating> call, Throwable t) {
ErrorHelper.showToastFromCommunicationError( getActivity(), t );
// Do nothing. // Do nothing.
} }
}); });
@ -131,7 +147,11 @@ public class VideoMetaDataFragment extends Fragment {
Button videoShareButton = activity.findViewById(R.id.video_share); Button videoShareButton = activity.findViewById(R.id.video_share);
videoShareButton.setText(R.string.video_share_icon); videoShareButton.setText(R.string.video_share_icon);
new Iconics.IconicsBuilder().ctx(context).on(videoShareButton).build(); new Iconics.IconicsBuilder().ctx(context).on(videoShareButton).build();
videoShareButton.setOnClickListener(v -> Intents.Share(context, video)); videoShareButton.setOnClickListener(v ->
{
leaveAppExpected = true;
Intents.Share( context, video );
} );
// Download // Download
Button videoDownloadButton = activity.findViewById(R.id.video_download); Button videoDownloadButton = activity.findViewById(R.id.video_download);
@ -140,6 +160,7 @@ public class VideoMetaDataFragment extends Fragment {
videoDownloadButton.setOnClickListener(v -> { videoDownloadButton.setOnClickListener(v -> {
// get permission to store file // get permission to store file
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
leaveAppExpected = true;
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Intents.Download(context, video); Intents.Download(context, video);

View File

@ -59,6 +59,7 @@ import com.mikepenz.iconics.Iconics;
import net.schueller.peertube.R; import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper; import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.ErrorHelper;
import net.schueller.peertube.model.File; import net.schueller.peertube.model.File;
import net.schueller.peertube.model.Video; import net.schueller.peertube.model.Video;
import net.schueller.peertube.network.GetVideoDataService; import net.schueller.peertube.network.GetVideoDataService;
@ -86,6 +87,7 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
private VideoPlayerService mService; private VideoPlayerService mService;
private TorrentStream torrentStream; private TorrentStream torrentStream;
private LinearLayout torrentStatus; private LinearLayout torrentStatus;
private float aspectRatio;
private static final String TAG = "VideoPlayerFragment"; private static final String TAG = "VideoPlayerFragment";
private GestureDetector mDetector; private GestureDetector mDetector;
@ -112,6 +114,14 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
mBound = false; mBound = false;
} }
}; };
private AspectRatioFrameLayout.AspectRatioListener aspectRatioListerner = new AspectRatioFrameLayout.AspectRatioListener()
{
@Override
public void onAspectRatioUpdated( float targetAspectRatio, float naturalAspectRatio, boolean aspectRatioMismatch )
{
aspectRatio = targetAspectRatio;
}
};
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
@ -144,6 +154,8 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
mDetector = new GestureDetector(context, new MyGestureListener()); mDetector = new GestureDetector(context, new MyGestureListener());
simpleExoPlayerView.setOnTouchListener(touchListener); simpleExoPlayerView.setOnTouchListener(touchListener);
simpleExoPlayerView.setAspectRatioListener( aspectRatioListerner );
torrentStatus = activity.findViewById(R.id.exo_torrent_status); torrentStatus = activity.findViewById(R.id.exo_torrent_status);
// Full screen Icon // Full screen Icon
@ -196,7 +208,7 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
@Override @Override
public void onFailure(@NonNull Call<Video> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<Video> call, @NonNull Throwable t) {
Log.wtf(TAG, t.fillInStackTrace()); Log.wtf(TAG, t.fillInStackTrace());
Toast.makeText(context, "Something went wrong: " + t.getLocalizedMessage(), Toast.LENGTH_LONG).show(); ErrorHelper.showToastFromCommunicationError( getActivity(), t );
} }
}); });
} }
@ -231,17 +243,22 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
Integer videoQuality = sharedPref.getInt(getString(R.string.pref_quality_key), 0); Integer videoQuality = sharedPref.getInt(getString(R.string.pref_quality_key), 0);
//get video qualities //get video qualities
String urlToPlay = video.getFiles().get(0).getFileUrl(); /// #
for (File file : video.getFiles()) { if (video.getFiles().size() > 0) {
// Set quality if it matches String urlToPlay = video.getFiles().get( 0 ).getFileUrl();
if (file.getResolution().getId().equals(videoQuality)) { for ( File file : video.getFiles() ) {
urlToPlay = file.getFileUrl(); // Set quality if it matches
if ( file.getResolution().getId().equals( videoQuality ) ) {
urlToPlay = file.getFileUrl();
}
} }
mService.setCurrentStreamUrl( urlToPlay );
torrentStatus.setVisibility(View.GONE);
startPlayer();
} else {
stopVideo();
Toast.makeText(context, R.string.api_error, Toast.LENGTH_LONG).show();
} }
mService.setCurrentStreamUrl(urlToPlay);
torrentStatus.setVisibility(View.GONE);
startPlayer();
} }
Log.v(TAG, "end of load Video"); Log.v(TAG, "end of load Video");
@ -278,6 +295,8 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
} }
} }
public float getVideoAspectRatio() { return aspectRatio; }
public boolean isPaused() { public boolean isPaused() {
return !mService.player.getPlayWhenReady(); return !mService.player.getPlayWhenReady();
} }

View File

@ -0,0 +1,26 @@
package net.schueller.peertube.helper;
import android.content.Context;
import android.widget.Toast;
import net.schueller.peertube.R;
import java.io.IOException;
import retrofit2.HttpException;
public class ErrorHelper {
public static void showToastFromCommunicationError( Context context, Throwable throwable ) {
if (throwable instanceof IOException ) {
//handle network error
Toast.makeText( context, context.getString( R.string.network_error), Toast.LENGTH_SHORT).show();
} else if (throwable instanceof HttpException ) {
//handle HTTP error response code
Toast.makeText(context, context.getString(R.string.api_error), Toast.LENGTH_SHORT).show();
} else {
//handle other exceptions
Toast.makeText(context, context.getString(R.string.api_error), Toast.LENGTH_SHORT).show();
}
}
}

View File

@ -27,6 +27,7 @@ import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import android.widget.Toast;
import com.github.se_bastiaan.torrentstream.TorrentOptions; import com.github.se_bastiaan.torrentstream.TorrentOptions;
@ -40,6 +41,7 @@ import androidx.core.app.ActivityCompat;
public class Intents { public class Intents {
private static final String TAG = "Intents";
/** /**
* https://troll.tv/videos/watch/6edbd9d1-e3c5-4a6c-8491-646e2020469c * https://troll.tv/videos/watch/6edbd9d1-e3c5-4a6c-8491-646e2020469c
@ -68,20 +70,25 @@ public class Intents {
// TODO, offer which version to download // TODO, offer which version to download
public static void Download(Context context, Video video) { public static void Download(Context context, Video video) {
String url = video.getFiles().get(0).getFileDownloadUrl(); if (video.getFiles().size() > 0)
// make sure it is a valid filename {
String destFilename = video.getName().replaceAll("[^a-zA-Z0-9]", "_") + "." + MimeTypeMap.getFileExtensionFromUrl(URLUtil.guessFileName(url,null,null)); String url = video.getFiles().get( 0 ).getFileDownloadUrl();
// make sure it is a valid filename
String destFilename = video.getName().replaceAll( "[^a-zA-Z0-9]", "_" ) + "." + MimeTypeMap.getFileExtensionFromUrl( URLUtil.guessFileName( url, null, null ) );
//Toast.makeText(context, destFilename, Toast.LENGTH_LONG).show(); //Toast.makeText(context, destFilename, Toast.LENGTH_LONG).show();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); DownloadManager.Request request = new DownloadManager.Request( Uri.parse( url ) );
request.setDescription(video.getDescription()); request.setDescription( video.getDescription() );
request.setTitle(video.getName()); request.setTitle( video.getName() );
request.allowScanningByMediaScanner(); request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setNotificationVisibility( DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED );
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, destFilename); request.setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS, destFilename );
// get download service and enqueue file // get download service and enqueue file
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager manager = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE );
manager.enqueue(request); manager.enqueue( request );
} else {
Toast.makeText( context, R.string.api_error, Toast.LENGTH_LONG ).show();
}
} }
} }

View File

@ -27,7 +27,8 @@ public interface GetServerListDataService {
@GET("instances/") @GET("instances/")
Call<ServerList> getInstancesData( Call<ServerList> getInstancesData(
@Query("start") int start, @Query("start") int start,
@Query("count") int count @Query("count") int count,
@Query("search") String text
); );
} }

View File

@ -33,6 +33,7 @@ import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.webkit.URLUtil;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.support.v4.media.MediaDescriptionCompat; import android.support.v4.media.MediaDescriptionCompat;
@ -70,21 +71,25 @@ import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID;
public class VideoPlayerService extends Service { public class VideoPlayerService extends Service {
private static final String TAG = "VideoPlayerService"; private static final String TAG = "VideoPlayerService";
private static final String MEDIA_SESSION_TAG = "peertube_player"; private static final String MEDIA_SESSION_TAG = "peertube_player";
private final IBinder mBinder = new LocalBinder(); private final IBinder mBinder = new LocalBinder();
private static final String PLAYBACK_CHANNEL_ID = "playback_channel"; private static final String PLAYBACK_CHANNEL_ID = "playback_channel";
private static final Integer PLAYBACK_NOTIFICATION_ID = 1; private static final Integer PLAYBACK_NOTIFICATION_ID = 1;
public SimpleExoPlayer player; public SimpleExoPlayer player;
private Video currentVideo; private Video currentVideo;
private String currentStreamUrl; private String currentStreamUrl;
private PlayerNotificationManager playerNotificationManager; private PlayerNotificationManager playerNotificationManager;
private IntentFilter becomeNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); private IntentFilter becomeNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private BecomingNoisyReceiver myNoisyAudioStreamReceiver = new BecomingNoisyReceiver(); private BecomingNoisyReceiver myNoisyAudioStreamReceiver = new BecomingNoisyReceiver();
@Override @Override
@ -105,13 +110,13 @@ public class VideoPlayerService extends Service {
registerReceiver(myNoisyAudioStreamReceiver, becomeNoisyIntentFilter); registerReceiver(myNoisyAudioStreamReceiver, becomeNoisyIntentFilter);
} }
if (playbackState == ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped if (playbackState
== ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped
Log.v(TAG, "ACTION_PAUSE: " + playbackState); Log.v(TAG, "ACTION_PAUSE: " + playbackState);
unregisterReceiver(myNoisyAudioStreamReceiver); safeUnregisterReceiver();
myNoisyAudioStreamReceiver=null;
} }
} }
} ); });
} }
@ -131,14 +136,9 @@ public class VideoPlayerService extends Service {
if (playerNotificationManager != null) { if (playerNotificationManager != null) {
playerNotificationManager.setPlayer(null); playerNotificationManager.setPlayer(null);
} }
//Was seeing an error when exiting the program about about not unregistering the receiver. //Was seeing an error when exiting the program about not unregistering the receiver.
try { safeUnregisterReceiver();
if (null!=myNoisyAudioStreamReceiver) {
this.unregisterReceiver(myNoisyAudioStreamReceiver);
}
} catch (Exception e) {
Log.e("VideoPlayerService", "attempted to unregister a nonregistered service");
}
if (player != null) { if (player != null) {
player.release(); player.release();
player = null; player = null;
@ -146,6 +146,15 @@ public class VideoPlayerService extends Service {
super.onDestroy(); super.onDestroy();
} }
private void safeUnregisterReceiver()
{
try {
unregisterReceiver(myNoisyAudioStreamReceiver);
} catch (Exception e) {
Log.e("VideoPlayerService", "attempted to unregister a nonregistered service");
}
}
@Nullable @Nullable
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@ -156,22 +165,23 @@ public class VideoPlayerService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Context context = this; Context context = this;
Log.v(TAG, "onStartCommand..."); Log.v(TAG, "onStartCommand...");
if(currentStreamUrl == null){
Toast.makeText(context, "currentStreamUrl must not null", Toast.LENGTH_SHORT).show(); if (!URLUtil.isValidUrl(currentStreamUrl)) {
Toast.makeText(context, "Invalid URL provided. Unable to play video.", Toast.LENGTH_SHORT).show();
return START_NOT_STICKY;
} else {
playVideo();
return START_STICKY;
} }
playVideo();
return START_STICKY;
} }
public void setCurrentVideo(Video video) public void setCurrentVideo(Video video) {
{
Log.v(TAG, "setCurrentVideo..."); Log.v(TAG, "setCurrentVideo...");
currentVideo = video; currentVideo = video;
} }
public void setCurrentStreamUrl(String streamUrl) public void setCurrentStreamUrl(String streamUrl) {
{
Log.v(TAG, "setCurrentStreamUrl..." + streamUrl); Log.v(TAG, "setCurrentStreamUrl..." + streamUrl);
currentStreamUrl = streamUrl; currentStreamUrl = streamUrl;
} }
@ -184,6 +194,7 @@ public class VideoPlayerService extends Service {
/** /**
* Returns the current playback speed of the player. * Returns the current playback speed of the player.
*
* @return the current playback speed of the player. * @return the current playback speed of the player.
*/ */
public float getPlayBackSpeed() { public float getPlayBackSpeed() {
@ -193,6 +204,8 @@ public class VideoPlayerService extends Service {
public void playVideo() { public void playVideo() {
Context context = this; Context context = this;
// We need a valid URL
Log.v(TAG, "playVideo..."); Log.v(TAG, "playVideo...");
// Produces DataSource instances through which media data is loaded. // Produces DataSource instances through which media data is loaded.
@ -242,7 +255,8 @@ public class VideoPlayerService extends Service {
@Nullable @Nullable
@Override @Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) { public Bitmap getCurrentLargeIcon(Player player,
PlayerNotificationManager.BitmapCallback callback) {
return null; return null;
} }
} }
@ -297,15 +311,16 @@ public class VideoPlayerService extends Service {
// Audio Focus // Audio Focus
AudioAttributes audioAttributes = new AudioAttributes.Builder() AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA) .setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MOVIE) .setContentType(C.CONTENT_TYPE_MOVIE)
.build(); .build();
player.setAudioAttributes(audioAttributes,true); player.setAudioAttributes(audioAttributes, true);
} }
// pause playback on audio output change // pause playback on audio output change
private class BecomingNoisyReceiver extends BroadcastReceiver { private class BecomingNoisyReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {

View File

@ -6,6 +6,11 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".activity.SearchServerActivity"> tools:context=".activity.SearchServerActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_server_selection" android:id="@+id/appbar_server_selection"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -29,11 +34,19 @@
android:text="@string/no_data_available" android:text="@string/no_data_available"
android:visibility="gone" /> android:visibility="gone" />
<EditText
android:id="@+id/search_server_input_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/server_selection_filter_hint"
android:singleLine="true"
android:imeOptions="actionGo"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/serversSwipeRefreshLayout" android:id="@+id/serversSwipeRefreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@+id/appbar_server_selection"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -45,5 +58,5 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -194,6 +194,7 @@
android:layout_marginStart="18dp" android:layout_marginStart="18dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:autoLink="web"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Body1" /> android:textAppearance="@style/Base.TextAppearance.AppCompat.Body1" />
<LinearLayout <LinearLayout

View File

@ -86,6 +86,7 @@
<string name="server_selection_set_server">Serveur réglé sur : %s</string> <string name="server_selection_set_server">Serveur réglé sur : %s</string>
<string name="server_selection_select_a_server">Sélectionnez un serveur de la liste ci-dessous ou entrez-le directement.</string> <string name="server_selection_select_a_server">Sélectionnez un serveur de la liste ci-dessous ou entrez-le directement.</string>
<string name="server_selection_peertube_server_url">URL du serveur PeerTube</string> <string name="server_selection_peertube_server_url">URL du serveur PeerTube</string>
<string name="server_selection_filter_hint">Filtrer la liste</string>
<string name="title_activity_account">Compte</string> <string name="title_activity_account">Compte</string>
<string name="menu_video_more_report">Signaler</string> <string name="menu_video_more_report">Signaler</string>
<string name="menu_video_more_blacklist">Liste noire</string> <string name="menu_video_more_blacklist">Liste noire</string>
@ -109,6 +110,7 @@
<string name="account_about_description">Description :</string> <string name="account_about_description">Description :</string>
<string name="account_about_joined">Inscrit·e le :</string> <string name="account_about_joined">Inscrit·e le :</string>
<string name="api_error">Quelque chose sest mal passé, veuillez essayer plus tard !</string> <string name="api_error">Quelque chose sest mal passé, veuillez essayer plus tard !</string>
<string name="network_error">Problème réseau, veuillez vérifier votre connection</string>
<string name="action_bar_title_server_selection">Sélectionnez un serveur</string> <string name="action_bar_title_server_selection">Sélectionnez un serveur</string>
<string name="ab">abkhaze</string> <string name="ab">abkhaze</string>
<string name="aa">afar</string> <string name="aa">afar</string>

View File

@ -316,4 +316,33 @@
<string name="clear_search_history">Cancella la cronologia delle ricerche</string> <string name="clear_search_history">Cancella la cronologia delle ricerche</string>
<string name="pref_description_language_app">Seleziona la lingua per l\'interfaccia dell\'applicazione. Riavvia l\'app per rendere effettive le modifiche.</string> <string name="pref_description_language_app">Seleziona la lingua per l\'interfaccia dell\'applicazione. Riavvia l\'app per rendere effettive le modifiche.</string>
<string name="pref_language_app">Lingua dell\'applicazione</string> <string name="pref_language_app">Lingua dell\'applicazione</string>
<string name="pref_background_behavior_summary">Come la riproduzione video risponde quando va in sottofondo</string>
<string name="authentication_token_refresh_success">Token aggiornato</string>
<string name="authentication_token_refresh_failed">Impossibile aggiornare il token</string>
<string name="pref_title_buildtime">Tempo di costruzione</string>
<string name="menu_video_options_quality_automated">Automatico</string>
<string name="server_selection_video_totals">Videos: %s, Video locali: %s</string>
<string name="server_selection_nsfw_instance">Instanza NSFW</string>
<string name="settings_activity_look_and_feel_category_title">Aspetto</string>
<string name="settings_activity_about_category_title">Info</string>
<string name="settings_activity_video_playback_category_title">Riproduzione video</string>
<string name="settings_activity_video_list_category_title">Lista dei video</string>
<string name="title_activity_settings2">ImpostazioniAttività2</string>
<string name="title_activity_me">Account</string>
<string name="title_activity_select_server">Cerca server</string>
<string name="server_book_del_alert_msg">Sicuro di voler rimuovere questo server dalla rubrica\?</string>
<string name="server_book_del_alert_title">Server remoto</string>
<string name="title_activity_server_address_book">Rubrica</string>
<string name="server_book_add_label">Etichetta</string>
<string name="server_book_label_is_required">L\'etichetta del server è obbligatoria</string>
<string name="hello_blank_fragment">Ciao frammento vuoto</string>
<string name="bn_rBD">Bengalese (Bangladesh)</string>
<string name="settings_permissions_error_float">Il permesso della modalità Picture-in-Picture è disattivata per questa app nelle impostazioni Android</string>
<string name="settings_api_error_float">Questa versione di Android non supporta la lettura fluttuante del video</string>
<string name="pref_background_behavior">Configurazione della lettura in sottfondo</string>
<string name="pref_background_float">Continua riproduzione in una finestra fluttuante</string>
<string name="pref_background_stop">Ferma la lettura video</string>
<string name="pref_background_audio">Continua come flusso sonoro in sottofondo</string>
<string name="pref_description_back_pause">Metti la riproduzione di sottofondo in pausa quando premi il tasto indietro durante la lettura del video.</string>
<string name="pref_title_back_pause">Pausa sul tasto backspace</string>
</resources> </resources>

View File

@ -1,2 +1,348 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="pref_background_stop">Parar toda a reprodução</string>
<string name="ak">Akan</string>
<string name="sfs">Língua de sinais sul-africana</string>
<string name="nb">Bokmål norueguês</string>
<string name="ve">Venda</string>
<string name="title_activity_search">Busca</string>
<string name="prompt_email">Email / Nome de utilizador</string>
<string name="search_hint">Busca no PeerTube</string>
<string name="be">Belarusian</string>
<string name="error_field_required">Este campo é obrigatório</string>
<string name="uz">Uzbeque</string>
<string name="title_activity_select_server">Busca servidor</string>
<string name="ty">Taitiano</string>
<string name="invalid_url">URL inválido.</string>
<string name="zh">Chinês</string>
<string name="pref_title_dark_mode">Tema Oscuro</string>
<string name="server_book_add_label">Nome Identificador</string>
<string name="ca">Catalan</string>
<string name="tg">Tajik</string>
<string name="fi">Finnish</string>
<string name="to">Tonga (Ilhas Tonga)</string>
<string name="bottom_nav_title_subscriptions">Subscrições</string>
<string name="error_invalid_password">Esta palavra-passe é muito curta</string>
<string name="bottom_nav_title_account">Conta</string>
<string name="ru">Russo</string>
<string name="fy">Frisiano Ocidental</string>
<string name="server_book_add_username">Nome do utilizador</string>
<string name="me_logout_button">Sair</string>
<string name="settings_activity_video_list_category_title">Lista de vídeos</string>
<string name="kw">Cornish</string>
<string name="bo">Tibetano</string>
<string name="indigo">Índigo</string>
<string name="video_download_permission_error">Não é possível fazer o download do vídeo sem permissão de gravação</string>
<string name="video_speed_20">2x</string>
<string name="as">Assamese</string>
<string name="pref_title_peertube_server">Servidor de PeerTube</string>
<string name="authentication_login_failed">Login Falhou!</string>
<string name="fa">Persa</string>
<string name="video_speed_05">0.5x</string>
<string name="bottom_nav_title_local">Local</string>
<string name="eo">Esperanto</string>
<string name="li">Limburgan</string>
<string name="video_rating_failed">Classificação falhou</string>
<string name="pref_title_background_play">Reprodução no fundo</string>
<string name="cse">Língua de sinais tcheca</string>
<string name="ny">Nyanja</string>
<string name="ar">Arabic</string>
<string name="ks">Kashmiri</string>
<string name="csl">Língua chinesa de sinais</string>
<string name="kr">Kanuri</string>
<string name="uk">Ucraniano</string>
<string name="fo">Faroese</string>
<string name="video_row_video_thumbnail">Miniatura do vídeo</string>
<string name="settings_permissions_error_float">A permissão Picture-in-Picture está desativada para este aplicação nas Configurações do Android</string>
<string name="pl">Polonês</string>
<string name="menu_video_options_quality" formatted="true">Qualidade (%1$s)</string>
<string name="ba">Bashkir</string>
<string name="lo">Lao</string>
<string name="my">Burmese</string>
<string name="kj">Kuanyama</string>
<string name="ki">Kikuyu</string>
<string name="pref_description_dark_mode">Reinicie o aplicação para que o Tema Escuro tenha efeito.</string>
<string name="tlh">Klingon</string>
<string name="id">Indonésio</string>
<string name="jsl">Língua japonesa de sinais</string>
<string name="en">Inglês</string>
<string name="server_book_del_alert_msg">Tem certeza que quer remover este servidor da lista de contatos\?</string>
<string name="vi">Vietnamita</string>
<string name="amber">Âmbar</string>
<string name="account_about_subscribers">Assinantes:</string>
<string name="action_bar_title_settings">Configurações</string>
<string name="om">Oromo</string>
<string name="an">Aragonese</string>
<string name="wa">Walloon</string>
<string name="gd">Gaélico escocês</string>
<string name="login_current_server_hint">Servidor atual</string>
<string name="pref_description_torrent_player">Reprodução de torrent vídeo. Isto requer permissões de armazenamento. (Alfa, não estável!)</string>
<string name="br">Breton</string>
<string name="ch">Chamorro</string>
<string name="menu_share">Compartilhar</string>
<string name="ff">Fulah</string>
<string name="pref_language_app">Idioma do aplicação</string>
<string name="no">Norueguês</string>
<string name="pks">Língua de sinais do Paquistão</string>
<string name="server_selection_nsfw_instance">Servidor NSFW</string>
<string name="deeppurple">Púrpura profunda</string>
<string name="nn">Norueguês Nynorsk</string>
<string name="ml">Malayalam</string>
<string name="fr">Francês</string>
<string name="os">Ossetian</string>
<string name="video_speed_075">0.75x</string>
<string name="video_meta_button_privacy">Privacidade</string>
<string name="mg">Malagasy</string>
<string name="sm">Samoan</string>
<string name="account_about_description">Descrição:</string>
<string name="sdl">Língua de sinais da Arábia Saudita</string>
<string name="prompt_server">Servidor</string>
<string name="mt">Maltês</string>
<string name="blue">Azul</string>
<string name="hello_blank_fragment">Olá secção em branco</string>
<string name="action_bar_title_account">Conta</string>
<string name="ta">Tamil</string>
<string name="kl">Kalaallisut</string>
<string name="km">Khmer</string>
<string name="video_row_account_avatar">Avatar da conta</string>
<string name="nr">Ndebele do Sul</string>
<string name="pref_description_language">Selecione um idioma de vídeo, em vez de mostrar todos os vídeos em todos os idiomas.</string>
<string name="server_book_no_servers_found">O Servidor de Reservas está vazio</string>
<string name="purple">Púrpura</string>
<string name="settings_api_error_float">A versão de Android não suporta vídeo flutuante</string>
<string name="se">Sami do Norte</string>
<string name="title_activity_login">Entrar</string>
<string name="video_meta_button_category">Categoria</string>
<string name="pref_description_background_play">Se ativado, continua a reprodução de vídeo no fundo.</string>
<string name="cv">Chuvash</string>
<string name="hz">Herero</string>
<string name="server_book_del_alert_title">Remover servidor</string>
<string name="pref_title_license">Licença</string>
<string name="settings_activity_video_playback_category_title">Reprodução de vídeo</string>
<string name="bzs">Língua Brasileira de Sinais</string>
<string name="am">Amharic</string>
<string name="hr">Croatian</string>
<string name="mh">Marshallese</string>
<string name="kv">Komi</string>
<string name="gsg">Língua Alemã de Sinais</string>
<string name="meta_data_views">" Visualizações"</string>
<string name="bluegray">Bluegray</string>
<string name="na">Nauru</string>
<string name="ee">Ewe</string>
<string name="sv">Sueco</string>
<string name="title_activity_server_address_book">Lista de contactos</string>
<string name="ku">Curdo</string>
<string name="yellow">Amarelo</string>
<string name="title_activity_url_video_play">UrlVideoPlayActivity</string>
<string name="server_selection_signup_allowed_yes">Sim</string>
<string name="server_selection_set_server">Servidor configurado para: %s</string>
<string name="ky">Kirghiz</string>
<string name="gray">Cinza</string>
<string name="pref_background_behavior_summary">Como um vídeo em reprodução responde quando vai para o fundo</string>
<string name="title_activity_account">Conta</string>
<string name="action_set_url">Selecione o servidor</string>
<string name="server_selection_peertube_server_url">URL do servidor de PeerTube</string>
<string name="video_meta_button_share">Compartilhar</string>
<string name="ps">Pushto</string>
<string name="hy">Armenian</string>
<string name="sg">Sango</string>
<string name="oc">Occitan</string>
<string name="clear_search_history_prompt">Quer apagar permanentemente o histórico de busca\?</string>
<string name="dsl">Língua de sinais dinamarquesa</string>
<string name="prompt_password">Palavra-passe</string>
<string name="su">Sundanese</string>
<string name="bn">Bengali</string>
<string name="video_speed_125">1.25x</string>
<string name="ms">Malay (macrolanguage)</string>
<string name="gu">Gujarati</string>
<string name="aa">Afar</string>
<string name="avk">Kotava</string>
<string name="bottom_nav_title_discover">Descobrir</string>
<string name="account_bottom_menu_channels">Canais</string>
<string name="pref_description_app_theme">Reinicie a aplicação para que o tema tenha efeito.</string>
<string name="sr">Sérvio</string>
<string name="ts">Tsonga</string>
<string name="pref_background_behavior">Configuração da reprodução no fundo</string>
<string name="ht">Haitiano</string>
<string name="server_book_valid_url_is_required">URL válido é requerido</string>
<string name="account_bottom_menu_about">Sobre</string>
<string name="error_invalid_email">Este e-mail é inválido</string>
<string name="th">Tailandês</string>
<string name="rn">Rundi</string>
<string name="cs">Czech</string>
<string name="nv">Navajo</string>
<string name="gn">Guarani</string>
<string name="pa">Panjabi</string>
<string name="server_book_label_is_required">Categoria do servidor é requerido</string>
<string name="lb">Luxemburguês</string>
<string name="sc">Sardo</string>
<string name="deeporange">Laranja Profunda</string>
<string name="pref_background_audio">Continuar como um Stream de áudio no fundo</string>
<string name="descr_overflow_button">Mais</string>
<string name="menu_video_more_blacklist">Lista negra</string>
<string name="pref_description_language_app">Selecione o idioma para a interface da aplicação. Reinicie a aplicação para que a alteração tenha efeito.</string>
<string name="pref_description_show_nsfw">Mostrar conteúdo NSFW</string>
<string name="da">Danish</string>
<string name="lightgreen">Verde claro</string>
<string name="ig">Igbo</string>
<string name="ab">Abkhazian</string>
<string name="pt">Português</string>
<string name="title_activity_settings2">SettingsActivity2</string>
<string name="tn">Tswana</string>
<string name="rsl">Língua de sinais russa</string>
<string name="ay">Aymara</string>
<string name="action_bar_title_logout">Sair</string>
<string name="action_sign_in_short">Entrar</string>
<string name="sd">Sindhi</string>
<string name="authentication_token_refresh_success">Token atualizado</string>
<string name="bg">Bulgarian</string>
<string name="pref_title_app_theme">Tema do App</string>
<string name="hi">Hindi</string>
<string name="authentication_login_success">Logado</string>
<string name="cy">Galês</string>
<string name="bs">Bosnian</string>
<string name="action_bar_title_server_selection">Selecione o servidor</string>
<string name="za">Zhuang</string>
<string name="qu">Quechua</string>
<string name="pref_title_back_pause">Pausa no clicar botão voltar</string>
<string name="sh">Servo-Croata</string>
<string name="video_speed_15">1.5x</string>
<string name="bfi">Língua de sinais britânica</string>
<string name="ase">Linguagem dos sinais americana</string>
<string name="clear_search_history">Limpiar todo histórico de busca</string>
<string name="menu_video_more_report">Relatar</string>
<string name="bi">Bislama</string>
<string name="ro">Romeno</string>
<string name="rw">Kinyarwanda</string>
<string name="permission_rationale">Conceda permissão de contato para preenchimento de e-mail.</string>
<string name="ka">Georgian</string>
<string name="no_data_available">Sem resultados</string>
<string name="is">Islandês</string>
<string name="zu">Zulu</string>
<string name="ho">Hiri Motu</string>
<string name="cr">Cree</string>
<string name="sk">Eslovaco</string>
<string name="title_activity_settings">Configurações</string>
<string name="jv">Javanese</string>
<string name="server_book_add_server_url">URL do servidor</string>
<string name="dv">Dhivehi</string>
<string name="menu_video_options_quality_automated">Automático</string>
<string name="video_login_required_for_service">Deve fazer o login para usar este serviço</string>
<string name="ne">Nepalês (macrolinguagem)</string>
<string name="tt">Tatar</string>
<string name="pref_language">Filtro de idiomas</string>
<string name="hu">Húngaro</string>
<string name="af">Afrikaans</string>
<string name="account_bottom_menu_videos">Vídeos</string>
<string name="ha">Hausa</string>
<string name="pref_title_torrent_player">Reprodutor de Torrent Vídeos</string>
<string name="swl">Língua Sueca de Sinais</string>
<string name="settings_activity_look_and_feel_category_title">Visual e Funcionalidade</string>
<string name="ik">Inupiaq</string>
<string name="yi">Yiddish</string>
<string name="av">Avaric</string>
<string name="rm">Romanche</string>
<string name="es">Espanhol</string>
<string name="title_activity_me">Conta</string>
<string name="ln">Lingala</string>
<string name="video_meta_button_license">Licença</string>
<string name="it">Italiano</string>
<string name="teal">Teal</string>
<string name="mr">Marathi</string>
<string name="ur">Urdu</string>
<string name="pref_description_license">"
\n&lt;b&gt;GNU Affero Licença Pública Geral v3.0&lt;/b&gt;
\n
\nAs permissões desta licença mais forte de copyleft estão condicionadas a disponibilizar o código fonte completo de obras licenciadas e modificações, que incluem obras maiores usando uma obra licenciada, sob a mesma licença. Os avisos de direitos autorais e de licença devem ser preservados. Os contribuidores fornecem uma concessão expressa de direitos de patente. Quando uma versão modificada é usada para fornecer um serviço através de uma rede, o código-fonte completo da versão modificada deve ser disponibilizado."<b>GNU Affero General Public License v3.0</b>\n\nPermissions of this strongest copyleft license are conditioned on making available complete source code of licensed works and modifications, which include larger works using a licensed work, under the same license. Copyright and license notices must be preserved. Contributors provide an express grant of patent rights. When a modified version is used to provide a service over a network, the complete source code of the modified version must be made available.</string>
<string name="si">Sinhala</string>
<string name="video_speed_10">Normal</string>
<string name="pref_title_version">Versão</string>
<string name="nd">Ndebele do Norte</string>
<string name="kg">Kongo</string>
<string name="he">Hebraico</string>
<string name="et">Estonian</string>
<string name="so">Somali</string>
<string name="te">Telugu</string>
<string name="server_book_list_has_login">Tem login</string>
<string name="lu">Luba-Katanga</string>
<string name="mn">Mongol</string>
<string name="error_incorrect_password">Esta palavra-passe está incorreta</string>
<string name="pref_title_show_nsfw">Conteúdo NSFW</string>
<string name="bn_rBD">Bengali (Bangladesh)</string>
<string name="tr">Turco</string>
<string name="dz">Dzongkha</string>
<string name="account_about_account">Conta:</string>
<string name="jbo">Lojban</string>
<string name="settings_activity_about_category_title">Sobre</string>
<string name="pref_background_float">Continuar reproduzindo vídeo na janela flutuante</string>
<string name="bm">Bambara</string>
<string name="action_bar_title_search">Busca</string>
<string name="ss">Swati</string>
<string name="tl">Tagalog</string>
<string name="server_book_add_pick_server_button">Busca</string>
<string name="red">Vermelho</string>
<string name="wo">Wolof</string>
<string name="bottom_nav_title_trending">Tendências</string>
<string name="server_selection_signup_allowed">Inscrição permitida: %s</string>
<string name="az">Azerbaijani</string>
<string name="lightblue">Azul claro</string>
<string name="cyan">Ciano</string>
<string name="gl">Galician</string>
<string name="server_book_add_add_button">Adicionar</string>
<string name="oj">Ojibwa</string>
<string name="ko">Coreano</string>
<string name="st">Sotho do Sul</string>
<string name="lime">Lime</string>
<string name="xh">Xhosa</string>
<string name="mk">Macedônio</string>
<string name="me_help_and_feedback_button">Ajuda e Opiniões</string>
<string name="yo">Yoruba</string>
<string name="co">Corsican</string>
<string name="sq">Albanian</string>
<string name="de">Alemão</string>
<string name="iu">Inuktitut</string>
<string name="video_meta_button_tags">Categorias</string>
<string name="ja">Japonês</string>
<string name="ce">Chechen</string>
<string name="kn">Kannada</string>
<string name="eu">Basque</string>
<string name="action_sign_in">Entrar</string>
<string name="sl">Esloveno</string>
<string name="pref_title_buildtime">Build Time</string>
<string name="ti">Tigrinya</string>
<string name="nl">Dutch</string>
<string name="mi">Maori</string>
<string name="authentication_token_refresh_failed">Não foi possível atualizar o token</string>
<string name="account_about_joined">Membro desde:</string>
<string name="video_meta_button_language">Idioma</string>
<string name="green">Verde</string>
<string name="lt">Lituano</string>
<string name="orange">Laranja</string>
<string name="lv">Letão</string>
<string name="fsl">Língua de sinais francesa</string>
<string name="video_meta_button_download">Descarregar</string>
<string name="server_selection_signup_allowed_no">Não</string>
<string name="server_book_add_password">Palavra-passe</string>
<string name="ga">Irlandês</string>
<string name="bottom_nav_title_recent">Recente</string>
<string name="sw">Swahili (macrolinguagem)</string>
<string name="menu_video_options_playback_speed" formatted="true">Velocidade de reprodução (%1$s)</string>
<string name="tk">Turcomeno</string>
<string name="ug">Uighur</string>
<string name="api_error">Algo deu errado, por favor tente mais tarde!</string>
<string name="tw">Twi</string>
<string name="fj">Fijian</string>
<string name="brown">Marrom</string>
<string name="server_selection_video_totals">Vídeos: %s, Vídeos locais: %s</string>
<string name="sn">Shona</string>
<string name="kk">Kazakh</string>
<string name="pref_description_back_pause">Pausar a reprodução no fundo ao pressionar botão voltar durante a reprodução do vídeo.</string>
<string name="ii">Sichuan Yi</string>
<string name="pink">Cor-de-rosa</string>
<string name="or">Oriya (macrolanguage)</string>
<string name="gv">Manx</string>
<string name="ng">Ndonga</string>
<string name="el">Grego moderno (1453-)</string>
<string name="server_selection_select_a_server">Selecione um servidor da lista abaixo ou digite-o diretamente.</string>
<string name="lg">Ganda</string>
</resources>

View File

@ -87,7 +87,7 @@
<string name="lo">老挝语</string> <string name="lo">老挝语</string>
<string name="el">现代希腊语1453年—</string> <string name="el">现代希腊语1453年—</string>
<string name="mn">蒙古语</string> <string name="mn">蒙古语</string>
<string name="or">奥里亚语</string> <string name="or">奥里亚语 (巨集语言)</string>
<string name="ru">俄语</string> <string name="ru">俄语</string>
<string name="si">僧伽罗字母</string> <string name="si">僧伽罗字母</string>
<string name="es">西班牙语</string> <string name="es">西班牙语</string>

View File

@ -292,6 +292,7 @@
<string name="server_selection_set_server">Server set to: %s</string> <string name="server_selection_set_server">Server set to: %s</string>
<string name="server_selection_select_a_server">Select a server from the list below or enter it directly.</string> <string name="server_selection_select_a_server">Select a server from the list below or enter it directly.</string>
<string name="server_selection_peertube_server_url">PeerTube Server URL</string> <string name="server_selection_peertube_server_url">PeerTube Server URL</string>
<string name="server_selection_filter_hint">Filter list</string>
<string name="title_activity_account">Account</string> <string name="title_activity_account">Account</string>
<string name="menu_video_more_report">Report</string> <string name="menu_video_more_report">Report</string>
<string name="menu_video_more_blacklist">Blacklist</string> <string name="menu_video_more_blacklist">Blacklist</string>
@ -315,6 +316,7 @@
<string name="account_about_description">Description:</string> <string name="account_about_description">Description:</string>
<string name="account_about_joined">Joined:</string> <string name="account_about_joined">Joined:</string>
<string name="api_error">Something went wrong, please try later!</string> <string name="api_error">Something went wrong, please try later!</string>
<string name="network_error">Network access error, please check your connectivity</string>
<string name="action_bar_title_server_selection">Select Server</string> <string name="action_bar_title_server_selection">Select Server</string>
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="action_bar_title_address_book"/> <string name="action_bar_title_address_book"/>

View File

@ -0,0 +1 @@
- f-droid release to fix auto deployment

View File

@ -0,0 +1,7 @@
- add support of hypertext redirection in description (@freeboub)
- various crash fixes (@freeboub)
- avoid going to pip when leaving the app due to share button (@freeboub)
- Add ability to filter server list (@freeboub)
- Refactor Toast error management to split network error (@freeboub)
- keep video aspect ratio for pip (@freeboub)
- navigation bar was not restored when leaving landscape mode (@freeboub)

View File

@ -0,0 +1 @@
- Rafraîchissement de l'authentification

View File

@ -0,0 +1 @@
Thorium est un lecteur non-officiel de PeerTube

View File

@ -0,0 +1 @@
https://www.youtube.com/watch?v=PJIsiuSdpq8

View File

@ -0,0 +1 @@
- Gjenoppfrisking av identitetsbekreftelse

View File

@ -0,0 +1 @@
Uoffisiell PeerTube-klient

View File

@ -0,0 +1 @@
Thorium

View File

@ -0,0 +1 @@
- Обновление аутентификации

View File

@ -0,0 +1,33 @@
Thorium - это клиент PeerTube, который может подключаться к любому серверу Peertube с версией v1.1.0-alpha.2 или выше.
PeerTube - это федеративная (ActivityPub) платформа потокового видео, использующая P2P (BitTorrent) непосредственно в веб-браузере. Для получения дополнительной информации посетите https://joinpeertube.org/, чтобы получить дополнительную информацию и список серверов.
Этот клиент поставляется с предварительно сконфигурированным одним сервером PeerTube, управляемым создателем приложения, а не самим проектом PeerTube, подробности которого перечислены на http://instances.joinpeertube.org/, чтобы вы могли почувствовать, на что способен клиент. Выберите свой сервер, чтобы настроить свой опыт!
Текущие возможности:
- Подключиться к любому серверу PeerTube
- Торрент-видео или прямое воспроизведение
- Поиск в PeerTube
- Скачать / поделиться видео
- Темы / Темный режим
- Фоновое воспроизведение
- Полноэкранное воспроизведение в альбомной ориентации
- Скорость воспроизведения
- Фильтр содержимого NSFW
- Аутентификация / Вход
- Лайк / дизлайк видео
Скоро:
- Комментировать видео
- Регистр
- Страница обзора пользователя / канала
- Пожаловаться на видео
Разрешения:
- Доступ к хранилищу, необходимый для скачивания через торрент или видео.
Под лицензией GNU Affero General Public License v3.0
Разрешения этой сильнейшей лицензии с авторским левом обусловлены предоставлением полного исходного кода лицензионных произведений и модификаций, которые включают более крупные произведения с использованием лицензионных произведений, по той же лицензии. Уведомления об авторских правах и лицензии должны быть сохранены. Соавторы предоставляют явное предоставление патентных прав. Когда измененная версия используется для предоставления услуги по сети, полный исходный код измененной версии должен быть доступен.
Исходный код: https://github.com/sschueller/peertube-android/

View File

@ -0,0 +1 @@
Thorium - неофициальный плеер PeerTube

View File

@ -0,0 +1 @@
Thorium-неоф. клиент PeerTube

View File

@ -0,0 +1 @@
https://www.youtube.com/watch?v=PJIsiuSdpq8

View File

@ -0,0 +1 @@
- Kimlik doğrulaması yenileme

View File

@ -0,0 +1,33 @@
Thorium, sürüm v1.1.0-alpha.2 veya daha üstünü çalıştıran herhangi bir PeerTube sunucusuna bağlanabilen bir PeerTube istemcisidir.
PeerTube, doğrudan web tarayıcısında P2P (BitTorrent) kullanan bir federe (ActivityPub) video yayınlama platformudur. Daha fazla bilgi ve sunucu listesi için lütfen https://joinpeertube.org/ adresini ziyaret edin.
Bu istemci, uygulamanın yaratıcısı tarafından - PeerTube projesinin kendisi değil, http://instances.joinpeertube.org/ adresinde daha fazlasını listelemektedir - yönetilen bir PeerTube sunucusuyla önceden yapılandırılmış olarak gelir, böylece istemcinin neler yapabileceğini görebilirsiniz. Deneyiminizi kendinize göre ayarlamak için sunucunuzu seçin!
Mevcut Özellikler:
- Herhangi bir PeerTube sunucusuna bağlanın
- Videoyu torrent ile paylaşma veya doğrudan oynatma
- PeerTube'de arayın
- Video indirin / paylaşın
- Temalar / Karanlık mod
- Arka planda oynatma
- Yatay modda tam ekran oynatma
- Oynatma hızı
- Uygunsuz (NSFW) içeriği filtreleyin
- Kimlik doğrulama / Oturum açma
- Video beğenin / beğenmeyin
Yakında Gelecekler:
- Videolara yorum yapma
- Kaydolma
- Kullanıcı / Kanal genel görünüm sayfası
- Videoları şikayet etme
İzinler:
- Depolama erişimi, torrent veya video indirme için gerekli.
GNU Affero Genel Kamu Lisansı v3.0 altında lisanslanmıştır.
Bu en güçlü copyleft lisansının izinleri, lisanslı bir çalışmayı içeren daha büyük çalışmalar dahil, lisanslı çalışmanın ve değişikliklerinin tüm kaynak kodlarının aynı lisans altında açık olarak sunulmasını gerektirmektedir. Telif hakkı ve lisans uyarıları korunmalıdır. Katkıda bulunanlar, açık bir patent hakları verirler. Değiştirilmiş bir sürüm ağ üzerinden bir hizmet sağlamak için kullanıldığında, değiştirilmiş sürümün tam kaynak kodu açık olarak sunulmalıdır.
Kaynak kodları: https://github.com/sschueller/peertube-android/

View File

@ -0,0 +1 @@
Thorium resmi olmayan bir PeerTube oynatıcısıdır

View File

@ -0,0 +1 @@
Thorium: PeerTube istemcisi

View File

@ -0,0 +1 @@
https://www.youtube.com/watch?v=PJIsiuSdpq8