diff --git a/CHANGELOG.md b/CHANGELOG.md index fc7448a..a3e7768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 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) diff --git a/app/build.gradle b/app/build.gradle index 8b69e35..7d6b93b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "net.schueller.peertube" minSdkVersion 21 targetSdkVersion 28 - versionCode 1019 - versionName "1.0.19" + versionCode 1020 + versionName "1.0.20" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) @@ -71,3 +71,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 e850419..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,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; @@ -83,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; @@ -126,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( @@ -262,6 +265,9 @@ public class VideoListActivity extends AppCompatActivity { Call call; if (!searchQuery.equals("")) { 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, languages); } @@ -381,6 +387,7 @@ public class VideoListActivity extends AppCompatActivity { sort = "-createdAt"; currentStart = 0; filter = null; + subscriptions = false; loadVideos(currentStart, count, sort, filter); } @@ -392,6 +399,7 @@ public class VideoListActivity extends AppCompatActivity { sort = "-trending"; currentStart = 0; filter = null; + subscriptions = false; loadVideos(currentStart, count, sort, filter); } @@ -403,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/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/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" /> - + - + - - + - - - -