From 4147767a1fc5bfd5cee80236634a94b8e68773dc Mon Sep 17 00:00:00 2001 From: Apostolof Date: Wed, 26 Dec 2018 12:23:36 +0200 Subject: [PATCH] Add base application and activity (okhttp supported), Add drawer --- .../flavoursWithoutBorders/app/build.gradle | 5 + .../app/src/main/AndroidManifest.xml | 8 +- .../flavours/activities/LoginActivity.java | 4 +- .../flavours/activities/SignUpActivity.java | 9 +- .../activities/main/MainActivity.java | 26 +- .../databases/flavours/base/BaseActivity.java | 265 ++++++++++++++++++ .../flavours/base/BaseApplication.java | 72 +++++ .../flavours/session/SessionManager.java | 205 ++++++++++++++ .../res/drawable-hdpi/ic_list_black_24dp.png | Bin 0 -> 128 bytes .../res/drawable-hdpi/ic_menu_black_24dp.png | Bin 0 -> 103 bytes .../res/drawable-mdpi/ic_list_black_24dp.png | Bin 0 -> 94 bytes .../res/drawable-mdpi/ic_menu_black_24dp.png | Bin 0 -> 90 bytes .../res/drawable-xhdpi/ic_list_black_24dp.png | Bin 0 -> 116 bytes .../res/drawable-xhdpi/ic_menu_black_24dp.png | Bin 0 -> 112 bytes .../drawable-xxhdpi/ic_list_black_24dp.png | Bin 0 -> 140 bytes .../drawable-xxhdpi/ic_menu_black_24dp.png | Bin 0 -> 135 bytes .../drawable-xxxhdpi/ic_list_black_24dp.png | Bin 0 -> 173 bytes .../drawable-xxxhdpi/ic_menu_black_24dp.png | Bin 0 -> 163 bytes .../res/layout/activity_main_list_row.xml | 4 +- .../app/src/main/res/values/colors.xml | 2 + .../app/src/main/res/values/strings.xml | 8 +- .../flavoursWithoutBorders/build.gradle | 1 + 22 files changed, 593 insertions(+), 16 deletions(-) create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseActivity.java create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseApplication.java create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/session/SessionManager.java create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_list_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_menu_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_list_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_menu_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_list_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_menu_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_list_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_menu_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_list_black_24dp.png create mode 100644 UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_menu_black_24dp.png diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/build.gradle b/UI/AndroidApp/flavoursWithoutBorders/app/build.gradle index 7ec20e0..7f76950 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/build.gradle +++ b/UI/AndroidApp/flavoursWithoutBorders/app/build.gradle @@ -26,9 +26,14 @@ dependencies { implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.coordinatorlayout:coordinatorlayout:1.0.0' + implementation 'com.squareup.okhttp3:okhttp:3.12.0' + implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1' implementation 'androidx.cardview:cardview:1.0.0' + implementation 'com.mikepenz:materialdrawer:6.1.1' implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' + implementation 'com.mikepenz:fontawesome-typeface:4.7.0.0@aar' + implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.gms:play-services-maps:16.0.0' diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/AndroidManifest.xml b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/AndroidManifest.xml index b889f34..4745b2a 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/AndroidManifest.xml +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ + + android:theme="@style/AppTheme" + tools:ignore="GoogleAppIndexingWarning"> @@ -40,7 +44,7 @@ + android:label="@string/main_activity_title" /> \ No newline at end of file diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/LoginActivity.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/LoginActivity.java index 5b66be4..b487f60 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/LoginActivity.java +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/LoginActivity.java @@ -4,11 +4,11 @@ import android.content.Intent; import android.os.Bundle; import android.view.View; -import androidx.appcompat.app.AppCompatActivity; import gr.auth.databases.flavours.R; import gr.auth.databases.flavours.activities.main.MainActivity; +import gr.auth.databases.flavours.base.BaseActivity; -public class LoginActivity extends AppCompatActivity { +public class LoginActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/SignUpActivity.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/SignUpActivity.java index 9495314..775fdcf 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/SignUpActivity.java +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/SignUpActivity.java @@ -1,5 +1,6 @@ package gr.auth.databases.flavours.activities; +import android.annotation.SuppressLint; import android.app.DatePickerDialog; import android.app.Dialog; import android.content.Intent; @@ -13,13 +14,13 @@ import java.util.Calendar; import java.util.Objects; import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.DialogFragment; import gr.auth.databases.flavours.R; -import gr.auth.databases.flavours.activities.LoginActivity; +import gr.auth.databases.flavours.base.BaseActivity; -public class SignUpActivity extends AppCompatActivity { +public class SignUpActivity extends BaseActivity { + @SuppressLint("ClickableViewAccessibility") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -65,7 +66,7 @@ public class SignUpActivity extends AppCompatActivity { } public void onDateSet(DatePicker view, int year, int month, int day) { - birthdayInput.setText("" + year + "-" + month + "-" + day); + birthdayInput.setText(getResources().getString(R.string.sign_up_birthday_placeholder, year, month + 1, day)); } } } diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/main/MainActivity.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/main/MainActivity.java index 7f251b8..de09f4f 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/main/MainActivity.java +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/activities/main/MainActivity.java @@ -4,9 +4,8 @@ import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; - import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -16,8 +15,9 @@ import androidx.viewpager.widget.ViewPager; import gr.auth.databases.flavours.R; import gr.auth.databases.flavours.activities.main.fragments.MainListFragment; import gr.auth.databases.flavours.activities.main.fragments.MainMapFragment; +import gr.auth.databases.flavours.base.BaseActivity; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends BaseActivity { private static final int NUM_PAGES = 2; private ViewPager viewPager; private MenuItem menuMapItem; @@ -30,6 +30,12 @@ public class MainActivity extends AppCompatActivity { Toolbar toolbar = findViewById(R.id.main_toolbar); toolbar.setTitle("Restaurants"); setSupportActionBar(toolbar); + ActionBar actionbar = getSupportActionBar(); + actionbar.setDisplayHomeAsUpEnabled(true); + actionbar.setHomeAsUpIndicator(R.drawable.ic_menu_black_24dp); + + + createDrawer(); viewPager = findViewById(R.id.main_pager); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -45,9 +51,9 @@ public class MainActivity extends AppCompatActivity { } if (position == 0) { - menuMapItem.setVisible(true); + menuMapItem.setIcon(R.drawable.ic_map_black_24dp); } else { - menuMapItem.setVisible(false); + menuMapItem.setIcon(R.drawable.ic_list_black_24dp); } } }); @@ -79,10 +85,18 @@ public class MainActivity extends AppCompatActivity { if (id == R.id.main_toolbar_menu_filter) { return true; } else if (id == R.id.main_toolbar_menu_map) { - viewPager.setCurrentItem(1); + if (viewPager.getCurrentItem() == 0) { + viewPager.setCurrentItem(1); + } else if (viewPager.getCurrentItem() == 1) { + viewPager.setCurrentItem(0); + } + return true; + } else if (id == android.R.id.home) { + drawer.openDrawer(); return true; } + return super.onOptionsItemSelected(item); } diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseActivity.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseActivity.java new file mode 100644 index 0000000..da83e19 --- /dev/null +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseActivity.java @@ -0,0 +1,265 @@ +package gr.auth.databases.flavours.base; + +import android.Manifest; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.view.View; + +import com.mikepenz.fontawesome_typeface_library.FontAwesome; +import com.mikepenz.google_material_typeface_library.GoogleMaterial; +import com.mikepenz.iconics.IconicsDrawable; +import com.mikepenz.materialdrawer.AccountHeader; +import com.mikepenz.materialdrawer.AccountHeaderBuilder; +import com.mikepenz.materialdrawer.Drawer; +import com.mikepenz.materialdrawer.DrawerBuilder; +import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; +import com.mikepenz.materialdrawer.model.ProfileDrawerItem; +import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; +import gr.auth.databases.flavours.R; +import gr.auth.databases.flavours.activities.LoginActivity; +import gr.auth.databases.flavours.activities.main.MainActivity; +import gr.auth.databases.flavours.session.SessionManager; +import okhttp3.OkHttpClient; + +public abstract class BaseActivity extends AppCompatActivity { + // Client & Cookies + protected static OkHttpClient client; + + //SessionManager + protected static SessionManager sessionManager; + + private SharedPreferences sharedPreferences; + + //Common UI elements + protected Toolbar toolbar; + protected Drawer drawer; + + private boolean isMainActivity; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + isMainActivity = this instanceof MainActivity; + + if (client == null) + client = BaseApplication.getInstance().getClient(); //must check every time - e.g. + + // they become null when app restarts after crash + if (sessionManager == null) + sessionManager = BaseApplication.getInstance().getSessionManager(); + + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + } + + @Override + protected void onResume() { + super.onResume(); + updateDrawer(); + } + + @Override + protected void onPause() { + super.onPause(); + if (drawer != null) //close drawer animation after returning to activity + drawer.closeDrawer(); + } + + + public static OkHttpClient getClient() { + return client; + } + + public static SessionManager getSessionManager() { + return sessionManager; + } + + //------------------------------------------DRAWER STUFF---------------------------------------- + protected static final int HOME_ID = 0; + protected static final int LOG_ID = 4; + + private AccountHeader accountHeader; + private ProfileDrawerItem profileDrawerItem; + private PrimaryDrawerItem loginLogoutItem; + + protected void createDrawer() { + final int primaryColor = ContextCompat.getColor(this, R.color.textPrimary); + final int selectedPrimaryColor = ContextCompat.getColor(this, R.color.primary_dark); + final int selectedSecondaryColor = ContextCompat.getColor(this, R.color.iron); + + PrimaryDrawerItem homeItem; + IconicsDrawable homeIcon, homeIconSelected; + + //Drawer Icons + homeIcon = new IconicsDrawable(this) + .icon(GoogleMaterial.Icon.gmd_home) + .color(primaryColor); + + homeIconSelected = new IconicsDrawable(this) + .icon(GoogleMaterial.Icon.gmd_home) + .color(selectedSecondaryColor); + + IconicsDrawable loginIcon = new IconicsDrawable(this) + .icon(FontAwesome.Icon.faw_sign_in) + .color(primaryColor); + + IconicsDrawable logoutIcon = new IconicsDrawable(this) + .icon(FontAwesome.Icon.faw_sign_out) + .color(primaryColor); + + //Drawer Items + homeItem = new PrimaryDrawerItem() + .withTextColor(primaryColor) + .withSelectedColor(selectedPrimaryColor) + .withSelectedTextColor(selectedSecondaryColor) + .withIdentifier(HOME_ID) + .withName(R.string.drawer_home) + .withIcon(homeIcon) + .withSelectedIcon(homeIconSelected); + + if (sessionManager.isLoggedIn()) { + loginLogoutItem = new PrimaryDrawerItem() + .withTextColor(primaryColor) + .withSelectedColor(selectedSecondaryColor) + .withIdentifier(LOG_ID) + .withName(R.string.drawer_logout) + .withIcon(logoutIcon) + .withSelectable(false); + } else { + loginLogoutItem = new PrimaryDrawerItem() + .withTextColor(primaryColor) + .withSelectedColor(selectedSecondaryColor) + .withIdentifier(LOG_ID).withName(R.string.drawer_login) + .withIcon(loginIcon) + .withSelectable(false); + } + + //Profile + profileDrawerItem = new ProfileDrawerItem().withName(sessionManager.getUsername()).withIdentifier(0); + + //AccountHeader + accountHeader = new AccountHeaderBuilder() + .withActivity(this) + .withCompactStyle(true) + .withSelectionListEnabledForSingleProfile(false) + .withHeaderBackground(R.color.primary) + .withTextColor(getResources().getColor(R.color.iron)) + .addProfiles(profileDrawerItem) + /*.withOnAccountHeaderListener((view, profile, currentProfile) -> { + if (sessionManager.isLoggedIn()) { + Intent intent = new Intent(BaseActivity.this, ProfileActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_PROFILE_URL, "https://www.thmmy.gr/smf/index.php?action=profile"); + extras.putString(BUNDLE_PROFILE_USERNAME, sessionManager.getUsername()); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + return false; + } else + startLoginActivity(); + return true; + + })*/ + .build(); + + DrawerBuilder drawerBuilder = new DrawerBuilder() + .withActivity(this) + .withToolbar(toolbar) + .withDrawerWidthDp((int) BaseApplication.getInstance().getDpWidth() / 2) + .withSliderBackgroundColor(ContextCompat.getColor(this, R.color.colorBackground)) + .withAccountHeader(accountHeader) + .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { + @Override + public boolean onItemClick(View view, int position, IDrawerItem drawerItem) { + if (drawerItem.equals(HOME_ID)) { + if (!isMainActivity) { + Intent intent = new Intent(BaseActivity.this, MainActivity.class); + startActivity(intent); + } + } else if (drawerItem.equals(LOG_ID)) { + if (!sessionManager.isLoggedIn()) //When logged out or if user is guest + startLoginActivity(); + /*else + new LogoutTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);*/ + } + + drawer.closeDrawer(); + return true; + } + }); + + + drawerBuilder.addDrawerItems(homeItem, loginLogoutItem); + drawer = drawerBuilder.build(); + + if (!isMainActivity) + drawer.getActionBarDrawerToggle().setDrawerIndicatorEnabled(false); + + drawer.setOnDrawerNavigationListener(new Drawer.OnDrawerNavigationListener() { + @Override + public boolean onNavigationClickListener(View clickedView) { + onBackPressed(); + return true; + } + }); + } + + private void updateDrawer() { + if (drawer != null) { + accountHeader.updateProfile(profileDrawerItem); + drawer.updateItem(loginLogoutItem); + } + } + + //-------PERMS--------- + private static final int PERMISSIONS_REQUEST_CODE = 69; + + //True if permissions are OK + private boolean checkPerms() { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { + String[] PERMISSIONS_STORAGE = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE}; + + return !(checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED || + checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED); + } + return true; + } + + //Display popup for user to grant permission + private void requestPerms() { //Runtime permissions request for devices with API >= 23 + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { + String[] PERMISSIONS_STORAGE = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE}; + + requestPermissions(PERMISSIONS_STORAGE, PERMISSIONS_REQUEST_CODE); + } + } + + + @Override + public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions + , @NonNull int[] grantResults) { + switch (permsRequestCode) { + case PERMISSIONS_REQUEST_CODE: + //downloadFile(); + break; + } + } + + private void startLoginActivity() { + Intent intent = new Intent(BaseActivity.this, LoginActivity.class); + startActivity(intent); + } +} diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseApplication.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseApplication.java new file mode 100644 index 0000000..0bd3383 --- /dev/null +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/base/BaseApplication.java @@ -0,0 +1,72 @@ +package gr.auth.databases.flavours.base; + +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; +import android.util.DisplayMetrics; + +import com.franmontiel.persistentcookiejar.PersistentCookieJar; +import com.franmontiel.persistentcookiejar.cache.SetCookieCache; +import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; + +import java.util.concurrent.TimeUnit; + +import gr.auth.databases.flavours.session.SessionManager; +import okhttp3.OkHttpClient; + +public class BaseApplication extends Application { + private static BaseApplication baseApplication; //BaseApplication singleton + + //Client & SessionManager + private OkHttpClient client; + private SessionManager sessionManager; + + private static final String SHARED_PREFS = "ThmmySharedPrefs"; + + private static float dpWidth; + + public static BaseApplication getInstance() { + return baseApplication; + } + + @Override + public void onCreate() { + super.onCreate(); + baseApplication = this; //init singleton + + //Shared Preferences + SharedPreferences sharedPrefs = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE); + + SharedPrefsCookiePersistor sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(getApplicationContext()); + PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .cookieJar(cookieJar) + .connectTimeout(40, TimeUnit.SECONDS) + .writeTimeout(40, TimeUnit.SECONDS) + .readTimeout(40, TimeUnit.SECONDS); + + client = builder.build(); + + sessionManager = new SessionManager(client, cookieJar, sharedPrefsCookiePersistor, sharedPrefs); + + DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics(); + dpWidth = displayMetrics.widthPixels / displayMetrics.density; + } + + //Getters + public Context getContext() { + return getApplicationContext(); + } + + public OkHttpClient getClient() { + return client; + } + + public SessionManager getSessionManager() { + return sessionManager; + } + + public float getDpWidth() { + return dpWidth; + } +} diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/session/SessionManager.java b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/session/SessionManager.java new file mode 100644 index 0000000..e4416ab --- /dev/null +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/java/gr/auth/databases/flavours/session/SessionManager.java @@ -0,0 +1,205 @@ +package gr.auth.databases.flavours.session; + + +import android.content.SharedPreferences; + +import com.franmontiel.persistentcookiejar.PersistentCookieJar; +import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; + +import java.util.List; + +import okhttp3.Cookie; +import okhttp3.FormBody; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class SessionManager { + //Generic constants + public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?theme=4"); + private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2"); + + // Client & Cookies + private final OkHttpClient client; + private final PersistentCookieJar cookieJar; + private final SharedPrefsCookiePersistor cookiePersistor; //Used to explicitly edit cookies in cookieJar + + //Shared Preferences & its keys + private final SharedPreferences sharedPrefs; + private static final String USERNAME = "Username"; + private static final String USER_ID = "UserID"; + private static final String LOGOUT_LINK = "LogoutLink"; + private static final String LOGGED_IN = "LoggedIn"; + private static final String LOGIN_SCREEN_AS_DEFAULT = "LoginScreenAsDefault"; + + //Constructor + public SessionManager(OkHttpClient client, PersistentCookieJar cookieJar, + SharedPrefsCookiePersistor cookiePersistor, SharedPreferences sharedPrefs) { + this.client = client; + this.cookiePersistor = cookiePersistor; + this.cookieJar = cookieJar; + this.sharedPrefs = sharedPrefs; + } + + public int login(String... strings) { + //Builds the login request for each case + Request request; + if (strings.length == 2) { + clearSessionData(); + + String loginName = strings[0]; + String password = strings[1]; + + RequestBody formBody = new FormBody.Builder() + .add("user", loginName) + .add("passwrd", password) + .add("cookielength", "-1") //-1 is forever + .build(); + request = new Request.Builder() + .url(loginUrl) + .post(formBody) + .build(); + } else { + request = new Request.Builder() + .url(loginUrl) + .build(); + } + + try { + //Makes request & handles response + Response response = client.newCall(request).execute(); + + if (validateRetrievedCookies()) { + setPersistentCookieSession(); //Store cookies + + //Edit SharedPreferences, save session's data + SharedPreferences.Editor editor = sharedPrefs.edit(); + setLoginScreenAsDefault(false); + editor.putBoolean(LOGGED_IN, true); + /*editor.putString(USERNAME, extractUserName(document)); + editor.putInt(USER_ID, extractUserId(document)); + String avatar = extractAvatarLink(document);*/ + /*if (avatar != null) + editor.putString(AVATAR_LINK, avatar); + editor.putBoolean(HAS_AVATAR, avatar != null); + editor.putString(LOGOUT_LINK, extractLogoutLink(document));*/ + editor.apply(); + + return 0; + } else { + //Investigates login failure + /*if (error.size() > 0) { //Wrong username + return WRONG_USER; + } + + if (error.size() > 0) { //Wrong password + return WRONG_PASSWORD; + } + + if (error.size() > 0) { //User is banned + return BANNED_USER; + }*/ + + //Other error e.g. session was reset server-side + clearSessionData(); //Clear invalid saved data + return 1; + } + //Handles exceptions + } catch (Exception e) { + return 2; + } + } + + public void validateSession() { + if (isLoggedIn()) { + int loginResult = login(); + if (loginResult != 1) + return; + } else if (isLoginScreenDefault()) + return; + + setLoginScreenAsDefault(true); + clearSessionData(); + } + + public int logout() { + Request request = new Request.Builder() + .url(sharedPrefs.getString(LOGOUT_LINK, "LogoutLink")) + .build(); + + try { + //Makes request & handles response + Response response = client.newCall(request).execute(); + } catch (Exception e) { + return 2; + } finally { + //All data should always be cleared from device regardless the result of logout + clearSessionData(); + } + + return 0; + } + + public String getUsername() { + return sharedPrefs.getString(USERNAME, USERNAME); + } + + public int getUserId() { + return sharedPrefs.getInt(USER_ID, -1); + } + + public Cookie getThmmyCookie() { + List cookieList = cookieJar.loadForRequest(indexUrl); + for (Cookie cookie : cookieList) { + if (cookie.name().equals("THMMYgrC00ki3")) + return cookie; + } + return null; + } + + public boolean isLoggedIn() { + return sharedPrefs.getBoolean(LOGGED_IN, false); + } + + public boolean isLoginScreenDefault() { + return sharedPrefs.getBoolean(LOGIN_SCREEN_AS_DEFAULT, true); + } + + private boolean validateRetrievedCookies() { + List cookieList = cookieJar.loadForRequest(indexUrl); + for (Cookie cookie : cookieList) { + if (cookie.name().equals("THMMYgrC00ki3")) + return true; + } + return false; + } + + // Call validateRetrievedCookies() first + private void setPersistentCookieSession() { + List cookieList = cookieJar.loadForRequest(indexUrl); + Cookie.Builder builder = new Cookie.Builder(); + builder.name(cookieList.get(1).name()) + .value(cookieList.get(1).value()) + .domain(cookieList.get(1).domain()) + .expiresAt(cookieList.get(0).expiresAt()); + cookieList.remove(1); + cookieList.add(builder.build()); + cookiePersistor.clear(); + cookiePersistor.saveAll(cookieList); + + } + + private void clearSessionData() { + cookieJar.clear(); + sharedPrefs.edit().clear().apply(); //Clear session data + sharedPrefs.edit().putString(USERNAME, "Guest").apply(); + sharedPrefs.edit().putInt(USER_ID, -1).apply(); + sharedPrefs.edit().putBoolean(LOGGED_IN, false).apply(); //User logs out + } + + private void setLoginScreenAsDefault(boolean b) { + sharedPrefs.edit().putBoolean(LOGIN_SCREEN_AS_DEFAULT, b).apply(); + } +} \ No newline at end of file diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_list_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_list_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..b74ff03383af74fed68b6288159d0c425373b515 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB+&x_!Ln>~)y==+FV8Fq0z~=1o zpPywWm`ymO)F^qwO^4;?HHIJlXP)@UJPYld-Fz+S{>j68w0=HyJinJm_p%WLF}&g_ XH@aTyf9T$Qppguou6{1-oD!M<4lXZL literal 0 HcmV?d00001 diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_menu_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_menu_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..be6504808a126b2187083a61e9623720eb2ff23d GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB^gLZ0Ln>~)y>gI~fq{d0fAJB77 qU6g+g>*7KKDRv;i<#uoZ3xoag_=OJV9lirKFnGH9xvXcxAr-fh6C_v{H{5z)KlQ_b nNCPf6mdKI;Vst04d}iu>b%7 literal 0 HcmV?d00001 diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_menu_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_menu_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..9b45e88237459fc81d1d8496da6d0127fd8df807 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCb59q?kcwMxuO8%NVBlch_-_9e zy$8`QLN6F$`I09MGA?Qg0#!gk%(VXBwf28m1RNL`p+rJ5Q0{@8^BEyAgy4aCpx}o2ifNqO n3JnZQ9AM&sJ literal 0 HcmV?d00001 diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_menu_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_menu_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a3fa6339f3948a2fd4baa1f63859d2cca138f634 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoS)MMAAr-gY-gM+;VBlch_|u%1 zuR=IuvgQtX6`(W(c;2*NWD#&+fD$_-K*A07GIwH}Sq&Ij!01m4BT#V1>4RrYLl}e| i!03QKSS3jHjirn$7i0kR<=d#Wzp$P!~9VIUS literal 0 HcmV?d00001 diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/layout/activity_main_list_row.xml b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/layout/activity_main_list_row.xml index 4e1b66d..055c231 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/layout/activity_main_list_row.xml +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/layout/activity_main_list_row.xml @@ -4,9 +4,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="5dp" - card_view:cardElevation="1dp" + card_view:cardElevation="2dp" card_view:cardPreventCornerOverlap="false" card_view:cardUseCompatPadding="true"> diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/colors.xml b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/colors.xml index d12a1ed..2a98221 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/colors.xml +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/colors.xml @@ -4,4 +4,6 @@ #00574B #D81B60 #DDDDDD + #F6F8Fa + #303030 diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/strings.xml b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/strings.xml index 8c37770..62caf88 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/strings.xml +++ b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/values/strings.xml @@ -16,9 +16,15 @@ Birthday SIGN UP or login - Main + %1$d-%2$d-%3$d + + + Home + Logout + Login + Main Filter results Show in map diff --git a/UI/AndroidApp/flavoursWithoutBorders/build.gradle b/UI/AndroidApp/flavoursWithoutBorders/build.gradle index 8d3ef8e..c935b4f 100644 --- a/UI/AndroidApp/flavoursWithoutBorders/build.gradle +++ b/UI/AndroidApp/flavoursWithoutBorders/build.gradle @@ -19,6 +19,7 @@ allprojects { repositories { google() jcenter() + maven { url "https://jitpack.io" } } }