diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5aa5606..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">
-
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..095c1d4
--- /dev/null
+++ b/app/src/main/java/net/schueller/peertube/activity/AccountActivity.java
@@ -0,0 +1,123 @@
+/*
+ * 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 com.mikepenz.fontawesome_typeface_library.FontAwesome;
+import com.mikepenz.iconics.IconicsDrawable;
+
+import net.schueller.peertube.R;
+import net.schueller.peertube.network.Session;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.appcompat.widget.Toolbar;
+
+import static net.schueller.peertube.helper.Constants.DEFAULT_THEME;
+import static net.schueller.peertube.helper.Constants.THEME_PREF_KEY;
+
+public class AccountActivity extends AppCompatActivity {
+
+
+ @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);
+ return true;
+ default:
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+
+ @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);
+
+ init();
+ }
+
+ private void init() {
+ // try to get user data
+ getUserData();
+ }
+
+ private boolean getUserData() {
+
+ // TODO
+
+ return false;
+ }
+
+ @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 e34c397..9ec1427 100644
--- a/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java
+++ b/app/src/main/java/net/schueller/peertube/activity/LoginActivity.java
@@ -18,10 +18,10 @@
package net.schueller.peertube.activity;
+import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.AutoCompleteTextView;
@@ -35,6 +35,8 @@ import net.schueller.peertube.model.Token;
import net.schueller.peertube.network.AuthenticationService;
import net.schueller.peertube.network.RetrofitInstance;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@@ -78,6 +80,8 @@ public class LoginActivity extends AppCompatActivity {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+ Context context = this;
+
// Reset errors.
mEmailView.setError(null);
mPasswordView.setError(null);
@@ -129,6 +133,12 @@ public class LoginActivity extends AppCompatActivity {
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);
+
} else {
Log.wtf(TAG, response2.toString());
}
diff --git a/app/src/main/java/net/schueller/peertube/activity/UserActivity.java b/app/src/main/java/net/schueller/peertube/activity/UserActivity.java
deleted file mode 100644
index b178c98..0000000
--- a/app/src/main/java/net/schueller/peertube/activity/UserActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.schueller.peertube.activity;
-
-import android.content.Intent;
-import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
-
-import net.schueller.peertube.R;
-
-public class UserActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_user);
-
- init();
- }
-
- private void init() {
- // try to get user data
- if (!getUserData()) {
- Intent intent = new Intent(this, LoginActivity.class);
- this.startActivity(intent);
- }
- }
-
- private boolean getUserData() {
-
- // TODO
-
- return false;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- init();
-
- }
-}
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..ed8b3d4 100644
--- a/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java
+++ b/app/src/main/java/net/schueller/peertube/activity/VideoListActivity.java
@@ -53,8 +53,10 @@ 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;
@@ -82,6 +84,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 +128,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(
@@ -261,6 +264,9 @@ public class VideoListActivity extends AppCompatActivity {
Call call;
if (!searchQuery.equals("")) {
call = service.searchVideosData(start, count, sort, nsfw, searchQuery, filter);
+ } 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);
}
@@ -380,6 +386,7 @@ public class VideoListActivity extends AppCompatActivity {
sort = "-createdAt";
currentStart = 0;
filter = null;
+ subscriptions = false;
loadVideos(currentStart, count, sort, filter);
}
@@ -391,6 +398,7 @@ public class VideoListActivity extends AppCompatActivity {
sort = "-trending";
currentStart = 0;
filter = null;
+ subscriptions = false;
loadVideos(currentStart, count, sort, filter);
}
@@ -402,24 +410,43 @@ 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);
+ } 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;
+ return true;
}
return false;
});
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/network/AuthorizationInterceptor.java b/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java
index da559c0..5329b7b 100644
--- a/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java
+++ b/app/src/main/java/net/schueller/peertube/network/AuthorizationInterceptor.java
@@ -1,24 +1,58 @@
+/*
+ * 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 net.schueller.peertube.model.Token;
+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 {
- Response mainResponse = chain.proceed(chain.request());
- if (mainResponse.code() == 401 || mainResponse.code() == 403) {
+ Session session = Session.getInstance();
+
+ Response mainResponse = chain.proceed(chain.request());
+ Request mainRequest = chain.request();
+
+ if (session.isLoggedIn()) {
+
+// if (mainResponse.code() == 401 || mainResponse.code() == 403) {
+// session.invalidate();
+// return mainResponse;
+// }
+
+ Request.Builder builder = mainRequest.newBuilder().header("Authorization", session.getToken()).
+ method(mainRequest.method(), mainRequest.body());
+ mainResponse = chain.proceed(builder.build());
+ Log.v("Authorization", "Intercept: " + session.getToken());
}
+
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
index 7c05bae..7c4d459 100644
--- a/app/src/main/java/net/schueller/peertube/network/GetUserService.java
+++ b/app/src/main/java/net/schueller/peertube/network/GetUserService.java
@@ -1,6 +1,7 @@
package net.schueller.peertube.network;
import net.schueller.peertube.model.Me;
+import net.schueller.peertube.model.VideoList;
import retrofit2.Call;
import retrofit2.http.GET;
@@ -11,4 +12,12 @@ public interface GetUserService {
@GET("users/me")
Call getMe(@Header("Authorization") String authorization);
+
+ @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/RetrofitInstance.java b/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
index 86fd92c..23e38da 100644
--- a/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
+++ b/app/src/main/java/net/schueller/peertube/network/RetrofitInstance.java
@@ -32,7 +32,6 @@ public class RetrofitInstance {
OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
- okhttpClientBuilder.addInterceptor(new TokenRenewInterceptor());
okhttpClientBuilder.addInterceptor(new AuthorizationInterceptor());
retrofit = new retrofit2.Retrofit.Builder()
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/java/net/schueller/peertube/network/TokenRenewInterceptor.java b/app/src/main/java/net/schueller/peertube/network/TokenRenewInterceptor.java
deleted file mode 100644
index 2ae3a69..0000000
--- a/app/src/main/java/net/schueller/peertube/network/TokenRenewInterceptor.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.schueller.peertube.network;
-
-import net.schueller.peertube.model.Token;
-
-import java.io.IOException;
-
-import okhttp3.Interceptor;
-import okhttp3.Response;
-
-public class TokenRenewInterceptor implements Interceptor {
-
- public TokenRenewInterceptor() {
- }
-
- @Override
- public Response intercept(Chain chain) throws IOException {
- Response response = chain.proceed(chain.request());
-
- // if 'x-auth-token' is available into the response header
- // save the new token into session.The header key can be
- // different upon implementation of backend.
- String newToken = response.header("x-auth-token");
- if (newToken != null) {
-
- }
-
- return response;
- }
-}
\ 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..bc4f3a5
--- /dev/null
+++ b/app/src/main/res/layout/activity_account.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_user.xml b/app/src/main/res/layout/activity_user.xml
deleted file mode 100644
index 39f110a..0000000
--- a/app/src/main/res/layout/activity_user.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ 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/strings.xml b/app/src/main/res/values/strings.xml
index 36158aa..524f60d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -22,6 +22,7 @@
Search
Settings
+ Logout
Home
@@ -96,9 +97,15 @@
Background Playback
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