diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e48cd4..a3e7768 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+### Version 1.0.20 Tag: v1.0.20 (2019-01-02)
+ * Added basic login framework
+ * AR Strings update (@rex07)
+
+### Version 1.0.19 Tag: v1.0.19 (2018-12-31)
+ * Video Language Filter (@lishoujun)
+
### Version 1.0.18 Tag: v1.0.18 (2018-12-31)
* Bug Fixes
* Arabic translation update
diff --git a/app/build.gradle b/app/build.gradle
index d51e17c..ddb6cc7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,9 +6,14 @@ android {
applicationId "net.schueller.peertube"
minSdkVersion 21
targetSdkVersion 28
- versionCode 1018
- versionName "1.0.18"
+ versionCode 1020
+ versionName "1.0.20"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ ext {
+ libVersions = [
+ exoplayer: '2.9.3'
+ ]
+ }
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
@@ -41,13 +46,13 @@ android {
// implementation "com.github.TorrentStream:TorrentStreamServer-Android:1.0.1"
// implementation 'org.webrtc:google-webrtc:1.0.+'
- // video player
- implementation 'com.google.android.exoplayer:exoplayer-core:2.9.2'
- implementation 'com.google.android.exoplayer:exoplayer-dash:2.9.2'
- implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.2'
- implementation 'com.google.android.exoplayer:exoplayer-hls:2.9.2'
- implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.9.2'
- implementation 'com.google.android.exoplayer:extension-mediasession:2.9.2'
+ // video player repo:jcenter()
+ implementation "com.google.android.exoplayer:exoplayer-core:$libVersions.exoplayer"
+ implementation "com.google.android.exoplayer:exoplayer-dash:$libVersions.exoplayer"
+ implementation "com.google.android.exoplayer:exoplayer-ui:$libVersions.exoplayer"
+ implementation "com.google.android.exoplayer:exoplayer-hls:$libVersions.exoplayer"
+ implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:$libVersions.exoplayer"
+ implementation "com.google.android.exoplayer:extension-mediasession:$libVersions.exoplayer"
// testing
testImplementation 'junit:junit:4.12'
@@ -71,3 +76,6 @@ android {
}
}
+dependencies {
+ implementation 'com.android.support.constraint:constraint-layout:+'
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6cc2ae4..de4a1d2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -18,7 +18,8 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
- tools:ignore="GoogleAppIndexingWarning">
+ tools:ignore="GoogleAppIndexingWarning"
+ android:name=".application.AppApplication">
+
+
+
+
+
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java b/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java
new file mode 100644
index 0000000..755c5c3
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2018 Stefan Schüller
+ *
+ * License: GPL-3.0+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package net.schueller.peertube.activity;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+import com.mikepenz.fontawesome_typeface_library.FontAwesome;
+import com.mikepenz.iconics.IconicsDrawable;
+
+import net.schueller.peertube.R;
+import net.schueller.peertube.helper.APIUrlHelper;
+import net.schueller.peertube.model.Me;
+import net.schueller.peertube.model.OauthClient;
+import net.schueller.peertube.model.Token;
+import net.schueller.peertube.network.AuthenticationService;
+import net.schueller.peertube.network.GetUserService;
+import net.schueller.peertube.network.RetrofitInstance;
+import net.schueller.peertube.network.Session;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.appcompat.widget.Toolbar;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
+import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
+
+public class AccountActivity extends AppCompatActivity {
+
+
+ private static final String TAG = "AccountActivity";
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.menu_top_user, menu);
+
+ // Set an icon in the ActionBar
+ menu.findItem(R.id.action_logout).setIcon(
+ new IconicsDrawable(this, FontAwesome.Icon.faw_sign_out_alt).actionBar());
+
+ return true;
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ switch (item.getItemId()) {
+ // action with ID action_refresh was selected
+
+ case R.id.action_logout:
+ Session.getInstance().invalidate();
+ Intent intent = new Intent(this, LoginActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ this.startActivity(intent);
+ finish();
+ return true;
+ default:
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ finish(); // close this activity as oppose to navigating up
+
+ return false;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set theme
+ SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+ setTheme(getResources().getIdentifier(
+ sharedPref.getString(THEME_PREF_KEY, DEFAULT_THEME),
+ "style",
+ getPackageName())
+ );
+
+ setContentView(R.layout.activity_account);
+
+
+ // Attaching the layout to the toolbar object
+ Toolbar toolbar = findViewById(R.id.tool_bar_user);
+ // Setting toolbar as the ActionBar with setSupportActionBar() call
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(
+ new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
+ );
+
+
+ init();
+ }
+
+ private void init() {
+ // try to get user data
+ getUserData();
+ }
+
+ private boolean getUserData() {
+
+ // TODO
+
+
+ String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
+
+ GetUserService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
+
+ Call call = service.getMe();
+
+ call.enqueue(new Callback() {
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+
+ if (response.isSuccessful()) {
+
+ Me me = response.body();
+
+ TextView username = findViewById(R.id.account_username);
+ TextView email = findViewById(R.id.account_email);
+
+ username.setText(me.getUsername());
+ email.setText(me.getEmail());
+
+ Log.v(TAG, me.getEmail());
+
+ }
+
+
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ init();
+
+ }
+}
diff --git a/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java b/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java
index 4ea13ea..a1cc45c 100644
--- a/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java
+++ b/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java
@@ -18,16 +18,19 @@
package net.schueller.peertube.activity;
+import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
-import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.Toast;
+
+import com.mikepenz.fontawesome_typeface_library.FontAwesome;
+import com.mikepenz.iconics.IconicsDrawable;
import net.schueller.peertube.R;
import net.schueller.peertube.helper.APIUrlHelper;
@@ -36,27 +39,23 @@ import net.schueller.peertube.model.Token;
import net.schueller.peertube.network.AuthenticationService;
import net.schueller.peertube.network.RetrofitInstance;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
import retrofit2.Call;
import retrofit2.Callback;
+import retrofit2.Response;
import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
public class LoginActivity extends AppCompatActivity {
- OkHttpClient client = new OkHttpClient();
- public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
-
private String TAG = "LoginActivity";
-
// UI references.
private AutoCompleteTextView mEmailView;
private EditText mPasswordView;
- private View mProgressView;
- private View mLoginFormView;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -79,17 +78,30 @@ public class LoginActivity extends AppCompatActivity {
mEmailView = findViewById(R.id.email);
mPasswordView = findViewById(R.id.password);
-// if (android.os.Build.VERSION.SDK_INT > 9) {
-// StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
-// StrictMode.setThreadPolicy(policy);
-// }
+
+ // Attaching the layout to the toolbar object
+ Toolbar toolbar = findViewById(R.id.tool_bar_login);
+ // Setting toolbar as the ActionBar with setSupportActionBar() call
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(
+ new IconicsDrawable(this, FontAwesome.Icon.faw_chevron_left).actionBar()
+ );
}
+ @Override
+ public boolean onSupportNavigateUp() {
+ finish(); // close this activity as oppose to navigating up
+ return false;
+ }
private void attemptLogin() {
+ SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+
+ Context context = this;
// Reset errors.
mEmailView.setError(null);
@@ -106,15 +118,18 @@ public class LoginActivity extends AppCompatActivity {
AuthenticationService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(AuthenticationService.class);
Call call = service.getOauthClientLocal();
+
call.enqueue(new Callback() {
@Override
- public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
- if (response.body() != null) {
+ if (response.isSuccessful()) {
+
+ OauthClient oauthClient = response.body();
Call call2 = service.getAuthenticationToken(
- response.body().getClientId(),
- response.body().getClientSecret(),
+ oauthClient.getClientId(),
+ oauthClient.getClientSecret(),
"code",
"password",
"upload",
@@ -125,13 +140,33 @@ public class LoginActivity extends AppCompatActivity {
@Override
public void onResponse(@NonNull Call call2, @NonNull retrofit2.Response response2) {
- if (response2.body() != null) {
- Log.wtf(TAG, response2.body().getAccessToken());
- Log.wtf(TAG, response2.body().getExpiresIn());
- Log.wtf(TAG, response2.body().getRefreshToken());
- Log.wtf(TAG, response2.body().getTokenType());
+ if (response2.isSuccessful()) {
+
+ Token token = response2.body();
+
+ SharedPreferences.Editor editor = sharedPref.edit();
+
+ // TODO: calc expiration
+ //editor.putInt(getString(R.string.pref_token_expiration), token.getRefreshToken());
+
+ editor.putString(getString(R.string.pref_token_access), token.getAccessToken());
+ editor.putString(getString(R.string.pref_token_refresh), token.getExpiresIn());
+ editor.putString(getString(R.string.pref_token_type), token.getTokenType());
+ editor.commit();
+
+ Log.wtf(TAG, "Logged in");
+
+ Intent intent = new Intent(context, AccountActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ context.startActivity(intent);
+
+ finish(); // close this activity
+
} else {
Log.wtf(TAG, response2.toString());
+
+ Toast.makeText(LoginActivity.this, "Login Error!", Toast.LENGTH_LONG).show();
+
}
}
diff --git a/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java b/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java
index bef23d9..df82443 100644
--- a/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java
+++ b/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java
@@ -53,13 +53,16 @@ import net.schueller.peertube.R;
import net.schueller.peertube.adapter.VideoAdapter;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.model.VideoList;
+import net.schueller.peertube.network.GetUserService;
import net.schueller.peertube.network.GetVideoDataService;
import net.schueller.peertube.network.RetrofitInstance;
+import net.schueller.peertube.network.Session;
import net.schueller.peertube.provider.SearchSuggestionsProvider;
import net.schueller.peertube.service.VideoPlayerService;
import java.util.ArrayList;
+import java.util.Set;
import retrofit2.Call;
import retrofit2.Callback;
@@ -82,6 +85,7 @@ public class VideoListActivity extends AppCompatActivity {
private String sort = "-createdAt";
private String filter = null;
private String searchQuery = "";
+ private Boolean subscriptions = false;
private TextView emptyView;
private RecyclerView recyclerView;
@@ -125,7 +129,7 @@ public class VideoListActivity extends AppCompatActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.menu_main, menu);
+ inflater.inflate(R.menu.menu_top_videolist, menu);
// Set an icon in the ActionBar
menu.findItem(R.id.action_settings).setIcon(
@@ -253,16 +257,19 @@ public class VideoListActivity extends AppCompatActivity {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String nsfw = sharedPref.getBoolean("pref_show_nsfw", false) ? "both" : "false";
-
+ Set languages = sharedPref.getStringSet("pref_language", null);
String apiBaseURL = APIUrlHelper.getUrlWithVersion(this);
GetVideoDataService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetVideoDataService.class);
Call call;
if (!searchQuery.equals("")) {
- call = service.searchVideosData(start, count, sort, nsfw, searchQuery, filter);
+ call = service.searchVideosData(start, count, sort, nsfw, searchQuery, filter, languages);
+ } else if (subscriptions) {
+ GetUserService userService = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetUserService.class);
+ call = userService.getVideosSubscripions(start, count, sort);
} else {
- call = service.getVideosData(start, count, sort, nsfw, filter);
+ call = service.getVideosData(start, count, sort, nsfw, filter, languages);
}
/*Log the URL called*/
@@ -380,6 +387,7 @@ public class VideoListActivity extends AppCompatActivity {
sort = "-createdAt";
currentStart = 0;
filter = null;
+ subscriptions = false;
loadVideos(currentStart, count, sort, filter);
}
@@ -391,6 +399,7 @@ public class VideoListActivity extends AppCompatActivity {
sort = "-trending";
currentStart = 0;
filter = null;
+ subscriptions = false;
loadVideos(currentStart, count, sort, filter);
}
@@ -402,22 +411,42 @@ public class VideoListActivity extends AppCompatActivity {
sort = "-publishedAt";
filter = "local";
currentStart = 0;
+ subscriptions = false;
loadVideos(currentStart, count, sort, filter);
}
return true;
case R.id.navigation_subscriptions:
//Log.v(TAG, "navigation_subscriptions");
- Toast.makeText(VideoListActivity.this, "Subscriptions Not Implemented", Toast.LENGTH_SHORT).show();
- return false;
+ if (!Session.getInstance().isLoggedIn()) {
+ Intent intent = new Intent(this, LoginActivity.class);
+ this.startActivity(intent);
+ return false;
+ } else {
+
+ if (!isLoading) {
+ sort = "-publishedAt";
+ filter = null;
+ currentStart = 0;
+ subscriptions = true;
+ loadVideos(currentStart, count, sort, filter);
+ }
+ return true;
+ }
+
case R.id.navigation_account:
//Log.v(TAG, "navigation_account");
- Toast.makeText(VideoListActivity.this, "Account Not Implemented", Toast.LENGTH_SHORT).show();
+ //Toast.makeText(VideoListActivity.this, "Account Not Implemented", Toast.LENGTH_SHORT).show();
-// Intent intent = new Intent(this, LoginActivity.class);
-// this.startActivity(intent);
+ if (!Session.getInstance().isLoggedIn()) {
+ Intent intent = new Intent(this, LoginActivity.class);
+ this.startActivity(intent);
+ } else {
+ Intent intent = new Intent(this, AccountActivity.class);
+ this.startActivity(intent);
+ }
return false;
}
diff --git a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java
index b8f0699..b747553 100644
--- a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java
+++ b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java
@@ -66,6 +66,7 @@ import net.schueller.peertube.fragment.VideoOptionsFragment;
import net.schueller.peertube.helper.APIUrlHelper;
import net.schueller.peertube.helper.MetaDataHelper;
import net.schueller.peertube.intents.Intents;
+import net.schueller.peertube.model.Account;
import net.schueller.peertube.model.Avatar;
import net.schueller.peertube.model.Video;
import net.schueller.peertube.network.GetVideoDataService;
@@ -89,7 +90,7 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
private Context context = this;
private TextView fullscreenButton;
private Boolean isFullscreen = false;
-
+ private TorrentStream torrentStream;
boolean mBound = false;
VideoPlayerService mService;
@@ -296,7 +297,16 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
String baseUrl = APIUrlHelper.getUrl(context);
- Avatar avatar = video.getAccount().getAvatar();
+ if(video == null){
+ Toast.makeText(VideoPlayActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Account account = video.getAccount();
+ if(account == null){
+ Toast.makeText(VideoPlayActivity.this, "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Avatar avatar = account.getAvatar();
if (avatar != null) {
String avatarPath = avatar.getPath();
Picasso.with(context)
@@ -349,6 +359,7 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
videoOptionsFragment.show(getSupportFragmentManager(),
"video_options_fragment");
});
+ Log.v(TAG, "url : " + video.getFiles().get(0).getFileUrl());
mService.setCurrentStreamUrl(video.getFiles().get(0).getFileUrl());
@@ -357,11 +368,13 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
if (sharedPref.getBoolean("pref_torrent_player", false)) {
String stream = video.getFiles().get(0).getTorrentUrl();
- TorrentStream torrentStream = setupTorrentStream();
+ Log.v(TAG, "getTorrentUrl : " + video.getFiles().get(0).getTorrentUrl());
+ torrentStream = setupTorrentStream();
torrentStream.startStream(stream);
} else {
startPlayer();
}
+ Log.v(TAG,"end of load Video");
}
@@ -412,8 +425,12 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere
@Override
protected void onDestroy() {
- super.onDestroy();
simpleExoPlayerView.setPlayer(null);
+ if (torrentStream != null){
+ torrentStream.stopStream();
+ }
+ super.onDestroy();
+ Log.v(TAG, "onDestroy...");
}
@Override
diff --git a/app/src/main/java/net/schueller/peertube/application/AppApplication.java b/app/src/main/java/net/schueller/peertube/application/AppApplication.java
new file mode 100644
index 0000000..05869b4
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/application/AppApplication.java
@@ -0,0 +1,18 @@
+package net.schueller.peertube.application;
+
+import android.app.Application;
+import android.content.Context;
+
+public class AppApplication extends Application {
+ private static Application instance;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ instance = this;
+ }
+
+ public static Context getContext() {
+ return instance.getApplicationContext();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/schueller/peertube/model/Me.java b/app/src/main/java/net/schueller/peertube/model/Me.java
new file mode 100644
index 0000000..1a0c96e
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/model/Me.java
@@ -0,0 +1,144 @@
+package net.schueller.peertube.model;
+
+public class Me {
+
+ private Integer id;
+ private Account account;
+ private Boolean autoPlayVideo;
+ private Boolean blocked;
+ private String blockedReason;
+ private String createdAt;
+ private String email;
+ private String emailVerified;
+ private String nsfwPolicy;
+ private Integer role;
+ private String roleLabel;
+ private String username;
+
+ // private VideoChannels videoChannels;
+ private Integer videoQuota;
+ private Integer videoQuotaDaily;
+ private String webTorrentEnabled;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Account getAccount() {
+ return account;
+ }
+
+ public void setAccount(Account account) {
+ this.account = account;
+ }
+
+ public Boolean getAutoPlayVideo() {
+ return autoPlayVideo;
+ }
+
+ public void setAutoPlayVideo(Boolean autoPlayVideo) {
+ this.autoPlayVideo = autoPlayVideo;
+ }
+
+ public Boolean getBlocked() {
+ return blocked;
+ }
+
+ public void setBlocked(Boolean blocked) {
+ this.blocked = blocked;
+ }
+
+ public String getBlockedReason() {
+ return blockedReason;
+ }
+
+ public void setBlockedReason(String blockedReason) {
+ this.blockedReason = blockedReason;
+ }
+
+ public String getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(String createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getEmailVerified() {
+ return emailVerified;
+ }
+
+ public void setEmailVerified(String emailVerified) {
+ this.emailVerified = emailVerified;
+ }
+
+ public String getNsfwPolicy() {
+ return nsfwPolicy;
+ }
+
+ public void setNsfwPolicy(String nsfwPolicy) {
+ this.nsfwPolicy = nsfwPolicy;
+ }
+
+ public Integer getRole() {
+ return role;
+ }
+
+ public void setRole(Integer role) {
+ this.role = role;
+ }
+
+ public String getRoleLabel() {
+ return roleLabel;
+ }
+
+ public void setRoleLabel(String roleLabel) {
+ this.roleLabel = roleLabel;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Integer getVideoQuota() {
+ return videoQuota;
+ }
+
+ public void setVideoQuota(Integer videoQuota) {
+ this.videoQuota = videoQuota;
+ }
+
+ public Integer getVideoQuotaDaily() {
+ return videoQuotaDaily;
+ }
+
+ public void setVideoQuotaDaily(Integer videoQuotaDaily) {
+ this.videoQuotaDaily = videoQuotaDaily;
+ }
+
+ public String getWebTorrentEnabled() {
+ return webTorrentEnabled;
+ }
+
+ public void setWebTorrentEnabled(String webTorrentEnabled) {
+ this.webTorrentEnabled = webTorrentEnabled;
+ }
+}
+
+
diff --git a/app/src/main/java/net/schueller/peertube/model/OauthClient.java b/app/src/main/java/net/schueller/peertube/model/OauthClient.java
index e8044be..9dd016f 100644
--- a/app/src/main/java/net/schueller/peertube/model/OauthClient.java
+++ b/app/src/main/java/net/schueller/peertube/model/OauthClient.java
@@ -17,9 +17,14 @@
*/
package net.schueller.peertube.model;
+import com.google.gson.annotations.SerializedName;
+
public class OauthClient {
+ @SerializedName("client_id")
private String clientId;
+
+ @SerializedName("client_secret")
private String clientSecret;
public String getClientId() {
diff --git a/app/src/main/java/net/schueller/peertube/model/Token.java b/app/src/main/java/net/schueller/peertube/model/Token.java
index a4ac1f1..f43bad0 100644
--- a/app/src/main/java/net/schueller/peertube/model/Token.java
+++ b/app/src/main/java/net/schueller/peertube/model/Token.java
@@ -17,11 +17,20 @@
*/
package net.schueller.peertube.model;
+import com.google.gson.annotations.SerializedName;
+
public class Token {
+ @SerializedName("access_token")
private String accessToken;
+
+ @SerializedName("expires_in")
private String expiresIn;
+
+ @SerializedName("refresh_token")
private String refreshToken;
+
+ @SerializedName("token_type")
private String tokenType;
public String getAccessToken() {
diff --git a/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java b/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java
new file mode 100644
index 0000000..37786c7
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 Stefan Schüller
+ *
+ * License: GPL-3.0+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package net.schueller.peertube.network;
+
+import android.util.Log;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class AuthorizationInterceptor implements Interceptor {
+
+ public AuthorizationInterceptor() {
+ }
+
+
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+
+ Session session = Session.getInstance();
+
+ Response mainResponse = chain.proceed(chain.request());
+ Request mainRequest = chain.request();
+
+ if (session.isLoggedIn()) {
+
+ // add authentication header to each request if we are logged in
+ Request.Builder builder = mainRequest.newBuilder().header("Authorization", session.getToken()).
+ method(mainRequest.method(), mainRequest.body());
+ // Log.v("Authorization", "Intercept: " + session.getToken());
+
+ // build request
+ mainResponse = chain.proceed(builder.build());
+
+ // logout on auth error
+ if (mainResponse.code() == 401 || mainResponse.code() == 403) {
+ session.invalidate();
+ Log.v("Authorization", "Intercept: Logout forced");
+ }
+
+ }
+
+ return mainResponse;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/schueller/peertube/network/GetUserService.java b/app/src/main/java/net/schueller/peertube/network/GetUserService.java
new file mode 100644
index 0000000..850b9f5
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/network/GetUserService.java
@@ -0,0 +1,23 @@
+package net.schueller.peertube.network;
+
+import net.schueller.peertube.model.Me;
+import net.schueller.peertube.model.VideoList;
+
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Header;
+import retrofit2.http.Query;
+
+public interface GetUserService {
+
+ @GET("users/me")
+ Call getMe();
+
+ @GET("users/me/subscriptions/videos")
+ Call getVideosSubscripions(
+ @Query("start") int start,
+ @Query("count") int count,
+ @Query("sort") String sort
+ );
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/schueller/peertube/network/GetVideoDataService.java b/app/src/main/java/net/schueller/peertube/network/GetVideoDataService.java
index b66b727..2159070 100644
--- a/app/src/main/java/net/schueller/peertube/network/GetVideoDataService.java
+++ b/app/src/main/java/net/schueller/peertube/network/GetVideoDataService.java
@@ -20,6 +20,8 @@ package net.schueller.peertube.network;
import net.schueller.peertube.model.Video;
import net.schueller.peertube.model.VideoList;
+import java.util.Set;
+
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
@@ -32,7 +34,8 @@ public interface GetVideoDataService {
@Query("count") int count,
@Query("sort") String sort,
@Query("nsfw") String nsfw,
- @Query("filter") String filter
+ @Query("filter") String filter,
+ @Query("languageOneOf") Set languages
);
@GET("videos/{id}")
@@ -47,6 +50,7 @@ public interface GetVideoDataService {
@Query("sort") String sort,
@Query("nsfw") String nsfw,
@Query("search") String search,
- @Query("filter") String filter
+ @Query("filter") String filter,
+ @Query("languageOneOf") Set languages
);
}
\ No newline at end of file
diff --git a/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java b/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
index fc8936f..23e38da 100644
--- a/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
+++ b/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
@@ -17,6 +17,7 @@
*/
package net.schueller.peertube.network;
+import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@@ -28,7 +29,13 @@ public class RetrofitInstance {
public static Retrofit getRetrofitInstance(String newBaseUrl) {
if (retrofit == null || !newBaseUrl.equals(baseUrl)) {
baseUrl = newBaseUrl;
+
+ OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
+
+ okhttpClientBuilder.addInterceptor(new AuthorizationInterceptor());
+
retrofit = new retrofit2.Retrofit.Builder()
+ .client(okhttpClientBuilder.build())
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
diff --git a/app/src/main/java/net/schueller/peertube/network/Session.java b/app/src/main/java/net/schueller/peertube/network/Session.java
new file mode 100644
index 0000000..525cbb9
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/network/Session.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2018 Stefan Schüller
+ *
+ * License: GPL-3.0+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package net.schueller.peertube.network;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+import net.schueller.peertube.R;
+import net.schueller.peertube.application.AppApplication;
+
+public class Session {
+
+ private static volatile Session sSoleInstance;
+ private static SharedPreferences sharedPreferences;
+
+ //private constructor.
+ private Session(){
+
+ Context context = AppApplication.getContext();
+ sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+ //Prevent form the reflection api.
+ if (sSoleInstance != null){
+ throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
+ }
+ }
+
+ public static Session getInstance() {
+ if (sSoleInstance == null) { //if there is no instance available... create new one
+ synchronized (Session.class) {
+ if (sSoleInstance == null) sSoleInstance = new Session();
+ }
+ }
+
+ return sSoleInstance;
+ }
+
+ //Make singleton from serialize and deserialize operation.
+ protected Session readResolve() {
+ return getInstance();
+ }
+
+
+
+ public boolean isLoggedIn() {
+ // check if token exist or not
+ // return true if exist otherwise false
+ // assuming that token exists
+
+ //Log.v("Session", "isLoggedIn: " + (getToken() != null));
+
+ return getToken() != null;
+ }
+
+ public void saveToken(String token) {
+ // save the token
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString(AppApplication.getContext().getString(R.string.pref_token_access), token);
+ editor.commit();
+ }
+
+ public String getToken() {
+ // return the token that was saved earlier
+
+ String token = sharedPreferences.getString(AppApplication.getContext().getString(R.string.pref_token_access), null);
+ String type = sharedPreferences.getString(AppApplication.getContext().getString(R.string.pref_token_type), "Bearer");
+
+ if (token != null) {
+ return type + " " + token;
+ }
+
+ return null;
+ }
+
+ public void saveUsername(String username) {
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString(AppApplication.getContext().getString(R.string.pref_auth_username), username);
+ editor.commit();
+ }
+
+ public String getEmail() {
+ return sharedPreferences.getString(AppApplication.getContext().getString(R.string.pref_auth_username), null);
+ }
+
+ public void savePassword(String password) {
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString(AppApplication.getContext().getString(R.string.pref_auth_password), password);
+ editor.commit();
+ }
+
+ public String getPassword() {
+ return sharedPreferences.getString(AppApplication.getContext().getString(R.string.pref_auth_password), null);
+
+ }
+
+ public void invalidate() {
+ // get called when user become logged out
+ // delete token and other user info
+ // (i.e: email, password)
+ // from the storage
+
+ Context context = AppApplication.getContext();
+
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putString(context.getString(R.string.pref_auth_password), null);
+ editor.putString(context.getString(R.string.pref_auth_username), null);
+ editor.putString(context.getString(R.string.pref_token_access), null);
+
+ editor.commit();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml
new file mode 100644
index 0000000..bfa68ce
--- /dev/null
+++ b/app/src/main/res/layout/activity_account.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index 82d760d..6ea1ec6 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -3,74 +3,93 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
- android:orientation="vertical"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="net.schueller.peertube.activity.LoginActivity">
+ android:orientation="vertical">
-
-
-
-
+ android:orientation="vertical">
-
+ android:elevation="4dp" />
-
+
-
+
-
-
+
-
-
-
-
-
-
-
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_top_user.xml b/app/src/main/res/menu/menu_top_user.xml
new file mode 100644
index 0000000..efd2356
--- /dev/null
+++ b/app/src/main/res/menu/menu_top_user.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_top_videolist.xml
similarity index 100%
rename from app/src/main/res/menu/menu_main.xml
rename to app/src/main/res/menu/menu_top_videolist.xml
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index e090072..37a45b8 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -35,8 +35,8 @@
- \0020-\0020
- \0020مشاهدات
+ \u0020-\u0020
+ \u0020 مشاهدات
\@
@@ -45,11 +45,13 @@
عرض NSFW
عند التنشيط سيتم عرض محتويات NSFW
+ عرض اللغات
+ أختيار لغة ليتم عرضها.
UrlVideoPlayActivity
مشغل فيديو التورنت
تشغيل الفيديو عبر بث التورنت . يتطلب هذا أذونات التخزين. (ألفا ، غير مستقر!)
الرخصة
- GNU Affero General Public License v3.0\n
+ رخصة جنو العمومية v3.0\n
\n
إن أذونات هذا الترخيص الأقوى للحقوق المتروكة مشروطة بإتاحة الشفرة المصدرية الكاملة للأعمال والتعديلات المرخصة ، والتي تشتمل على أعمال أكبر باستخدام عمل مرخص ، تحت نفس الترخيص. يجب الحفاظ على حقوق النشر وإشعارات الترخيص. يقدم المساهمون منحة صريحة لحقوق البراءة. عند استخدام إصدار معدل لتوفير خدمة عبر شبكة ، يجب توفير شفرة المصدر الكاملة للإصدار المعدل.
الإصدار
@@ -64,7 +66,10 @@
أعد تشغيل التطبيق لتنشيط الوضع الداكن.
مظهر التطبيق
أعد تشغيل التطبيق لتفعيل التعديلات التي طرأت على المظهر.
-
+
+ الإنجليزية
+ الفرنسية
+
أحمر
وردي
بنفسجي
@@ -91,7 +96,7 @@
التشغيل في الخلفية
- إن تم تنشيطه، ستواصل الفيديو في الإشتغال في الخلفية.
+ إن تم تنشيطه، سيستمر تشغيل الفيديو في الخلفية.
المحلي
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index e28c726..f31f9c9 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -8,7 +8,7 @@
Serveur
Email
- Mot de passe (optionnel)
+ Mot de passe
Connexion
Connexion
Cette adresse mail n\'est pas valide
diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml
index 1625c00..e842230 100644
--- a/app/src/main/res/values/array.xml
+++ b/app/src/main/res/values/array.xml
@@ -44,5 +44,395 @@
- AppTheme.GRAY
- AppTheme.BLUEGRAY
+
+ - @string/ab
+ - @string/aa
+ - @string/af
+ - @string/ak
+ - @string/sq
+ - @string/ase
+ - @string/am
+ - @string/ar
+ - @string/an
+ - @string/hy
+ - @string/as
+ - @string/av
+ - @string/ay
+ - @string/az
+ - @string/bm
+ - @string/ba
+ - @string/eu
+ - @string/be
+ - @string/bn
+ - @string/bi
+ - @string/bs
+ - @string/bzs
+ - @string/br
+ - @string/bfi
+ - @string/bg
+ - @string/my
+ - @string/ca
+ - @string/ch
+ - @string/ce
+ - @string/zh
+ - @string/csl
+ - @string/cv
+ - @string/kw
+ - @string/co
+ - @string/cr
+ - @string/hr
+ - @string/cs
+ - @string/cse
+ - @string/da
+ - @string/dsl
+ - @string/dv
+ - @string/nl
+ - @string/dz
+ - @string/en
+ - @string/eo
+ - @string/et
+ - @string/ee
+ - @string/fo
+ - @string/fj
+ - @string/fi
+ - @string/fr
+ - @string/fsl
+ - @string/ff
+ - @string/gl
+ - @string/lg
+ - @string/ka
+ - @string/de
+ - @string/gsg
+ - @string/gn
+ - @string/gu
+ - @string/ht
+ - @string/ha
+ - @string/he
+ - @string/hz
+ - @string/hi
+ - @string/ho
+ - @string/hu
+ - @string/is
+ - @string/ig
+ - @string/id
+ - @string/iu
+ - @string/ik
+ - @string/ga
+ - @string/it
+ - @string/ja
+ - @string/jsl
+ - @string/jv
+ - @string/kl
+ - @string/kn
+ - @string/kr
+ - @string/ks
+ - @string/kk
+ - @string/km
+ - @string/ki
+ - @string/rw
+ - @string/ky
+ - @string/tlh
+ - @string/kv
+ - @string/kg
+ - @string/ko
+ - @string/avk
+ - @string/kj
+ - @string/ku
+ - @string/lo
+ - @string/lv
+ - @string/li
+ - @string/ln
+ - @string/lt
+ - @string/jbo
+ - @string/lu
+ - @string/lb
+ - @string/mk
+ - @string/mg
+ - @string/ms
+ - @string/ml
+ - @string/mt
+ - @string/gv
+ - @string/mi
+ - @string/mr
+ - @string/mh
+ - @string/el
+ - @string/mn
+ - @string/na
+ - @string/nv
+ - @string/ng
+ - @string/ne
+ - @string/nd
+ - @string/se
+ - @string/no
+ - @string/nb
+ - @string/nn
+ - @string/ny
+ - @string/oc
+ - @string/oj
+ - @string/or
+ - @string/om
+ - @string/os
+ - @string/pks
+ - @string/pa
+ - @string/fa
+ - @string/pl
+ - @string/pt
+ - @string/ps
+ - @string/qu
+ - @string/ro
+ - @string/rm
+ - @string/rn
+ - @string/ru
+ - @string/rsl
+ - @string/sm
+ - @string/sg
+ - @string/sc
+ - @string/sdl
+ - @string/gd
+ - @string/sr
+ - @string/sh
+ - @string/sn
+ - @string/ii
+ - @string/sd
+ - @string/si
+ - @string/sk
+ - @string/sl
+ - @string/so
+ - @string/sfs
+ - @string/nr
+ - @string/st
+ - @string/es
+ - @string/su
+ - @string/sw
+ - @string/ss
+ - @string/sv
+ - @string/swl
+ - @string/tl
+ - @string/ty
+ - @string/tg
+ - @string/ta
+ - @string/tt
+ - @string/te
+ - @string/th
+ - @string/bo
+ - @string/ti
+ - @string/to
+ - @string/ts
+ - @string/tn
+ - @string/tr
+ - @string/tk
+ - @string/tw
+ - @string/ug
+ - @string/uk
+ - @string/ur
+ - @string/uz
+ - @string/ve
+ - @string/vi
+ - @string/wa
+ - @string/cy
+ - @string/fy
+ - @string/wo
+ - @string/xh
+ - @string/yi
+ - @string/yo
+ - @string/za
+ - @string/zu
+
+
+
+ - ab
+ - aa
+ - af
+ - ak
+ - sq
+ - ase
+ - am
+ - ar
+ - an
+ - hy
+ - as
+ - av
+ - ay
+ - az
+ - bm
+ - ba
+ - eu
+ - be
+ - bn
+ - bi
+ - bs
+ - bzs
+ - br
+ - bfi
+ - bg
+ - my
+ - ca
+ - ch
+ - ce
+ - zh
+ - csl
+ - cv
+ - kw
+ - co
+ - cr
+ - hr
+ - cs
+ - cse
+ - da
+ - dsl
+ - dv
+ - nl
+ - dz
+ - en
+ - eo
+ - et
+ - ee
+ - fo
+ - fj
+ - fi
+ - fr
+ - fsl
+ - ff
+ - gl
+ - lg
+ - ka
+ - de
+ - gsg
+ - gn
+ - gu
+ - ht
+ - ha
+ - he
+ - hz
+ - hi
+ - ho
+ - hu
+ - is
+ - ig
+ - id
+ - iu
+ - ik
+ - ga
+ - it
+ - ja
+ - jsl
+ - jv
+ - kl
+ - kn
+ - kr
+ - ks
+ - kk
+ - km
+ - ki
+ - rw
+ - ky
+ - tlh
+ - kv
+ - kg
+ - ko
+ - avk
+ - kj
+ - ku
+ - lo
+ - lv
+ - li
+ - ln
+ - lt
+ - jbo
+ - lu
+ - lb
+ - mk
+ - mg
+ - ms
+ - ml
+ - mt
+ - gv
+ - mi
+ - mr
+ - mh
+ - el
+ - mn
+ - na
+ - nv
+ - ng
+ - ne
+ - nd
+ - se
+ - no
+ - nb
+ - nn
+ - ny
+ - oc
+ - oj
+ - or
+ - om
+ - os
+ - pks
+ - pa
+ - fa
+ - pl
+ - pt
+ - ps
+ - qu
+ - ro
+ - rm
+ - rn
+ - ru
+ - rsl
+ - sm
+ - sg
+ - sc
+ - sdl
+ - gd
+ - sr
+ - sh
+ - sn
+ - ii
+ - sd
+ - si
+ - sk
+ - sl
+ - so
+ - sfs
+ - nr
+ - st
+ - es
+ - su
+ - sw
+ - ss
+ - sv
+ - swl
+ - tl
+ - ty
+ - tg
+ - ta
+ - tt
+ - te
+ - th
+ - bo
+ - ti
+ - to
+ - ts
+ - tn
+ - tr
+ - tk
+ - tw
+ - ug
+ - uk
+ - ur
+ - uz
+ - ve
+ - vi
+ - wa
+ - cy
+ - fy
+ - wo
+ - xh
+ - yi
+ - yo
+ - za
+ - zu
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8f8f546..959ad98 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,7 +8,7 @@
Server
Email
- Password (optional)
+ Password
Sign in
Sign in
This email address is invalid
@@ -22,6 +22,7 @@
Search
Settings
+ Logout
Home
@@ -47,6 +48,8 @@
Show NSFW
NSFW content will be shown if enabled.
+ Languages filter
+ Select video languages that should be shown. None selected will show all videos in all languages.
UrlVideoPlayActivity
Torrent Video Player
Video playback via a torrent stream. This requires Storage Permissions. (Alpha, not stable!)
@@ -65,6 +68,199 @@
App Theme
Restart App for theme to take effect.
+ Abkhazian
+ Afar
+ Afrikaans
+ Akan
+ Albanian
+ American Sign Language
+ Amharic
+ Arabic
+ Aragonese
+ Armenian
+ Assamese
+ Avaric
+ Aymara
+ Azerbaijani
+ Bambara
+ Bashkir
+ Basque
+ Belarusian
+ Bengali
+ Bislama
+ Bosnian
+ Brazilian Sign Language
+ Breton
+ British Sign Language
+ Bulgarian
+ Burmese
+ Catalan
+ Chamorro
+ Chechen
+ Chinese
+ Chinese Sign Language
+ Chuvash
+ Cornish
+ Corsican
+ Cree
+ Croatian
+ Czech
+ Czech Sign Language
+ Danish
+ Danish Sign Language
+ Dhivehi
+ Dutch
+ Dzongkha
+ English
+ Esperanto
+ Estonian
+ Ewe
+ Faroese
+ Fijian
+ Finnish
+ French
+ French Sign Language
+ Fulah
+ Galician
+ Ganda
+ Georgian
+ German
+ German Sign Language
+ Guarani
+ Gujarati
+ Haitian
+ Hausa
+ Hebrew
+ Herero
+ Hindi
+ Hiri Motu
+ Hungarian
+ Icelandic
+ Igbo
+ Indonesian
+ Inuktitut
+ Inupiaq
+ Irish
+ Italian
+ Japanese
+ Japanese Sign Language
+ Javanese
+ Kalaallisut
+ Kannada
+ Kanuri
+ Kashmiri
+ Kazakh
+ Khmer
+ Kikuyu
+ Kinyarwanda
+ Kirghiz
+ Klingon
+ Komi
+ Kongo
+ Korean
+ Kotava
+ Kuanyama
+ Kurdish
+ Lao
+ Latvian
+ Limburgan
+ Lingala
+ Lithuanian
+ Lojban
+ Luba-Katanga
+ Luxembourgish
+ Macedonian
+ Malagasy
+ Malay (macrolanguage)
+ Malayalam
+ Maltese
+ Manx
+ Maori
+ Marathi
+ Marshallese
+ Modern Greek (1453-)
+ Mongolian
+ Nauru
+ Navajo
+ Ndonga
+ Nepali (macrolanguage)
+ North Ndebele
+ Northern Sami
+ Norwegian
+ Norwegian Bokmål
+ Norwegian Nynorsk
+ Nyanja
+ Occitan
+ Ojibwa
+ Oriya (macrolanguage)
+ Oromo
+ Ossetian
+ Pakistan Sign Language
+ Panjabi
+ Persian
+ Polish
+ Portuguese
+ Pushto
+ Quechua
+ Romanian
+ Romansh
+ Rundi
+ Russian
+ Russian Sign Language
+ Samoan
+ Sango
+ Sardinian
+ Saudi Arabian Sign Language
+ Scottish Gaelic
+ Serbian
+ Serbo-Croatian
+ Shona
+ Sichuan Yi
+ Sindhi
+ Sinhala
+ Slovak
+ Slovenian
+ Somali
+ South African Sign Language
+ South Ndebele
+ Southern Sotho
+ Spanish
+ Sundanese
+ Swahili (macrolanguage)
+ Swati
+ Swedish
+ Swedish Sign Language
+ Tagalog
+ Tahitian
+ Tajik
+ Tamil
+ Tatar
+ Telugu
+ Thai
+ Tibetan
+ Tigrinya
+ Tonga (Tonga Islands)
+ Tsonga
+ Tswana
+ Turkish
+ Turkmen
+ Twi
+ Uighur
+ Ukrainian
+ Urdu
+ Uzbek
+ Venda
+ Vietnamese
+ Walloon
+ Welsh
+ Western Frisian
+ Wolof
+ Xhosa
+ Yiddish
+ Yoruba
+ Zhuang
+ Zulu
+
Red
Pink
Purple
@@ -98,4 +294,14 @@
If enabled, continues to play video in background.
Local
+ Account
+
+
+ pref_token_access
+ pref_token_refresh
+ pref_token_expiration
+ pref_token_type
+ pref_auth_username
+ pref_auth_password
+
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
index d287b5d..98b1da9 100644
--- a/app/src/main/res/xml/pref_general.xml
+++ b/app/src/main/res/xml/pref_general.xml
@@ -22,6 +22,14 @@
android:summary="@string/pref_description_show_nsfw"
android:defaultValue="false" />
+
+