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 0000000..b74ff03
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_list_black_24dp.png differ
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 0000000..be65048
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-hdpi/ic_menu_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_list_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_list_black_24dp.png
new file mode 100644
index 0000000..7d3a909
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_list_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_menu_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_menu_black_24dp.png
new file mode 100644
index 0000000..fdd0623
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-mdpi/ic_menu_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_list_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_list_black_24dp.png
new file mode 100644
index 0000000..040ef46
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_list_black_24dp.png differ
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 0000000..9b45e88
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xhdpi/ic_menu_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_list_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_list_black_24dp.png
new file mode 100644
index 0000000..e6bf705
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_list_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_menu_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_menu_black_24dp.png
new file mode 100644
index 0000000..4135efe
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxhdpi/ic_menu_black_24dp.png differ
diff --git a/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_list_black_24dp.png b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_list_black_24dp.png
new file mode 100644
index 0000000..64bf667
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_list_black_24dp.png differ
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 0000000..a3fa633
Binary files /dev/null and b/UI/AndroidApp/flavoursWithoutBorders/app/src/main/res/drawable-xxxhdpi/ic_menu_black_24dp.png differ
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" }
}
}